From 4ba8ad0e6c161e9149d3f703b8af4eecc7622999 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 01/69] =?UTF-8?q?Datenschutzbestimmungen=20und=20F=C3=B6rd?= =?UTF-8?q?errichtlinien=20=C3=B6ffnen=20nun=20auch=20in=20neuem=20Tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- input/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/forms.py b/input/forms.py index 826898b..9fb4ed9 100644 --- a/input/forms.py +++ b/input/forms.py @@ -32,7 +32,7 @@ class ExternForm(FdbForm): label='Was möchtest Du beantragen?') check = BooleanField(required=True, - label=format_html("Ich stimme den Datenschutzbestimmungen und den Förderrichtlinen zu", + label=format_html("Ich stimme den Datenschutzbestimmungen und den Förderrichtlinen zu", DATAPROTECTION, FOERDERRICHTLINIEN)) class Meta: From b403ef1cddfbe017fb15211dffc92df639829320 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 02/69] added search field in admin panel model Projects, added displayed fields almost like wanted --- input/admin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/input/admin.py b/input/admin.py index 29e35e4..544b531 100644 --- a/input/admin.py +++ b/input/admin.py @@ -29,7 +29,8 @@ admin.site.add_action(export_as_csv) @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): save_as = True - readonly_fields = ('pid','finance_id','project_of_year') + search_fields = ('name', 'pid','finance_id', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') + list_display = ('name', 'pid','finance_id', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') # action = ['export_as_csv'] From 14de26de7097fd96931fabbe9422b52cf8208e05 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 03/69] full search and display fields for Projects, Services also added fields --- input/admin.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/input/admin.py b/input/admin.py index 544b531..55d5cc8 100644 --- a/input/admin.py +++ b/input/admin.py @@ -29,11 +29,16 @@ admin.site.add_action(export_as_csv) @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): save_as = True - search_fields = ('name', 'pid','finance_id', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') - list_display = ('name', 'pid','finance_id', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') + search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') + list_display = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') # action = ['export_as_csv'] - +@admin.register(BusinessCard) +class BusinessCardAdmin(admin.ModelAdmin): + save_as = True + search_fields = ('realname', 'service_id', 'granted', 'granted_date', 'project') + list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project') + # action = ['export_as_csv'] admin.site.register([ Account, @@ -42,7 +47,6 @@ admin.site.register([ IFG, Travel, Email, - BusinessCard, List, Literature, ]) From 94d8d7a50b6dd8a90dfbe8dd0aaef7c4d2fda9b3 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 04/69] dates in tabulatures, based on django style with almost no new code. only applied to projects change list page --- input/admin.py | 9 +++++++-- input/models.py | 6 ++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/input/admin.py b/input/admin.py index 55d5cc8..536c91a 100644 --- a/input/admin.py +++ b/input/admin.py @@ -32,13 +32,18 @@ class ProjectAdmin(admin.ModelAdmin): search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') list_display = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') # action = ['export_as_csv'] + date_hierarchy = 'start' @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): - save_as = True - search_fields = ('realname', 'service_id', 'granted', 'granted_date', 'project') + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date', 'project') list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project') + list_display_links = ('realname', 'service_id') # action = ['export_as_csv'] + classes = ['collapse'] + + admin.site.register([ Account, diff --git a/input/models.py b/input/models.py index 997a3a5..ec412d3 100644 --- a/input/models.py +++ b/input/models.py @@ -93,12 +93,14 @@ class Project(Volunteer): # we don't call save with args/kwargs to avoid UNIQUE CONSTRAINT errors # but maybe there is a better solution? super().save() - self.pid = str(self.account.code) + str(self.pk).zfill(3) + self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) + # self.pid = str(self.account.code) + str(self.pk).zfill(3) # generation of finance_id if not self.project_of_year: - #print('AAA') + print('AAA') # we need to determine if this is a new year with its first new project... year = self.start.year + print(year) projects = Project.objects.filter(start__year=year) if not projects: #print('BBB') From f6ae9e640e902ddd4d8ed84b53ec6bbf50594161 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 05/69] added NOT choice, 'nicht stattgefunden', to project status button --- input/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/models.py b/input/models.py index ec412d3..dae00e3 100644 --- a/input/models.py +++ b/input/models.py @@ -83,7 +83,7 @@ class Project(Volunteer): # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) end_mail_send = models.BooleanField(null=True) - status = models.CharField(max_length=3,choices=(('RUN', 'läuft'),('END','beendet')),default='RUN') + status = models.CharField(max_length=3,choices=(('RUN', 'läuft'),('END','beendet'),('NOT','nicht stattgefunden')),default='RUN') persons = models.IntegerField(default=1) finance_id = models.CharField(max_length=15, null= True, blank=True) project_of_year = models.IntegerField(default=0) From 28e1570bee86cf9326922fe29edcd8923891730e Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 06/69] notes field is now bigger, changed to Textfield analog. new entry url_of_pic, migrated, javascript to hide in businesscard if nopic is choice --- input/admin.py | 5 +- input/forms.py | 3 +- ...ard_url_of_pic_alter_ifg_notes_and_more.py | 58 +++++++++++++++++++ input/models.py | 9 ++- input/static/dropdown/js/base.js | 24 ++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py create mode 100644 input/static/dropdown/js/base.js diff --git a/input/admin.py b/input/admin.py index 536c91a..dc83ea1 100644 --- a/input/admin.py +++ b/input/admin.py @@ -41,8 +41,11 @@ class BusinessCardAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project') list_display_links = ('realname', 'service_id') # action = ['export_as_csv'] - classes = ['collapse'] + class Media: + js = ('dropdown/js/base.js',) + + admin.site.register([ diff --git a/input/forms.py b/input/forms.py index 9fb4ed9..9f12c31 100644 --- a/input/forms.py +++ b/input/forms.py @@ -96,7 +96,8 @@ class EmailForm(CheckForm): class BusinessCardForm(CheckForm): class Meta: model = BusinessCard - fields = ['project', 'data', 'variant', 'sent_to'] + + fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to'] class ListForm(CheckForm): class Meta: diff --git a/input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py b/input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py new file mode 100644 index 0000000..0a2427f --- /dev/null +++ b/input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py @@ -0,0 +1,58 @@ +# Generated by Django 4.1.2 on 2022-11-11 07:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0062_auto_20211103_1155'), + ] + + operations = [ + migrations.AddField( + model_name='businesscard', + name='url_of_pic', + field=models.TextField(default='', help_text='Bitte gib die Wikimedia-Commons-URL des Bildes an.', max_length=200, verbose_name='Url des Bildes'), + ), + migrations.AlterField( + model_name='ifg', + name='notes', + field=models.TextField(blank=True, help_text='Bitte gib an wofür Du das Stipendium verwenden willst.', max_length=1000, verbose_name='Anmerkungen'), + ), + migrations.AlterField( + model_name='library', + name='notes', + field=models.TextField(blank=True, help_text='Bitte gib an wofür Du das Stipendium verwenden willst.', max_length=1000, verbose_name='Anmerkungen'), + ), + 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')], default='BIB', max_length=4), + ), + migrations.AlterField( + model_name='literature', + name='notes', + field=models.TextField(blank=True, help_text='Bitte gib an wofür Du das Stipendium verwenden willst.', max_length=1000, verbose_name='Anmerkungen'), + ), + migrations.AlterField( + model_name='project', + name='notes', + field=models.TextField(blank=True, max_length=1000, null=True, verbose_name='Anmerkungen'), + ), + migrations.AlterField( + model_name='project', + name='start', + field=models.DateField(null=True, verbose_name='Startdatum'), + ), + migrations.AlterField( + model_name='project', + name='status', + field=models.CharField(choices=[('RUN', 'läuft'), ('END', 'beendet'), ('NOT', 'nicht stattgefunden')], default='RUN', max_length=3), + ), + migrations.AlterField( + model_name='travel', + name='notes', + field=models.TextField(blank=True, max_length=1000), + ), + ] diff --git a/input/models.py b/input/models.py index dae00e3..a016742 100644 --- a/input/models.py +++ b/input/models.py @@ -78,7 +78,7 @@ class Project(Volunteer): cost = models.IntegerField(blank=True, null=True) 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.CharField(max_length=1000,null=True,blank=True,verbose_name='Anmerkungen') + notes = models.TextField(max_length=1000,null=True,blank=True,verbose_name='Anmerkungen') # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) @@ -152,14 +152,14 @@ class Travel(Intern): 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') - notes = models.CharField(max_length=500, blank=True) + notes = models.TextField(max_length=1000, blank=True) #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.") - notes = models.TextField(max_length=500, blank=True, verbose_name='Anmerkungen', + notes = models.TextField(max_length=1000, blank=True, verbose_name='Anmerkungen', help_text="Bitte gib an wofür Du das Stipendium verwenden willst.") class Meta: @@ -265,5 +265,8 @@ class BusinessCard(Extern): default='NOPIC', verbose_name='Variante', help_text=format_html('so sehen die Varianten aus: \ 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.") + sent_to = models.TextField(max_length=1000, verbose_name='Versandadresse', default='', help_text="Bitte gib den Namen und die vollständige Adresse ein, an welche die Visitenkarten geschickt werden sollen.") diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js new file mode 100644 index 0000000..d469bb5 --- /dev/null +++ b/input/static/dropdown/js/base.js @@ -0,0 +1,24 @@ +window.addEventListener("load", function() { +(function($) { + $(function() { + var selectField = $('#id_variant'), + verified = $('.field-url_of_pic'); + + function toggleVerified(value) { + if (value === 'PIC') { + verified.show(); + } else { + verified.hide(); + } + } + + // show/hide on load based on existing value of selectField + toggleVerified(selectField.val()); + + // show/hide on change + selectField.change(function() { + toggleVerified($(this).val()); + }); + }); +})(django.jQuery); +}); From 418fef477a1325b8efb6410c431736041c7e88b4 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 07/69] added boolean field send_data_to_print with html formatted link to businesscard --- input/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/input/models.py b/input/models.py index a016742..341561c 100644 --- a/input/models.py +++ b/input/models.py @@ -270,3 +270,4 @@ class BusinessCard(Extern): sent_to = models.TextField(max_length=1000, verbose_name='Versandadresse', default='', help_text="Bitte gib den Namen und die vollständige Adresse ein, an welche die Visitenkarten geschickt werden sollen.") + send_data_to_print = models.BooleanField(null=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.')) From 9d0f8fd477f0d29c05cc3a6118797cd67ca3e355 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 08/69] pic_of_url hidden in all views --- input/static/dropdown/js/base.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js index d469bb5..5769caa 100644 --- a/input/static/dropdown/js/base.js +++ b/input/static/dropdown/js/base.js @@ -2,7 +2,7 @@ window.addEventListener("load", function() { (function($) { $(function() { var selectField = $('#id_variant'), - verified = $('.field-url_of_pic'); + verified = $('#id_url_of_pic').parent().parent(); function toggleVerified(value) { if (value === 'PIC') { From 2f4ee1ee13700d67f45becf88c4e0b52132d64f5 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 09/69] added dropdown agreement to send my data for buying literature for me --- input/static/dropdown/js/base.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js index 5769caa..0d8d5c4 100644 --- a/input/static/dropdown/js/base.js +++ b/input/static/dropdown/js/base.js @@ -1,9 +1,33 @@ window.addEventListener("load", function() { (function($) { $(function() { + var selectField_selfbuy = $('#id_selfbuy'), + verified_selfbuy_div = $('#id_selfbuy_give_data').parent().parent(), + verified_selfbuy = $('#id_selfbuy_give_data'); + + function toggleVerified_selfbuy(value) { + if (value === "FALSE") { + verified_selfbuy_div.show(); + verified_selfbuy.prop("checked", false); + } else { + verified_selfbuy_div.hide(); + verified_selfbuy.prop("checked", true); + } + } + + // show/hide on load based on existing value of selectField + toggleVerified_selfbuy(selectField_selfbuy.val()); + + // show/hide on change + selectField_selfbuy.change(function() { + toggleVerified_selfbuy($(this).val()); + }); + + + var selectField = $('#id_variant'), verified = $('#id_url_of_pic').parent().parent(); - + function toggleVerified(value) { if (value === 'PIC') { verified.show(); From cb6710e758345ad8e45a2555e264ca1c835c1f45 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:28 +0000 Subject: [PATCH 10/69] Anfang code der Funktion end of proj approved in sendmails.py --- input/admin.py | 7 +++- input/forms.py | 20 +++++++++-- input/management/commands/sendmails.py | 30 ++++++++++++++++- ...ta_to_print_literature_selfbuy_and_more.py | 33 +++++++++++++++++++ .../0065_alter_literature_selfbuy_and_more.py | 23 +++++++++++++ input/models.py | 12 ++++++- input/settings.py | 6 ++-- 7 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py create mode 100644 input/migrations/0065_alter_literature_selfbuy_and_more.py diff --git a/input/admin.py b/input/admin.py index dc83ea1..f617d8e 100644 --- a/input/admin.py +++ b/input/admin.py @@ -34,6 +34,7 @@ class ProjectAdmin(admin.ModelAdmin): # action = ['export_as_csv'] date_hierarchy = 'start' + @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): save_as = True @@ -45,6 +46,11 @@ class BusinessCardAdmin(admin.ModelAdmin): class Media: js = ('dropdown/js/base.js',) +@admin.register(Literature) +class LiteratureAdmin(admin.ModelAdmin): + + class Media: + js = ('dropdown/js/base.js',) @@ -56,5 +62,4 @@ admin.site.register([ Travel, Email, List, - Literature, ]) diff --git a/input/forms.py b/input/forms.py index 9f12c31..20b0746 100644 --- a/input/forms.py +++ b/input/forms.py @@ -83,21 +83,37 @@ class CheckForm(FdbForm): NUTZUNGSBEDINGUNGEN)) class LiteratureForm(CheckForm): + 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'] + fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_give_data'] + class Media: + js = ('dropdown/js/base.js',) class EmailForm(CheckForm): # TODO: add some javascript to show/hide other-field class Meta: model = Email fields = ['domain', 'address', 'other'] + class Media: + js = ('dropdown/js/base.js',) + + class BusinessCardForm(CheckForm): - class Meta: + # this is the code, to change required to false if needed + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['url_of_pic'].required = True + + class Meta: model = BusinessCard fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to'] + class Media: + js = ('dropdown/js/base.js',) class ListForm(CheckForm): class Meta: diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 4e3e2ae..917fc74 100644 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -50,9 +50,11 @@ class Command(BaseCommand): def end_of_projects_reached(self): ''' end of project reached ''' # get all projects which ended + + print(Project.objects.filter(end__lt = date.today())) old = Project.objects.filter(end__lt = date.today())\ .exclude(end_mail_send = True) - + mail_template = get_template('input/if_end_of_project.txt') for project in old: context = {'project': project} @@ -70,6 +72,31 @@ class Command(BaseCommand): self.stdout.write(self.style.SUCCESS('end_of_projects_reached() executed.')) + def end_of_projects_approved(self): + ''' end of project approved ''' + # get all projects where end was reached already, and send mails for the ones already set to status "ended" by the admins + + approved_end = Project.objects.filter(status = 'END')\ + .exclude(end_mail_send = False) + print(approved_end) + mail_template = get_template('input/if_end_of_project.txt') + for project in approved_end: + context = {'project': project} + context['URLPREFIX'] = settings.URLPREFIX + try: + send_mail('Projektende erreicht', + mail_template.render(context), + IF_EMAIL, + [IF_EMAIL], + fail_silently=False) + project.end_mail_send = True + project.save() + except BadHeaderError: + self.stdout.write(self.style.ERROR('Invalid header found.')) + + self.stdout.write(self.style.SUCCESS('end_of_projects_reached() executed.')) + + def surveymails_to_object(self, supported, name='', type='LIB'): mytype=type myname = name @@ -158,6 +185,7 @@ class Command(BaseCommand): '''the main function which is called by the custom command''' self.end_of_projects_reached() + self.end_of_projects_approved() self.surveymails_to_lib() self.surveymails_to_hon() self.surveymails_to_ifg() diff --git a/input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py b/input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py new file mode 100644 index 0000000..2875fec --- /dev/null +++ b/input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.2 on 2022-11-11 10:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0063_businesscard_url_of_pic_alter_ifg_notes_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='businesscard', + name='send_data_to_print', + field=models.BooleanField(default=False, help_text='Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.', verbose_name='Datenweitergabe erlauben'), + ), + migrations.AddField( + model_name='literature', + name='selfbuy', + field=models.CharField(choices=[('TRUE', 'Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'), ('FALSE', 'Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft')], default='TRUE', max_length=10, verbose_name='Selbstkauf?'), + ), + migrations.AddField( + model_name='literature', + name='selfbuy_give_data', + field=models.BooleanField(default=False, help_text='Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.', verbose_name='Datenweitergabe erlauben'), + ), + migrations.AlterField( + model_name='businesscard', + name='url_of_pic', + field=models.CharField(default='', help_text='Bitte gib die Wikimedia-Commons-URL des Bildes an.', max_length=200, verbose_name='Url des Bildes'), + ), + ] diff --git a/input/migrations/0065_alter_literature_selfbuy_and_more.py b/input/migrations/0065_alter_literature_selfbuy_and_more.py new file mode 100644 index 0000000..d081397 --- /dev/null +++ b/input/migrations/0065_alter_literature_selfbuy_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.2 on 2022-11-11 11:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0064_businesscard_send_data_to_print_literature_selfbuy_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='literature', + name='selfbuy', + field=models.CharField(choices=[('TRUE', 'Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'), ('FALSE', 'Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft'), ('NONE', 'Nichts ausgewählt')], default='TRUE', max_length=10, verbose_name='Selbstkauf?'), + ), + migrations.AlterField( + model_name='literature', + name='selfbuy_give_data', + field=models.BooleanField(default='NONE', help_text='Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.', verbose_name='Datenweitergabe erlauben'), + ), + ] diff --git a/input/models.py b/input/models.py index 341561c..d1f6589 100644 --- a/input/models.py +++ b/input/models.py @@ -190,17 +190,27 @@ class Library(Grant): def __str__(self): return self.library + +SELFBUY_CHOICES = {'TRUE': format_html('Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'), + 'FALSE': format_html('Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft'), + 'NONE': format_html('Nichts ausgewählt') + } + + class Literature(Grant): info = models.CharField(max_length=500, verbose_name='Informationen zum Werk', help_text=format_html("Bitte gib alle Informationen zum benötigten Werk an,
\ die eine eindeutige Identifizierung ermöglichen (Autor, Titel, Verlag, ISBN, ...)")) source = models.CharField(max_length=200, verbose_name='Bezugsquelle', help_text="Bitte gib an, wo du das Werk kaufen möchtest.") + selfbuy = models.CharField( max_length=10, verbose_name='Selbstkauf?', choices=SELFBUY_CHOICES.items(), default='TRUE') + selfbuy_give_data = models.BooleanField(default='NONE', verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.')) 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.") + def __str__(self): return "IFG-Anfrage von " + self.realname @@ -270,4 +280,4 @@ class BusinessCard(Extern): sent_to = models.TextField(max_length=1000, verbose_name='Versandadresse', default='', help_text="Bitte gib den Namen und die vollständige Adresse ein, an welche die Visitenkarten geschickt werden sollen.") - send_data_to_print = models.BooleanField(null=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.')) + send_data_to_print = models.BooleanField(default=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.')) diff --git a/input/settings.py b/input/settings.py index eacac3f..8b01de1 100644 --- a/input/settings.py +++ b/input/settings.py @@ -1,6 +1,8 @@ # mail for IF-OTRS -IF_EMAIL = 'community@wikimedia.de' -SURVEY_EMAIL = 'christof.pins@wikimedia.de' +#IF_EMAIL = 'community@wikimedia.de' +IF_EMAIL = 'luca@cannabinieri.de' +#SURVEY_EMAIL = 'christof.pins@wikimedia.de' +SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' # prefix for urls SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?' From b5b0dc61e497ff2f23fc5e0a7c18b88ce4b52021 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 11/69] added templates for changed sendmail.txt --- .../input/if_end_of_project_approved.txt | 35 +++++++++++++++++++ .../input/if_not_of_project_approved.txt | 29 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 input/templates/input/if_end_of_project_approved.txt create mode 100644 input/templates/input/if_not_of_project_approved.txt diff --git a/input/templates/input/if_end_of_project_approved.txt b/input/templates/input/if_end_of_project_approved.txt new file mode 100644 index 0000000..6d7f941 --- /dev/null +++ b/input/templates/input/if_end_of_project_approved.txt @@ -0,0 +1,35 @@ +Hallo, + +dein Projekt/die Veranstaltung {{project.name}} ist nun beendet und wir hoffen, dass alles gut geklappt hat! + +Bitte beachte nun, dass im Vorfeld besprochene Kostenerstattungen innerhalb eines Monats nach Entstehen der Kosten über unser Online-Formular Antrag auf Kostenerstattung eingereicht werden müssen. Spätere Einsendungen können ggf. nicht mehr erstattet werden. + +Da wir verpflichtet sind, über unsere geförderten Maßnahmen zu berichten, möchten wir dich gerne bitten uns kurz folgende Infos zu deinem Projekt zukommen zu lassen: +* Wie viele Personen haben an dem Projekt teilgenommen? +* Wo können die Ergebnisse des Projektes eingesehen werden? (Projektseite, Commons-Link, Bericht o. ä.) + +Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen. + +Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du diesen nun archivieren, indem du den Projektstatus oben im Quellcode entsprechend anpasst und die Liste der geförderten Aktivitäten entsprechend aktualisierst. + +Falls nicht bereits geschehen, wirst du demnächst eine weitere E-Mail erhalten, mit der du die Möglichkeit hast uns Feedback zu der Unterstützung zu geben. Danke, dass du dir Zeit dafür nimmst! + +Insbesondere möchten wir uns an dieser Stelle ganz herzlich bei dir für die Zusammenarbeit und dein Engagement für Freies Wissen bedanken! + +Viele Grüße +Dein Team Communitys und Engagement + +----- +Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden. + +Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin +Tel. (030) 219 158 26-0 +https://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! +https://spenden.wikimedia.de + +Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. + +Datenschutzerklärung: +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. diff --git a/input/templates/input/if_not_of_project_approved.txt b/input/templates/input/if_not_of_project_approved.txt new file mode 100644 index 0000000..af3a719 --- /dev/null +++ b/input/templates/input/if_not_of_project_approved.txt @@ -0,0 +1,29 @@ +Hallo, + +dein Projekt/die Veranstaltung {{project.name}} konnte leider nicht wie geplant stattfinden. Gib uns gerne Bescheid, falls es bereits einen Nachholtermin geben sollte. Ansonsten freuen wir uns auf dein nächstes Vorhaben! + +Solltest du für dieses Projekt bereits Ausgaben gehabt haben, müssen im Vorfeld besprochene Kostenerstattungen innerhalb eines Monats nach Entstehen der Kosten über unser Online-Formular Antrag auf Kostenerstattung eingereicht werden. Spätere Einsendungen können ggf. nicht mehr erstattet werden. + +Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du den Projektstatus oben im Quellcode entsprechend anpassen (z. B. „ausgesetztes Förderprojekt”). + +Auch wenn ein Projekt mal nicht wie geplant stattfindet: Wir möchten jeden Schritt unserer Arbeit bestmöglich gestalten und freuen uns über dein Feedback dazu. Falls nicht bereits geschehen, wirst du daher demnächst eine weitere E-Mail erhalten, mit der du die Möglichkeit hast uns Rückmeldung zu unserer Unterstützung zu geben. Danke, dass du dir Zeit dafür nimmst! + +Insbesondere möchten wir uns an dieser Stelle ganz herzlich bei dir für die Zusammenarbeit und dein Engagement für Freies Wissen bedanken! + +Viele Grüße +Dein Team Communitys und Engagement + +----- +Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden. + +Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin +Tel. (030) 219 158 26-0 +https://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! +https://spenden.wikimedia.de + +Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. + +Datenschutzerklärung: +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. From 95e9bdd5a88bc4ba28a310a0ea2c5fbd98b988dd Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 12/69] added two sendmails functions, that are executed when admins change status of ended project --- foerderbarometer/settings.py_old | 151 ++++++++++++++++++ foerderbarometer/settings_development.py | 9 +- foerderbarometer/settings_production.py | 7 +- input/management/commands/sendmails.py | 50 +++++- input/settings.py | 2 +- .../input/if_end_of_project_orginformed.txt | 13 ++ 6 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 foerderbarometer/settings.py_old create mode 100644 input/templates/input/if_end_of_project_orginformed.txt diff --git a/foerderbarometer/settings.py_old b/foerderbarometer/settings.py_old new file mode 100644 index 0000000..3b3ff79 --- /dev/null +++ b/foerderbarometer/settings.py_old @@ -0,0 +1,151 @@ +""" +Django settings for foerderbarometer project. + +Generated by 'django-admin startproject' using Django 3.1.1. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.1/ref/settings/ +""" + +import json +import os +from pathlib import Path + +from django.core.exceptions import ImproperlyConfigured + +# prefix for urls in mails +URLPREFIX = 'http://localhost:8000' + +# mails in development go to stdout +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + +# get secrets +with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file: + secrets = json.load(secrets_file) + +def get_secret(setting, secrets=secrets): + """Get secret setting or fail with ImproperlyConfigured""" + try: + return secrets[setting] + except KeyError: + raise ImproperlyConfigured("Set the {} setting".format(setting)) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '*&7p9#_n$@^%0z49s+7jpy@+j1rw_hqh05knyd6y2*!0)r&b6h' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +STATIC_ROOT = BASE_DIR / 'staticfiles' + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'input.apps.InputConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'formtools', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'foerderbarometer.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'foerderbarometer.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + 'PASSWORD': get_secret('DATABASE_PASSWORD') + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.1/howto/static-files/ + +STATIC_URL = '/static/' + +# needed since django 3.2 +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' diff --git a/foerderbarometer/settings_development.py b/foerderbarometer/settings_development.py index 3b3ff79..15c0f3d 100644 --- a/foerderbarometer/settings_development.py +++ b/foerderbarometer/settings_development.py @@ -20,7 +20,14 @@ from django.core.exceptions import ImproperlyConfigured URLPREFIX = 'http://localhost:8000' # mails in development go to stdout -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' + +EMAIL_HOST = 'email.wikimedia.de' +EMAIL_PORT = '587' +EMAIL_USE_TLS = True +EMAIL_HOST_USER = '636ea784dd6ec43' +EMAIL_HOST_PASSWORD = 'wsgqp4ZaVRZZEpRJ' + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent diff --git a/foerderbarometer/settings_production.py b/foerderbarometer/settings_production.py index 2e40922..720e689 100644 --- a/foerderbarometer/settings_production.py +++ b/foerderbarometer/settings_production.py @@ -19,8 +19,11 @@ from django.core.exceptions import ImproperlyConfigured # mails in development go to stdout EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' -EMAIL_HOST = '10.0.6.25' -EMAIL_PORT = '25' +EMAIL_HOST = 'email.wikimedia.de' +EMAIL_PORT = '587' +EMAIL_USE_TLS = True +EMAIL_HOST_USER = '636ea784dd6ec43' +EMAIL_HOST_PASSWORD = 'wsgqp4ZaVRZZEpRJ' # prefix for urls in mails URLPREFIX = 'http://foerderung.wikimedia.de' diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 917fc74..8471f43 100644 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -63,7 +63,7 @@ class Command(BaseCommand): send_mail('Projektende erreicht', mail_template.render(context), IF_EMAIL, - [IF_EMAIL], + ['luca@cannabinieri.de'], fail_silently=False) project.end_mail_send = True project.save() @@ -79,7 +79,10 @@ class Command(BaseCommand): approved_end = Project.objects.filter(status = 'END')\ .exclude(end_mail_send = False) print(approved_end) - mail_template = get_template('input/if_end_of_project.txt') + mail_template = get_template('input/if_end_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 filling out the form + for project in approved_end: context = {'project': project} context['URLPREFIX'] = settings.URLPREFIX @@ -87,14 +90,54 @@ class Command(BaseCommand): 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, [IF_EMAIL], fail_silently=False) + project.end_mail_send = True project.save() except BadHeaderError: self.stdout.write(self.style.ERROR('Invalid header found.')) - self.stdout.write(self.style.SUCCESS('end_of_projects_reached() executed.')) + self.stdout.write(self.style.SUCCESS('end_of_projects_approved() executed.')) + + def notHappened_of_projects_approved(self): + ''' notHappened of project approved ''' + # get all projects where end was reached already, and send mails for the ones where status was put to NOT by admins + + approved_notHappened = Project.objects.filter(status = 'NOT')\ + .exclude(end_mail_send = False) + + 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 + + for project in approved_notHappened: + context = {'project': project} + context['URLPREFIX'] = settings.URLPREFIX + try: + 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, + [IF_EMAIL], + fail_silently=False) + + project.end_mail_send = True + project.save() + except BadHeaderError: + self.stdout.write(self.style.ERROR('Invalid header found.')) + + self.stdout.write(self.style.SUCCESS('notHappened_of_projects_approved() executed.')) def surveymails_to_object(self, supported, name='', type='LIB'): @@ -186,6 +229,7 @@ class Command(BaseCommand): self.end_of_projects_reached() self.end_of_projects_approved() + self.notHappened_of_projects_approved() self.surveymails_to_lib() self.surveymails_to_hon() self.surveymails_to_ifg() diff --git a/input/settings.py b/input/settings.py index 8b01de1..5ee83b0 100644 --- a/input/settings.py +++ b/input/settings.py @@ -1,6 +1,6 @@ # mail for IF-OTRS #IF_EMAIL = 'community@wikimedia.de' -IF_EMAIL = 'luca@cannabinieri.de' +IF_EMAIL = 'test-luca-ext@wikimedia.de' #SURVEY_EMAIL = 'christof.pins@wikimedia.de' SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' diff --git a/input/templates/input/if_end_of_project_orginformed.txt b/input/templates/input/if_end_of_project_orginformed.txt new file mode 100644 index 0000000..05b12a3 --- /dev/null +++ b/input/templates/input/if_end_of_project_orginformed.txt @@ -0,0 +1,13 @@ +Hallo Team Communitys und Engagement! + +Das Project {{project.name}} hat am {{project.end}} sein vorraussichtliches +Ende erreicht. + +Hier könnt ihr es in der Datenbank editieren: + +{{URLPREFIX}}/admin/input/project/{{project.pk}}/change + + +Projektorganisator*in wurde über den Projektabschluss informiert. + +mit freundlichen Grüßen, Eure Lieblingsdatenbank From 9bc852a23e4dea6e64fec0aace7023771681cde3 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 13/69] buttons in input form displaying 'Weiter', if last step then displaying 'Absenden' --- input/templates/input/extern.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/input/templates/input/extern.html b/input/templates/input/extern.html index 7efd013..f4386a4 100644 --- a/input/templates/input/extern.html +++ b/input/templates/input/extern.html @@ -52,7 +52,11 @@ Du hast {{choice}} ausgewählt. {% if wizard.steps.prev %} {% endif %} + {% if wizard.steps.current == wizard.steps.last %} + + {% else %} + {% endif %}

From 95774952e215fde9d1e234933fbf1a811b2003f9 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 14/69] if not happened mail is now in html format, if not html then txt --- .../input/if_not_of_project_approved.html | 41 +++++++++++++++++++ .../input/if_not_of_project_approved.txt | 1 + 2 files changed, 42 insertions(+) create mode 100644 input/templates/input/if_not_of_project_approved.html diff --git a/input/templates/input/if_not_of_project_approved.html b/input/templates/input/if_not_of_project_approved.html new file mode 100644 index 0000000..fa5f4df --- /dev/null +++ b/input/templates/input/if_not_of_project_approved.html @@ -0,0 +1,41 @@ + + + + +

+Hallo, +
+dein Projekt/die Veranstaltung {{project.name}} konnte leider nicht wie geplant stattfinden. Gib uns gerne Bescheid, falls es bereits einen Nachholtermin geben sollte. Ansonsten freuen wir uns auf dein nächstes Vorhaben! +
+Solltest du für dieses Projekt bereits Ausgaben gehabt haben, müssen im Vorfeld besprochene Kostenerstattungen innerhalb eines Monats nach Entstehen der Kosten über unser Online-Formular Antrag auf Kostenerstattung eingereicht werden. Spätere Einsendungen können ggf. nicht mehr erstattet werden. +
+Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du den Projektstatus oben im Quellcode entsprechend anpassen (z. B. „ausgesetztes Förderprojekt”). +
+Auch wenn ein Projekt mal nicht wie geplant stattfindet: Wir möchten jeden Schritt unserer Arbeit bestmöglich gestalten und freuen uns über dein Feedback dazu. Falls nicht bereits geschehen, wirst du daher demnächst eine weitere E-Mail erhalten, mit der du die Möglichkeit hast uns Rückmeldung zu unserer Unterstützung zu geben. Danke, dass du dir Zeit dafür nimmst! +
+Insbesondere möchten wir uns an dieser Stelle ganz herzlich bei dir für die Zusammenarbeit und dein Engagement für Freies Wissen bedanken! +
+Ein Link zum Probieren +
+Viele Grüße +Dein Team Communitys und Engagement +

+----- +Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden. +

+Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
+Tel. (030) 219 158 26-0
+https://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!
+https://spenden.wikimedia.de +

+Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. +

+Datenschutzerklärung:
+Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +

+

+ + + diff --git a/input/templates/input/if_not_of_project_approved.txt b/input/templates/input/if_not_of_project_approved.txt index af3a719..3fe07fa 100644 --- a/input/templates/input/if_not_of_project_approved.txt +++ b/input/templates/input/if_not_of_project_approved.txt @@ -27,3 +27,4 @@ Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Einge Datenschutzerklärung: Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. + From 960ec8841c7def51aefc957048e31b61db4bec04 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 15/69] added the automated mail with the possibility to grant travel costs by link in email --- input/forms.py | 8 ++++++- input/management/commands/sendmails.py | 23 ++++++++++++++----- input/migrations/0066_email_adult.py | 18 +++++++++++++++ ..._travel_project_name_alter_library_type.py | 23 +++++++++++++++++++ input/migrations/0068_travel_hotel.py | 18 +++++++++++++++ .../migrations/0069_alter_travel_transport.py | 18 +++++++++++++++ input/migrations/0070_alter_travel_project.py | 19 +++++++++++++++ input/models.py | 14 +++++++++-- input/views.py | 7 +++++- 9 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 input/migrations/0066_email_adult.py create mode 100644 input/migrations/0067_travel_project_name_alter_library_type.py create mode 100644 input/migrations/0068_travel_hotel.py create mode 100644 input/migrations/0069_alter_travel_transport.py create mode 100644 input/migrations/0070_alter_travel_project.py 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 From 0d72a4b7c0314e1f8303fffa9e2cf07b1f3d1916 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 16/69] intern url commented out in urls.py --- input/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/urls.py b/input/urls.py index 4854f11..ba4c2b4 100644 --- a/input/urls.py +++ b/input/urls.py @@ -4,7 +4,7 @@ from .views import ExternView, done, authorize, deny, InternView, export urlpatterns = [ path('', ExternView.as_view(), name='extern'), - path('intern', InternView.as_view(), name='intern'), +# path('intern', InternView.as_view(), name='intern'), path('saved', done, name='done'), path('export', export, name='export'), path('authorize//', authorize, name='authorize'), From a8d8f6fdd606cb7fee6ea7f273e3bd260954ad74 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 17/69] made mail.adult a required field --- input/forms.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/input/forms.py b/input/forms.py index de6fc83..3a7bae9 100644 --- a/input/forms.py +++ b/input/forms.py @@ -97,10 +97,17 @@ class LiteratureForm(CheckForm): js = ('dropdown/js/base.js',) class EmailForm(CheckForm): + + # this is the code, to change required to false if needed + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['adult'].required = True + + # TODO: add some javascript to show/hide other-field class Meta: model = Email - fields = ['domain', 'address', 'other'] + fields = ['domain', 'address', 'other', 'adult'] class Media: js = ('dropdown/js/base.js',) From f58ac52109963c1f9f825d0a885ca8a05233ca44 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 18/69] added date hierarchy and overview in admin panel to all other forms in admin.py, also created variable intern_notes --- input/admin.py | 81 ++++++++++++++++--- ...ficate_intern_notes_travel_intern_notes.py | 23 ++++++ input/models.py | 2 +- 3 files changed, 94 insertions(+), 12 deletions(-) create mode 100644 input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py diff --git a/input/admin.py b/input/admin.py index f617d8e..eff2e5e 100644 --- a/input/admin.py +++ b/input/admin.py @@ -42,24 +42,83 @@ class BusinessCardAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project') list_display_links = ('realname', 'service_id') # action = ['export_as_csv'] - + date_hierarchy = 'granted_date' class Media: js = ('dropdown/js/base.js',) @admin.register(Literature) class LiteratureAdmin(admin.ModelAdmin): - + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + list_display = ('realname', 'service_id', 'granted', 'granted_date') + list_display_links = ('realname', 'service_id') + date_hierarchy = 'granted_date' class Media: js = ('dropdown/js/base.js',) +@admin.register(Account) +class AccountAdmin(admin.ModelAdmin): + save_as = True -admin.site.register([ - Account, - HonoraryCertificate, - Library, - IFG, - Travel, - Email, - List, - ]) + +@admin.register(HonoraryCertificate) +class HonoraryCertificateAdmin(admin.ModelAdmin): + save_as = True + search_fields = ('realname', 'granted', 'granted_date', 'project') + list_display = ('realname', 'granted', 'granted_date', 'project') + list_display_links = ('realname', 'project') + date_hierarchy = 'granted_date' + +@admin.register(Library) +class LibraryAdmin(admin.ModelAdmin): + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + list_display = ('realname', 'service_id', 'granted', 'granted_date') + list_display_links = ('realname', 'service_id') + date_hierarchy = 'granted_date' + +@admin.register(IFG) +class IFGAdmin(admin.ModelAdmin): + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + list_display = ('realname', 'service_id', 'granted', 'granted_date') + list_display_links = ('realname', 'service_id') + date_hierarchy = 'granted_date' + +@admin.register(Travel) +class TravelAdmin(admin.ModelAdmin): + save_as = True + search_fields = ('realname', 'granted', 'granted_date', 'project') + list_display = ('realname', 'granted', 'granted_date', 'project') + list_display_links = ('realname', 'project') + date_hierarchy = 'granted_date' + +@admin.register(Email) +class EmailAdmin(admin.ModelAdmin): + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + list_display = ('realname', 'service_id', 'granted', 'granted_date') + list_display_links = ('realname', 'service_id') + date_hierarchy = 'granted_date' + + +@admin.register(List) +class ListAdmin(admin.ModelAdmin): + save_as = True + search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + list_display = ('realname', 'service_id', 'granted', 'granted_date') + list_display_links = ('realname', 'service_id') + date_hierarchy = 'granted_date' + +# commented out because of the individual registering to control displays in admin panel + +#admin.site.register([ +# Account, +# HonoraryCertificate, +# Library, +# IFG, +# Travel, +# Email, +# List, +# ]) diff --git a/input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py b/input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py new file mode 100644 index 0000000..ed4f2df --- /dev/null +++ b/input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.2 on 2022-11-17 17:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0070_alter_travel_project'), + ] + + operations = [ + migrations.AddField( + model_name='honorarycertificate', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='travel', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + ] diff --git a/input/models.py b/input/models.py index a92ff61..703c43d 100644 --- a/input/models.py +++ b/input/models.py @@ -119,7 +119,7 @@ class Project(Volunteer): class Intern(Volunteer): '''abstrat 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) class Meta: abstract = True From 980ee45066d82cce3947a2bbded11c0d1948d89c Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 19/69] added intern_notes variable to all dbs, not excluded in extern view for all --- input/forms.py | 10 ++++- ...ntern_notes_email_intern_notes_and_more.py | 43 +++++++++++++++++++ input/migrations/0073_account_intern_notes.py | 18 ++++++++ input/migrations/0074_project_intern_notes.py | 18 ++++++++ input/models.py | 13 ++++-- 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py create mode 100644 input/migrations/0073_account_intern_notes.py create mode 100644 input/migrations/0074_project_intern_notes.py diff --git a/input/forms.py b/input/forms.py index 3a7bae9..c3e8127 100644 --- a/input/forms.py +++ b/input/forms.py @@ -58,7 +58,7 @@ 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', 'project', 'request_url', 'payed_for_hotel_by', 'payed_for_travel_by' ) + 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' ) widgets = {'checkin': AdminDateWidget(), 'checkout': AdminDateWidget(),} @@ -67,16 +67,19 @@ class LibraryForm(FdbForm): class Meta: model = Library fields = ['cost', 'library', 'duration', 'notes'] + exclude = ['intern_notes'] class HonoraryCertificateForm(FdbForm): class Meta: model = HonoraryCertificate fields = ['request_url', 'project'] + exclude = ['intern_notes'] class IFGForm(FdbForm): class Meta: model = IFG fields = ['cost', 'url', 'notes'] + exclude = ['intern_notes'] class CheckForm(FdbForm): @@ -93,6 +96,7 @@ class LiteratureForm(CheckForm): class Meta: model = Literature fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_give_data'] + exclude = ['intern_notes'] class Media: js = ('dropdown/js/base.js',) @@ -108,6 +112,7 @@ class EmailForm(CheckForm): class Meta: model = Email fields = ['domain', 'address', 'other', 'adult'] + exclude = ['intern_notes'] class Media: js = ('dropdown/js/base.js',) @@ -121,7 +126,7 @@ class BusinessCardForm(CheckForm): class Meta: model = BusinessCard - + exclude = ['intern_notes'] fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to'] class Media: js = ('dropdown/js/base.js',) @@ -131,4 +136,5 @@ class ListForm(CheckForm): class Meta: model = List fields = ['domain', 'address'] + exclude = ['intern_notes'] diff --git a/input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py b/input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py new file mode 100644 index 0000000..d837869 --- /dev/null +++ b/input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py @@ -0,0 +1,43 @@ +# Generated by Django 4.1.2 on 2022-11-17 18:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0071_honorarycertificate_intern_notes_travel_intern_notes'), + ] + + operations = [ + migrations.AddField( + model_name='businesscard', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='email', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='ifg', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='library', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='list', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + migrations.AddField( + model_name='literature', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + ] diff --git a/input/migrations/0073_account_intern_notes.py b/input/migrations/0073_account_intern_notes.py new file mode 100644 index 0000000..1048bc7 --- /dev/null +++ b/input/migrations/0073_account_intern_notes.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2022-11-17 18:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0072_businesscard_intern_notes_email_intern_notes_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='account', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + ] diff --git a/input/migrations/0074_project_intern_notes.py b/input/migrations/0074_project_intern_notes.py new file mode 100644 index 0000000..ef6dce2 --- /dev/null +++ b/input/migrations/0074_project_intern_notes.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2022-11-17 18:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0073_account_intern_notes'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000), + ), + ] diff --git a/input/models.py b/input/models.py index 703c43d..e42cd43 100644 --- a/input/models.py +++ b/input/models.py @@ -55,7 +55,7 @@ class Account(models.Model): 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) def __str__(self): return f"{self.code} {self.description}" @@ -79,7 +79,8 @@ class Project(Volunteer): 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) + # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) end_mail_send = models.BooleanField(null=True) @@ -190,7 +191,7 @@ class Library(Grant): ) library = models.CharField(max_length=200) duration = models.CharField(max_length=100, verbose_name="Dauer") - + intern_notes = models.TextField(max_length=1000, blank=True) def __str__(self): return self.library @@ -209,11 +210,12 @@ class Literature(Grant): help_text="Bitte gib an, wo du das Werk kaufen möchtest.") selfbuy = models.CharField( max_length=10, verbose_name='Selbstkauf?', choices=SELFBUY_CHOICES.items(), default='TRUE') selfbuy_give_data = models.BooleanField(default='NONE', verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.')) + intern_notes = models.TextField(max_length=1000, blank=True) 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.") - + intern_notes = models.TextField(max_length=1000, blank=True) def __str__(self): return "IFG-Anfrage von " + self.realname @@ -249,11 +251,13 @@ class Email(Domain): 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') + intern_notes = models.TextField(max_length=1000, blank=True) class List(Domain): address = models.CharField(max_length=50, default='NO_ADDRESS', verbose_name="Adressbestandteil für Projektmailingliste", help_text=format_html("Bitte gib hier den gewünschten Adressbestandteil an,
der sich vor der Domain befinden soll.")) + intern_notes = models.TextField(max_length=1000, blank=True) PROJECT_CHOICE = {'PEDIA': 'Wikipedia', 'SOURCE': 'Wikisource', @@ -291,3 +295,4 @@ class BusinessCard(Extern): sent_to = models.TextField(max_length=1000, verbose_name='Versandadresse', default='', help_text="Bitte gib den Namen und die vollständige Adresse ein, an welche die Visitenkarten geschickt werden sollen.") send_data_to_print = models.BooleanField(default=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.')) + intern_notes = models.TextField(max_length=1000, blank=True) From 5eb2ee2b9d05a0cd30730e0d0fef2ecbd8cf1c0a Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 20/69] created html versions of all mail templates --- input/templates/input/if_end_of_project.html | 16 +++++++ .../input/if_end_of_project_approved.html | 41 ++++++++++++++++++ .../input/if_end_of_project_orginformed.html | 19 +++++++++ input/templates/input/if_mail.html | 35 ++++++++++++++++ input/templates/input/ifg_volunteer_mail.html | 34 +++++++++++++++ input/templates/input/survey_mail.html | 42 +++++++++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 input/templates/input/if_end_of_project.html create mode 100644 input/templates/input/if_end_of_project_approved.html create mode 100644 input/templates/input/if_end_of_project_orginformed.html create mode 100644 input/templates/input/if_mail.html create mode 100644 input/templates/input/ifg_volunteer_mail.html create mode 100644 input/templates/input/survey_mail.html diff --git a/input/templates/input/if_end_of_project.html b/input/templates/input/if_end_of_project.html new file mode 100644 index 0000000..fefd007 --- /dev/null +++ b/input/templates/input/if_end_of_project.html @@ -0,0 +1,16 @@ + + + +Hallo Team Communitys und Engagement! +

+Das Project {{project.name}} hat am {{project.end}} sein vorraussichtliches +Ende erreicht.

+ +Hier könnt ihr es in der Datenbank editieren: +

+{{URLPREFIX}}/admin/input/project/{{project.pk}}/change +

+mit freundlichen Grüßen, Eure Lieblingsdatenbank + + + diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/input/if_end_of_project_approved.html new file mode 100644 index 0000000..5ab0b79 --- /dev/null +++ b/input/templates/input/if_end_of_project_approved.html @@ -0,0 +1,41 @@ + + +Hallo, +

+dein Projekt/die Veranstaltung {{project.name}} ist nun beendet und wir hoffen, dass alles gut geklappt hat! +

+Bitte beachte nun, dass im Vorfeld besprochene Kostenerstattungen innerhalb eines Monats nach Entstehen der Kosten über unser Online-Formular Antrag auf Kostenerstattung eingereicht werden müssen. Spätere Einsendungen können ggf. nicht mehr erstattet werden. +

+Da wir verpflichtet sind, über unsere geförderten Maßnahmen zu berichten, möchten wir dich gerne bitten uns kurz folgende Infos zu deinem Projekt zukommen zu lassen:
+* Wie viele Personen haben an dem Projekt teilgenommen?
+* Wo können die Ergebnisse des Projektes eingesehen werden? (Projektseite, Commons-Link, Bericht o. ä.) +

+Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen. +

+Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du diesen nun archivieren, indem du den Projektstatus oben im Quellcode entsprechend anpasst und die Liste der geförderten Aktivitäten entsprechend aktualisierst. +

+Falls nicht bereits geschehen, wirst du demnächst eine weitere E-Mail erhalten, mit der du die Möglichkeit hast uns Feedback zu der Unterstützung zu geben. Danke, dass du dir Zeit dafür nimmst! +

+Insbesondere möchten wir uns an dieser Stelle ganz herzlich bei dir für die Zusammenarbeit und dein Engagement für Freies Wissen bedanken! +

+Viele Grüße
+Dein Team Communitys und Engagement +

+-----
+Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden. +

+Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
+Tel. (030) 219 158 26-0
+https://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!
+https://spenden.wikimedia.de
+

+Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207. +

+Datenschutzerklärung:
+Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +

+ + + diff --git a/input/templates/input/if_end_of_project_orginformed.html b/input/templates/input/if_end_of_project_orginformed.html new file mode 100644 index 0000000..2d83129 --- /dev/null +++ b/input/templates/input/if_end_of_project_orginformed.html @@ -0,0 +1,19 @@ + + + +Hallo Team Communitys und Engagement! +

+Das Project {{project.name}} hat am {{project.end}} sein vorraussichtliches +Ende erreicht. +

+Hier könnt ihr es in der Datenbank editieren: +

+{{URLPREFIX}}/admin/input/project/{{project.pk}}/change +

+ +Projektorganisator*in wurde über den Projektabschluss informiert. +


+mit freundlichen Grüßen, Eure Lieblingsdatenbank + + + diff --git a/input/templates/input/if_mail.html b/input/templates/input/if_mail.html new file mode 100644 index 0000000..b7ec91f --- /dev/null +++ b/input/templates/input/if_mail.html @@ -0,0 +1,35 @@ + + +Hallo Team Communitys und Engagement, +

+es gab einen neuen Antrag von {{data.realname}}. +

+Der Nutzer mit dem Username {{data.username}} ({{data.email}}) fragt ein_e {{data.typestring|striptags}} an.
+{% if data.choice in data.grant %}
+Vorraussichtliche Kosten: {{data.cost}}
+Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
+Domain: {{data.domain}}
+Adressenbestandteil: {{data.address}}
{% endif %} {% if data.choice == 'BIB' %} +Bibliothek: {{data.library}}
+Dauer: {{data.duration}}
{% elif data.choice == 'ELIT' %} +Datenbank: {{data.library}}
+Dauer: {{data.duration}}
{% elif data.choice == 'SOFT' %} +Software: {{data.library}}
+Dauer: {{data.duration}}
{% elif data.choice == 'IFG'%} +Anfrage-URL: {{data.url}}
{% elif data.choice == 'LIT'%} +Info zum Werk: {{data.info}}
+Bezugsquelle: {{data.source}}
{% elif data.choice == 'MAIL'%} +Adressenbestandteil frei gewählt: {{data.other}}
{% elif data.choice == 'VIS'%} +Wikimedia-Projekt: {{data.project}}
+Persönliche Daten: {{data.data}}
+Variante: {{data.variant}}
+Sendungsadrese: {{data.send_to}}
{% endif %} +

+Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %} +

+Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %} +

+Stets zu Diensten, Deine Förderdatenbank + + + diff --git a/input/templates/input/ifg_volunteer_mail.html b/input/templates/input/ifg_volunteer_mail.html new file mode 100644 index 0000000..e8da031 --- /dev/null +++ b/input/templates/input/ifg_volunteer_mail.html @@ -0,0 +1,34 @@ + + +Hallo {{data.realname}}, +

+wir haben Deine Anfrage ({{data.typestring|striptags}}) erhalten.
+{% if data.choice in data.grant %}
+Vorraussichtliche Kosten: {{data.cost}}
+Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
+Domain: {{data.domain}}
+Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
+Bibliothek: {{data.library}}
+Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
+Datenbank: {{data.library}}
+Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
+Software: {{data.library}}
+Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
+Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
+Info zum Werk: {{data.info}}
+Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
+Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
+Wikimedia-Projekt: {{data.project}}
+Persönliche Daten: {{data.data}}
+Variante: {{data.variant}}
+Sendungsadrese: {{data.send_to}} {% endif %}
+

+Das Team Comunitys und Engagement wird sich um die Bearbeitung deiner Anfrage kümmern
+und sich in den nächsten Tagen bei dir melden. Solltest du Rückfragen haben,
+wende dich gern an community@wikimedia.de.
+

+Viele Grüße, dein freundliches aber komplett unmenschliches automatisches +Formularbeantwortungssystem. + + + diff --git a/input/templates/input/survey_mail.html b/input/templates/input/survey_mail.html new file mode 100644 index 0000000..f62c146 --- /dev/null +++ b/input/templates/input/survey_mail.html @@ -0,0 +1,42 @@ + + +Hallo, +

+Vor einiger Zeit durfte Wikimedia Deutschland Deine Aktivität für Freies Wissen +unterstützen.
+{% if type == 'PRO' %} +Deine Aktivitäten werden von uns unter dem Projekttitel "{{name}}" geführt.

+{% elif type == 'HON' %} +Du hast von uns eine Bescheinigung ({{name}}) erhalten.

+{% elif type == 'BIB' %} +Du hast von uns ein Bibliotheksstipendium für {{name}} erhalten.

+{% elif type == 'ELIT' %} +Du hast von uns ein eLiteraturstipendium für {{name}} erhalten.

+{% elif type == 'IFG' %} +Wir haben Dich bei einer IFG-Anfrage unterstützt: {{name}}

+{% elif type == 'LIT' %} +Du hast von uns ein Literaturstipendium für {{name}} erhalten.

+{% elif type == 'TRAV' %} +Wir haben Dich mit Reisekostenübernahme für {{name}} unterstützt.

+{% elif type == 'SOFT' %} +Du hast von uns ein Softwarestipendium für {{name}} erhalten.

+{% elif type == 'MAIL' %} +Du hast von uns eine E-Mail-Adresse erhalten.

+{% elif type == 'LIST' %} +Wir haben Dir eine Mailingliste bereit gestellt.

+{% elif type == 'VIS' %} +Du hast von uns Visitenkarten erhalten.

+{% endif %} + +Zu dieser Unterstützung kannst du uns ein Feedback über einen kurzen Fragebogen +geben. Deine Teilnahme ist freiwillig und hilft uns dabei, die verschiedenen +Förderprogramme im Sinne der Communitys weiter zu verbessern. Wir freuen uns, +wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren +Informationen findest du unter dem folgenden Link:
+ +{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1

+ +Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an community@wikimedia.de + + + From 1ed10b2b8c189fd6e3ab3734c40fc42889bbf83d Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 21/69] sendmails is sending html regarding the informing of the organisator when not happened --- input/management/commands/sendmails.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 243c396..fe4b471 100644 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -115,8 +115,9 @@ class Command(BaseCommand): 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') - + + 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: @@ -137,11 +138,19 @@ class Command(BaseCommand): # IF_EMAIL, # [project.email], # fail_silently=False) - send_mail('Projektorganisator*in wurde informiert', - informMail_template.render(context), - IF_EMAIL, - [IF_EMAIL], - fail_silently=False) + + inform_subject, inform_from_email, inform_to = Projektorganisator*in wurde informiert', IF_EMAIL, 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_mail('Projektorganisator*in wurde informiert', + # informMail_template.render(context), + # IF_EMAIL, + # [IF_EMAIL], + # fail_silently=False) project.end_mail_send = True project.save() From 34857ccf03048776243b991e0e9398421c6f81ca Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 22/69] changed sending of last mails in sendmails.py and in views.py --- input/management/commands/sendmails.py | 86 ++++++++++++++++++-------- input/views.py | 54 +++++++++++----- 2 files changed, 97 insertions(+), 43 deletions(-) diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index fe4b471..e08c877 100644 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -35,14 +35,22 @@ class Command(BaseCommand): 'name': name, 'pid': pid, 'SURVEYPREFIX': SURVEYPREFIX, } - mail_template = get_template('input/survey_mail.txt') + txt_mail_template = get_template('input/survey_mail.txt') + html_mail_template = get_template('input/survey_mail.html') try: - survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland', - mail_template.render(context), - IF_EMAIL, - [email], - bcc=[SURVEY_EMAIL]) - survey_mail.send(fail_silently=False) + subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', 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=[SURVEY_EMAIL]) + msg.attach_alternative(html_content, "text/html") + msg.send() + + #survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland', + # mail_template.render(context), + # IF_EMAIL, + # [email], + # bcc=[SURVEY_EMAIL]) + #survey_mail.send(fail_silently=False) except BadHeaderError: return HttpResponse('Invalid header found.') @@ -52,20 +60,28 @@ class Command(BaseCommand): ''' end of project reached ''' # get all projects which ended - print(Project.objects.filter(end__lt = date.today())) old = Project.objects.filter(end__lt = date.today())\ .exclude(end_mail_send = True) - mail_template = get_template('input/if_end_of_project.txt') + txt_mail_template = get_template('input/if_end_of_project.txt') + html_mail_template = get_template('input/if_end_of_project.html') + for project in old: context = {'project': project} context['URLPREFIX'] = settings.URLPREFIX try: - send_mail('Projektende erreicht', - mail_template.render(context), - IF_EMAIL, - ['luca@cannabinieri.de'], - fail_silently=False) + subject, from_email, to = 'Projektende erreicht', IF_EMAIL, 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_mail('Projektende erreicht', + # mail_template.render(context), + # IF_EMAIL, + # [IF_EMAIL], + # fail_silently=False) project.end_mail_send = True project.save() except BadHeaderError: @@ -80,24 +96,42 @@ class Command(BaseCommand): approved_end = Project.objects.filter(status = 'END')\ .exclude(end_mail_send = False) print(approved_end) - mail_template = get_template('input/if_end_of_project_approved.txt') - informMail_template = get_template('input/if_end_of_project_orginformed.txt') + 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['URLPREFIX'] = settings.URLPREFIX try: - 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, - [IF_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() + + inform_subject, inform_from_email, inform_to = Projektorganisator*in wurde informiert', IF_EMAIL, 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_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, + # [IF_EMAIL], + # fail_silently=False) project.end_mail_send = True project.save() diff --git a/input/views.py b/input/views.py index e86ebbf..dd9fb4f 100644 --- a/input/views.py +++ b/input/views.py @@ -5,7 +5,7 @@ from django.shortcuts import render from django.forms import modelformset_factory from django.http import HttpResponse from formtools.wizard.views import CookieWizardView -from django.core.mail import send_mail, BadHeaderError +from django.core.mail import send_mail, BadHeaderError, EmailMultiAlternatives from django.conf import settings from django.template.loader import get_template from django.template import Context @@ -227,22 +227,42 @@ class ExternView(CookieWizardView): context = { 'data': data } try: # - mail with entered data to the Volunteer - mail_template = get_template('input/ifg_volunteer_mail.txt') - send_mail( - 'Formular ausgefüllt', - mail_template.render(context), - IF_EMAIL, - [data['email']], - fail_silently=False) - # - mail to IF with link to accept/decline - mail_template = get_template('input/if_mail.txt') - send_mail( - 'Formular ausgefüllt', - mail_template.render(context), - IF_EMAIL, - [IF_EMAIL], - fail_silently=False) - # raise SMTPException("testing pupose only") + + txt_mail_template = get_template('input/ifg_volunteer_mail.txt') + html_mail_template = get_template('input/ifg_volunteer_mail.html') + + subject, from_email, to = 'Formular ausgefüllt', IF_EMAIL, data['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( + # 'Formular ausgefüllt', + # mail_template.render(context), + # IF_EMAIL, + # [data['email']], + # fail_silently=False) + ## - mail to IF with link to accept/decline + + txt_mail_template = get_template('input/if_mail.txt') + html_mail_template = get_template('input/if_mail.html') + + subject, from_email, to = 'Formular ausgefüllt', IF_EMAIL, 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_mail( + # 'Formular ausgefüllt', + # mail_template.render(context), + # IF_EMAIL, + # [IF_EMAIL], + # fail_silently=False) + ## raise SMTPException("testing pupose only") except BadHeaderError: modell.delete() From 2254b77a0d21f373f314eee003ef2a66860dceb1 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 23/69] changed fields in Travel to required, changed saving of value of selfbuy_give_data when person wants to selfbuy to false --- input/forms.py | 12 ++++++++++++ input/static/dropdown/js/base.js | 8 ++++++-- input/views.py | 6 +++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/input/forms.py b/input/forms.py index c3e8127..da386f8 100644 --- a/input/forms.py +++ b/input/forms.py @@ -56,11 +56,23 @@ class InternForm(FdbForm): class TravelForm(FdbForm): # TODO: add some javascript to show/hide other-field + + # this is the code, to change required to false if needed + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['project_name'].required = True + self.fields['transport'].required = True + self.fields['travelcost'].required = True + self.fields['checkin'].required = True + self.fields['checkout'].required = True + self.fields['hotel'].required = True + 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' ) widgets = {'checkin': AdminDateWidget(), 'checkout': AdminDateWidget(),} + fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes'] class LibraryForm(FdbForm): diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js index 0d8d5c4..df0ae5f 100644 --- a/input/static/dropdown/js/base.js +++ b/input/static/dropdown/js/base.js @@ -1,10 +1,16 @@ window.addEventListener("load", function() { (function($) { $(function() { + + + // selfbuy section + var selectField_selfbuy = $('#id_selfbuy'), verified_selfbuy_div = $('#id_selfbuy_give_data').parent().parent(), verified_selfbuy = $('#id_selfbuy_give_data'); + + // make checked to get through the required function toggleVerified_selfbuy(value) { if (value === "FALSE") { verified_selfbuy_div.show(); @@ -23,8 +29,6 @@ window.addEventListener("load", function() { toggleVerified_selfbuy($(this).val()); }); - - var selectField = $('#id_variant'), verified = $('#id_url_of_pic').parent().parent(); diff --git a/input/views.py b/input/views.py index dd9fb4f..3ca0f33 100644 --- a/input/views.py +++ b/input/views.py @@ -202,8 +202,11 @@ class ExternView(CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} + + if data['selfbuy'] == 'TRUE': + data['selfbuy_give_data'] = 'False' print(data) - + # write data to database modell = form.save(commit=False) # we have to copy the data from the first form here @@ -214,6 +217,7 @@ class ExternView(CookieWizardView): # write type of form in some cases if data['choice'] in ('BIB', 'ELIT', 'SOFT'): modell.type = data['choice'] + form.save() # add some data to context for mail templates From e9de3fcb993b88c3025ad08c53416b652b966090 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 24/69] changing saved value in database selfbuy_give_data to false when selfbuy true also in internview done() --- input/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/input/views.py b/input/views.py index 3ca0f33..2b28773 100644 --- a/input/views.py +++ b/input/views.py @@ -110,6 +110,8 @@ class InternView(LoginRequiredMixin, CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} + if data['selfbuy'] == 'TRUE': + data['selfbuy_give_data'] = 'False' print(data) # write data to database From 10503087127368251ea3086d8e530be4c0ed3b78 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 25/69] conditional hiding of address textfield in literature form added --- input/forms.py | 2 +- .../migrations/0075_literature_selfbuy_data.py | 18 ++++++++++++++++++ input/models.py | 9 ++++++++- input/static/dropdown/js/base.js | 11 +++++++++-- input/views.py | 9 ++++++++- 5 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 input/migrations/0075_literature_selfbuy_data.py diff --git a/input/forms.py b/input/forms.py index da386f8..e2e6d07 100644 --- a/input/forms.py +++ b/input/forms.py @@ -107,7 +107,7 @@ class LiteratureForm(CheckForm): self.fields['selfbuy_give_data'].required = True class Meta: model = Literature - fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_give_data'] + fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_data', 'selfbuy_give_data'] exclude = ['intern_notes'] class Media: js = ('dropdown/js/base.js',) diff --git a/input/migrations/0075_literature_selfbuy_data.py b/input/migrations/0075_literature_selfbuy_data.py new file mode 100644 index 0000000..2565a73 --- /dev/null +++ b/input/migrations/0075_literature_selfbuy_data.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.2 on 2022-11-21 13:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0074_project_intern_notes'), + ] + + operations = [ + migrations.AddField( + model_name='literature', + name='selfbuy_data', + field=models.TextField(default='', help_text='Bitte gib hier alle persönlichen Daten an, und zwar genau so,
wie sie (auch in der entsprechenden Reihenfolge) auf den Visitenkarten stehen sollen
(z.B. Vorname Nachname, Benutzer:/Benutzerin:, Benutzer-/-innenname, Anschrift,
Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.
Hinweis: Telefonnummern bilden wir üblicherweise im internationalen Format gemäß
DIN 5008 ab. Als anzugebende E-Mail-Adresse empfehlen wir dir eine Wikimedia-Projekt-
Adresse, die du ebenfalls beantragen kannst, sofern du nicht bereits eine besitzt.', max_length=1000, verbose_name='Persönliche Daten für die Visitenkarten'), + ), + ] diff --git a/input/models.py b/input/models.py index e42cd43..b1b4f83 100644 --- a/input/models.py +++ b/input/models.py @@ -209,7 +209,14 @@ class Literature(Grant): source = models.CharField(max_length=200, verbose_name='Bezugsquelle', help_text="Bitte gib an, wo du das Werk kaufen möchtest.") selfbuy = models.CharField( max_length=10, verbose_name='Selbstkauf?', choices=SELFBUY_CHOICES.items(), default='TRUE') - selfbuy_give_data = models.BooleanField(default='NONE', verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.')) + selfbuy_give_data = models.BooleanField(verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.')) + selfbuy_data = models.TextField(max_length=1000, verbose_name='Persönliche Daten sowie Adresse', default='', + help_text=format_html("Bitte gib hier alle persönlichen Daten an, die wir benötigen, um das Werk
\ + für dich zu kaufen und es dir anschließend zu schicken (z.B. Vorname Nachname, Anschrift,
\ + Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.
\ + Hinweis: Telefonnummern bilden wir üblicherweise im internationalen Format gemäß
\ + DIN 5008 ab. Als anzugebende E-Mail-Adresse empfehlen wir dir eine Wikimedia-Projekt-
\ + Adresse, die du ebenfalls beantragen kannst, sofern du nicht bereits eine besitzt.")) intern_notes = models.TextField(max_length=1000, blank=True) class IFG(Grant): diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js index df0ae5f..b93cf52 100644 --- a/input/static/dropdown/js/base.js +++ b/input/static/dropdown/js/base.js @@ -7,16 +7,23 @@ window.addEventListener("load", function() { var selectField_selfbuy = $('#id_selfbuy'), verified_selfbuy_div = $('#id_selfbuy_give_data').parent().parent(), - verified_selfbuy = $('#id_selfbuy_give_data'); - + verified_selfbuy = $('#id_selfbuy_give_data'), + data_selfbuy_div = $('#id_selfbuy_data').parent().parent(), + data_selfbuy = $('#id_selfbuy_data'); + + // make checked to get through the required function toggleVerified_selfbuy(value) { if (value === "FALSE") { verified_selfbuy_div.show(); + data_selfbuy_div.show(); + data_selfbuy.val(""); verified_selfbuy.prop("checked", false); } else { verified_selfbuy_div.hide(); + data_selfbuy_div.hide(); + data_selfbuy.val("NONE"); verified_selfbuy.prop("checked", true); } } diff --git a/input/views.py b/input/views.py index 2b28773..4a257dd 100644 --- a/input/views.py +++ b/input/views.py @@ -124,6 +124,10 @@ class InternView(LoginRequiredMixin, CookieWizardView): form.email = data['email'] form.granted = True form.granted_date = date.today() + + if data['choice'] == 'LIT': + form.selfbuy_give_data = data['selfbuy_give_data'] + form.save() return done(self.request) @@ -204,7 +208,6 @@ class ExternView(CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} - if data['selfbuy'] == 'TRUE': data['selfbuy_give_data'] = 'False' print(data) @@ -213,6 +216,10 @@ class ExternView(CookieWizardView): modell = form.save(commit=False) # we have to copy the data from the first form here # this is a bit ugly code. can we copy this without explicit writing? + + if data['choice'] == 'LIT': + modell.selfbuy_give_data = data['selfbuy_give_data'] + modell.realname = data['realname'] modell.username = data['username'] modell.email = data['email'] From d9db5238eadbcc259626a1868af0b202927d0114 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 26/69] added mail_state to all objects, added filters regarding sendmail.py --- .gitignore | 3 +- LICENSE | 0 README.md | 0 TODO | 0 foerderbarometer/__init__.py | 0 foerderbarometer/asgi.py | 0 foerderbarometer/settings.py_old | 0 foerderbarometer/settings_development.py | 0 .../settings_mariadb_development.py | 0 foerderbarometer/settings_production.py | 4 +- foerderbarometer/urls.py | 0 foerderbarometer/wsgi.py | 0 input/__init__.py | 0 input/admin.py | 0 input/apps.py | 0 input/fixtures/accounts.json | 0 input/forms.py | 6 +- input/management/commands/sendmails.py | 75 +++++++---- input/migrations/0001_initial.py | 0 input/migrations/0002_auto_20200922_1340.py | 0 input/migrations/0003_volonteer.py | 0 input/migrations/0004_project_contact.py | 0 input/migrations/0005_auto_20200930_1015.py | 0 input/migrations/0006_honorarycertificate.py | 0 input/migrations/0007_library.py | 0 input/migrations/0008_ifg.py | 0 input/migrations/0009_project_pid.py | 0 input/migrations/0010_auto_20201007_0732.py | 0 input/migrations/0011_auto_20201007_0743.py | 0 input/migrations/0012_auto_20201007_0754.py | 0 input/migrations/0013_library_type.py | 0 input/migrations/0014_auto_20201020_0714.py | 0 input/migrations/0015_auto_20201021_0721.py | 0 input/migrations/0016_project_account.py | 0 input/migrations/0017_auto_20201021_1145.py | 0 input/migrations/0018_auto_20201021_1147.py | 0 input/migrations/0019_auto_20201021_1148.py | 0 .../0020_project_project_end_mail.py | 0 input/migrations/0021_auto_20201022_0934.py | 0 input/migrations/0022_auto_20201022_1233.py | 0 input/migrations/0023_auto_20201022_1400.py | 0 input/migrations/0024_travel.py | 0 input/migrations/0025_auto_20201026_1048.py | 0 input/migrations/0026_auto_20201026_1214.py | 0 .../0027_businesscard_email_list.py | 0 input/migrations/0028_auto_20201027_1131.py | 0 input/migrations/0029_auto_20201027_1247.py | 0 input/migrations/0030_auto_20201027_1337.py | 0 input/migrations/0031_auto_20201028_1402.py | 0 input/migrations/0032_auto_20201029_1213.py | 0 input/migrations/0033_auto_20201029_1338.py | 0 input/migrations/0034_auto_20201102_0913.py | 0 input/migrations/0035_auto_20201102_0944.py | 0 input/migrations/0036_auto_20201102_1049.py | 0 input/migrations/0037_auto_20201102_1054.py | 0 input/migrations/0038_auto_20201102_1055.py | 0 input/migrations/0039_auto_20201102_1212.py | 0 input/migrations/0040_auto_20201102_1302.py | 0 input/migrations/0041_auto_20201102_1318.py | 0 input/migrations/0042_auto_20201102_1319.py | 0 input/migrations/0043_auto_20201102_1320.py | 0 input/migrations/0044_auto_20201103_1545.py | 0 input/migrations/0044_auto_20201116_1531.py | 0 input/migrations/0045_auto_20201116_1557.py | 0 input/migrations/0046_auto_20201117_1542.py | 0 input/migrations/0047_auto_20201117_1546.py | 0 input/migrations/0048_auto_20201118_1503.py | 0 input/migrations/0049_auto_20201118_1509.py | 0 input/migrations/0050_auto_20201118_1512.py | 0 input/migrations/0051_auto_20201118_1521.py | 0 input/migrations/0052_auto_20201118_1524.py | 0 input/migrations/0053_auto_20201118_1531.py | 0 input/migrations/0054_auto_20201118_1702.py | 0 input/migrations/0055_merge_20201118_1734.py | 0 input/migrations/0056_auto_20201217_1215.py | 0 input/migrations/0057_auto_20210104_0937.py | 0 input/migrations/0058_auto_20210412_0946.py | 0 input/migrations/0059_auto_20210412_1142.py | 0 input/migrations/0060_concreteextern.py | 0 input/migrations/0061_concretevolunteer.py | 0 input/migrations/0062_auto_20211103_1155.py | 0 ...ard_url_of_pic_alter_ifg_notes_and_more.py | 0 ...ta_to_print_literature_selfbuy_and_more.py | 0 .../0065_alter_literature_selfbuy_and_more.py | 0 input/migrations/0066_email_adult.py | 0 ..._travel_project_name_alter_library_type.py | 0 input/migrations/0068_travel_hotel.py | 0 .../migrations/0069_alter_travel_transport.py | 0 input/migrations/0070_alter_travel_project.py | 0 ...ficate_intern_notes_travel_intern_notes.py | 0 ...ntern_notes_email_intern_notes_and_more.py | 0 input/migrations/0073_account_intern_notes.py | 0 input/migrations/0074_project_intern_notes.py | 0 .../0075_literature_selfbuy_data.py | 0 input/migrations/0076_auto_20221129_1601.py | 78 +++++++++++ input/migrations/0077_auto_20221129_1706.py | 123 ++++++++++++++++++ input/migrations/0078_auto_20221129_1712.py | 68 ++++++++++ input/migrations/0079_auto_20221129_2310.py | 68 ++++++++++ input/migrations/0080_auto_20221129_2323.py | 68 ++++++++++ input/migrations/__init__.py | 0 input/models.py | 6 + input/settings.py | 0 input/static/dropdown/js/base.js | 0 input/static/input/logo.png | Bin input/static/input/nutzungsbedingungen.html | 0 input/templates/input/extern.html | 0 input/templates/input/if_end_of_project.html | 0 input/templates/input/if_end_of_project.txt | 0 .../input/if_end_of_project_approved.html | 0 .../input/if_end_of_project_approved.txt | 0 .../input/if_end_of_project_orginformed.html | 0 .../input/if_end_of_project_orginformed.txt | 0 input/templates/input/if_mail.html | 0 input/templates/input/if_mail.txt | 0 .../input/if_not_of_project_approved.html | 0 .../input/if_not_of_project_approved.txt | 0 input/templates/input/ifg_volunteer_mail.html | 0 input/templates/input/ifg_volunteer_mail.txt | 0 input/templates/input/survey_mail.html | 0 input/templates/input/survey_mail.txt | 0 input/templates/registration/login.html | 0 input/tests.py | 0 input/urls.py | 0 input/views.py | 8 +- requirements.txt | 7 + 125 files changed, 482 insertions(+), 32 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 TODO mode change 100644 => 100755 foerderbarometer/__init__.py mode change 100644 => 100755 foerderbarometer/asgi.py mode change 100644 => 100755 foerderbarometer/settings.py_old mode change 100644 => 100755 foerderbarometer/settings_development.py mode change 100644 => 100755 foerderbarometer/settings_mariadb_development.py mode change 100644 => 100755 foerderbarometer/settings_production.py mode change 100644 => 100755 foerderbarometer/urls.py mode change 100644 => 100755 foerderbarometer/wsgi.py mode change 100644 => 100755 input/__init__.py mode change 100644 => 100755 input/admin.py mode change 100644 => 100755 input/apps.py mode change 100644 => 100755 input/fixtures/accounts.json mode change 100644 => 100755 input/forms.py mode change 100644 => 100755 input/management/commands/sendmails.py mode change 100644 => 100755 input/migrations/0001_initial.py mode change 100644 => 100755 input/migrations/0002_auto_20200922_1340.py mode change 100644 => 100755 input/migrations/0003_volonteer.py mode change 100644 => 100755 input/migrations/0004_project_contact.py mode change 100644 => 100755 input/migrations/0005_auto_20200930_1015.py mode change 100644 => 100755 input/migrations/0006_honorarycertificate.py mode change 100644 => 100755 input/migrations/0007_library.py mode change 100644 => 100755 input/migrations/0008_ifg.py mode change 100644 => 100755 input/migrations/0009_project_pid.py mode change 100644 => 100755 input/migrations/0010_auto_20201007_0732.py mode change 100644 => 100755 input/migrations/0011_auto_20201007_0743.py mode change 100644 => 100755 input/migrations/0012_auto_20201007_0754.py mode change 100644 => 100755 input/migrations/0013_library_type.py mode change 100644 => 100755 input/migrations/0014_auto_20201020_0714.py mode change 100644 => 100755 input/migrations/0015_auto_20201021_0721.py mode change 100644 => 100755 input/migrations/0016_project_account.py mode change 100644 => 100755 input/migrations/0017_auto_20201021_1145.py mode change 100644 => 100755 input/migrations/0018_auto_20201021_1147.py mode change 100644 => 100755 input/migrations/0019_auto_20201021_1148.py mode change 100644 => 100755 input/migrations/0020_project_project_end_mail.py mode change 100644 => 100755 input/migrations/0021_auto_20201022_0934.py mode change 100644 => 100755 input/migrations/0022_auto_20201022_1233.py mode change 100644 => 100755 input/migrations/0023_auto_20201022_1400.py mode change 100644 => 100755 input/migrations/0024_travel.py mode change 100644 => 100755 input/migrations/0025_auto_20201026_1048.py mode change 100644 => 100755 input/migrations/0026_auto_20201026_1214.py mode change 100644 => 100755 input/migrations/0027_businesscard_email_list.py mode change 100644 => 100755 input/migrations/0028_auto_20201027_1131.py mode change 100644 => 100755 input/migrations/0029_auto_20201027_1247.py mode change 100644 => 100755 input/migrations/0030_auto_20201027_1337.py mode change 100644 => 100755 input/migrations/0031_auto_20201028_1402.py mode change 100644 => 100755 input/migrations/0032_auto_20201029_1213.py mode change 100644 => 100755 input/migrations/0033_auto_20201029_1338.py mode change 100644 => 100755 input/migrations/0034_auto_20201102_0913.py mode change 100644 => 100755 input/migrations/0035_auto_20201102_0944.py mode change 100644 => 100755 input/migrations/0036_auto_20201102_1049.py mode change 100644 => 100755 input/migrations/0037_auto_20201102_1054.py mode change 100644 => 100755 input/migrations/0038_auto_20201102_1055.py mode change 100644 => 100755 input/migrations/0039_auto_20201102_1212.py mode change 100644 => 100755 input/migrations/0040_auto_20201102_1302.py mode change 100644 => 100755 input/migrations/0041_auto_20201102_1318.py mode change 100644 => 100755 input/migrations/0042_auto_20201102_1319.py mode change 100644 => 100755 input/migrations/0043_auto_20201102_1320.py mode change 100644 => 100755 input/migrations/0044_auto_20201103_1545.py mode change 100644 => 100755 input/migrations/0044_auto_20201116_1531.py mode change 100644 => 100755 input/migrations/0045_auto_20201116_1557.py mode change 100644 => 100755 input/migrations/0046_auto_20201117_1542.py mode change 100644 => 100755 input/migrations/0047_auto_20201117_1546.py mode change 100644 => 100755 input/migrations/0048_auto_20201118_1503.py mode change 100644 => 100755 input/migrations/0049_auto_20201118_1509.py mode change 100644 => 100755 input/migrations/0050_auto_20201118_1512.py mode change 100644 => 100755 input/migrations/0051_auto_20201118_1521.py mode change 100644 => 100755 input/migrations/0052_auto_20201118_1524.py mode change 100644 => 100755 input/migrations/0053_auto_20201118_1531.py mode change 100644 => 100755 input/migrations/0054_auto_20201118_1702.py mode change 100644 => 100755 input/migrations/0055_merge_20201118_1734.py mode change 100644 => 100755 input/migrations/0056_auto_20201217_1215.py mode change 100644 => 100755 input/migrations/0057_auto_20210104_0937.py mode change 100644 => 100755 input/migrations/0058_auto_20210412_0946.py mode change 100644 => 100755 input/migrations/0059_auto_20210412_1142.py mode change 100644 => 100755 input/migrations/0060_concreteextern.py mode change 100644 => 100755 input/migrations/0061_concretevolunteer.py mode change 100644 => 100755 input/migrations/0062_auto_20211103_1155.py mode change 100644 => 100755 input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py mode change 100644 => 100755 input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py mode change 100644 => 100755 input/migrations/0065_alter_literature_selfbuy_and_more.py mode change 100644 => 100755 input/migrations/0066_email_adult.py mode change 100644 => 100755 input/migrations/0067_travel_project_name_alter_library_type.py mode change 100644 => 100755 input/migrations/0068_travel_hotel.py mode change 100644 => 100755 input/migrations/0069_alter_travel_transport.py mode change 100644 => 100755 input/migrations/0070_alter_travel_project.py mode change 100644 => 100755 input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py mode change 100644 => 100755 input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py mode change 100644 => 100755 input/migrations/0073_account_intern_notes.py mode change 100644 => 100755 input/migrations/0074_project_intern_notes.py mode change 100644 => 100755 input/migrations/0075_literature_selfbuy_data.py create mode 100644 input/migrations/0076_auto_20221129_1601.py create mode 100644 input/migrations/0077_auto_20221129_1706.py create mode 100644 input/migrations/0078_auto_20221129_1712.py create mode 100644 input/migrations/0079_auto_20221129_2310.py create mode 100644 input/migrations/0080_auto_20221129_2323.py mode change 100644 => 100755 input/migrations/__init__.py mode change 100644 => 100755 input/models.py mode change 100644 => 100755 input/settings.py mode change 100644 => 100755 input/static/dropdown/js/base.js mode change 100644 => 100755 input/static/input/logo.png mode change 100644 => 100755 input/static/input/nutzungsbedingungen.html mode change 100644 => 100755 input/templates/input/extern.html mode change 100644 => 100755 input/templates/input/if_end_of_project.html mode change 100644 => 100755 input/templates/input/if_end_of_project.txt mode change 100644 => 100755 input/templates/input/if_end_of_project_approved.html mode change 100644 => 100755 input/templates/input/if_end_of_project_approved.txt mode change 100644 => 100755 input/templates/input/if_end_of_project_orginformed.html mode change 100644 => 100755 input/templates/input/if_end_of_project_orginformed.txt mode change 100644 => 100755 input/templates/input/if_mail.html mode change 100644 => 100755 input/templates/input/if_mail.txt mode change 100644 => 100755 input/templates/input/if_not_of_project_approved.html mode change 100644 => 100755 input/templates/input/if_not_of_project_approved.txt mode change 100644 => 100755 input/templates/input/ifg_volunteer_mail.html mode change 100644 => 100755 input/templates/input/ifg_volunteer_mail.txt mode change 100644 => 100755 input/templates/input/survey_mail.html mode change 100644 => 100755 input/templates/input/survey_mail.txt mode change 100644 => 100755 input/templates/registration/login.html mode change 100644 => 100755 input/tests.py mode change 100644 => 100755 input/urls.py mode change 100644 => 100755 input/views.py create mode 100755 requirements.txt diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index bc0ab41..1139068 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # secret passwords and so /secrets.json /staticfiles -/foerderbarometer/settings.py +# /foerderbarometer/settings.py +/foerderbarometer/*settings* /nohup.out /logfile *~ diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/TODO b/TODO old mode 100644 new mode 100755 diff --git a/foerderbarometer/__init__.py b/foerderbarometer/__init__.py old mode 100644 new mode 100755 diff --git a/foerderbarometer/asgi.py b/foerderbarometer/asgi.py old mode 100644 new mode 100755 diff --git a/foerderbarometer/settings.py_old b/foerderbarometer/settings.py_old old mode 100644 new mode 100755 diff --git a/foerderbarometer/settings_development.py b/foerderbarometer/settings_development.py old mode 100644 new mode 100755 diff --git a/foerderbarometer/settings_mariadb_development.py b/foerderbarometer/settings_mariadb_development.py old mode 100644 new mode 100755 diff --git a/foerderbarometer/settings_production.py b/foerderbarometer/settings_production.py old mode 100644 new mode 100755 index 720e689..7a77496 --- a/foerderbarometer/settings_production.py +++ b/foerderbarometer/settings_production.py @@ -111,8 +111,8 @@ WSGI_APPLICATION = 'foerderbarometer.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'fdb', - 'USER': 'fdb', + 'NAME': 'fdbdevel', + 'USER': 'fdbdevel', 'PASSWORD': get_secret('DATABASE_PASSWORD'), 'HOST': '10.0.6.7', # Or an IP Address that your database is hosted on # 'PORT': '3306', diff --git a/foerderbarometer/urls.py b/foerderbarometer/urls.py old mode 100644 new mode 100755 diff --git a/foerderbarometer/wsgi.py b/foerderbarometer/wsgi.py old mode 100644 new mode 100755 diff --git a/input/__init__.py b/input/__init__.py old mode 100644 new mode 100755 diff --git a/input/admin.py b/input/admin.py old mode 100644 new mode 100755 diff --git a/input/apps.py b/input/apps.py old mode 100644 new mode 100755 diff --git a/input/fixtures/accounts.json b/input/fixtures/accounts.json old mode 100644 new mode 100755 diff --git a/input/forms.py b/input/forms.py old mode 100644 new mode 100755 index e2e6d07..c8e6897 --- a/input/forms.py +++ b/input/forms.py @@ -72,13 +72,13 @@ class TravelForm(FdbForm): 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' ) widgets = {'checkin': AdminDateWidget(), 'checkout': AdminDateWidget(),} - fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes'] + fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes', 'mail_state'] class LibraryForm(FdbForm): class Meta: model = Library - fields = ['cost', 'library', 'duration', 'notes'] + fields = ['cost', 'library', 'duration', 'notes', 'survey_mail_send'] exclude = ['intern_notes'] class HonoraryCertificateForm(FdbForm): @@ -139,7 +139,7 @@ class BusinessCardForm(CheckForm): class Meta: model = BusinessCard exclude = ['intern_notes'] - fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to'] + fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to', 'mail_state'] class Media: js = ('dropdown/js/base.js',) diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py old mode 100644 new mode 100755 index e08c877..9451cac --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -39,11 +39,12 @@ class Command(BaseCommand): html_mail_template = get_template('input/survey_mail.html') try: subject, from_email, to = 'Dein Feedback zur Förderung durch Wikimedia Deutschland', 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=[SURVEY_EMAIL]) - msg.attach_alternative(html_content, "text/html") - msg.send() + text_content = txt_mail_template.render(context) + html_content = html_mail_template.render(context) + msg = EmailMultiAlternatives(subject, text_content, from_email, [to], bcc=[SURVEY_EMAIL]) + msg.attach_alternative(html_content, "text/html") + msg.send() + #print('survey mail would have been send') #survey_mail = EmailMessage('Dein Feedback zur Förderung durch Wikimedia Deutschland', # mail_template.render(context), @@ -56,12 +57,19 @@ class Command(BaseCommand): print(f'send surveylinkemail to {email}...') + ''' the db entry mail_state was added. Useful when migrating databases. first delete the entry, then makemigrations + then migrate.. after that, recreate the entry with default END, after that makemigrations and migrate. + now all entries have the value END. after that rewrite the default to NONE in models.py, then makemigrations + and migrate again, to have NONE as default for all new queries. ''' + + def end_of_projects_reached(self): ''' end of project reached ''' # get all projects which ended old = Project.objects.filter(end__lt = date.today())\ - .exclude(end_mail_send = True) + .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') @@ -69,6 +77,7 @@ class Command(BaseCommand): for project in old: context = {'project': project} context['URLPREFIX'] = settings.URLPREFIX + try: subject, from_email, to = 'Projektende erreicht', IF_EMAIL, IF_EMAIL text_content = txt_mail_template.render(context) @@ -76,6 +85,7 @@ class Command(BaseCommand): msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() + #print('end of project mail would have been sent') #send_mail('Projektende erreicht', # mail_template.render(context), @@ -83,7 +93,11 @@ class Command(BaseCommand): # [IF_EMAIL], # fail_silently=False) project.end_mail_send = True - project.save() + project.mail_state = 'INF' + try: + project.save() + except: + print( 'For project', project, 'there is possibly no project.start (', project.start, ') class') except BadHeaderError: self.stdout.write(self.style.ERROR('Invalid header found.')) @@ -94,8 +108,8 @@ class Command(BaseCommand): # get all projects where end was reached already, and send mails for the ones already set to status "ended" by the admins approved_end = Project.objects.filter(status = 'END')\ - .exclude(end_mail_send = False) - print(approved_end) + .exclude(end_mail_send = False)\ + .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') @@ -106,6 +120,8 @@ class Command(BaseCommand): for project in approved_end: context = {'project': project} context['URLPREFIX'] = settings.URLPREFIX + + try: subject, from_email, to = 'Projektende erreicht', IF_EMAIL, project.email text_content = txt_mail_template.render(context) @@ -113,14 +129,15 @@ class Command(BaseCommand): msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() + #print('if and of project approved mail would have been sent') - inform_subject, inform_from_email, inform_to = Projektorganisator*in wurde informiert', IF_EMAIL, IF_EMAIL + inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', IF_EMAIL, 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() - + #print('if end of project orginformed mail would have been sent') #send_mail('Projektende erreicht', # mail_template.render(context), @@ -134,7 +151,11 @@ class Command(BaseCommand): # fail_silently=False) project.end_mail_send = True - project.save() + project.mail_state = 'END' + try: + project.save() + except: + print( 'For project', project, 'there is possibly no project.start (', project.start, ') class') except BadHeaderError: self.stdout.write(self.style.ERROR('Invalid header found.')) @@ -145,7 +166,8 @@ class Command(BaseCommand): # get all projects where end was reached already, and send mails for the ones where status was put to NOT by admins approved_notHappened = Project.objects.filter(status = 'NOT')\ - .exclude(end_mail_send = False) + .exclude(end_mail_send = False)\ + .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') @@ -164,7 +186,7 @@ class Command(BaseCommand): 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') #send_mail('Projektende erreicht', @@ -173,12 +195,13 @@ class Command(BaseCommand): # [project.email], # fail_silently=False) - inform_subject, inform_from_email, inform_to = Projektorganisator*in wurde informiert', IF_EMAIL, IF_EMAIL + inform_subject, inform_from_email, inform_to = 'Projektorganisator*in wurde informiert', IF_EMAIL, 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() + #print('if not of project approved end mail orginformed would have been sent') #send_mail('Projektorganisator*in wurde informiert', # informMail_template.render(context), @@ -187,6 +210,7 @@ class Command(BaseCommand): # fail_silently=False) project.end_mail_send = True + project.mail_state = 'END' project.save() except BadHeaderError: self.stdout.write(self.style.ERROR('Invalid header found.')) @@ -221,7 +245,8 @@ class Command(BaseCommand): supported = Library.objects.filter(granted=True)\ .filter(granted_date__lt = date.today() - timedelta(days=14))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported,name='library') def surveymails_to_hon(self): @@ -229,7 +254,8 @@ class Command(BaseCommand): supported = HonoraryCertificate.objects.filter(granted=True)\ .filter(granted_date__lt = date.today() - timedelta(days=14))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type='HON', name='project') def surveymails_to_ifg(self): @@ -237,7 +263,8 @@ class Command(BaseCommand): supported = IFG.objects.filter(granted=True)\ .filter(granted_date__lt = date.today() - timedelta(days=14))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type='IFG', name='url') def surveymails_to_lit(self): @@ -245,14 +272,16 @@ class Command(BaseCommand): supported = Literature.objects.filter(granted=True)\ .filter(granted_date__lt = date.today() - timedelta(days=14))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type='LIT', name='info') def surveymails_to_project(self): '''send survey link 4 weeks after end of project reached''' supported = Project.objects.filter(granted=True)\ .filter(end__lt = date.today() - timedelta(days=28))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type='PRO', name='name') def surveymails_to_travel(self): @@ -260,7 +289,8 @@ class Command(BaseCommand): supported = Travel.objects.filter(project__granted=True)\ .filter(project__end__lt = date.today() - timedelta(days=21))\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type='TRAV', name='project') def surveymails_to_mail_vis_lis(self): @@ -273,7 +303,8 @@ class Command(BaseCommand): # get class via string supported = getattr(sys.modules[__name__], c).objects.filter(granted=True)\ .filter(granted_date__lt = lastdate)\ - .exclude(survey_mail_send=True) + .exclude(survey_mail_send=True)\ + .exclude(mail_state = 'END') self.surveymails_to_object(supported, type=typefield[count]) count += 1 diff --git a/input/migrations/0001_initial.py b/input/migrations/0001_initial.py old mode 100644 new mode 100755 diff --git a/input/migrations/0002_auto_20200922_1340.py b/input/migrations/0002_auto_20200922_1340.py old mode 100644 new mode 100755 diff --git a/input/migrations/0003_volonteer.py b/input/migrations/0003_volonteer.py old mode 100644 new mode 100755 diff --git a/input/migrations/0004_project_contact.py b/input/migrations/0004_project_contact.py old mode 100644 new mode 100755 diff --git a/input/migrations/0005_auto_20200930_1015.py b/input/migrations/0005_auto_20200930_1015.py old mode 100644 new mode 100755 diff --git a/input/migrations/0006_honorarycertificate.py b/input/migrations/0006_honorarycertificate.py old mode 100644 new mode 100755 diff --git a/input/migrations/0007_library.py b/input/migrations/0007_library.py old mode 100644 new mode 100755 diff --git a/input/migrations/0008_ifg.py b/input/migrations/0008_ifg.py old mode 100644 new mode 100755 diff --git a/input/migrations/0009_project_pid.py b/input/migrations/0009_project_pid.py old mode 100644 new mode 100755 diff --git a/input/migrations/0010_auto_20201007_0732.py b/input/migrations/0010_auto_20201007_0732.py old mode 100644 new mode 100755 diff --git a/input/migrations/0011_auto_20201007_0743.py b/input/migrations/0011_auto_20201007_0743.py old mode 100644 new mode 100755 diff --git a/input/migrations/0012_auto_20201007_0754.py b/input/migrations/0012_auto_20201007_0754.py old mode 100644 new mode 100755 diff --git a/input/migrations/0013_library_type.py b/input/migrations/0013_library_type.py old mode 100644 new mode 100755 diff --git a/input/migrations/0014_auto_20201020_0714.py b/input/migrations/0014_auto_20201020_0714.py old mode 100644 new mode 100755 diff --git a/input/migrations/0015_auto_20201021_0721.py b/input/migrations/0015_auto_20201021_0721.py old mode 100644 new mode 100755 diff --git a/input/migrations/0016_project_account.py b/input/migrations/0016_project_account.py old mode 100644 new mode 100755 diff --git a/input/migrations/0017_auto_20201021_1145.py b/input/migrations/0017_auto_20201021_1145.py old mode 100644 new mode 100755 diff --git a/input/migrations/0018_auto_20201021_1147.py b/input/migrations/0018_auto_20201021_1147.py old mode 100644 new mode 100755 diff --git a/input/migrations/0019_auto_20201021_1148.py b/input/migrations/0019_auto_20201021_1148.py old mode 100644 new mode 100755 diff --git a/input/migrations/0020_project_project_end_mail.py b/input/migrations/0020_project_project_end_mail.py old mode 100644 new mode 100755 diff --git a/input/migrations/0021_auto_20201022_0934.py b/input/migrations/0021_auto_20201022_0934.py old mode 100644 new mode 100755 diff --git a/input/migrations/0022_auto_20201022_1233.py b/input/migrations/0022_auto_20201022_1233.py old mode 100644 new mode 100755 diff --git a/input/migrations/0023_auto_20201022_1400.py b/input/migrations/0023_auto_20201022_1400.py old mode 100644 new mode 100755 diff --git a/input/migrations/0024_travel.py b/input/migrations/0024_travel.py old mode 100644 new mode 100755 diff --git a/input/migrations/0025_auto_20201026_1048.py b/input/migrations/0025_auto_20201026_1048.py old mode 100644 new mode 100755 diff --git a/input/migrations/0026_auto_20201026_1214.py b/input/migrations/0026_auto_20201026_1214.py old mode 100644 new mode 100755 diff --git a/input/migrations/0027_businesscard_email_list.py b/input/migrations/0027_businesscard_email_list.py old mode 100644 new mode 100755 diff --git a/input/migrations/0028_auto_20201027_1131.py b/input/migrations/0028_auto_20201027_1131.py old mode 100644 new mode 100755 diff --git a/input/migrations/0029_auto_20201027_1247.py b/input/migrations/0029_auto_20201027_1247.py old mode 100644 new mode 100755 diff --git a/input/migrations/0030_auto_20201027_1337.py b/input/migrations/0030_auto_20201027_1337.py old mode 100644 new mode 100755 diff --git a/input/migrations/0031_auto_20201028_1402.py b/input/migrations/0031_auto_20201028_1402.py old mode 100644 new mode 100755 diff --git a/input/migrations/0032_auto_20201029_1213.py b/input/migrations/0032_auto_20201029_1213.py old mode 100644 new mode 100755 diff --git a/input/migrations/0033_auto_20201029_1338.py b/input/migrations/0033_auto_20201029_1338.py old mode 100644 new mode 100755 diff --git a/input/migrations/0034_auto_20201102_0913.py b/input/migrations/0034_auto_20201102_0913.py old mode 100644 new mode 100755 diff --git a/input/migrations/0035_auto_20201102_0944.py b/input/migrations/0035_auto_20201102_0944.py old mode 100644 new mode 100755 diff --git a/input/migrations/0036_auto_20201102_1049.py b/input/migrations/0036_auto_20201102_1049.py old mode 100644 new mode 100755 diff --git a/input/migrations/0037_auto_20201102_1054.py b/input/migrations/0037_auto_20201102_1054.py old mode 100644 new mode 100755 diff --git a/input/migrations/0038_auto_20201102_1055.py b/input/migrations/0038_auto_20201102_1055.py old mode 100644 new mode 100755 diff --git a/input/migrations/0039_auto_20201102_1212.py b/input/migrations/0039_auto_20201102_1212.py old mode 100644 new mode 100755 diff --git a/input/migrations/0040_auto_20201102_1302.py b/input/migrations/0040_auto_20201102_1302.py old mode 100644 new mode 100755 diff --git a/input/migrations/0041_auto_20201102_1318.py b/input/migrations/0041_auto_20201102_1318.py old mode 100644 new mode 100755 diff --git a/input/migrations/0042_auto_20201102_1319.py b/input/migrations/0042_auto_20201102_1319.py old mode 100644 new mode 100755 diff --git a/input/migrations/0043_auto_20201102_1320.py b/input/migrations/0043_auto_20201102_1320.py old mode 100644 new mode 100755 diff --git a/input/migrations/0044_auto_20201103_1545.py b/input/migrations/0044_auto_20201103_1545.py old mode 100644 new mode 100755 diff --git a/input/migrations/0044_auto_20201116_1531.py b/input/migrations/0044_auto_20201116_1531.py old mode 100644 new mode 100755 diff --git a/input/migrations/0045_auto_20201116_1557.py b/input/migrations/0045_auto_20201116_1557.py old mode 100644 new mode 100755 diff --git a/input/migrations/0046_auto_20201117_1542.py b/input/migrations/0046_auto_20201117_1542.py old mode 100644 new mode 100755 diff --git a/input/migrations/0047_auto_20201117_1546.py b/input/migrations/0047_auto_20201117_1546.py old mode 100644 new mode 100755 diff --git a/input/migrations/0048_auto_20201118_1503.py b/input/migrations/0048_auto_20201118_1503.py old mode 100644 new mode 100755 diff --git a/input/migrations/0049_auto_20201118_1509.py b/input/migrations/0049_auto_20201118_1509.py old mode 100644 new mode 100755 diff --git a/input/migrations/0050_auto_20201118_1512.py b/input/migrations/0050_auto_20201118_1512.py old mode 100644 new mode 100755 diff --git a/input/migrations/0051_auto_20201118_1521.py b/input/migrations/0051_auto_20201118_1521.py old mode 100644 new mode 100755 diff --git a/input/migrations/0052_auto_20201118_1524.py b/input/migrations/0052_auto_20201118_1524.py old mode 100644 new mode 100755 diff --git a/input/migrations/0053_auto_20201118_1531.py b/input/migrations/0053_auto_20201118_1531.py old mode 100644 new mode 100755 diff --git a/input/migrations/0054_auto_20201118_1702.py b/input/migrations/0054_auto_20201118_1702.py old mode 100644 new mode 100755 diff --git a/input/migrations/0055_merge_20201118_1734.py b/input/migrations/0055_merge_20201118_1734.py old mode 100644 new mode 100755 diff --git a/input/migrations/0056_auto_20201217_1215.py b/input/migrations/0056_auto_20201217_1215.py old mode 100644 new mode 100755 diff --git a/input/migrations/0057_auto_20210104_0937.py b/input/migrations/0057_auto_20210104_0937.py old mode 100644 new mode 100755 diff --git a/input/migrations/0058_auto_20210412_0946.py b/input/migrations/0058_auto_20210412_0946.py old mode 100644 new mode 100755 diff --git a/input/migrations/0059_auto_20210412_1142.py b/input/migrations/0059_auto_20210412_1142.py old mode 100644 new mode 100755 diff --git a/input/migrations/0060_concreteextern.py b/input/migrations/0060_concreteextern.py old mode 100644 new mode 100755 diff --git a/input/migrations/0061_concretevolunteer.py b/input/migrations/0061_concretevolunteer.py old mode 100644 new mode 100755 diff --git a/input/migrations/0062_auto_20211103_1155.py b/input/migrations/0062_auto_20211103_1155.py old mode 100644 new mode 100755 diff --git a/input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py b/input/migrations/0063_businesscard_url_of_pic_alter_ifg_notes_and_more.py old mode 100644 new mode 100755 diff --git a/input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py b/input/migrations/0064_businesscard_send_data_to_print_literature_selfbuy_and_more.py old mode 100644 new mode 100755 diff --git a/input/migrations/0065_alter_literature_selfbuy_and_more.py b/input/migrations/0065_alter_literature_selfbuy_and_more.py old mode 100644 new mode 100755 diff --git a/input/migrations/0066_email_adult.py b/input/migrations/0066_email_adult.py old mode 100644 new mode 100755 diff --git a/input/migrations/0067_travel_project_name_alter_library_type.py b/input/migrations/0067_travel_project_name_alter_library_type.py old mode 100644 new mode 100755 diff --git a/input/migrations/0068_travel_hotel.py b/input/migrations/0068_travel_hotel.py old mode 100644 new mode 100755 diff --git a/input/migrations/0069_alter_travel_transport.py b/input/migrations/0069_alter_travel_transport.py old mode 100644 new mode 100755 diff --git a/input/migrations/0070_alter_travel_project.py b/input/migrations/0070_alter_travel_project.py old mode 100644 new mode 100755 diff --git a/input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py b/input/migrations/0071_honorarycertificate_intern_notes_travel_intern_notes.py old mode 100644 new mode 100755 diff --git a/input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py b/input/migrations/0072_businesscard_intern_notes_email_intern_notes_and_more.py old mode 100644 new mode 100755 diff --git a/input/migrations/0073_account_intern_notes.py b/input/migrations/0073_account_intern_notes.py old mode 100644 new mode 100755 diff --git a/input/migrations/0074_project_intern_notes.py b/input/migrations/0074_project_intern_notes.py old mode 100644 new mode 100755 diff --git a/input/migrations/0075_literature_selfbuy_data.py b/input/migrations/0075_literature_selfbuy_data.py old mode 100644 new mode 100755 diff --git a/input/migrations/0076_auto_20221129_1601.py b/input/migrations/0076_auto_20221129_1601.py new file mode 100644 index 0000000..988c42e --- /dev/null +++ b/input/migrations/0076_auto_20221129_1601.py @@ -0,0 +1,78 @@ +# Generated by Django 3.1.2 on 2022-11-29 16:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0075_literature_selfbuy_data'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='concreteextern', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='email', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='ifg', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='library', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='list', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='literature', + name='selfbuy_data', + field=models.TextField(default='', help_text='Bitte gib hier alle persönlichen Daten an, die wir benötigen, um das Werk
für dich zu kaufen und es dir anschließend zu schicken (z.B. Vorname Nachname, Anschrift,
Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.
Hinweis: Telefonnummern bilden wir üblicherweise im internationalen Format gemäß
DIN 5008 ab. Als anzugebende E-Mail-Adresse empfehlen wir dir eine Wikimedia-Projekt-
Adresse, die du ebenfalls beantragen kannst, sofern du nicht bereits eine besitzt.', max_length=1000, verbose_name='Persönliche Daten sowie Adresse'), + ), + migrations.AlterField( + model_name='literature', + name='selfbuy_give_data', + field=models.BooleanField(help_text='Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.', verbose_name='Datenweitergabe erlauben'), + ), + migrations.AlterField( + model_name='literature', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='project', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='travel', + name='survey_mail_send', + field=models.BooleanField(default=True, verbose_name='Keine Umfragemail schicken'), + ), + ] diff --git a/input/migrations/0077_auto_20221129_1706.py b/input/migrations/0077_auto_20221129_1706.py new file mode 100644 index 0000000..e59dba8 --- /dev/null +++ b/input/migrations/0077_auto_20221129_1706.py @@ -0,0 +1,123 @@ +# Generated by Django 3.1.2 on 2022-11-29 17:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0076_auto_20221129_1601'), + ] + + operations = [ + migrations.AddField( + model_name='businesscard', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='concreteextern', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='concretevolunteer', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='email', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='honorarycertificate', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='ifg', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='library', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='list', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='literature', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='project', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AddField( + model_name='travel', + name='mailState', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('SURVEY', 'die Survey Mail wurde bereits versendet'), ('END', 'alle automatischen Mails wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='businesscard', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='concreteextern', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='email', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='ifg', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='library', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='list', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='literature', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='project', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + migrations.AlterField( + model_name='travel', + name='survey_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken'), + ), + ] diff --git a/input/migrations/0078_auto_20221129_1712.py b/input/migrations/0078_auto_20221129_1712.py new file mode 100644 index 0000000..f4520f4 --- /dev/null +++ b/input/migrations/0078_auto_20221129_1712.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2022-11-29 17:12 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0077_auto_20221129_1706'), + ] + + operations = [ + migrations.RenameField( + model_name='businesscard', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='concreteextern', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='concretevolunteer', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='email', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='honorarycertificate', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='ifg', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='library', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='list', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='literature', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='project', + old_name='mailState', + new_name='mail_state', + ), + migrations.RenameField( + model_name='travel', + old_name='mailState', + new_name='mail_state', + ), + ] diff --git a/input/migrations/0079_auto_20221129_2310.py b/input/migrations/0079_auto_20221129_2310.py new file mode 100644 index 0000000..9e7967b --- /dev/null +++ b/input/migrations/0079_auto_20221129_2310.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2022-11-29 23:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0078_auto_20221129_1712'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='concreteextern', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='email', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='ifg', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='library', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='list', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='literature', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='project', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + migrations.AlterField( + model_name='travel', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('END', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('APPR', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='APPR', max_length=6), + ), + ] diff --git a/input/migrations/0080_auto_20221129_2323.py b/input/migrations/0080_auto_20221129_2323.py new file mode 100644 index 0000000..2ed8741 --- /dev/null +++ b/input/migrations/0080_auto_20221129_2323.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2022-11-29 23:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0079_auto_20221129_2310'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concreteextern', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='email', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='ifg', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='library', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='list', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='literature', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='project', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='travel', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + ] diff --git a/input/migrations/__init__.py b/input/migrations/__init__.py old mode 100644 new mode 100755 diff --git a/input/models.py b/input/models.py old mode 100644 new mode 100755 index b1b4f83..f5ced02 --- a/input/models.py +++ b/input/models.py @@ -6,6 +6,10 @@ from django.utils.html import format_html from .settings import ACCOUNTS +EMAIL_STATES = {'NONE': 'noch keine Mail versendet', + 'INF': 'die Benachrichtigung End-Mail wurde bereits versendet', + 'END': 'alle automatischen Mails, auch surveyMail, wurden bereits versendet'} + class Volunteer(models.Model): realname = models.CharField(max_length=200, null=True, verbose_name="Realname", help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.") @@ -17,6 +21,8 @@ class Volunteer(models.Model): granted_date = models.DateField(null=True) survey_mail_send = models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken') survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True) + mail_state = models.CharField(max_length=6, choices=EMAIL_STATES.items(), default='NONE') + @classmethod def set_granted(cl, key, b): diff --git a/input/settings.py b/input/settings.py old mode 100644 new mode 100755 diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js old mode 100644 new mode 100755 diff --git a/input/static/input/logo.png b/input/static/input/logo.png old mode 100644 new mode 100755 diff --git a/input/static/input/nutzungsbedingungen.html b/input/static/input/nutzungsbedingungen.html old mode 100644 new mode 100755 diff --git a/input/templates/input/extern.html b/input/templates/input/extern.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project.html b/input/templates/input/if_end_of_project.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project.txt b/input/templates/input/if_end_of_project.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/input/if_end_of_project_approved.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project_approved.txt b/input/templates/input/if_end_of_project_approved.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project_orginformed.html b/input/templates/input/if_end_of_project_orginformed.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_end_of_project_orginformed.txt b/input/templates/input/if_end_of_project_orginformed.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/if_mail.html b/input/templates/input/if_mail.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_mail.txt b/input/templates/input/if_mail.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/if_not_of_project_approved.html b/input/templates/input/if_not_of_project_approved.html old mode 100644 new mode 100755 diff --git a/input/templates/input/if_not_of_project_approved.txt b/input/templates/input/if_not_of_project_approved.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/ifg_volunteer_mail.html b/input/templates/input/ifg_volunteer_mail.html old mode 100644 new mode 100755 diff --git a/input/templates/input/ifg_volunteer_mail.txt b/input/templates/input/ifg_volunteer_mail.txt old mode 100644 new mode 100755 diff --git a/input/templates/input/survey_mail.html b/input/templates/input/survey_mail.html old mode 100644 new mode 100755 diff --git a/input/templates/input/survey_mail.txt b/input/templates/input/survey_mail.txt old mode 100644 new mode 100755 diff --git a/input/templates/registration/login.html b/input/templates/registration/login.html old mode 100644 new mode 100755 diff --git a/input/tests.py b/input/tests.py old mode 100644 new mode 100755 diff --git a/input/urls.py b/input/urls.py old mode 100644 new mode 100755 diff --git a/input/views.py b/input/views.py old mode 100644 new mode 100755 index 4a257dd..9f48e10 --- a/input/views.py +++ b/input/views.py @@ -249,8 +249,8 @@ class ExternView(CookieWizardView): html_content = html_mail_template.render(context) msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") - msg.send() - + #msg.send() + print('ifg volunteer mail would have been sent') #send_mail( # 'Formular ausgefüllt', # mail_template.render(context), @@ -267,8 +267,8 @@ class ExternView(CookieWizardView): html_content = html_mail_template.render(context) msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") - msg.send() - + #msg.send() + print('if mail would have been sent') #send_mail( # 'Formular ausgefüllt', # mail_template.render(context), diff --git a/requirements.txt b/requirements.txt new file mode 100755 index 0000000..59966ae --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +asgiref==3.2.10 +Django==3.1.2 +django-formtools==2.4 +gunicorn==20.0.4 +mysqlclient==2.1.1 +sqlparse==0.4.3 +whitenoise==6.2.0 From a117b484d97c271f85a71abc2d7460a228f686b3 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 27/69] =?UTF-8?q?html=20format=20ge=C3=A4ndert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- input/settings.py | 8 ++++---- input/templates/input/if_end_of_project.html | 2 +- .../templates/input/if_end_of_project_approved.html | 10 +++++----- .../input/if_end_of_project_orginformed.html | 2 +- input/templates/input/if_mail.html | 8 ++++---- .../templates/input/if_not_of_project_approved.html | 12 ++++++------ input/templates/input/ifg_volunteer_mail.html | 6 +++--- input/templates/input/survey_mail.html | 4 ++-- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/input/settings.py b/input/settings.py index 5ee83b0..bda472e 100755 --- a/input/settings.py +++ b/input/settings.py @@ -1,9 +1,9 @@ # mail for IF-OTRS -#IF_EMAIL = 'community@wikimedia.de' -IF_EMAIL = 'test-luca-ext@wikimedia.de' +IF_EMAIL = 'community@wikimedia.de' +#IF_EMAIL = 'test-luca-ext@wikimedia.de' #SURVEY_EMAIL = 'christof.pins@wikimedia.de' -SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' - +#SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' +SURVEY_EMAIL = 'sandro.halank@wikimedia.de' # prefix for urls SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?' diff --git a/input/templates/input/if_end_of_project.html b/input/templates/input/if_end_of_project.html index fefd007..e52b86c 100755 --- a/input/templates/input/if_end_of_project.html +++ b/input/templates/input/if_end_of_project.html @@ -8,7 +8,7 @@ Ende erreicht.

Hier könnt ihr es in der Datenbank editieren:

-{{URLPREFIX}}/admin/input/project/{{project.pk}}/change +{{URLPREFIX}}/admin/input/project/{{project.pk}}/change

mit freundlichen Grüßen, Eure Lieblingsdatenbank diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/input/if_end_of_project_approved.html index 5ab0b79..317e412 100755 --- a/input/templates/input/if_end_of_project_approved.html +++ b/input/templates/input/if_end_of_project_approved.html @@ -24,17 +24,17 @@ Dein Team Communitys und Engagement -----
Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden.

-Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
+Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
Tel. (030) 219 158 26-0
-https://wikimedia.de
+https://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!
-https://spenden.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!
+https://spenden.wikimedia.de


Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207.

Datenschutzerklärung:
-Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung.

diff --git a/input/templates/input/if_end_of_project_orginformed.html b/input/templates/input/if_end_of_project_orginformed.html index 2d83129..83ad2d3 100755 --- a/input/templates/input/if_end_of_project_orginformed.html +++ b/input/templates/input/if_end_of_project_orginformed.html @@ -8,7 +8,7 @@ Ende erreicht.

Hier könnt ihr es in der Datenbank editieren:

-{{URLPREFIX}}/admin/input/project/{{project.pk}}/change +{{URLPREFIX}}/admin/input/project/{{project.pk}}/change

Projektorganisator*in wurde über den Projektabschluss informiert. diff --git a/input/templates/input/if_mail.html b/input/templates/input/if_mail.html index b7ec91f..d130016 100755 --- a/input/templates/input/if_mail.html +++ b/input/templates/input/if_mail.html @@ -8,7 +8,7 @@ Der Nutzer mit dem Username {{data.username}} ({{data.email}}) fragt ein_e {{dat {% if data.choice in data.grant %}
Vorraussichtliche Kosten: {{data.cost}}
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
+Domain: {{data.domain}}
Adressenbestandteil: {{data.address}}
{% endif %} {% if data.choice == 'BIB' %} Bibliothek: {{data.library}}
Dauer: {{data.duration}}
{% elif data.choice == 'ELIT' %} @@ -16,7 +16,7 @@ Datenbank: {{data.library}}
Dauer: {{data.duration}}
{% elif data.choice == 'SOFT' %} Software: {{data.library}}
Dauer: {{data.duration}}
{% elif data.choice == 'IFG'%} -Anfrage-URL: {{data.url}}
{% elif data.choice == 'LIT'%} +Anfrage-URL: {{data.url}}
{% elif data.choice == 'LIT'%} Info zum Werk: {{data.info}}
Bezugsquelle: {{data.source}}
{% elif data.choice == 'MAIL'%} Adressenbestandteil frei gewählt: {{data.other}}
{% elif data.choice == 'VIS'%} @@ -25,9 +25,9 @@ Persönliche Daten: {{data.data}}
Variante: {{data.variant}}
Sendungsadrese: {{data.send_to}}
{% endif %}

-Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %} +Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %}

-Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %} +Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %}

Stets zu Diensten, Deine Förderdatenbank diff --git a/input/templates/input/if_not_of_project_approved.html b/input/templates/input/if_not_of_project_approved.html index fa5f4df..0ab585b 100755 --- a/input/templates/input/if_not_of_project_approved.html +++ b/input/templates/input/if_not_of_project_approved.html @@ -15,25 +15,25 @@ Auch wenn ein Projekt mal nicht wie geplant stattfindet: Wir möchten jeden Schr
Insbesondere möchten wir uns an dieser Stelle ganz herzlich bei dir für die Zusammenarbeit und dein Engagement für Freies Wissen bedanken!
-Ein Link zum Probieren +
Viele Grüße Dein Team Communitys und Engagement

----- -Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden. +Diese E-Mail wurde automatisch verschickt, bei Rückfragen kannst du dich jederzeit an community@wikimedia.de wenden.

Wikimedia Deutschland e. V. | Tempelhofer Ufer 23–24 | 10963 Berlin
Tel. (030) 219 158 26-0
-https://wikimedia.de
+https://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!
-https://spenden.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!
+https://spenden.wikimedia.de

Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207.

Datenschutzerklärung:
-Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung.

diff --git a/input/templates/input/ifg_volunteer_mail.html b/input/templates/input/ifg_volunteer_mail.html index e8da031..646a653 100755 --- a/input/templates/input/ifg_volunteer_mail.html +++ b/input/templates/input/ifg_volunteer_mail.html @@ -6,7 +6,7 @@ wir haben Deine Anfrage ({{data.typestring|striptags}}) erhalten.
{% if data.choice in data.grant %}
Vorraussichtliche Kosten: {{data.cost}}
Anmerkungen: {{data.notes}} {% endif %} {% if data.choice in data.domain %}
-Domain: {{data.domain}}
+Domain: {{data.domain}}
Adressenbestandteil: {{data.address}} {% endif %} {% if data.choice == 'BIB' %}
Bibliothek: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'ELIT' %}
@@ -14,7 +14,7 @@ Datenbank: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'SOFT' %}
Software: {{data.library}}
Dauer: {{data.duration}} {% elif data.choice == 'IFG'%}
-Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
+Anfrage-URL: {{data.url}} {% elif data.choice == 'LIT'%}
Info zum Werk: {{data.info}}
Bezugsquelle: {{data.source}} {% elif data.choice == 'MAIL'%}
Adressenbestandteil frei gewählt: {{data.other}} {% elif data.choice == 'VIS'%}
@@ -25,7 +25,7 @@ Sendungsadrese: {{data.send_to}} {% endif %}


Das Team Comunitys und Engagement wird sich um die Bearbeitung deiner Anfrage kümmern
und sich in den nächsten Tagen bei dir melden. Solltest du Rückfragen haben,
-wende dich gern an community@wikimedia.de.
+wende dich gern an community@wikimedia.de.


Viele Grüße, dein freundliches aber komplett unmenschliches automatisches Formularbeantwortungssystem. diff --git a/input/templates/input/survey_mail.html b/input/templates/input/survey_mail.html index f62c146..bc381ae 100755 --- a/input/templates/input/survey_mail.html +++ b/input/templates/input/survey_mail.html @@ -34,9 +34,9 @@ Förderprogramme im Sinne der Communitys weiter zu verbessern. Wir freuen uns, wenn du dir kurz die Zeit dafür nehmen würdest. Die Umfrage mit weiteren Informationen findest du unter dem folgenden Link:
-{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1

+{{SURVEYPREFIX}}{% if type == 'PRO' %}O{% else %}I{% endif %}=1&{{pid}}=1

-Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an community@wikimedia.de +Da dies eine automatisch erzeugte Nachricht ist, wende dich bei Rückfragen zur Umfrage bitte an community@wikimedia.de From bdd6d25b70d969a90cd59a0d84d69eaf7ed802fa Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 28/69] admin search bar working now for all models, gave a 500 error because of wrong syntax in admin.py - searchfields --- input/admin.py | 12 ++++++------ input/models.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/input/admin.py b/input/admin.py index eff2e5e..20db719 100755 --- a/input/admin.py +++ b/input/admin.py @@ -38,7 +38,7 @@ class ProjectAdmin(admin.ModelAdmin): @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date', 'project') + search_fields = ('realname', 'service_id', 'granted', 'granted_date', 'project') list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project') list_display_links = ('realname', 'service_id') # action = ['export_as_csv'] @@ -49,7 +49,7 @@ class BusinessCardAdmin(admin.ModelAdmin): @admin.register(Literature) class LiteratureAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + search_fields = ('realname', 'service_id', 'granted', 'granted_date') list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' @@ -73,7 +73,7 @@ class HonoraryCertificateAdmin(admin.ModelAdmin): @admin.register(Library) class LibraryAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + search_fields = ('realname', 'service_id', 'granted', 'granted_date') list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' @@ -81,7 +81,7 @@ class LibraryAdmin(admin.ModelAdmin): @admin.register(IFG) class IFGAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + search_fields = ('realname', 'service_id', 'granted', 'granted_date') list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' @@ -97,7 +97,7 @@ class TravelAdmin(admin.ModelAdmin): @admin.register(Email) class EmailAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + search_fields = ('realname', 'service_id', 'granted', 'granted_date') list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' @@ -106,7 +106,7 @@ class EmailAdmin(admin.ModelAdmin): @admin.register(List) class ListAdmin(admin.ModelAdmin): save_as = True - search_fields = (('realname', 'service_id'), 'granted', 'granted_date') + search_fields = ('realname', 'service_id', 'granted', 'granted_date') list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' diff --git a/input/models.py b/input/models.py index f5ced02..a302bd3 100755 --- a/input/models.py +++ b/input/models.py @@ -124,7 +124,7 @@ class Project(Volunteer): class Intern(Volunteer): - '''abstrat base class for data entry from /intern (except Project)''' + '''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) class Meta: From 997c45d1ee3522c21cffc93846ab30d0cd36d730 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 29/69] changed the data protection link in html mails --- input/templates/input/if_end_of_project_approved.html | 2 +- input/templates/input/if_not_of_project_approved.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/input/if_end_of_project_approved.html index 317e412..75a5893 100755 --- a/input/templates/input/if_end_of_project_approved.html +++ b/input/templates/input/if_end_of_project_approved.html @@ -34,7 +34,7 @@ Unsere Vision ist eine Welt, in der alle Menschen am Wissen der Menschheit teilh Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207.

Datenschutzerklärung:
-Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung.

diff --git a/input/templates/input/if_not_of_project_approved.html b/input/templates/input/if_not_of_project_approved.html index 0ab585b..0e70e34 100755 --- a/input/templates/input/if_not_of_project_approved.html +++ b/input/templates/input/if_not_of_project_approved.html @@ -33,7 +33,7 @@ Unsere Vision ist eine Welt, in der alle Menschen am Wissen der Menschheit teilh Wikimedia Deutschland — Gesellschaft zur Förderung Freien Wissens e. V. Eingetragen im Vereinsregister des Amtsgerichts Berlin-Charlottenburg unter der Nummer 23855 B. Als gemeinnützig anerkannt durch das Finanzamt für Körperschaften I Berlin, Steuernummer 27/029/42207.

Datenschutzerklärung:
-Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung. +Soweit Sie uns personenbezogene Daten mitteilen, verarbeiten wir diese Daten gemäß unserer Datenschutzerklärung.

From 76d68531f9679601e8c119d7cfb51663d4a16663 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 30/69] sort of label choices on extern.html view alphabetically, change of text when form was sent to communitys und engagement instead of Ideenfoerderung --- input/models.py | 2 +- input/views.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/input/models.py b/input/models.py index a302bd3..dcc81b1 100755 --- a/input/models.py +++ b/input/models.py @@ -182,9 +182,9 @@ TYPE_CHOICES = {'BIB': format_html('Kostenübernahme IFG-Anfrage'), 'LIT': format_html('Literaturstipendium'), 'LIST': format_html('Mailingliste'), + 'TRAV': format_html('Reisekosten'), 'SOFT': format_html('Softwarestipendium'), 'VIS': format_html('Visitenkarten'), - 'TRAV': format_html('Reisekosten'), } # same model is used for Library, ELitStip and Software! diff --git a/input/views.py b/input/views.py index 9f48e10..d875537 100755 --- a/input/views.py +++ b/input/views.py @@ -61,7 +61,7 @@ def deny(request, choice, pk): def done(request): - return HttpResponse("Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Ideenförderung unter community@wikimedia.de.") + return HttpResponse("Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Communitys und Engagement unter community@wikimedia.de.") class InternView(LoginRequiredMixin, CookieWizardView): @@ -140,9 +140,9 @@ LABEL_CHOICES = {'BIB': format_html('Bibliothek'), 'IFG': format_html('Kostenübernahme IFG-Anfrage'), 'LIT': format_html('Literaturstipendium'), 'LIST': format_html('Mailingliste'), + 'TRAV': format_html('Reisekosten'), '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?"), From 26a1c9a500ee05d61cf41f0cfd24e3ba45f29eb4 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 31/69] added link to Reisekosten in label choices in extern.html view --- input/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/models.py b/input/models.py index dcc81b1..09bf011 100755 --- a/input/models.py +++ b/input/models.py @@ -182,7 +182,7 @@ TYPE_CHOICES = {'BIB': format_html('Kostenübernahme IFG-Anfrage'), 'LIT': format_html('Literaturstipendium'), 'LIST': format_html('Mailingliste'), - 'TRAV': format_html('Reisekosten'), + 'TRAV': format_html('Reisekosten'), 'SOFT': format_html('Softwarestipendium'), 'VIS': format_html('Visitenkarten'), } From 73ad8f90cf7a019a5d604aa5207a15af6b1abe89 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 32/69] changed languages default to german, translated last labels (verbosename) for variables --- foerderbarometer/urls.py | 8 ++++++++ input/admin.py | 2 +- input/management/commands/sendmails.py | 2 -- input/models.py | 10 +++++----- input/settings.py | 6 ++++++ input/urls.py | 4 ++-- input/views.py | 1 + 7 files changed, 23 insertions(+), 10 deletions(-) diff --git a/foerderbarometer/urls.py b/foerderbarometer/urls.py index 7f1b85a..3fdfb85 100755 --- a/foerderbarometer/urls.py +++ b/foerderbarometer/urls.py @@ -15,9 +15,17 @@ Including another URLconf """ from django.contrib import admin from django.urls import path, include +from django.conf.urls.i18n import i18n_patterns urlpatterns = [ path('', include("input.urls")), path('admin/', admin.site.urls), path('accounts/', include('django.contrib.auth.urls')), ] + +#urlpatterns = i18n_patterns('', +# path('', include("input.urls")), +# path('admin/', admin.site.urls), +# path('accounts/', include('django.contrib.auth.urls')), +# #your urls +#) diff --git a/input/admin.py b/input/admin.py index 20db719..469bcf8 100755 --- a/input/admin.py +++ b/input/admin.py @@ -22,7 +22,7 @@ def export_as_csv(self, request, queryset): return response -export_as_csv.short_description = "Export Selected" +export_as_csv.short_description = "Ausgewähltes zu CSV exportieren" admin.site.add_action(export_as_csv) diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 9451cac..43abad3 100755 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -150,7 +150,6 @@ class Command(BaseCommand): # [IF_EMAIL], # fail_silently=False) - project.end_mail_send = True project.mail_state = 'END' try: project.save() @@ -209,7 +208,6 @@ class Command(BaseCommand): # [IF_EMAIL], # fail_silently=False) - project.end_mail_send = True project.mail_state = 'END' project.save() except BadHeaderError: diff --git a/input/models.py b/input/models.py index 09bf011..fc7ad5b 100755 --- a/input/models.py +++ b/input/models.py @@ -17,8 +17,8 @@ class Volunteer(models.Model): help_text=format_html('Bitte gib deine E-Mail-Adresse ein, damit dich
Wikimedia Deutschland bei Rückfragen oder für
die Zusage kontaktieren kann.')) # the following Fields are not supposed to be edited by users - granted = models.BooleanField(null=True) - granted_date = models.DateField(null=True) + granted = models.BooleanField(null=True, verbose_name='bewilligt') + granted_date = models.DateField(null=True, verbose_name='bewilligt am') survey_mail_send = models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken') survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True) mail_state = models.CharField(max_length=6, choices=EMAIL_STATES.items(), default='NONE') @@ -61,7 +61,7 @@ class Account(models.Model): 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) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name="interne Anmerkungen") def __str__(self): return f"{self.code} {self.description}" @@ -81,7 +81,7 @@ class Project(Volunteer): insurance = models.BooleanField(default=False, verbose_name='Haftpflichtversicherung') 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) + 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') @@ -89,7 +89,7 @@ class Project(Volunteer): # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) - end_mail_send = models.BooleanField(null=True) + end_mail_send = models.BooleanField(null=True, verbose_name='Endmail versenden') status = models.CharField(max_length=3,choices=(('RUN', 'läuft'),('END','beendet'),('NOT','nicht stattgefunden')),default='RUN') persons = models.IntegerField(default=1) finance_id = models.CharField(max_length=15, null= True, blank=True) diff --git a/input/settings.py b/input/settings.py index bda472e..3b43e9a 100755 --- a/input/settings.py +++ b/input/settings.py @@ -12,6 +12,12 @@ DATAPROTECTION = "https://www.wikimedia.de/datenschutz/#datenerfassung" FOERDERRICHTLINIEN = "https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/F%C3%B6rderrichtlinien" NUTZUNGSBEDINGUNGEN = 'static/input/nutzungsbedingungen.html' +LANGUAGE_CODE = 'de' +TIME_ZONE = 'UTC' +USE_I18N = True +USE_L10N = True +USE_TZ = True + ACCOUNTS ={ # "21103": '21103 Willkommen', "DEF": 'DEFAULT VALUE, you hould not see this!', diff --git a/input/urls.py b/input/urls.py index ba4c2b4..e5fd5a9 100755 --- a/input/urls.py +++ b/input/urls.py @@ -1,12 +1,12 @@ from django.urls import path - from .views import ExternView, done, authorize, deny, InternView, export + urlpatterns = [ path('', ExternView.as_view(), name='extern'), # path('intern', InternView.as_view(), name='intern'), path('saved', done, name='done'), path('export', export, name='export'), path('authorize//', authorize, name='authorize'), - path('deny//', deny, name='deny') + path('deny//', deny, name='deny'), ] diff --git a/input/views.py b/input/views.py index d875537..919c9e5 100755 --- a/input/views.py +++ b/input/views.py @@ -12,6 +12,7 @@ from django.template import Context from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin from django.utils.html import format_html +from django.utils.translation import gettext as _ from .forms import ProjectForm, ExternForm, LibraryForm, IFGForm, LiteratureForm,\ HonoraryCertificateForm, InternForm, TravelForm, EmailForm,\ From 37e629de708b77dade5bace365044717f28c52dd Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 33/69] rewrote the javascript part --- input/admin.py | 9 +- input/forms.py | 34 ++-- input/logfile | 120 +++++++++++ input/migrations/0081_auto_20221204_1733.py | 213 ++++++++++++++++++++ input/migrations/0082_auto_20221204_1822.py | 23 +++ input/migrations/0083_auto_20221205_0946.py | 18 ++ input/models.py | 45 ++--- input/static/dropdown/js/base.js | 1 + input/static/dropdown/js/businessCard.js | 28 +++ input/static/dropdown/js/literature.js | 42 ++++ input/static/dropdown/js/mail.js | 35 ++++ input/views.py | 13 +- 12 files changed, 530 insertions(+), 51 deletions(-) create mode 100644 input/logfile create mode 100644 input/migrations/0081_auto_20221204_1733.py create mode 100644 input/migrations/0082_auto_20221204_1822.py create mode 100644 input/migrations/0083_auto_20221205_0946.py create mode 100644 input/static/dropdown/js/businessCard.js create mode 100644 input/static/dropdown/js/literature.js create mode 100644 input/static/dropdown/js/mail.js diff --git a/input/admin.py b/input/admin.py index 469bcf8..cce44e1 100755 --- a/input/admin.py +++ b/input/admin.py @@ -65,9 +65,8 @@ class AccountAdmin(admin.ModelAdmin): @admin.register(HonoraryCertificate) class HonoraryCertificateAdmin(admin.ModelAdmin): save_as = True - search_fields = ('realname', 'granted', 'granted_date', 'project') - list_display = ('realname', 'granted', 'granted_date', 'project') - list_display_links = ('realname', 'project') + search_fields = ['realname', 'granted'] + list_display = ('realname', 'granted','project') date_hierarchy = 'granted_date' @admin.register(Library) @@ -89,7 +88,7 @@ class IFGAdmin(admin.ModelAdmin): @admin.register(Travel) class TravelAdmin(admin.ModelAdmin): save_as = True - search_fields = ('realname', 'granted', 'granted_date', 'project') + search_fields = ['realname', 'granted_date'] list_display = ('realname', 'granted', 'granted_date', 'project') list_display_links = ('realname', 'project') date_hierarchy = 'granted_date' @@ -101,6 +100,8 @@ class EmailAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + class Media: + js = ('dropdown/js/base.js',) @admin.register(List) diff --git a/input/forms.py b/input/forms.py index c8e6897..261da35 100755 --- a/input/forms.py +++ b/input/forms.py @@ -22,7 +22,7 @@ class ProjectForm(FdbForm): class Meta: model = Project exclude = ('pid', 'project_of_year', 'finance_id','granted', 'granted_date', 'realname', 'email',\ - 'end_mail_send', 'status', 'persons', 'survey_mail_date') + 'end_mail_send', 'status', 'persons', 'survey_mail_date', 'mail_state') widgets = {'start': AdminDateWidget(), 'end': AdminDateWidget(),} @@ -38,7 +38,7 @@ class ExternForm(FdbForm): class Meta: model = ConcreteExtern - exclude = ('granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date') + exclude = ('granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state') INTERN_CHOICES = {'PRO': 'Projektsteckbrief', @@ -51,7 +51,7 @@ class InternForm(FdbForm): class Meta: model = ConcreteVolunteer - exclude = ('granted', 'granted_date', 'survey_mail_send', 'survey_mail_date') + exclude = ('granted', 'granted_date', 'survey_mail_send', 'survey_mail_date', 'mail_state') class TravelForm(FdbForm): @@ -69,19 +69,20 @@ class TravelForm(FdbForm): 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' ) + 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', 'mail_state'] + fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes'] class LibraryForm(FdbForm): class Meta: model = Library fields = ['cost', 'library', 'duration', 'notes', 'survey_mail_send'] - exclude = ['intern_notes'] + exclude = ['intern_notes', 'survey_mail_send', 'mail_state'] class HonoraryCertificateForm(FdbForm): + class Meta: model = HonoraryCertificate fields = ['request_url', 'project'] @@ -91,7 +92,7 @@ class IFGForm(FdbForm): class Meta: model = IFG fields = ['cost', 'url', 'notes'] - exclude = ['intern_notes'] + exclude = ['intern_notes', 'survey_mail_send', 'mail_state'] class CheckForm(FdbForm): @@ -108,9 +109,9 @@ class LiteratureForm(CheckForm): class Meta: model = Literature fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_data', 'selfbuy_give_data'] - exclude = ['intern_notes'] + exclude = ['intern_notes', 'survey_mail_send', 'mail_state'] class Media: - js = ('dropdown/js/base.js',) + js = ('dropdown/js/literature.js',) class EmailForm(CheckForm): @@ -118,15 +119,15 @@ class EmailForm(CheckForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['adult'].required = True - + self.fields['other'].required = True # TODO: add some javascript to show/hide other-field class Meta: model = Email fields = ['domain', 'address', 'other', 'adult'] - exclude = ['intern_notes'] + exclude = ['intern_notes', 'survey_mail_send', 'mail_state'] class Media: - js = ('dropdown/js/base.js',) + js = ('dropdown/js/mail.js',) @@ -135,18 +136,19 @@ class BusinessCardForm(CheckForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['url_of_pic'].required = True + self.fields['send_data_to_print'].required = True class Meta: model = BusinessCard - exclude = ['intern_notes'] - fields = ['project', 'data', 'variant', 'url_of_pic', 'sent_to', 'mail_state'] + exclude = ['intern_notes', 'survey_mail_send', 'mail_state'] + fields = ['project', 'data', 'variant', 'url_of_pic', 'send_data_to_print', 'sent_to'] class Media: - js = ('dropdown/js/base.js',) + js = ('dropdown/js/businessCard.js',) class ListForm(CheckForm): class Meta: model = List fields = ['domain', 'address'] - exclude = ['intern_notes'] + exclude = ['intern_notes', 'survey_mail_send','mail_state'] diff --git a/input/logfile b/input/logfile new file mode 100644 index 0000000..861f27e --- /dev/null +++ b/input/logfile @@ -0,0 +1,120 @@ +nohup: ignoring input +[2022-12-05 10:02:21 +0000] [12084] [DEBUG] Current configuration: + config: None + bind: ['0:8000'] + backlog: 2048 + workers: 1 + worker_class: sync + threads: 1 + worker_connections: 1000 + max_requests: 0 + max_requests_jitter: 0 + timeout: 30 + graceful_timeout: 30 + keepalive: 2 + limit_request_line: 4094 + limit_request_fields: 100 + limit_request_field_size: 8190 + reload: False + reload_engine: auto + reload_extra_files: [] + spew: False + check_config: False + preload_app: False + sendfile: None + reuse_port: False + chdir: /home/fdb/foerderbaro/foerderbarometer/input + daemon: False + raw_env: [] + pidfile: None + worker_tmp_dir: None + user: 1001 + group: 1001 + umask: 0 + initgroups: False + tmp_upload_dir: None + secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'} + forwarded_allow_ips: ['*'] + accesslog: None + disable_redirect_access_to_syslog: False + access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" + errorlog: - + loglevel: debug + capture_output: False + logger_class: gunicorn.glogging.Logger + logconfig: None + logconfig_dict: {} + syslog_addr: udp://localhost:514 + syslog: False + syslog_prefix: None + syslog_facility: user + enable_stdio_inheritance: False + statsd_host: None + dogstatsd_tags: + statsd_prefix: + proc_name: None + default_proc_name: foerderbarometer.wsgi + pythonpath: None + paste: None + on_starting: + on_reload: + when_ready: + pre_fork: + post_fork: + post_worker_init: + worker_int: + worker_abort: + pre_exec: + pre_request: + post_request: + child_exit: + worker_exit: + nworkers_changed: + on_exit: + proxy_protocol: False + proxy_allow_ips: ['127.0.0.1'] + keyfile: None + certfile: None + ssl_version: 2 + cert_reqs: 0 + ca_certs: None + suppress_ragged_eofs: True + do_handshake_on_connect: False + ciphers: None + raw_paste_global_conf: [] + strip_header_spaces: False +[2022-12-05 10:02:21 +0000] [12084] [INFO] Starting gunicorn 20.0.4 +[2022-12-05 10:02:21 +0000] [12084] [DEBUG] Arbiter booted +[2022-12-05 10:02:21 +0000] [12084] [INFO] Listening at: http://0.0.0.0:8000 (12084) +[2022-12-05 10:02:21 +0000] [12084] [INFO] Using worker: sync +[2022-12-05 10:02:21 +0000] [12086] [INFO] Booting worker with pid: 12086 +[2022-12-05 10:02:21 +0000] [12084] [DEBUG] 1 workers +[2022-12-05 10:02:21 +0000] [12086] [ERROR] Exception in worker process +Traceback (most recent call last): + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker + worker.init_process() + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 119, in init_process + self.load_wsgi() + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi + self.wsgi = self.app.wsgi() + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi + self.callable = self.load() + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 49, in load + return self.load_wsgiapp() + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp + return util.import_app(self.app_uri) + File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/util.py", line 358, in import_app + mod = importlib.import_module(module) + File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + File "", line 1014, in _gcd_import + File "", line 991, in _find_and_load + File "", line 961, in _find_and_load_unlocked + File "", line 219, in _call_with_frames_removed + File "", line 1014, in _gcd_import + File "", line 991, in _find_and_load + File "", line 973, in _find_and_load_unlocked +ModuleNotFoundError: No module named 'foerderbarometer' +[2022-12-05 10:02:21 +0000] [12086] [INFO] Worker exiting (pid: 12086) +[2022-12-05 10:02:21 +0000] [12084] [INFO] Shutting down: Master +[2022-12-05 10:02:21 +0000] [12084] [INFO] Reason: Worker failed to boot. diff --git a/input/migrations/0081_auto_20221204_1733.py b/input/migrations/0081_auto_20221204_1733.py new file mode 100644 index 0000000..9be8454 --- /dev/null +++ b/input/migrations/0081_auto_20221204_1733.py @@ -0,0 +1,213 @@ +# Generated by Django 3.1.2 on 2022-12-04 17:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0080_auto_20221129_2323'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='businesscard', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='businesscard', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='businesscard', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='businesscard', + name='send_data_to_print', + field=models.BooleanField(default=False, help_text='Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia
Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten
Versands der Druckerzeugnisse an mich.', verbose_name='Datenweitergabe erlauben'), + ), + migrations.AlterField( + model_name='concreteextern', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='concreteextern', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='email', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='email', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='email', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='ifg', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='ifg', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='ifg', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='library', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='library', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='library', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + 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'), ('TRAV', 'Reisekosten'), ('SOFT', 'Softwarestipendium'), ('VIS', 'Visitenkarten')], default='BIB', max_length=4), + ), + migrations.AlterField( + model_name='list', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='list', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='list', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='literature', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='literature', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='literature', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='literature', + name='selfbuy', + field=models.CharField(choices=[('TRUE', 'Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'), ('FALSE', 'Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft')], default='TRUE', max_length=10, verbose_name='Selbstkauf?'), + ), + migrations.AlterField( + model_name='project', + name='cost', + field=models.IntegerField(blank=True, null=True, verbose_name='Kosten'), + ), + migrations.AlterField( + model_name='project', + name='end_mail_send', + field=models.BooleanField(null=True, verbose_name='Endmail versenden'), + ), + migrations.AlterField( + model_name='project', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='project', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='project', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='travel', + name='checkin', + field=models.DateTimeField(blank=True, null=True, verbose_name='Anreise'), + ), + migrations.AlterField( + model_name='travel', + name='checkout', + field=models.DateTimeField(blank=True, null=True, verbose_name='Abreise'), + ), + migrations.AlterField( + model_name='travel', + name='granted', + field=models.BooleanField(null=True, verbose_name='bewilligt'), + ), + migrations.AlterField( + model_name='travel', + name='granted_date', + field=models.DateField(null=True, verbose_name='bewilligt am'), + ), + migrations.AlterField( + model_name='travel', + name='intern_notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='interne Anmerkungen'), + ), + migrations.AlterField( + model_name='travel', + name='notes', + field=models.TextField(blank=True, max_length=1000, verbose_name='Anmerkungen'), + ), + ] diff --git a/input/migrations/0082_auto_20221204_1822.py b/input/migrations/0082_auto_20221204_1822.py new file mode 100644 index 0000000..ae5b196 --- /dev/null +++ b/input/migrations/0082_auto_20221204_1822.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.2 on 2022-12-04 18:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0081_auto_20221204_1733'), + ] + + operations = [ + migrations.AlterField( + model_name='literature', + name='selfbuy_data', + field=models.TextField(default='', help_text='Bitte gib hier alle persönlichen Daten an, die wir benötigen, um das Werk
für dich zu kaufen und es dir anschließend zu schicken (z.B. Vorname Nachname, Anschrift,
Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.', max_length=1000, verbose_name='Persönliche Daten sowie Adresse'), + ), + migrations.AlterField( + model_name='literature', + name='selfbuy_give_data', + field=models.BooleanField(help_text='Ich stimme der Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister zu.', verbose_name='Datenweitergabe erlauben'), + ), + ] diff --git a/input/migrations/0083_auto_20221205_0946.py b/input/migrations/0083_auto_20221205_0946.py new file mode 100644 index 0000000..81f6d5f --- /dev/null +++ b/input/migrations/0083_auto_20221205_0946.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-05 09:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0082_auto_20221204_1822'), + ] + + operations = [ + migrations.AlterField( + model_name='email', + name='adult', + field=models.CharField(choices=[('TRUE', 'Ich bin volljährig.'), ('FALSE', 'Ich bin noch nicht volljährig.')], default='FALSE', max_length=10, verbose_name='Volljährigkeit'), + ), + ] diff --git a/input/models.py b/input/models.py index fc7ad5b..78d44c4 100755 --- a/input/models.py +++ b/input/models.py @@ -85,7 +85,7 @@ class Project(Volunteer): 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) + 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) @@ -126,7 +126,7 @@ class Project(Volunteer): 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) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen') class Meta: abstract = True @@ -138,7 +138,6 @@ 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 @@ -150,20 +149,21 @@ TRANSPORT_CHOICES = {'BAHN': 'Bahn', PAYEDBY_CHOICES = {'WMDE': 'WMDE', 'REQU': 'Antragstellender Mensch'} -class Travel(Intern): +class Travel(Volunteer): # 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') + travelcost = models.CharField(max_length=10, default="0", verbose_name='Fahrtkosten') + checkin = models.DateTimeField(blank=True, null=True, verbose_name='Anreise') + checkout = models.DateTimeField(blank=True, null=True, verbose_name='Abreise') 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) - + notes = models.TextField(max_length=1000, blank=True, verbose_name='Anmerkungen') + request_url = models.URLField(max_length=2000, verbose_name='Antrag (URL)') + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen') #abstract base class for Library and IFG class Grant(Extern): @@ -197,14 +197,13 @@ class Library(Grant): ) library = models.CharField(max_length=200) duration = models.CharField(max_length=100, verbose_name="Dauer") - intern_notes = models.TextField(max_length=1000, blank=True) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name="interne Anmerkungen") def __str__(self): return self.library SELFBUY_CHOICES = {'TRUE': format_html('Ich möchte das Werk selbst kaufen und per Kostenerstattung bei Wikimedia Deutschland abrechnen.'), 'FALSE': format_html('Ich möchte, dass Wikimedia Deutschland das Werk für mich kauft'), - 'NONE': format_html('Nichts ausgewählt') } @@ -215,20 +214,17 @@ class Literature(Grant): source = models.CharField(max_length=200, verbose_name='Bezugsquelle', help_text="Bitte gib an, wo du das Werk kaufen möchtest.") selfbuy = models.CharField( max_length=10, verbose_name='Selbstkauf?', choices=SELFBUY_CHOICES.items(), default='TRUE') - selfbuy_give_data = models.BooleanField(verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister.')) + selfbuy_give_data = models.BooleanField(verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Ich stimme der Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister zu.')) selfbuy_data = models.TextField(max_length=1000, verbose_name='Persönliche Daten sowie Adresse', default='', help_text=format_html("Bitte gib hier alle persönlichen Daten an, die wir benötigen, um das Werk
\ für dich zu kaufen und es dir anschließend zu schicken (z.B. Vorname Nachname, Anschrift,
\ - Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.
\ - Hinweis: Telefonnummern bilden wir üblicherweise im internationalen Format gemäß
\ - DIN 5008 ab. Als anzugebende E-Mail-Adresse empfehlen wir dir eine Wikimedia-Projekt-
\ - Adresse, die du ebenfalls beantragen kannst, sofern du nicht bereits eine besitzt.")) - intern_notes = models.TextField(max_length=1000, blank=True) + 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.") - intern_notes = models.TextField(max_length=1000, blank=True) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name="interne Anmerkungen") def __str__(self): return "IFG-Anfrage von " + self.realname @@ -252,8 +248,7 @@ MAIL_CHOICES = {'REALNAME': 'Vorname.Nachname', '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') + 'FALSE': format_html('Ich bin noch nicht volljährig.') } class Email(Domain): @@ -263,14 +258,14 @@ 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') - intern_notes = models.TextField(max_length=1000, blank=True) + 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(Domain): address = models.CharField(max_length=50, default='NO_ADDRESS', verbose_name="Adressbestandteil für Projektmailingliste", help_text=format_html("Bitte gib hier den gewünschten Adressbestandteil an,
der sich vor der Domain befinden soll.")) - intern_notes = models.TextField(max_length=1000, blank=True) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name="interne Anmerkungen") PROJECT_CHOICE = {'PEDIA': 'Wikipedia', 'SOURCE': 'Wikisource', @@ -307,5 +302,5 @@ class BusinessCard(Extern): sent_to = models.TextField(max_length=1000, verbose_name='Versandadresse', default='', help_text="Bitte gib den Namen und die vollständige Adresse ein, an welche die Visitenkarten geschickt werden sollen.") - send_data_to_print = models.BooleanField(default=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten Versands der Druckerzeugnisse an mich.')) - intern_notes = models.TextField(max_length=1000, blank=True) + send_data_to_print = models.BooleanField(default=False, verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Hiermit erlaube ich die Weitergabe meiner Daten (Name, Postadresse) an den von Wikimedia
Deutschland ausgewählten Dienstleister (z. B. wir-machen-druck.de) zum Zwecke des direkten
Versands der Druckerzeugnisse an mich.')) + intern_notes = models.TextField(max_length=1000, blank=True, verbose_name="interne Anmerkungen") diff --git a/input/static/dropdown/js/base.js b/input/static/dropdown/js/base.js index b93cf52..842bb7d 100755 --- a/input/static/dropdown/js/base.js +++ b/input/static/dropdown/js/base.js @@ -54,6 +54,7 @@ window.addEventListener("load", function() { selectField.change(function() { toggleVerified($(this).val()); }); + }); })(django.jQuery); }); diff --git a/input/static/dropdown/js/businessCard.js b/input/static/dropdown/js/businessCard.js new file mode 100644 index 0000000..cec9f9f --- /dev/null +++ b/input/static/dropdown/js/businessCard.js @@ -0,0 +1,28 @@ +window.addEventListener("load", function() { +(function($) { + $(function() { + + var selectField = $('#id_variant'), + verified_div = $('#id_url_of_pic').parent().parent(), + verified_data = $('#id_url_of_pic'); + function toggleVerified(value) { + if (value === 'PIC') { + verified_div.show(); + verified_data.val(""); + } else { + verified_div.hide(); + verified_data.val("NONE"); + } + } + + // show/hide on load based on existing value of selectField + toggleVerified(selectField.val()); + + // show/hide on change + selectField.change(function() { + toggleVerified($(this).val()); + }); + + }); +})(django.jQuery); +}); diff --git a/input/static/dropdown/js/literature.js b/input/static/dropdown/js/literature.js new file mode 100644 index 0000000..893b4a9 --- /dev/null +++ b/input/static/dropdown/js/literature.js @@ -0,0 +1,42 @@ +window.addEventListener("load", function() { +(function($) { + $(function() { + + + // selfbuy section + + var selectField_selfbuy = $('#id_selfbuy'), + verified_selfbuy_div = $('#id_selfbuy_give_data').parent().parent(), + verified_selfbuy = $('#id_selfbuy_give_data'), + data_selfbuy_div = $('#id_selfbuy_data').parent().parent(), + data_selfbuy = $('#id_selfbuy_data'); + + + + // make checked to get through the required + function toggleVerified_selfbuy(value) { + if (value === "FALSE") { + verified_selfbuy_div.show(); + data_selfbuy_div.show(); + data_selfbuy.val(""); + verified_selfbuy.prop("checked", false); + } else { + verified_selfbuy_div.hide(); + data_selfbuy_div.hide(); + data_selfbuy.val("NONE"); + verified_selfbuy.prop("checked", true); + } + } + + // show/hide on load based on existing value of selectField + toggleVerified_selfbuy(selectField_selfbuy.val()); + + // show/hide on change + selectField_selfbuy.change(function() { + toggleVerified_selfbuy($(this).val()); + }); + + }); +})(django.jQuery); +}); + diff --git a/input/static/dropdown/js/mail.js b/input/static/dropdown/js/mail.js new file mode 100644 index 0000000..c5626b8 --- /dev/null +++ b/input/static/dropdown/js/mail.js @@ -0,0 +1,35 @@ +window.addEventListener("load", function() { +(function($) { + $(function() { + + // mail section + + var selectField_addrOther = $('#id_address'), + data_addrOther_div = $('#id_other').parent().parent(), + data_addrOther = $('#id_other'); + console.log(data_addrOther, data_addrOther_div ); + // make checked to get through the required + function toggleVerified_addrOther(value) { + if (value === "OTHER") { + data_addrOther_div.show(); + data_addrOther.val(""); + } else { + data_addrOther_div.hide(); + data_addrOther.val("NONE"); + } + } + + // show/hide on load based on existing value of selectField + toggleVerified_addrOther(selectField_addrOther.val()); + + // show/hide on change + selectField_addrOther.change(function() { + toggleVerified_addrOther($(this).val()); + }); + + + + + }); +})(django.jQuery); +}); diff --git a/input/views.py b/input/views.py index 919c9e5..4dbff38 100755 --- a/input/views.py +++ b/input/views.py @@ -111,9 +111,10 @@ class InternView(LoginRequiredMixin, CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} - if data['selfbuy'] == 'TRUE': - data['selfbuy_give_data'] = 'False' - print(data) + + if data['choice'] == 'LIT': + if data['selfbuy'] == 'TRUE': + data['selfbuy_give_data'] = 'False' # write data to database form = form.save(commit=False) @@ -209,9 +210,9 @@ class ExternView(CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} - if data['selfbuy'] == 'TRUE': - data['selfbuy_give_data'] = 'False' - print(data) + if data['choice'] == 'LIT': + if data['selfbuy'] == 'TRUE': + data['selfbuy_give_data'] = 'False' # write data to database modell = form.save(commit=False) From b451cbbb160aae747928b092a4719354fa70efb4 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 34/69] added a presave signal for travel model to update own field with foreign key project field --- input/admin.py | 2 +- input/forms.py | 1 + input/migrations/0084_travel_project_end.py | 18 +++++++++++++++ input/migrations/0085_auto_20221205_1820.py | 18 +++++++++++++++ input/models.py | 25 ++++++++++++++++++++- 5 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 input/migrations/0084_travel_project_end.py create mode 100644 input/migrations/0085_auto_20221205_1820.py diff --git a/input/admin.py b/input/admin.py index cce44e1..9c5f954 100755 --- a/input/admin.py +++ b/input/admin.py @@ -32,7 +32,7 @@ class ProjectAdmin(admin.ModelAdmin): search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') list_display = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') # action = ['export_as_csv'] - date_hierarchy = 'start' + date_hierarchy = 'end' @admin.register(BusinessCard) diff --git a/input/forms.py b/input/forms.py index 261da35..076b099 100755 --- a/input/forms.py +++ b/input/forms.py @@ -66,6 +66,7 @@ class TravelForm(FdbForm): self.fields['checkin'].required = True self.fields['checkout'].required = True self.fields['hotel'].required = True + self.fields['project_end'].required = False class Meta: model = Travel diff --git a/input/migrations/0084_travel_project_end.py b/input/migrations/0084_travel_project_end.py new file mode 100644 index 0000000..6098047 --- /dev/null +++ b/input/migrations/0084_travel_project_end.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-05 18:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0083_auto_20221205_0946'), + ] + + operations = [ + migrations.AddField( + model_name='travel', + name='project_end', + field=models.DateField(null=True, verbose_name='Projektende'), + ), + ] diff --git a/input/migrations/0085_auto_20221205_1820.py b/input/migrations/0085_auto_20221205_1820.py new file mode 100644 index 0000000..2cc3038 --- /dev/null +++ b/input/migrations/0085_auto_20221205_1820.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-05 18:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0084_travel_project_end'), + ] + + operations = [ + migrations.AlterField( + model_name='travel', + name='project_end', + field=models.DateField(blank=True, null=True, verbose_name='Projektende'), + ), + ] diff --git a/input/models.py b/input/models.py index 78d44c4..30d1c02 100755 --- a/input/models.py +++ b/input/models.py @@ -87,9 +87,10 @@ class Project(Volunteer): 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") + end_mail_send = models.BooleanField(null=True, verbose_name='Endmail versenden') + # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) - end_mail_send = models.BooleanField(null=True, verbose_name='Endmail versenden') status = models.CharField(max_length=3,choices=(('RUN', 'läuft'),('END','beendet'),('NOT','nicht stattgefunden')),default='RUN') persons = models.IntegerField(default=1) finance_id = models.CharField(max_length=15, null= True, blank=True) @@ -149,6 +150,8 @@ TRANSPORT_CHOICES = {'BAHN': 'Bahn', PAYEDBY_CHOICES = {'WMDE': 'WMDE', 'REQU': 'Antragstellender Mensch'} +from django.contrib.contenttypes.models import ContentType + class Travel(Volunteer): # 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) @@ -164,6 +167,26 @@ class Travel(Volunteer): notes = models.TextField(max_length=1000, blank=True, verbose_name='Anmerkungen') request_url = models.URLField(max_length=2000, verbose_name='Antrag (URL)') intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen') + project_end = models.DateField(blank=True, null=True, verbose_name='Projektende') + # use content type model to get the end date for the project foreign key + + +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 + instance.project_end = instance.project.end + + +# 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 class Grant(Extern): From 402a6f047ca1a3ba7eb14ba367b531a886c0938f Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 35/69] travel und project models now have date hierarchy based on project end --- input/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input/admin.py b/input/admin.py index 9c5f954..ce8fe34 100755 --- a/input/admin.py +++ b/input/admin.py @@ -89,9 +89,9 @@ class IFGAdmin(admin.ModelAdmin): class TravelAdmin(admin.ModelAdmin): save_as = True search_fields = ['realname', 'granted_date'] - list_display = ('realname', 'granted', 'granted_date', 'project') + list_display = ('realname', 'granted', 'granted_date', 'project_end', 'project') list_display_links = ('realname', 'project') - date_hierarchy = 'granted_date' + date_hierarchy = 'project_end' @admin.register(Email) class EmailAdmin(admin.ModelAdmin): From e638afabd5844e51215d73c186bf3f4f5c7de60e Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 36/69] added adult multiple choice radio button by changing admin.py and forms.py --- input/admin.py | 1 + input/forms.py | 9 +++++++++ input/models.py | 1 + 3 files changed, 11 insertions(+) diff --git a/input/admin.py b/input/admin.py index ce8fe34..547fc8f 100755 --- a/input/admin.py +++ b/input/admin.py @@ -100,6 +100,7 @@ class EmailAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + radio_fields = {'adult': admin.VERTICAL} class Media: js = ('dropdown/js/base.js',) diff --git a/input/forms.py b/input/forms.py index 076b099..8b0b898 100755 --- a/input/forms.py +++ b/input/forms.py @@ -114,6 +114,11 @@ class LiteratureForm(CheckForm): class Media: js = ('dropdown/js/literature.js',) +ADULT_CHOICES = {'TRUE': format_html('Ich bin volljährig.'), + 'FALSE': format_html('Ich bin noch nicht volljährig.') + } + + class EmailForm(CheckForm): # this is the code, to change required to false if needed @@ -122,6 +127,10 @@ class EmailForm(CheckForm): self.fields['adult'].required = True self.fields['other'].required = True + adult = ChoiceField(label='Volljährigkeit', choices=ADULT_CHOICES.items(), widget=RadioSelect()) + + + # TODO: add some javascript to show/hide other-field class Meta: model = Email diff --git a/input/models.py b/input/models.py index 30d1c02..8ae7958 100755 --- a/input/models.py +++ b/input/models.py @@ -180,6 +180,7 @@ def getProjectEnd(sender, instance, **kwargs): instance.project_end = instance.project.end +# 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 From a064b7895887ab657eb106842bcfb69b13a30d49 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 37/69] hidden for all 'today' shortcuts in datetimefields via css --- input/templates/input/extern.html | 1 + 1 file changed, 1 insertion(+) diff --git a/input/templates/input/extern.html b/input/templates/input/extern.html index f4386a4..13dcb6a 100755 --- a/input/templates/input/extern.html +++ b/input/templates/input/extern.html @@ -9,6 +9,7 @@ + {% load i18n %} {% block content %} From 0b450feac92b75cd42df1ee06dc9f53001db2ca4 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 38/69] changed logic of generation of finId and pId, solved Travelform error, hotel variable travelmodel is not required anymore --- input/admin.py | 9 +++-- input/forms.py | 3 +- input/migrations/0086_project_end_quartal.py | 18 +++++++++ .../0087_travel_project_end_quartal.py | 18 +++++++++ input/models.py | 39 +++++++++++++++---- .../css/dateFieldNoNowShortcutInTravels.css | 5 +++ 6 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 input/migrations/0086_project_end_quartal.py create mode 100644 input/migrations/0087_travel_project_end_quartal.py create mode 100644 input/static/css/dateFieldNoNowShortcutInTravels.css diff --git a/input/admin.py b/input/admin.py index 547fc8f..59746a0 100755 --- a/input/admin.py +++ b/input/admin.py @@ -29,11 +29,11 @@ admin.site.add_action(export_as_csv) @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): save_as = True - search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') - list_display = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status') + search_fields = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status', 'end_quartal') + list_display = ('name', 'pid','finance_id', 'realname', 'start', 'end', 'participants_estimated', 'participants_real', 'cost', 'status', 'end_quartal') # action = ['export_as_csv'] date_hierarchy = 'end' - + readonly_fields = ('end_quartal', 'project_of_year', 'pid', 'finance_id') @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): @@ -89,9 +89,10 @@ class IFGAdmin(admin.ModelAdmin): class TravelAdmin(admin.ModelAdmin): save_as = True search_fields = ['realname', 'granted_date'] - list_display = ('realname', 'granted', 'granted_date', 'project_end', 'project') + list_display = ('realname', 'granted', 'granted_date', 'project_end', 'project', 'project_end_quartal') list_display_links = ('realname', 'project') date_hierarchy = 'project_end' + readonly_fields = ('project_end_quartal', 'project_end') @admin.register(Email) class EmailAdmin(admin.ModelAdmin): diff --git a/input/forms.py b/input/forms.py index 8b0b898..f4bf805 100755 --- a/input/forms.py +++ b/input/forms.py @@ -65,8 +65,7 @@ class TravelForm(FdbForm): self.fields['travelcost'].required = True self.fields['checkin'].required = True self.fields['checkout'].required = True - self.fields['hotel'].required = True - self.fields['project_end'].required = False + self.fields['hotel'].required = False class Meta: model = Travel diff --git a/input/migrations/0086_project_end_quartal.py b/input/migrations/0086_project_end_quartal.py new file mode 100644 index 0000000..6eb6ed7 --- /dev/null +++ b/input/migrations/0086_project_end_quartal.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-07 09:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0085_auto_20221205_1820'), + ] + + operations = [ + migrations.AddField( + model_name='project', + name='end_quartal', + field=models.CharField(blank=True, max_length=15, null=True, verbose_name='Quartal Projekt Ende'), + ), + ] diff --git a/input/migrations/0087_travel_project_end_quartal.py b/input/migrations/0087_travel_project_end_quartal.py new file mode 100644 index 0000000..c1d8ea8 --- /dev/null +++ b/input/migrations/0087_travel_project_end_quartal.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-07 09:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0086_project_end_quartal'), + ] + + operations = [ + migrations.AddField( + model_name='travel', + name='project_end_quartal', + field=models.CharField(blank=True, max_length=15, null=True, verbose_name='Quartal Projekt Ende'), + ), + ] diff --git a/input/models.py b/input/models.py index 8ae7958..96ce900 100755 --- a/input/models.py +++ b/input/models.py @@ -95,6 +95,7 @@ class Project(Volunteer): persons = models.IntegerField(default=1) finance_id = models.CharField(max_length=15, null= True, blank=True) 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): '''we generate the autogenerated fields here''' @@ -103,21 +104,43 @@ class Project(Volunteer): super().save() self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) # self.pid = str(self.account.code) + str(self.pk).zfill(3) - # generation of finance_id + + # generation of field quartals + if self.end.month in [1, 2, 3]: + self.end_quartal = 'Q1' + if self.end.month in [4, 5, 6]: + self.end_quartal = 'Q2' + if self.end.month in [7, 8, 9]: + self.end_quartal = 'Q3' + if self.end.month in [10, 11, 12]: + self.end_quartal = 'Q4' + + # generation of pid and financeID + if not self.project_of_year: - print('AAA') + #print('AAA') # we need to determine if this is a new year with its first new project... year = self.start.year - print(year) + #print(year) projects = Project.objects.filter(start__year=year) if not projects: #print('BBB') self.project_of_year = 1 + self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3) else: #print('CCC') + # 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.finance_id = 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) + + super().save() def __str__(self): @@ -169,7 +192,7 @@ class Travel(Volunteer): intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen') project_end = models.DateField(blank=True, null=True, verbose_name='Projektende') # 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 @@ -177,8 +200,10 @@ 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 - instance.project_end = instance.project.end - + + 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): diff --git a/input/static/css/dateFieldNoNowShortcutInTravels.css b/input/static/css/dateFieldNoNowShortcutInTravels.css new file mode 100644 index 0000000..0c0c7f2 --- /dev/null +++ b/input/static/css/dateFieldNoNowShortcutInTravels.css @@ -0,0 +1,5 @@ + +span.datetimeshortcuts > a:first-child { + visibility: hidden; +} + From 1d9811b0ff67019843e033110c4a5f19a2787800 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 39/69] custom css is now only applied to travel form, not to all forms --- input/forms.py | 6 ++++++ input/templates/input/extern.html | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/input/forms.py b/input/forms.py index f4bf805..262f376 100755 --- a/input/forms.py +++ b/input/forms.py @@ -74,6 +74,12 @@ class TravelForm(FdbForm): 'checkout': AdminDateWidget(),} fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes'] + class Media: + css = { + 'all': ('admin/css/dateFieldNoNowShortcutInTravels.css',) + } + + class LibraryForm(FdbForm): class Meta: diff --git a/input/templates/input/extern.html b/input/templates/input/extern.html index 13dcb6a..d0721bf 100755 --- a/input/templates/input/extern.html +++ b/input/templates/input/extern.html @@ -9,7 +9,7 @@ - + {% load i18n %} {% block content %} From 94f82d57334fe99a02be94cbb87ebbcba3924c84 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 40/69] fixed literature selfbuy variables in admin view --- input/admin.py | 2 -- input/forms.py | 2 +- input/models.py | 2 +- input/views.py | 3 ++- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/input/admin.py b/input/admin.py index 59746a0..82d1bfc 100755 --- a/input/admin.py +++ b/input/admin.py @@ -53,8 +53,6 @@ class LiteratureAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' - class Media: - js = ('dropdown/js/base.js',) @admin.register(Account) diff --git a/input/forms.py b/input/forms.py index 262f376..152cc97 100755 --- a/input/forms.py +++ b/input/forms.py @@ -111,7 +111,7 @@ class CheckForm(FdbForm): class LiteratureForm(CheckForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['selfbuy_give_data'].required = True + self.fields['selfbuy_give_data'].required = False class Meta: model = Literature fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_data', 'selfbuy_give_data'] diff --git a/input/models.py b/input/models.py index 96ce900..4b45457 100755 --- a/input/models.py +++ b/input/models.py @@ -264,7 +264,7 @@ class Literature(Grant): help_text="Bitte gib an, wo du das Werk kaufen möchtest.") selfbuy = models.CharField( max_length=10, verbose_name='Selbstkauf?', choices=SELFBUY_CHOICES.items(), default='TRUE') selfbuy_give_data = models.BooleanField(verbose_name=format_html('Datenweitergabe erlauben'), help_text=format_html('Ich stimme der Weitergabe meiner Daten (Name, Postadresse) an den von mir angegebenen Anbieter/Dienstleister zu.')) - selfbuy_data = models.TextField(max_length=1000, verbose_name='Persönliche Daten sowie Adresse', default='', + selfbuy_data = models.TextField(max_length=1000, verbose_name='Persönliche Daten sowie Adresse', default='',\ help_text=format_html("Bitte gib hier alle persönlichen Daten an, die wir benötigen, um das Werk
\ für dich zu kaufen und es dir anschließend zu schicken (z.B. Vorname Nachname, Anschrift,
\ Telefonnummer, E-Mail-Adresse usw.). Trenne die einzelnen Angaben durch Zeilenumbrüche.")) diff --git a/input/views.py b/input/views.py index 4dbff38..281fd52 100755 --- a/input/views.py +++ b/input/views.py @@ -210,10 +210,11 @@ class ExternView(CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} + if data['choice'] == 'LIT': if data['selfbuy'] == 'TRUE': data['selfbuy_give_data'] = 'False' - + # write data to database modell = form.save(commit=False) # we have to copy the data from the first form here From 5b91d335de1497ba26ec5124947a25dd90de8d92 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 41/69] hotel in forms.py is now radioselect choicefield and required --- input/forms.py | 8 +++++++- input/migrations/0088_auto_20221208_2128.py | 18 ++++++++++++++++++ input/models.py | 6 +++++- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 input/migrations/0088_auto_20221208_2128.py diff --git a/input/forms.py b/input/forms.py index 152cc97..48600af 100755 --- a/input/forms.py +++ b/input/forms.py @@ -54,6 +54,11 @@ class InternForm(FdbForm): exclude = ('granted', 'granted_date', 'survey_mail_send', 'survey_mail_date', 'mail_state') +HOTEL_CHOICES = {'TRUE': format_html('Hotelzimmer benötigt'), + 'FALSE': format_html('Kein Hotelzimmer benötigt') + } + + class TravelForm(FdbForm): # TODO: add some javascript to show/hide other-field @@ -65,7 +70,7 @@ class TravelForm(FdbForm): self.fields['travelcost'].required = True self.fields['checkin'].required = True self.fields['checkout'].required = True - self.fields['hotel'].required = False + self.fields['hotel'].required = True class Meta: model = Travel @@ -73,6 +78,7 @@ class TravelForm(FdbForm): 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()) class Media: css = { diff --git a/input/migrations/0088_auto_20221208_2128.py b/input/migrations/0088_auto_20221208_2128.py new file mode 100644 index 0000000..9291efe --- /dev/null +++ b/input/migrations/0088_auto_20221208_2128.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-08 21:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0087_travel_project_end_quartal'), + ] + + operations = [ + migrations.AlterField( + model_name='travel', + name='hotel', + field=models.CharField(choices=[('TRUE', 'Hotelzimmer benötigt'), ('FALSE', 'Kein Hotelzimmer benötigt')], max_length=10, verbose_name='Hotelzimmer benötigt:'), + ), + ] diff --git a/input/models.py b/input/models.py index 4b45457..d1d00e0 100755 --- a/input/models.py +++ b/input/models.py @@ -173,6 +173,10 @@ TRANSPORT_CHOICES = {'BAHN': 'Bahn', PAYEDBY_CHOICES = {'WMDE': 'WMDE', 'REQU': 'Antragstellender Mensch'} +HOTEL_CHOICES = {'TRUE': format_html('Hotelzimmer benötigt'), + 'FALSE': format_html('Kein Hotelzimmer benötigt') + } + from django.contrib.contenttypes.models import ContentType class Travel(Volunteer): @@ -186,7 +190,7 @@ class Travel(Volunteer): checkout = models.DateTimeField(blank=True, null=True, verbose_name='Abreise') 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:') + hotel = models.CharField(max_length=10, choices=HOTEL_CHOICES.items(), verbose_name='Hotelzimmer benötigt:') notes = models.TextField(max_length=1000, blank=True, verbose_name='Anmerkungen') request_url = models.URLField(max_length=2000, verbose_name='Antrag (URL)') intern_notes = models.TextField(max_length=1000, blank=True, verbose_name='interne Anmerkungen') From 5402733a9ccbb0d65c3ff49291c6079f6e724272 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 42/69] added search bar to foreign key choice field project in model travel --- input/admin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/input/admin.py b/input/admin.py index 82d1bfc..2c406ec 100755 --- a/input/admin.py +++ b/input/admin.py @@ -91,6 +91,7 @@ class TravelAdmin(admin.ModelAdmin): list_display_links = ('realname', 'project') date_hierarchy = 'project_end' readonly_fields = ('project_end_quartal', 'project_end') + autocomplete_fields = ['project'] @admin.register(Email) class EmailAdmin(admin.ModelAdmin): From 08dd961cbe25379837242287e91687a10e680cbb Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 43/69] all service ids are readonly fields now --- input/.models.py.swp | Bin 0 -> 1024 bytes input/admin.py | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 input/.models.py.swp diff --git a/input/.models.py.swp b/input/.models.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..b7ad36d7725791f9570a22e76a5936683e1ae43c GIT binary patch literal 1024 zcmYc?$V<%2S1{4DU_b#H0SpXjDM=_|xHxI~sYNM3lvt9Qmz0>7os*cGl#+<4IyXNh WHK$mwpb}GRRAe*+Mnhl#LI407F%c*L literal 0 HcmV?d00001 diff --git a/input/admin.py b/input/admin.py index 2c406ec..08df4ec 100755 --- a/input/admin.py +++ b/input/admin.py @@ -43,6 +43,7 @@ class BusinessCardAdmin(admin.ModelAdmin): list_display_links = ('realname', 'service_id') # action = ['export_as_csv'] date_hierarchy = 'granted_date' + readonly_fields = ['service_id'] class Media: js = ('dropdown/js/base.js',) @@ -53,6 +54,7 @@ class LiteratureAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + readonly_fields = ['service_id'] @admin.register(Account) @@ -74,6 +76,7 @@ class LibraryAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + readonly_fields = ['service_id'] @admin.register(IFG) class IFGAdmin(admin.ModelAdmin): @@ -82,6 +85,7 @@ class IFGAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + readonly_fields = ['service_id'] @admin.register(Travel) class TravelAdmin(admin.ModelAdmin): @@ -101,6 +105,7 @@ class EmailAdmin(admin.ModelAdmin): list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' radio_fields = {'adult': admin.VERTICAL} + readonly_fields = ['service_id'] class Media: js = ('dropdown/js/base.js',) @@ -112,6 +117,7 @@ class ListAdmin(admin.ModelAdmin): list_display = ('realname', 'service_id', 'granted', 'granted_date') list_display_links = ('realname', 'service_id') date_hierarchy = 'granted_date' + readonly_fields = ['service_id'] # commented out because of the individual registering to control displays in admin panel From 6d3888172fe7112dabb4093a0007c6ba6b446e99 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 44/69] model travel is now based on extern instead of intern, service id is displayed and a readonly field --- input/.models.py.swp | Bin 1024 -> 0 bytes input/admin.py | 5 +++-- input/migrations/0089_auto_20221209_1648.py | 23 ++++++++++++++++++++ input/models.py | 2 +- 4 files changed, 27 insertions(+), 3 deletions(-) delete mode 100644 input/.models.py.swp create mode 100644 input/migrations/0089_auto_20221209_1648.py diff --git a/input/.models.py.swp b/input/.models.py.swp deleted file mode 100644 index b7ad36d7725791f9570a22e76a5936683e1ae43c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYc?$V<%2S1{4DU_b#H0SpXjDM=_|xHxI~sYNM3lvt9Qmz0>7os*cGl#+<4IyXNh WHK$mwpb}GRRAe*+Mnhl#LI407F%c*L diff --git a/input/admin.py b/input/admin.py index 08df4ec..5537d38 100755 --- a/input/admin.py +++ b/input/admin.py @@ -90,12 +90,13 @@ class IFGAdmin(admin.ModelAdmin): @admin.register(Travel) class TravelAdmin(admin.ModelAdmin): save_as = True - search_fields = ['realname', 'granted_date'] - list_display = ('realname', 'granted', 'granted_date', 'project_end', 'project', 'project_end_quartal') + search_fields = ['realname', 'service_id', 'granted_date'] + list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project_end', 'project', 'project_end_quartal') list_display_links = ('realname', 'project') date_hierarchy = 'project_end' readonly_fields = ('project_end_quartal', 'project_end') autocomplete_fields = ['project'] + readonly_fields = ['service_id'] @admin.register(Email) class EmailAdmin(admin.ModelAdmin): diff --git a/input/migrations/0089_auto_20221209_1648.py b/input/migrations/0089_auto_20221209_1648.py new file mode 100644 index 0000000..55f394d --- /dev/null +++ b/input/migrations/0089_auto_20221209_1648.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.2 on 2022-12-09 16:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0088_auto_20221208_2128'), + ] + + operations = [ + migrations.AddField( + model_name='travel', + name='service_id', + field=models.CharField(blank=True, max_length=15, null=True), + ), + migrations.AddField( + model_name='travel', + name='username', + field=models.CharField(help_text='Bitte gib den Namen ein, mit dem du dich
in den Wikimedia-Projekten registriert hast.', max_length=200, null=True, verbose_name='Benutzer_innenname'), + ), + ] diff --git a/input/models.py b/input/models.py index d1d00e0..d57d599 100755 --- a/input/models.py +++ b/input/models.py @@ -179,7 +179,7 @@ HOTEL_CHOICES = {'TRUE': format_html('Hotelzimmer benötigt'), from django.contrib.contenttypes.models import ContentType -class Travel(Volunteer): +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 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:') From 914989d6ac65826532fa2c9bdccae31412c104df Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 45/69] literature self_buy_giveData variable is now required in extern view --- input/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input/forms.py b/input/forms.py index 48600af..3951955 100755 --- a/input/forms.py +++ b/input/forms.py @@ -117,7 +117,7 @@ class CheckForm(FdbForm): class LiteratureForm(CheckForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['selfbuy_give_data'].required = False + self.fields['selfbuy_give_data'].required = True class Meta: model = Literature fields = ['cost', 'info', 'source', 'notes', 'selfbuy', 'selfbuy_data', 'selfbuy_give_data'] From 29cdd7b6536834ccd92deb45010492f642ab76f8 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 46/69] now the | in datefield is also hidden via css --- input/forms.py | 2 +- input/static/css/dateFieldNoNowShortcutInTravels.css | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/input/forms.py b/input/forms.py index 3951955..79fa58c 100755 --- a/input/forms.py +++ b/input/forms.py @@ -82,7 +82,7 @@ class TravelForm(FdbForm): class Media: css = { - 'all': ('admin/css/dateFieldNoNowShortcutInTravels.css',) + 'all': ('css/dateFieldNoNowShortcutInTravels.css',) } diff --git a/input/static/css/dateFieldNoNowShortcutInTravels.css b/input/static/css/dateFieldNoNowShortcutInTravels.css index 0c0c7f2..08c9cd0 100644 --- a/input/static/css/dateFieldNoNowShortcutInTravels.css +++ b/input/static/css/dateFieldNoNowShortcutInTravels.css @@ -1,5 +1,14 @@ +/* span.datetimeshortcuts > a:first-child { visibility: hidden; } +*/ +span.datetimeshortcuts { + visibility: hidden; +} + +span.datetimeshortcuts > a:nth-child(2) { + visibility: visible; +} From 9200459028f9c577461df17815e20cc410e23272 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 47/69] admin model travel has now datefields instead of datetimefields for checkin and checkout --- input/migrations/0090_auto_20221209_1720.py | 23 +++++++++++++++++++++ input/models.py | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 input/migrations/0090_auto_20221209_1720.py diff --git a/input/migrations/0090_auto_20221209_1720.py b/input/migrations/0090_auto_20221209_1720.py new file mode 100644 index 0000000..440811b --- /dev/null +++ b/input/migrations/0090_auto_20221209_1720.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.2 on 2022-12-09 17:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0089_auto_20221209_1648'), + ] + + operations = [ + migrations.AlterField( + model_name='travel', + name='checkin', + field=models.DateField(blank=True, null=True, verbose_name='Anreise'), + ), + migrations.AlterField( + model_name='travel', + name='checkout', + field=models.DateField(blank=True, null=True, verbose_name='Abreise'), + ), + ] diff --git a/input/models.py b/input/models.py index d57d599..fa336a4 100755 --- a/input/models.py +++ b/input/models.py @@ -186,8 +186,8 @@ class Travel(Extern): 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.DateTimeField(blank=True, null=True, verbose_name='Anreise') - checkout = models.DateTimeField(blank=True, null=True, verbose_name='Abreise') + checkin = models.DateField(blank=True, null=True, verbose_name='Anreise') + checkout = models.DateField(blank=True, null=True, verbose_name='Abreise') 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.CharField(max_length=10, choices=HOTEL_CHOICES.items(), verbose_name='Hotelzimmer benötigt:') From b8cdaa1bf7bc5e79fb33a274984deb2062a6a3d3 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 48/69] send end mails var in admin.model.project changed to boolean check field, also true is false now, so changed logic in sendmails.py --- input/management/commands/sendmails.py | 8 ++++---- input/migrations/0091_auto_20221209_1752.py | 18 ++++++++++++++++++ input/migrations/0092_auto_20221209_1754.py | 18 ++++++++++++++++++ input/models.py | 4 ++-- 4 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 input/migrations/0091_auto_20221209_1752.py create mode 100644 input/migrations/0092_auto_20221209_1754.py diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 43abad3..4e1ad64 100755 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -68,7 +68,7 @@ class Command(BaseCommand): # get all projects which ended old = Project.objects.filter(end__lt = date.today())\ - .exclude(end_mail_send = True)\ + .exclude(end_mail_send = False)\ .filter(mail_state = 'NONE') txt_mail_template = get_template('input/if_end_of_project.txt') @@ -92,7 +92,7 @@ class Command(BaseCommand): # IF_EMAIL, # [IF_EMAIL], # fail_silently=False) - project.end_mail_send = True + project.end_mail_send = False project.mail_state = 'INF' try: project.save() @@ -108,7 +108,7 @@ class Command(BaseCommand): # get all projects where end was reached already, and send mails for the ones already set to status "ended" by the admins approved_end = Project.objects.filter(status = 'END')\ - .exclude(end_mail_send = False)\ + .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') @@ -165,7 +165,7 @@ class Command(BaseCommand): # get all projects where end was reached already, and send mails for the ones where status was put to NOT by admins approved_notHappened = Project.objects.filter(status = 'NOT')\ - .exclude(end_mail_send = False)\ + .exclude(end_mail_send = True)\ .filter(mail_state = 'INF') html_mail_template = get_template('input/if_not_of_project_approved.html') diff --git a/input/migrations/0091_auto_20221209_1752.py b/input/migrations/0091_auto_20221209_1752.py new file mode 100644 index 0000000..63905de --- /dev/null +++ b/input/migrations/0091_auto_20221209_1752.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-09 17:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0090_auto_20221209_1720'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='end_mail_send', + field=models.BooleanField(null=True, verbose_name='Keine Projektabschlussmail schicken'), + ), + ] diff --git a/input/migrations/0092_auto_20221209_1754.py b/input/migrations/0092_auto_20221209_1754.py new file mode 100644 index 0000000..ac5a873 --- /dev/null +++ b/input/migrations/0092_auto_20221209_1754.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.2 on 2022-12-09 17:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0091_auto_20221209_1752'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='end_mail_send', + field=models.BooleanField(default=False, verbose_name='Keine Projektabschlussmail schicken'), + ), + ] diff --git a/input/models.py b/input/models.py index fa336a4..cce427a 100755 --- a/input/models.py +++ b/input/models.py @@ -19,9 +19,9 @@ class Volunteer(models.Model): # the following Fields are not supposed to be edited by users granted = models.BooleanField(null=True, verbose_name='bewilligt') granted_date = models.DateField(null=True, verbose_name='bewilligt am') - survey_mail_send = models.BooleanField(default=False, verbose_name='Keine Umfragemail schicken') survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True) 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 @@ -66,6 +66,7 @@ class Account(models.Model): 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') description = models.CharField(max_length=500, verbose_name="Kurzbeschreibung", null=True) start = models.DateField('Startdatum', null=True) @@ -87,7 +88,6 @@ class Project(Volunteer): 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") - end_mail_send = models.BooleanField(null=True, verbose_name='Endmail versenden') # the following Fields are not supposed to be edited by users pid = models.CharField(max_length=15, null=True, blank=True) From 0b7b161383297b20ec25f30da1ce9a28b4efe5ce Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 49/69] deleted variable persons in admin model project --- input/migrations/0093_remove_project_persons.py | 17 +++++++++++++++++ input/models.py | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 input/migrations/0093_remove_project_persons.py diff --git a/input/migrations/0093_remove_project_persons.py b/input/migrations/0093_remove_project_persons.py new file mode 100644 index 0000000..b467960 --- /dev/null +++ b/input/migrations/0093_remove_project_persons.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.2 on 2022-12-09 18:28 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0092_auto_20221209_1754'), + ] + + operations = [ + migrations.RemoveField( + model_name='project', + name='persons', + ), + ] diff --git a/input/models.py b/input/models.py index cce427a..2e70b41 100755 --- a/input/models.py +++ b/input/models.py @@ -92,7 +92,6 @@ class Project(Volunteer): # 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') - persons = models.IntegerField(default=1) finance_id = models.CharField(max_length=15, null= True, blank=True) project_of_year = models.IntegerField(default=0) end_quartal = models.CharField(max_length=15, null=True, blank=True, verbose_name="Quartal Projekt Ende") From c29b410ec575ddf343fa91698b5f62d1d9c60bb5 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 50/69] changed order of fields in admin panel of model project --- input/.models.py.swp | Bin 0 -> 1024 bytes input/admin.py | 1 + 2 files changed, 1 insertion(+) create mode 100644 input/.models.py.swp diff --git a/input/.models.py.swp b/input/.models.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..19391f2caab1944a1ce039476b6c9045810e9889 GIT binary patch literal 1024 zcmYc?$V<%2S1{4DU_b%$0~r|7Qj$=_aB Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 51/69] honorary certificate model now has autocomplete field foreign key project too --- input/.models.py.swp | Bin 1024 -> 0 bytes input/admin.py | 1 + 2 files changed, 1 insertion(+) delete mode 100644 input/.models.py.swp diff --git a/input/.models.py.swp b/input/.models.py.swp deleted file mode 100644 index 19391f2caab1944a1ce039476b6c9045810e9889..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYc?$V<%2S1{4DU_b%$0~r|7Qj$=_aB Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 52/69] search fields for travel and honorary are using foreign keys now, with the notation of double underscores --- input/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input/admin.py b/input/admin.py index 01902fd..209e578 100755 --- a/input/admin.py +++ b/input/admin.py @@ -66,7 +66,7 @@ class AccountAdmin(admin.ModelAdmin): @admin.register(HonoraryCertificate) class HonoraryCertificateAdmin(admin.ModelAdmin): save_as = True - search_fields = ['realname', 'granted'] + search_fields = ['realname', 'granted', 'project__name', 'project__pid'] list_display = ('realname', 'granted','project') date_hierarchy = 'granted_date' autocomplete_fields = ['project'] @@ -92,7 +92,7 @@ class IFGAdmin(admin.ModelAdmin): @admin.register(Travel) class TravelAdmin(admin.ModelAdmin): save_as = True - search_fields = ['realname', 'service_id', 'granted_date'] + search_fields = ['realname', 'service_id', 'granted_date', 'project__name', 'project__pid'] list_display = ('realname', 'service_id', 'granted', 'granted_date', 'project_end', 'project', 'project_end_quartal') list_display_links = ('realname', 'project') date_hierarchy = 'project_end' From ebdc3be9030a136e4bbc951f930501dbc60eda93 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 53/69] changed mail_state, implemented live, changed mail sender --- input/logfile | 52 ++++++++-------- input/migrations/0094_auto_20221212_1146.py | 68 +++++++++++++++++++++ input/migrations/0095_auto_20221214_1207.py | 68 +++++++++++++++++++++ input/views.py | 34 +++++------ 4 files changed, 179 insertions(+), 43 deletions(-) create mode 100644 input/migrations/0094_auto_20221212_1146.py create mode 100644 input/migrations/0095_auto_20221214_1207.py diff --git a/input/logfile b/input/logfile index 861f27e..9fc7c01 100644 --- a/input/logfile +++ b/input/logfile @@ -1,5 +1,5 @@ nohup: ignoring input -[2022-12-05 10:02:21 +0000] [12084] [DEBUG] Current configuration: +[2022-12-14 11:22:16 +0000] [29484] [DEBUG] Current configuration: config: None bind: ['0:8000'] backlog: 2048 @@ -56,21 +56,21 @@ nohup: ignoring input default_proc_name: foerderbarometer.wsgi pythonpath: None paste: None - on_starting: - on_reload: - when_ready: - pre_fork: - post_fork: - post_worker_init: - worker_int: - worker_abort: - pre_exec: - pre_request: - post_request: - child_exit: - worker_exit: - nworkers_changed: - on_exit: + on_starting: + on_reload: + when_ready: + pre_fork: + post_fork: + post_worker_init: + worker_int: + worker_abort: + pre_exec: + pre_request: + post_request: + child_exit: + worker_exit: + nworkers_changed: + on_exit: proxy_protocol: False proxy_allow_ips: ['127.0.0.1'] keyfile: None @@ -83,13 +83,13 @@ nohup: ignoring input ciphers: None raw_paste_global_conf: [] strip_header_spaces: False -[2022-12-05 10:02:21 +0000] [12084] [INFO] Starting gunicorn 20.0.4 -[2022-12-05 10:02:21 +0000] [12084] [DEBUG] Arbiter booted -[2022-12-05 10:02:21 +0000] [12084] [INFO] Listening at: http://0.0.0.0:8000 (12084) -[2022-12-05 10:02:21 +0000] [12084] [INFO] Using worker: sync -[2022-12-05 10:02:21 +0000] [12086] [INFO] Booting worker with pid: 12086 -[2022-12-05 10:02:21 +0000] [12084] [DEBUG] 1 workers -[2022-12-05 10:02:21 +0000] [12086] [ERROR] Exception in worker process +[2022-12-14 11:22:16 +0000] [29484] [INFO] Starting gunicorn 20.0.4 +[2022-12-14 11:22:16 +0000] [29484] [DEBUG] Arbiter booted +[2022-12-14 11:22:16 +0000] [29484] [INFO] Listening at: http://0.0.0.0:8000 (29484) +[2022-12-14 11:22:16 +0000] [29484] [INFO] Using worker: sync +[2022-12-14 11:22:16 +0000] [29486] [INFO] Booting worker with pid: 29486 +[2022-12-14 11:22:16 +0000] [29484] [DEBUG] 1 workers +[2022-12-14 11:22:16 +0000] [29486] [ERROR] Exception in worker process Traceback (most recent call last): File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() @@ -115,6 +115,6 @@ Traceback (most recent call last): File "", line 991, in _find_and_load File "", line 973, in _find_and_load_unlocked ModuleNotFoundError: No module named 'foerderbarometer' -[2022-12-05 10:02:21 +0000] [12086] [INFO] Worker exiting (pid: 12086) -[2022-12-05 10:02:21 +0000] [12084] [INFO] Shutting down: Master -[2022-12-05 10:02:21 +0000] [12084] [INFO] Reason: Worker failed to boot. +[2022-12-14 11:22:16 +0000] [29486] [INFO] Worker exiting (pid: 29486) +[2022-12-14 11:22:16 +0000] [29484] [INFO] Shutting down: Master +[2022-12-14 11:22:16 +0000] [29484] [INFO] Reason: Worker failed to boot. diff --git a/input/migrations/0094_auto_20221212_1146.py b/input/migrations/0094_auto_20221212_1146.py new file mode 100644 index 0000000..f4b804f --- /dev/null +++ b/input/migrations/0094_auto_20221212_1146.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2022-12-12 11:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0093_remove_project_persons'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='concreteextern', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='email', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='ifg', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='library', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='list', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='literature', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='project', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + migrations.AlterField( + model_name='travel', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='END', max_length=6), + ), + ] diff --git a/input/migrations/0095_auto_20221214_1207.py b/input/migrations/0095_auto_20221214_1207.py new file mode 100644 index 0000000..57a9331 --- /dev/null +++ b/input/migrations/0095_auto_20221214_1207.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2022-12-14 12:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0094_auto_20221212_1146'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concreteextern', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='email', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='ifg', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='library', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='list', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='literature', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='project', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='travel', + name='mail_state', + field=models.CharField(choices=[('NONE', 'noch keine Mail versendet'), ('INF', 'die Benachrichtigung End-Mail wurde bereits versendet'), ('END', 'alle automatischen Mails, auch surveyMail, wurden bereits versendet')], default='NONE', max_length=6), + ), + ] diff --git a/input/views.py b/input/views.py index 281fd52..203de7a 100755 --- a/input/views.py +++ b/input/views.py @@ -244,19 +244,19 @@ class ExternView(CookieWizardView): try: # - mail with entered data to the Volunteer - txt_mail_template = get_template('input/ifg_volunteer_mail.txt') - html_mail_template = get_template('input/ifg_volunteer_mail.html') + txt_mail_template1 = get_template('input/ifg_volunteer_mail.txt') + html_mail_template1 = get_template('input/ifg_volunteer_mail.html') - subject, from_email, to = 'Formular ausgefüllt', IF_EMAIL, data['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('ifg volunteer mail would have been sent') + subject1, from_email1, to1 = 'Formular ausgefüllt', IF_EMAIL, data['email'] + text_content1 = txt_mail_template1.render(context) + html_content1 = html_mail_template1.render(context) + msg1 = EmailMultiAlternatives(subject1, text_content1, from_email1, [to1]) + msg1.attach_alternative(html_content1, "text/html") + msg1.send() + #print('ifg volunteer mail would have been sent') #send_mail( # 'Formular ausgefüllt', - # mail_template.render(context), + # txt_mail_template1.render(context), # IF_EMAIL, # [data['email']], # fail_silently=False) @@ -268,24 +268,24 @@ class ExternView(CookieWizardView): subject, from_email, to = 'Formular ausgefüllt', IF_EMAIL, 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() - print('if mail would have been sent') + msg2 = EmailMultiAlternatives(subject, text_content, from_email, [to]) + msg2.attach_alternative(html_content, "text/html") + msg2.send() + #print('if mail would have been sent') #send_mail( # 'Formular ausgefüllt', - # mail_template.render(context), + # txt_mail_template.render(context), # IF_EMAIL, # [IF_EMAIL], # fail_silently=False) ## raise SMTPException("testing pupose only") - + except BadHeaderError: modell.delete() return HttpResponse('Invalid header found. Data not saved!') except SMTPException: modell.delete() - return HttpResponse('Error in sending mails (propably wrong adress?). Data not saved!') + return HttpResponse('Error in sending mails (probably wrong adress?). Data not saved!') return done(self.request) From 5c35948859adaedc1baf24a3c2fb6abafb10200a Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 54/69] trying with different username --- input/logfile | 120 -------------------------------------------------- 1 file changed, 120 deletions(-) delete mode 100644 input/logfile diff --git a/input/logfile b/input/logfile deleted file mode 100644 index 9fc7c01..0000000 --- a/input/logfile +++ /dev/null @@ -1,120 +0,0 @@ -nohup: ignoring input -[2022-12-14 11:22:16 +0000] [29484] [DEBUG] Current configuration: - config: None - bind: ['0:8000'] - backlog: 2048 - workers: 1 - worker_class: sync - threads: 1 - worker_connections: 1000 - max_requests: 0 - max_requests_jitter: 0 - timeout: 30 - graceful_timeout: 30 - keepalive: 2 - limit_request_line: 4094 - limit_request_fields: 100 - limit_request_field_size: 8190 - reload: False - reload_engine: auto - reload_extra_files: [] - spew: False - check_config: False - preload_app: False - sendfile: None - reuse_port: False - chdir: /home/fdb/foerderbaro/foerderbarometer/input - daemon: False - raw_env: [] - pidfile: None - worker_tmp_dir: None - user: 1001 - group: 1001 - umask: 0 - initgroups: False - tmp_upload_dir: None - secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'} - forwarded_allow_ips: ['*'] - accesslog: None - disable_redirect_access_to_syslog: False - access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" - errorlog: - - loglevel: debug - capture_output: False - logger_class: gunicorn.glogging.Logger - logconfig: None - logconfig_dict: {} - syslog_addr: udp://localhost:514 - syslog: False - syslog_prefix: None - syslog_facility: user - enable_stdio_inheritance: False - statsd_host: None - dogstatsd_tags: - statsd_prefix: - proc_name: None - default_proc_name: foerderbarometer.wsgi - pythonpath: None - paste: None - on_starting: - on_reload: - when_ready: - pre_fork: - post_fork: - post_worker_init: - worker_int: - worker_abort: - pre_exec: - pre_request: - post_request: - child_exit: - worker_exit: - nworkers_changed: - on_exit: - proxy_protocol: False - proxy_allow_ips: ['127.0.0.1'] - keyfile: None - certfile: None - ssl_version: 2 - cert_reqs: 0 - ca_certs: None - suppress_ragged_eofs: True - do_handshake_on_connect: False - ciphers: None - raw_paste_global_conf: [] - strip_header_spaces: False -[2022-12-14 11:22:16 +0000] [29484] [INFO] Starting gunicorn 20.0.4 -[2022-12-14 11:22:16 +0000] [29484] [DEBUG] Arbiter booted -[2022-12-14 11:22:16 +0000] [29484] [INFO] Listening at: http://0.0.0.0:8000 (29484) -[2022-12-14 11:22:16 +0000] [29484] [INFO] Using worker: sync -[2022-12-14 11:22:16 +0000] [29486] [INFO] Booting worker with pid: 29486 -[2022-12-14 11:22:16 +0000] [29484] [DEBUG] 1 workers -[2022-12-14 11:22:16 +0000] [29486] [ERROR] Exception in worker process -Traceback (most recent call last): - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker - worker.init_process() - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 119, in init_process - self.load_wsgi() - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi - self.wsgi = self.app.wsgi() - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi - self.callable = self.load() - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 49, in load - return self.load_wsgiapp() - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp - return util.import_app(self.app_uri) - File "/home/fdb/foerderbaro/foerderbarometer/venv/lib/python3.8/site-packages/gunicorn/util.py", line 358, in import_app - mod = importlib.import_module(module) - File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module - return _bootstrap._gcd_import(name[level:], package, level) - File "", line 1014, in _gcd_import - File "", line 991, in _find_and_load - File "", line 961, in _find_and_load_unlocked - File "", line 219, in _call_with_frames_removed - File "", line 1014, in _gcd_import - File "", line 991, in _find_and_load - File "", line 973, in _find_and_load_unlocked -ModuleNotFoundError: No module named 'foerderbarometer' -[2022-12-14 11:22:16 +0000] [29486] [INFO] Worker exiting (pid: 29486) -[2022-12-14 11:22:16 +0000] [29484] [INFO] Shutting down: Master -[2022-12-14 11:22:16 +0000] [29484] [INFO] Reason: Worker failed to boot. From 440df28b0efa452df0d4d64349ff8409cf9826b5 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 55/69] last version, talked to admin today --- input/management/commands/sendmails.py | 14 +++-- input/migrations/0096_auto_20230106_1338.py | 68 +++++++++++++++++++++ input/models.py | 5 +- 3 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 input/migrations/0096_auto_20230106_1338.py diff --git a/input/management/commands/sendmails.py b/input/management/commands/sendmails.py index 4e1ad64..f22fa8f 100755 --- a/input/management/commands/sendmails.py +++ b/input/management/commands/sendmails.py @@ -68,12 +68,13 @@ class Command(BaseCommand): # get all projects which ended old = Project.objects.filter(end__lt = date.today())\ - .exclude(end_mail_send = False)\ + .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') + for project in old: context = {'project': project} context['URLPREFIX'] = settings.URLPREFIX @@ -92,7 +93,7 @@ class Command(BaseCommand): # IF_EMAIL, # [IF_EMAIL], # fail_silently=False) - project.end_mail_send = False + project.end_mail_send = True project.mail_state = 'INF' try: project.save() @@ -149,8 +150,8 @@ class Command(BaseCommand): # IF_EMAIL, # [IF_EMAIL], # fail_silently=False) - - project.mail_state = 'END' + project.end_mail_send = True + project.mail_state = 'CLOSE' try: project.save() except: @@ -207,8 +208,8 @@ class Command(BaseCommand): # IF_EMAIL, # [IF_EMAIL], # fail_silently=False) - - project.mail_state = 'END' + project.end_mail_send = True + project.mail_state = 'CLOSE' project.save() except BadHeaderError: self.stdout.write(self.style.ERROR('Invalid header found.')) @@ -231,6 +232,7 @@ class Command(BaseCommand): name=myname, realname=item.realname) item.survey_mail_send = True + item.mail_state = 'END' item.survey_mail_date = date.today() item.save() self.stdout.write(self.style.SUCCESS(f'surveymails for object type {type} sent')) diff --git a/input/migrations/0096_auto_20230106_1338.py b/input/migrations/0096_auto_20230106_1338.py new file mode 100644 index 0000000..ecca5e3 --- /dev/null +++ b/input/migrations/0096_auto_20230106_1338.py @@ -0,0 +1,68 @@ +# Generated by Django 3.1.2 on 2023-01-06 13:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('input', '0095_auto_20221214_1207'), + ] + + operations = [ + migrations.AlterField( + model_name='businesscard', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concreteextern', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='concretevolunteer', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='email', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='honorarycertificate', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='ifg', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='library', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='list', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='literature', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='project', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + migrations.AlterField( + model_name='travel', + name='mail_state', + field=models.CharField(choices=[('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')], default='NONE', max_length=6), + ), + ] diff --git a/input/models.py b/input/models.py index 2e70b41..6e0e58a 100755 --- a/input/models.py +++ b/input/models.py @@ -7,8 +7,9 @@ from .settings import ACCOUNTS EMAIL_STATES = {'NONE': 'noch keine Mail versendet', - 'INF': 'die Benachrichtigung End-Mail wurde bereits versendet', - 'END': 'alle automatischen Mails, auch surveyMail, wurden bereits versendet'} + 'INF': 'die Benachrichtigung zur Projektabschlussmail wurde versendet', + 'CLOSE': 'die Projektabschlussmail wurde versendet', + 'END': 'alle automatischen Mails, auch surveyMail, wurden versendet'} class Volunteer(models.Model): realname = models.CharField(max_length=200, null=True, verbose_name="Realname", From fc0414a286fe101be7e2e0551c676878d99c245e Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 56/69] bugfixFDB completed --- .gitignore | 1 + input/logfile | 34 ++++++++++++++++++++++++++++++ input/settings.py | 8 +++---- input/templates/input/if_mail.html | 23 ++++++++++++++++++++ input/templates/input/if_mail.txt | 22 +++++++++++++++++++ input/views.py | 8 ++++++- 6 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 input/logfile diff --git a/.gitignore b/.gitignore index 1139068..f041b72 100755 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /staticfiles # /foerderbarometer/settings.py /foerderbarometer/*settings* +/foerderbarometer/input/settings.py /nohup.out /logfile *~ diff --git a/input/logfile b/input/logfile new file mode 100644 index 0000000..5f53927 --- /dev/null +++ b/input/logfile @@ -0,0 +1,34 @@ +nohup: ignoring input +[2023-02-07 12:36:29 +0000] [2449] [INFO] Starting gunicorn 20.1.0 +[2023-02-07 12:36:29 +0000] [2449] [INFO] Listening at: http://0.0.0.0:8000 (2449) +[2023-02-07 12:36:29 +0000] [2449] [INFO] Using worker: sync +[2023-02-07 12:36:29 +0000] [2450] [INFO] Booting worker with pid: 2450 +[2023-02-07 12:36:29 +0000] [2450] [ERROR] Exception in worker process +Traceback (most recent call last): + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker + worker.init_process() + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/workers/base.py", line 134, in init_process + self.load_wsgi() + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi + self.wsgi = self.app.wsgi() + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/base.py", line 67, in wsgi + self.callable = self.load() + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/wsgiapp.py", line 58, in load + return self.load_wsgiapp() + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp + return util.import_app(self.app_uri) + File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/util.py", line 359, in import_app + mod = importlib.import_module(module) + File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + File "", line 1050, in _gcd_import + File "", line 1027, in _find_and_load + File "", line 992, in _find_and_load_unlocked + File "", line 241, in _call_with_frames_removed + File "", line 1050, in _gcd_import + File "", line 1027, in _find_and_load + File "", line 1004, in _find_and_load_unlocked +ModuleNotFoundError: No module named 'foerderbarometer' +[2023-02-07 12:36:29 +0000] [2450] [INFO] Worker exiting (pid: 2450) +[2023-02-07 12:36:29 +0000] [2449] [INFO] Shutting down: Master +[2023-02-07 12:36:29 +0000] [2449] [INFO] Reason: Worker failed to boot. diff --git a/input/settings.py b/input/settings.py index 3b43e9a..e1ba53e 100755 --- a/input/settings.py +++ b/input/settings.py @@ -1,9 +1,9 @@ # mail for IF-OTRS -IF_EMAIL = 'community@wikimedia.de' -#IF_EMAIL = 'test-luca-ext@wikimedia.de' +#IF_EMAIL = 'community@wikimedia.de' +IF_EMAIL = 'test-luca-ext@wikimedia.de' #SURVEY_EMAIL = 'christof.pins@wikimedia.de' -#SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' -SURVEY_EMAIL = 'sandro.halank@wikimedia.de' +SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' +#SURVEY_EMAIL = 'sandro.halank@wikimedia.de' # prefix for urls SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?' diff --git a/input/templates/input/if_mail.html b/input/templates/input/if_mail.html index d130016..efd2941 100755 --- a/input/templates/input/if_mail.html +++ b/input/templates/input/if_mail.html @@ -25,6 +25,29 @@ Persönliche Daten: {{data.data}}
Variante: {{data.variant}}
Sendungsadrese: {{data.send_to}}
{% endif %}

+ +Zum Eintrag in der Förderdatenbank: +{% if data.choice == 'BIB' %} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'ELIT'%} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'LIT'%} +{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change +{% elif data.choice == 'MAIL'%} +{{data.urlprefix}}/admin/input/email/{{data.pk}}/change +{% elif data.choice == 'IFG'%} +{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change +{% elif data.choice == 'LIST'%} +{{data.urlprefix}}/admin/input/list/{{data.pk}}/change +{% elif data.choice == 'TRAV'%} +{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change +{% elif data.choice == 'SOFT'%} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'VIS'%} +{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change +{% endif %} +

+ Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %}

Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %} diff --git a/input/templates/input/if_mail.txt b/input/templates/input/if_mail.txt index d3cfd04..4cb0375 100755 --- a/input/templates/input/if_mail.txt +++ b/input/templates/input/if_mail.txt @@ -23,6 +23,28 @@ Persönliche Daten: {{data.data}} Variante: {{data.variant}} Sendungsadrese: {{data.send_to}} {% endif %} +Zum Eintrag in der Förderdatenbank: +{% if data.choice == 'BIB' %} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'ELIT'%} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'LIT'%} +{{data.urlprefix}}/admin/input/literature/{{data.pk}}/change +{% elif data.choice == 'MAIL'%} +{{data.urlprefix}}/admin/input/email/{{data.pk}}/change +{% elif data.choice == 'IFG'%} +{{data.urlprefix}}/admin/input/ifg/{{data.pk}}/change +{% elif data.choice == 'LIST'%} +{{data.urlprefix}}/admin/input/list/{{data.pk}}/change +{% elif data.choice == 'TRAV'%} +{{data.urlprefix}}/admin/input/travel/{{data.pk}}/change +{% elif data.choice == 'SOFT'%} +{{data.urlprefix}}/admin/input/library/{{data.pk}}/change +{% elif data.choice == 'VIS'%} +{{data.urlprefix}}/admin/input/businesscard/{{data.pk}}/change +{% endif %} + + Zum Genehmigen hier klicken: {{data.urlprefix}}{% url 'authorize' data.choice data.pk %} Zu Ablehnen hier klicken: {{data.urlprefix}}{% url 'deny' data.choice data.pk %} diff --git a/input/views.py b/input/views.py index 203de7a..8a3df6f 100755 --- a/input/views.py +++ b/input/views.py @@ -17,7 +17,7 @@ from django.utils.translation import gettext as _ from .forms import ProjectForm, ExternForm, LibraryForm, IFGForm, LiteratureForm,\ HonoraryCertificateForm, InternForm, TravelForm, EmailForm,\ ListForm, BusinessCardForm, INTERN_CHOICES -from .models import Project, TYPE_CHOICES, Library, Literature, Travel +from .models import Project, TYPE_CHOICES, Library, Literature, Travel, IFG, BusinessCard, Email, List from .settings import IF_EMAIL def auth_deny(choice,pk,auth): @@ -29,6 +29,12 @@ def auth_deny(choice,pk,auth): IFG.set_granted(pk,auth) elif choice == 'TRAV': Travel.set_granted(pk,auth) + elif choice == 'VIS': + BusinessCard.set_granted(pk,auth) + elif choice == 'MAIL': + Email.set_granted(pk,auth) + elif choice == 'LIST': + List.set_granted(pk,auth) else: return HttpResponse(f'ERROR! UNKNOWN CHOICE TYPE! {choice}') return False From 9537aaf667327320d6932e732ce3e876367ee39a Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Mon, 27 Feb 2023 17:09:29 +0000 Subject: [PATCH 57/69] removed wrongly generated logfile within input folder --- input/logfile | 34 ---------------------------------- input/settings.py | 8 ++++---- 2 files changed, 4 insertions(+), 38 deletions(-) delete mode 100644 input/logfile diff --git a/input/logfile b/input/logfile deleted file mode 100644 index 5f53927..0000000 --- a/input/logfile +++ /dev/null @@ -1,34 +0,0 @@ -nohup: ignoring input -[2023-02-07 12:36:29 +0000] [2449] [INFO] Starting gunicorn 20.1.0 -[2023-02-07 12:36:29 +0000] [2449] [INFO] Listening at: http://0.0.0.0:8000 (2449) -[2023-02-07 12:36:29 +0000] [2449] [INFO] Using worker: sync -[2023-02-07 12:36:29 +0000] [2450] [INFO] Booting worker with pid: 2450 -[2023-02-07 12:36:29 +0000] [2450] [ERROR] Exception in worker process -Traceback (most recent call last): - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/arbiter.py", line 589, in spawn_worker - worker.init_process() - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/workers/base.py", line 134, in init_process - self.load_wsgi() - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi - self.wsgi = self.app.wsgi() - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/base.py", line 67, in wsgi - self.callable = self.load() - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/wsgiapp.py", line 58, in load - return self.load_wsgiapp() - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp - return util.import_app(self.app_uri) - File "/home/alpcentaur/ProjektA/wikimedia/wmdeit_foerderbarometer/foerderbarometer/venv/lib/python3.10/site-packages/gunicorn/util.py", line 359, in import_app - mod = importlib.import_module(module) - File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module - return _bootstrap._gcd_import(name[level:], package, level) - File "", line 1050, in _gcd_import - File "", line 1027, in _find_and_load - File "", line 992, in _find_and_load_unlocked - File "", line 241, in _call_with_frames_removed - File "", line 1050, in _gcd_import - File "", line 1027, in _find_and_load - File "", line 1004, in _find_and_load_unlocked -ModuleNotFoundError: No module named 'foerderbarometer' -[2023-02-07 12:36:29 +0000] [2450] [INFO] Worker exiting (pid: 2450) -[2023-02-07 12:36:29 +0000] [2449] [INFO] Shutting down: Master -[2023-02-07 12:36:29 +0000] [2449] [INFO] Reason: Worker failed to boot. diff --git a/input/settings.py b/input/settings.py index e1ba53e..3b43e9a 100755 --- a/input/settings.py +++ b/input/settings.py @@ -1,9 +1,9 @@ # mail for IF-OTRS -#IF_EMAIL = 'community@wikimedia.de' -IF_EMAIL = 'test-luca-ext@wikimedia.de' +IF_EMAIL = 'community@wikimedia.de' +#IF_EMAIL = 'test-luca-ext@wikimedia.de' #SURVEY_EMAIL = 'christof.pins@wikimedia.de' -SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' -#SURVEY_EMAIL = 'sandro.halank@wikimedia.de' +#SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' +SURVEY_EMAIL = 'sandro.halank@wikimedia.de' # prefix for urls SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?' From 777d05c26cb113ad952079a43447a39e30adefab Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Wed, 25 Oct 2023 09:47:56 +0000 Subject: [PATCH 58/69] basic oauth added --- .gitignore | 2 +- input/asgi.py | 16 ++++ input/middleware/__init__.py | 0 input/middleware/oauth.py | 84 +++++++++++++++++++ input/settings.py | 30 +++++++ input/settings.py.old | 41 +++++++++ .../input/if_end_of_project_approved.html | 2 +- .../input/if_end_of_project_approved.txt | 2 +- requirements.txt | 14 ++++ 9 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 input/asgi.py create mode 100644 input/middleware/__init__.py create mode 100644 input/middleware/oauth.py create mode 100755 input/settings.py.old diff --git a/.gitignore b/.gitignore index f041b72..f796096 100755 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ /staticfiles # /foerderbarometer/settings.py /foerderbarometer/*settings* -/foerderbarometer/input/settings.py +/input/settings.py /nohup.out /logfile *~ diff --git a/input/asgi.py b/input/asgi.py new file mode 100644 index 0000000..2ff9254 --- /dev/null +++ b/input/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for oauth_demo project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'oauth_demo.settings') + +application = get_asgi_application() diff --git a/input/middleware/__init__.py b/input/middleware/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/input/middleware/oauth.py b/input/middleware/oauth.py new file mode 100644 index 0000000..ca30b1f --- /dev/null +++ b/input/middleware/oauth.py @@ -0,0 +1,84 @@ +from authlib.integrations.base_client import OAuthError +from authlib.integrations.django_client import OAuth +from authlib.oauth2.rfc6749 import OAuth2Token +from django.shortcuts import redirect +from django.utils.deprecation import MiddlewareMixin +from foerderbarometer import settings +from input import views + + +class OAuthMiddleware(MiddlewareMixin): + + def __init__(self, get_response=None): + super().__init__(get_response) + self.oauth = OAuth() + + def process_request(self, request): + if settings.OAUTH_URL_WHITELISTS is not None: + for w in settings.OAUTH_URL_WHITELISTS: + if request.path.startswith(w): + return self.get_response(request) + + def update_token(token, refresh_token, access_token): + request.session['token'] = token + print('oioi') + print('oi token', token) + return None + + sso_client = self.oauth.register( + settings.OAUTH_CLIENT_NAME, overwrite=True, **settings.OAUTH_CLIENT, update_token=update_token + ) + + if request.path.startswith('/oauth/callback'): + print('oi') + self.clear_session(request) + request.session['token'] = sso_client.authorize_access_token(request) + print('blub', request.session['token']) + print('user', self.get_current_user(sso_client, request)) + if self.get_current_user(sso_client, request) is not None: + redirect_uri = request.session.pop('redirect_uri', None) + if redirect_uri is not None: + return redirect(redirect_uri) + return redirect(views.ExternView) + + if request.session.get('token', None) is not None: + current_user = self.get_current_user(sso_client, request) + if current_user is not None: + return self.get_response(request) + + # remember redirect URI for redirecting to the original URL. + request.session['redirect_uri'] = request.path + return sso_client.authorize_redirect(request, settings.OAUTH_CLIENT['redirect_uri']) + + # fetch current login user info + # 1. check if it's in cache + # 2. fetch from remote API when it's not in cache + @staticmethod + def get_current_user(sso_client, request): + token = request.session.get('token', None) + if token is None or 'access_token' not in token: + return None + + if not OAuth2Token.from_dict(token).is_expired() and 'user' in request.session: + return request.session['user'] + + try: + res = sso_client.get(settings.OAUTH_CLIENT['userinfo_endpoint'], token=OAuth2Token(token)) + print('json oi oi' , res.json()) + if res.ok: + request.session['user'] = res.json() + return res.json() + except OAuthError as e: + print(e) + return None + + @staticmethod + def clear_session(request): + try: + del request.session['user'] + del request.session['token'] + except KeyError: + pass + + def __del__(self): + print('destroyed') diff --git a/input/settings.py b/input/settings.py index 3b43e9a..6d9bf53 100755 --- a/input/settings.py +++ b/input/settings.py @@ -39,3 +39,33 @@ ACCOUNTS ={ # "21103": '21103 Willkommen', "21140": '21140 Wikipedia-Kampagne', "21141": '21141 Wikipedia-Onboarding', "21150": '21150 Fürsorge und Online-Kommunikationskultur',} + + + +# teken from working oauth prototype as additional settings + +WSGI_APPLICATION = 'oauth_demo.wsgi.application' + +# OAuth Settings +OAUTH_URL_WHITELISTS = [] + +OAUTH_CLIENT_NAME = '' + + + +OAUTH_CLIENT = { + 'client_id': '', + 'client_secret': '', + 'access_token_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/access_token', + 'authorize_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/authorize', + 'api_base_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/resource', + 'redirect_uri': 'http://localhost:8000/oauth/callback', + 'client_kwargs': { + 'scope': 'basic', + 'token_placement': 'header' + }, + 'userinfo_endpoint': 'resource/profile', +} + +OAUTH_COOKIE_SESSION_ID = 'sso_session_id' + diff --git a/input/settings.py.old b/input/settings.py.old new file mode 100755 index 0000000..3b43e9a --- /dev/null +++ b/input/settings.py.old @@ -0,0 +1,41 @@ +# mail for IF-OTRS +IF_EMAIL = 'community@wikimedia.de' +#IF_EMAIL = 'test-luca-ext@wikimedia.de' +#SURVEY_EMAIL = 'christof.pins@wikimedia.de' +#SURVEY_EMAIL = 'luca.wulf@cannabinieri.de' +SURVEY_EMAIL = 'sandro.halank@wikimedia.de' +# prefix for urls +SURVEYPREFIX = 'https://wikimedia.sslsurvey.de/Foerderbarometer/?' + +# some links +DATAPROTECTION = "https://www.wikimedia.de/datenschutz/#datenerfassung" +FOERDERRICHTLINIEN = "https://de.wikipedia.org/wiki/Wikipedia:Wikimedia_Deutschland/F%C3%B6rderrichtlinien" +NUTZUNGSBEDINGUNGEN = 'static/input/nutzungsbedingungen.html' + +LANGUAGE_CODE = 'de' +TIME_ZONE = 'UTC' +USE_I18N = True +USE_L10N = True +USE_TZ = True + + +ACCOUNTS ={ # "21103": '21103 Willkommen', + "DEF": 'DEFAULT VALUE, you hould not see this!', + "21111": '21111 Förderung (reaktiv)', + "21112": '21112 WikiCon', +# "21113": '21113 Wikimania/Unterstützung Ehrenamtliche', + "21115": '21115 Lokale Räume, Berlin', + "21116": '21116 Lokale Räume, Hamburg', + "21117": '21117 Lokale Räume, Hannover', + "21118": '21118 Lokale Räume, Köln', + "21119": '21119 Lokale Räume, München', + "21120": '21120 Lokale Räume, Fürth', + "21125": '21125 Lokale Räume, allgemein', + "21130": '21130 GLAM-Förderung', + "21131": '21131 Initiative Förderung', +# "21134": '21134 Größe', +# "21137": '21137 Beitragen', +# "21138": '21138 Vermittlung', + "21140": '21140 Wikipedia-Kampagne', + "21141": '21141 Wikipedia-Onboarding', + "21150": '21150 Fürsorge und Online-Kommunikationskultur',} diff --git a/input/templates/input/if_end_of_project_approved.html b/input/templates/input/if_end_of_project_approved.html index 75a5893..7e442ff 100755 --- a/input/templates/input/if_end_of_project_approved.html +++ b/input/templates/input/if_end_of_project_approved.html @@ -10,7 +10,7 @@ Da wir verpflichtet sind, über unsere geförderten Maßnahmen zu berichten, mö * Wie viele Personen haben an dem Projekt teilgenommen?
* Wo können die Ergebnisse des Projektes eingesehen werden? (Projektseite, Commons-Link, Bericht o. ä.)

-Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen. +Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen.

Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du diesen nun archivieren, indem du den Projektstatus oben im Quellcode entsprechend anpasst und die Liste der geförderten Aktivitäten entsprechend aktualisierst.

diff --git a/input/templates/input/if_end_of_project_approved.txt b/input/templates/input/if_end_of_project_approved.txt index 6d7f941..6ca687b 100755 --- a/input/templates/input/if_end_of_project_approved.txt +++ b/input/templates/input/if_end_of_project_approved.txt @@ -8,7 +8,7 @@ Da wir verpflichtet sind, über unsere geförderten Maßnahmen zu berichten, mö * Wie viele Personen haben an dem Projekt teilgenommen? * Wo können die Ergebnisse des Projektes eingesehen werden? (Projektseite, Commons-Link, Bericht o. ä.) -Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen. +Sollten bei dem Projekt Fotos oder andere Mediendateien entstanden sein, findest du hier eine Anleitung, wie diese bei Commons hochgeladen werden sollen: https://commons.wikimedia.org/wiki/Category:Supported_by_Wikimedia_Deutschland Solltest du einen öffentlichen Förderantrag in der Wikipedia erstellt haben, kannst du diesen nun archivieren, indem du den Projektstatus oben im Quellcode entsprechend anpasst und die Liste der geförderten Aktivitäten entsprechend aktualisierst. diff --git a/requirements.txt b/requirements.txt index 59966ae..1c54076 100755 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,17 @@ gunicorn==20.0.4 mysqlclient==2.1.1 sqlparse==0.4.3 whitenoise==6.2.0 +asgiref +Authlib==1.2.1 +certifi==2023.7.22 +cffi==1.16.0 +chardet==5.2.0 +charset-normalizer==3.3.0 +cryptography==41.0.4 +idna==3.4 +pycparser==2.21 +pytz==2023.3.post1 +requests==2.31.0 +six==1.16.0 +typing_extensions==4.8.0 +urllib3==2.0.6 From 4b7423cd7616e3b7185d009e543b2c31c452ecbe Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Wed, 25 Oct 2023 10:17:08 +0000 Subject: [PATCH 59/69] updated README.md with right deps --- README.md | 26 +++++++++++++++++++++----- requirements.txt | 13 ++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b9ba654..164ba53 100755 --- a/README.md +++ b/README.md @@ -35,11 +35,27 @@ entries to a csv file ## versions used in development - python 3.8.2 - django 3.1.x (does not work with django 3.2 in the moment!) - django-formtools 2.2 - whitenoise 5.2.0 - gunicorn 20.0.4 + asgiref==3.2.10 + Django==3.1.2 + django-formtools==2.4 + gunicorn==20.0.4 + mysqlclient==2.1.1 + sqlparse==0.4.3 + whitenoise==6.2.0 + asgiref==3.2.10 + Authlib==1.2.1 + certifi==2023.7.22 + cffi==1.16.0 + chardet==5.2.0 + charset-normalizer==3.3.0 + cryptography==41.0.4 + idna==3.4 + pycparser==2.21 + pytz==2023.3.post1 + requests==2.31.0 + six==1.16.0 + typing_extensions==4.8.0 + urllib3==2.0.6 ## testing diff --git a/requirements.txt b/requirements.txt index 1c54076..a1371f1 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,21 +1,20 @@ asgiref==3.2.10 -Django==3.1.2 -django-formtools==2.4 -gunicorn==20.0.4 -mysqlclient==2.1.1 -sqlparse==0.4.3 -whitenoise==6.2.0 -asgiref Authlib==1.2.1 certifi==2023.7.22 cffi==1.16.0 chardet==5.2.0 charset-normalizer==3.3.0 cryptography==41.0.4 +Django==3.1.2 +django-formtools==2.4 +gunicorn==20.0.4 idna==3.4 +mysqlclient==2.1.1 pycparser==2.21 pytz==2023.3.post1 requests==2.31.0 six==1.16.0 +sqlparse==0.4.3 typing_extensions==4.8.0 urllib3==2.0.6 +whitenoise==6.2.0 From d0fb14bf17e53a47eadbe993b756c344cdd9fdf4 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Wed, 25 Oct 2023 13:45:17 +0000 Subject: [PATCH 60/69] whitelisted admin url for oauth --- input/urls.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/input/urls.py b/input/urls.py index e5fd5a9..792c686 100755 --- a/input/urls.py +++ b/input/urls.py @@ -1,10 +1,11 @@ from django.urls import path from .views import ExternView, done, authorize, deny, InternView, export - +from django.contrib import admin urlpatterns = [ path('', ExternView.as_view(), name='extern'), # path('intern', InternView.as_view(), name='intern'), + path('admin/', admin.site.urls), path('saved', done, name='done'), path('export', export, name='export'), path('authorize//', authorize, name='authorize'), From f60623d485c2a410395f583c1c2a1d718f339253 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Wed, 25 Oct 2023 15:50:40 +0000 Subject: [PATCH 61/69] user gets automatically written, not in the form anymore --- input/forms.py | 2 +- input/middleware/oauth.py | 6 +++--- input/models.py | 7 +++++-- input/views.py | 2 ++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/input/forms.py b/input/forms.py index 79fa58c..a66b828 100755 --- a/input/forms.py +++ b/input/forms.py @@ -38,7 +38,7 @@ class ExternForm(FdbForm): class Meta: model = ConcreteExtern - exclude = ('granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state') + exclude = ('username', 'granted', 'granted_date', 'survey_mail_send', 'service_id', 'survey_mail_date', 'mail_state') INTERN_CHOICES = {'PRO': 'Projektsteckbrief', diff --git a/input/middleware/oauth.py b/input/middleware/oauth.py index ca30b1f..0d5239e 100644 --- a/input/middleware/oauth.py +++ b/input/middleware/oauth.py @@ -5,7 +5,7 @@ from django.shortcuts import redirect from django.utils.deprecation import MiddlewareMixin from foerderbarometer import settings from input import views - +from input import models class OAuthMiddleware(MiddlewareMixin): @@ -33,8 +33,8 @@ class OAuthMiddleware(MiddlewareMixin): print('oi') self.clear_session(request) request.session['token'] = sso_client.authorize_access_token(request) - print('blub', request.session['token']) - print('user', self.get_current_user(sso_client, request)) + # print('blub', request.session['token']) + models.Extern.username = self.get_current_user(sso_client, request)['username'] if self.get_current_user(sso_client, request) is not None: redirect_uri = request.session.pop('redirect_uri', None) if redirect_uri is not None: diff --git a/input/models.py b/input/models.py index 6e0e58a..de4b8b5 100755 --- a/input/models.py +++ b/input/models.py @@ -13,11 +13,12 @@ EMAIL_STATES = {'NONE': 'noch keine Mail versendet', class Volunteer(models.Model): realname = models.CharField(max_length=200, null=True, verbose_name="Realname", - help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.") + help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.", default='oi') email = models.EmailField(max_length=200, null=True, verbose_name='E-Mail-Adresse', help_text=format_html('Bitte gib deine E-Mail-Adresse ein, damit dich
Wikimedia Deutschland bei Rückfragen oder für
die Zusage kontaktieren kann.')) # the following Fields are not supposed to be edited by users + granted = models.BooleanField(null=True, verbose_name='bewilligt') granted_date = models.DateField(null=True, verbose_name='bewilligt am') survey_mail_date = models.DateField(verbose_name='Umfragemail wurde verschickt am', null=True, blank=True) @@ -36,10 +37,12 @@ class Volunteer(models.Model): abstract = True + class Extern(Volunteer): ''' abstract basis class for all data entered by extern volunteers ''' + username = models.CharField(max_length=200, null=True, verbose_name='Benutzer_innenname', - help_text=format_html("Bitte gib den Namen ein, mit dem du dich
in den Wikimedia-Projekten registriert hast.")) + help_text=format_html("Wikimedia Benutzer_innenname")) # the following Fields are not supposed to be edited by users service_id = models.CharField(max_length=15, null=True, blank=True) diff --git a/input/views.py b/input/views.py index 8a3df6f..e25e12d 100755 --- a/input/views.py +++ b/input/views.py @@ -216,6 +216,8 @@ class ExternView(CookieWizardView): data = {} for form in form_list: data = {**data, **form.cleaned_data} + + data['username'] = self.request.session['user']['username'] if data['choice'] == 'LIT': if data['selfbuy'] == 'TRUE': From c113e37b3f9131faabf90957af5dadd6643e684a Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Tue, 21 Nov 2023 10:49:38 +0000 Subject: [PATCH 62/69] deleted main settings.py in foerderbarometerfrom .gitignore file --- .gitignore | 2 +- foerderbarometer/settings.py | 186 +++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+), 1 deletion(-) create mode 100755 foerderbarometer/settings.py diff --git a/.gitignore b/.gitignore index f796096..439c279 100755 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /secrets.json /staticfiles # /foerderbarometer/settings.py -/foerderbarometer/*settings* +# /foerderbarometer/*settings* /input/settings.py /nohup.out /logfile diff --git a/foerderbarometer/settings.py b/foerderbarometer/settings.py new file mode 100755 index 0000000..06390a1 --- /dev/null +++ b/foerderbarometer/settings.py @@ -0,0 +1,186 @@ +""" +Django settings for foerderbarometer project. + +Generated by 'django-admin startproject' using Django 3.1.1. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.1/ref/settings/ +""" + +import json +import os +from pathlib import Path + +from django.core.exceptions import ImproperlyConfigured + +# prefix for urls in mails +URLPREFIX = 'http://localhost:8000' + + +# mails in development go to stdout +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' + +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' + +#EMAIL_HOST = 'email.wikimedia.de' +#EMAIL_PORT = '587' +#EMAIL_USE_TLS = True +#EMAIL_HOST_USER = get_secret('EMAIL_HOST_USER') +#EMAIL_HOST_PASSWORD = get_secret('EMAIL_HOST_PASSWORD') + + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + +# get secrets +with open(os.path.join(BASE_DIR, 'secrets.json')) as secrets_file: + secrets = json.load(secrets_file) + +def get_secret(setting, secrets=secrets): + """Get secret setting or fail with ImproperlyConfigured""" + try: + return secrets[setting] + except KeyError: + raise ImproperlyConfigured("Set the {} setting".format(setting)) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = get_secret('SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +STATIC_ROOT = BASE_DIR / 'staticfiles' + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'input.apps.InputConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'formtools', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'whitenoise.middleware.WhiteNoiseMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'input.middleware.oauth.OAuthMiddleware' +] + +ROOT_URLCONF = 'foerderbarometer.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'foerderbarometer.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + 'PASSWORD': get_secret('DATABASE_PASSWORD') + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.1/howto/static-files/ + +STATIC_URL = '/static/' + +# needed since django 3.2 +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' + + +# OAuth Settings +OAUTH_URL_WHITELISTS = ['/admin'] + +OAUTH_CLIENT_NAME = '' +OAUTH_CLIENT_NAME = get_secret('OAUTH_CLIENT_NAME') + + +OAUTH_CLIENT = { + 'client_id': get_secret('OAUTH_CLIENT_ID'), + 'client_secret': get_secret('OAUTH_CLIENT_SECRET'), + 'access_token_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/access_token', + 'authorize_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/authorize', + 'api_base_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/resource', + 'redirect_uri': 'http://localhost:8000/oauth/callback', + 'client_kwargs': { + 'scope': 'basic', + 'token_placement': 'header' + }, + 'userinfo_endpoint': 'resource/profile', +} + +OAUTH_COOKIE_SESSION_ID = 'sso_session_id' From 7c05040d7bf3dedcfc0682cc359cb93fc2047828 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Wed, 27 Dec 2023 15:48:11 +0000 Subject: [PATCH 63/69] created if cases for changing of year for projects that were already there, but already have a project_of_year number --- input/models.py | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/input/models.py b/input/models.py index de4b8b5..1bc57ab 100755 --- a/input/models.py +++ b/input/models.py @@ -104,10 +104,21 @@ class Project(Volunteer): '''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? + startyear_tmp = 'NONE' + + if self.pid: + if self.pid[:4] != self.start.year: + startyear_tmp = self.start.year + super().save() - self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) - # self.pid = str(self.account.code) + str(self.pk).zfill(3) - + + if startyear_tmp == 'NONE': + + self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) + # self.pid = str(self.account.code) + str(self.pk).zfill(3) + + + # generation of field quartals if self.end.month in [1, 2, 3]: self.end_quartal = 'Q1' @@ -119,13 +130,25 @@ class Project(Volunteer): self.end_quartal = 'Q4' # generation of pid and financeID + # project of year is true if entry gets updated with changes.. but year can change!!!!!!!! + if self.project_of_year: + print('oi oi oi oi oi') + print(self.pid) - if not self.project_of_year: - #print('AAA') + + + + # project of year is false if entry gets saved as new + if not self.project_of_year or startyear_tmp != 'NONE': + print('AAA') + + print('self projekt of year', self.project_of_year, self.start.year) + # we need to determine if this is a new year with its first new project... year = self.start.year #print(year) projects = Project.objects.filter(start__year=year) + print('projects after filter of startyear of project',projects) if not projects: #print('BBB') self.project_of_year = 1 From 1454fce9baa4095460bdedcf4cb65e79be63de9c Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Sat, 30 Dec 2023 17:46:15 +0000 Subject: [PATCH 64/69] corrected small error regarding pid financeid bug fix, started javascript manipulation to get browsers to not translate url to url encoded characters for otrs link bug fix --- input/admin.py | 1 + input/forms.py | 3 +++ input/models.py | 27 +++++++++++++++++++++++++-- input/static/dropdown/js/otrs_link.js | 12 ++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 input/static/dropdown/js/otrs_link.js diff --git a/input/admin.py b/input/admin.py index 209e578..1b178e5 100755 --- a/input/admin.py +++ b/input/admin.py @@ -36,6 +36,7 @@ class ProjectAdmin(admin.ModelAdmin): date_hierarchy = 'end' readonly_fields = ('end_quartal', 'project_of_year', 'pid', 'finance_id') + @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): save_as = True diff --git a/input/forms.py b/input/forms.py index a66b828..d67ba51 100755 --- a/input/forms.py +++ b/input/forms.py @@ -26,6 +26,9 @@ class ProjectForm(FdbForm): widgets = {'start': AdminDateWidget(), 'end': AdminDateWidget(),} + class Media: + js = ('dropdown/js/otrs_link.js',) + class ExternForm(FdbForm): diff --git a/input/models.py b/input/models.py index 1bc57ab..8513fd9 100755 --- a/input/models.py +++ b/input/models.py @@ -1,7 +1,9 @@ from datetime import date - +from django.utils.http import urlencode from django.db import models from django.utils.html import format_html +import urllib +from django.utils.safestring import mark_safe from .settings import ACCOUNTS @@ -100,16 +102,37 @@ 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 some_otrs(self): + """ This returns a HTML anchor (hyperlink) to somewhere """ + return u'Link' % self.otrs + some_otrs.allow_tags = True + 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? + preotrs = self.otrs + + #postotrs = '' + #for n in range(len(preotrs)): + # if preotrs[n] == ';': + # postotrs += '\;' + # else: + # postotrs += preotrs[n] + #print(self.otrs) + #print(preotrs) + #print(postotrs) + postotrs = urllib.parse.quote(preotrs, safe=':;/=?&') + self.otrs = mark_safe(urllib.parse.unquote(postotrs)) startyear_tmp = 'NONE' if self.pid: - if self.pid[:4] != self.start.year: + print('self pid last four', self.pid[:4], self.start.year) + if int(self.pid[:4]) != int(self.start.year): startyear_tmp = self.start.year + print('the startyear_tmp is as follows ', startyear_tmp) + super().save() if startyear_tmp == 'NONE': diff --git a/input/static/dropdown/js/otrs_link.js b/input/static/dropdown/js/otrs_link.js new file mode 100644 index 0000000..49468eb --- /dev/null +++ b/input/static/dropdown/js/otrs_link.js @@ -0,0 +1,12 @@ +window.addEventListener("load", function() { +(function($) { + $(function() { + + + + html.body.style.backgroundColor = color[red]; + + + }); +})(django.jQuery); +}); From a51552d4dd2962fa0fb28a055b51812d3dfd6640 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Sat, 30 Dec 2023 19:01:06 +0000 Subject: [PATCH 65/69] prettifying the otrs links as wished through a javascript function onload, in /static/dropdown/js/otrs_link.js --- input/admin.py | 4 ++++ input/models.py | 4 ---- input/static/dropdown/js/otrs_link.js | 13 ++++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/input/admin.py b/input/admin.py index 1b178e5..1f1ffa7 100755 --- a/input/admin.py +++ b/input/admin.py @@ -36,6 +36,10 @@ class ProjectAdmin(admin.ModelAdmin): date_hierarchy = 'end' readonly_fields = ('end_quartal', 'project_of_year', 'pid', 'finance_id') + class Media: + js = ('dropdown/js/otrs_link.js',) + + @admin.register(BusinessCard) class BusinessCardAdmin(admin.ModelAdmin): diff --git a/input/models.py b/input/models.py index 8513fd9..9bdd3d7 100755 --- a/input/models.py +++ b/input/models.py @@ -102,10 +102,6 @@ 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 some_otrs(self): - """ This returns a HTML anchor (hyperlink) to somewhere """ - return u'Link' % self.otrs - some_otrs.allow_tags = True def save(self,*args,**kwargs): '''we generate the autogenerated fields here''' diff --git a/input/static/dropdown/js/otrs_link.js b/input/static/dropdown/js/otrs_link.js index 49468eb..778bb43 100644 --- a/input/static/dropdown/js/otrs_link.js +++ b/input/static/dropdown/js/otrs_link.js @@ -2,10 +2,17 @@ window.addEventListener("load", function() { (function($) { $(function() { - - - html.body.style.backgroundColor = color[red]; + let otrs_link = document.querySelector(".field-otrs > div > p.url > a").href; + console.log(otrs_link); + alert(otrs_link); + let otrs_link_pret = otrs_link.replace(/%3B/g, ";"); + let otrs_link_pretty = otrs_link_pret.replace(/%3D/g, "="); + + console.log(otrs_link_pretty); + + document.querySelector(".field-otrs > div > p.url > a").href = otrs_link_pretty; + }); })(django.jQuery); From a5834ee8c9b62cf07a6d71595d08fd783c0c7649 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Sun, 7 Jan 2024 14:13:21 +0000 Subject: [PATCH 66/69] implemented the logic for having a landingpage with a button poining to oauth login for extern view, while leaving /admin with passwort login --- foerderbarometer/settings.py | 2 +- input/middleware/oauth.py | 3 ++ input/templates/input/index.html | 47 ++++++++++++++++++++++++++++++++ input/urls.py | 5 ++-- input/views.py | 2 ++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100755 input/templates/input/index.html diff --git a/foerderbarometer/settings.py b/foerderbarometer/settings.py index 06390a1..885321d 100755 --- a/foerderbarometer/settings.py +++ b/foerderbarometer/settings.py @@ -163,7 +163,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' # OAuth Settings -OAUTH_URL_WHITELISTS = ['/admin'] +OAUTH_URL_WHITELISTS = ['/admin', '/index'] OAUTH_CLIENT_NAME = '' OAUTH_CLIENT_NAME = get_secret('OAUTH_CLIENT_NAME') diff --git a/input/middleware/oauth.py b/input/middleware/oauth.py index 0d5239e..1e20cf9 100644 --- a/input/middleware/oauth.py +++ b/input/middleware/oauth.py @@ -14,6 +14,9 @@ class OAuthMiddleware(MiddlewareMixin): self.oauth = OAuth() def process_request(self, request): + # added this if clause to get the landing page before oauth + if request.path == '/': + return self.get_response(request) if settings.OAUTH_URL_WHITELISTS is not None: for w in settings.OAUTH_URL_WHITELISTS: if request.path.startswith(w): diff --git a/input/templates/input/index.html b/input/templates/input/index.html new file mode 100755 index 0000000..35b5110 --- /dev/null +++ b/input/templates/input/index.html @@ -0,0 +1,47 @@ +{% load static %} + + + + + + +{{ form.media }} + + + + + +{% load i18n %} + +{% csrf_token %} + + +
+ + +

+

+Eine Übersicht aller Förderangebote von Wikimedia Deutschland findest du im + Förderportal in der deutschsprachigen Wikipedia. +
Für alle Fragen wende dich gern an das Team Communitys und Engagement. +

+Für interessierte Hacker gibts auch den Sourcecode zum Formular und was damit passiert. +

+ Impressum +

+ OAUTH +

+ + + diff --git a/input/urls.py b/input/urls.py index 792c686..28ec03a 100755 --- a/input/urls.py +++ b/input/urls.py @@ -1,9 +1,10 @@ from django.urls import path -from .views import ExternView, done, authorize, deny, InternView, export +from .views import ExternView, index, done, authorize, deny, InternView, export from django.contrib import admin urlpatterns = [ - path('', ExternView.as_view(), name='extern'), + path('', index, name='index'), + path('extern', ExternView.as_view(), name='extern'), # path('intern', InternView.as_view(), name='intern'), path('admin/', admin.site.urls), path('saved', done, name='done'), diff --git a/input/views.py b/input/views.py index e25e12d..1b58564 100755 --- a/input/views.py +++ b/input/views.py @@ -70,6 +70,8 @@ def deny(request, choice, pk): def done(request): return HttpResponse("Deine Anfrage wurde gesendet. Du erhältst in Kürze eine E-Mail-Benachrichtigung mit deinen Angaben. Für alle Fragen kontaktiere bitte das Team Communitys und Engagement unter community@wikimedia.de.") +def index(request): + return render(request, 'input/index.html') class InternView(LoginRequiredMixin, CookieWizardView): '''This View is for WMDE-employees only''' From 6b41d3320b37463beca3c76f2803d1e90415f464 Mon Sep 17 00:00:00 2001 From: alpcentaur Date: Sun, 7 Jan 2024 17:42:07 +0000 Subject: [PATCH 67/69] added html and css for the landing page, almost done --- input/templates/input/index.html | 44 ++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/input/templates/input/index.html b/input/templates/input/index.html index 35b5110..83db377 100755 --- a/input/templates/input/index.html +++ b/input/templates/input/index.html @@ -1,11 +1,5 @@ {% load static %} - - - - - -{{ form.media }} @@ -28,19 +22,47 @@ content: ' *'; color: red; } + .div15 { + height: 15%; + } + .div5 { + height: 5%; + } + .button1 { + width: 40vw; + height: 6vh; + display: flex; + justify-content: center; + align-items: center; + font-weight: bold; + font-size: 4vh; + } + +
+

+Herzlich willkommen im Förderanfrageportal von Wikimedia Deutschland! +

+
+ OAUTH + OAUTH

-Eine Übersicht aller Förderangebote von Wikimedia Deutschland findest du im - Förderportal in der deutschsprachigen Wikipedia. -
Für alle Fragen wende dich gern an das Team Communitys und Engagement. +Um eine Unterstützungsleistung im Rahmen der Förderangebote anfragen zu können, verifiziere dich bitte mit deinem Wikimedia-Konto. +
Weitere Informationen und Hintergründe findest du unter + + Förderportal in der deutschsprachigen Wikipedia.

-Für interessierte Hacker gibts auch den Sourcecode zum Formular und was damit passiert. +

+
Anmelden
+
+
+
Für alle Fragen wende dich gern an das Team Communitys und Engagement. +
Für interessierte Hacker gibts auch den Sourcecode zum Formular und was damit passiert.

Impressum

- OAUTH From 4e3d915e90f4fca0ae7494e6eaa9337d3225f145 Mon Sep 17 00:00:00 2001 From: Tobias Herre Date: Mon, 8 Jan 2024 13:31:18 +0000 Subject: [PATCH 68/69] Fixes for gdb with OATH --- foerderbarometer/settings.py | 6 ++-- input/models.py | 56 ++++---------------------------- input/templates/input/index.html | 6 ++-- 3 files changed, 13 insertions(+), 55 deletions(-) diff --git a/foerderbarometer/settings.py b/foerderbarometer/settings.py index 885321d..1672ed0 100755 --- a/foerderbarometer/settings.py +++ b/foerderbarometer/settings.py @@ -17,7 +17,7 @@ from pathlib import Path from django.core.exceptions import ImproperlyConfigured # prefix for urls in mails -URLPREFIX = 'http://localhost:8000' +URLPREFIX = 'https://fdb-devel.wikimedia.de' # mails in development go to stdout @@ -163,7 +163,7 @@ DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' # OAuth Settings -OAUTH_URL_WHITELISTS = ['/admin', '/index'] +OAUTH_URL_WHITELISTS = ['/admin'] OAUTH_CLIENT_NAME = '' OAUTH_CLIENT_NAME = get_secret('OAUTH_CLIENT_NAME') @@ -175,7 +175,7 @@ OAUTH_CLIENT = { 'access_token_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/access_token', 'authorize_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/authorize', 'api_base_url': 'https://meta.wikimedia.org/w/rest.php/oauth2/resource', - 'redirect_uri': 'http://localhost:8000/oauth/callback', + 'redirect_uri': 'https://fdb-devel.wikimedia.de/oauth/callback', 'client_kwargs': { 'scope': 'basic', 'token_placement': 'header' diff --git a/input/models.py b/input/models.py index 9bdd3d7..b1b617a 100755 --- a/input/models.py +++ b/input/models.py @@ -1,9 +1,7 @@ from datetime import date -from django.utils.http import urlencode + from django.db import models from django.utils.html import format_html -import urllib -from django.utils.safestring import mark_safe from .settings import ACCOUNTS @@ -15,7 +13,7 @@ EMAIL_STATES = {'NONE': 'noch keine Mail versendet', class Volunteer(models.Model): realname = models.CharField(max_length=200, null=True, verbose_name="Realname", - help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.", default='oi') + help_text="Bitte gib deinen Vornamen und deinen Nachnamen ein.", default='') email = models.EmailField(max_length=200, null=True, verbose_name='E-Mail-Adresse', help_text=format_html('Bitte gib deine E-Mail-Adresse ein, damit dich
Wikimedia Deutschland bei Rückfragen oder für
die Zusage kontaktieren kann.')) @@ -102,42 +100,14 @@ 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): '''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? - preotrs = self.otrs - - #postotrs = '' - #for n in range(len(preotrs)): - # if preotrs[n] == ';': - # postotrs += '\;' - # else: - # postotrs += preotrs[n] - #print(self.otrs) - #print(preotrs) - #print(postotrs) - postotrs = urllib.parse.quote(preotrs, safe=':;/=?&') - self.otrs = mark_safe(urllib.parse.unquote(postotrs)) - startyear_tmp = 'NONE' - - if self.pid: - print('self pid last four', self.pid[:4], self.start.year) - if int(self.pid[:4]) != int(self.start.year): - startyear_tmp = self.start.year - - print('the startyear_tmp is as follows ', startyear_tmp) - super().save() - - if startyear_tmp == 'NONE': - - self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) - # self.pid = str(self.account.code) + str(self.pk).zfill(3) - - - + self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) + # self.pid = str(self.account.code) + str(self.pk).zfill(3) + # generation of field quartals if self.end.month in [1, 2, 3]: self.end_quartal = 'Q1' @@ -149,25 +119,13 @@ class Project(Volunteer): self.end_quartal = 'Q4' # generation of pid and financeID - # project of year is true if entry gets updated with changes.. but year can change!!!!!!!! - if self.project_of_year: - print('oi oi oi oi oi') - print(self.pid) - - - - # project of year is false if entry gets saved as new - if not self.project_of_year or startyear_tmp != 'NONE': - print('AAA') - - print('self projekt of year', self.project_of_year, self.start.year) - + if not self.project_of_year: + #print('AAA') # we need to determine if this is a new year with its first new project... year = self.start.year #print(year) projects = Project.objects.filter(start__year=year) - print('projects after filter of startyear of project',projects) if not projects: #print('BBB') self.project_of_year = 1 diff --git a/input/templates/input/index.html b/input/templates/input/index.html index 83db377..3c2a9f3 100755 --- a/input/templates/input/index.html +++ b/input/templates/input/index.html @@ -45,8 +45,8 @@ Herzlich willkommen im Förderanfrageportal von Wikimedia Deutschland!

- OAUTH - OAUTH +

Um eine Unterstützungsleistung im Rahmen der Förderangebote anfragen zu können, verifiziere dich bitte mit deinem Wikimedia-Konto. @@ -55,7 +55,7 @@ Um eine Unterstützungsleistung im Rahmen der Förderangebote anfragen zu könne Förderportal in der deutschsprachigen Wikipedia.

-
Anmelden
+

Für alle Fragen wende dich gern an das Team Communitys und Engagement. From 2a771888870b4e21580ac000dd45401217a75238 Mon Sep 17 00:00:00 2001 From: Tobias Herre Date: Tue, 18 Feb 2025 14:34:05 +0000 Subject: [PATCH 69/69] Fixes wrong project counter when saving with modyfied start year. PID is also constant now. --- input/models.py | 80 +++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/input/models.py b/input/models.py index b1b617a..52ce002 100755 --- a/input/models.py +++ b/input/models.py @@ -100,13 +100,60 @@ 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): + + 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? - super().save() - self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.pk).zfill(3) - # self.pid = str(self.account.code) + str(self.pk).zfill(3) + + if not self.pk: + 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 + if orig.account.code != self.account.code: + if str(self.account.code) == '21111': + generate_finance_id=True + else: + self.finance_id = str(self.account.code) + + + + + + if 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) + 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) + + + 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)) + + 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)) + # generation of field quartals if self.end.month in [1, 2, 3]: @@ -118,34 +165,9 @@ class Project(Volunteer): if self.end.month in [10, 11, 12]: self.end_quartal = 'Q4' - # generation of pid and financeID - - if not self.project_of_year: - #print('AAA') - # we need to determine if this is a new year with its first new project... - year = self.start.year - #print(year) - projects = Project.objects.filter(start__year=year) - if not projects: - #print('BBB') - self.project_of_year = 1 - self.pid = str(self.start.year) + '-' + str(self.account.code) + str(self.project_of_year).zfill(3) - else: - #print('CCC') - # 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) - - 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) - - super().save() + def __str__(self): return f"{self.pid} {self.name}"