1
0
Fork 0

Compare commits

...

58 Commits

Author SHA1 Message Date
corsaronero 6ecc5e985f removed wrongly generated logfile within input folder 2023-02-13 14:59:44 +00:00
corsaronero a72d9de3dd bugfixFDB completed 2023-02-07 14:02:58 +00:00
corsaronero 689da90083 last version, talked to admin today 2023-01-13 18:18:29 +00:00
corsaronero c06b7f39b1 trying with different username 2022-12-20 09:14:45 +00:00
Benni Bärmann e41ba42e1e changed mail_state, implemented live, changed mail sender 2022-12-14 16:28:09 +00:00
Benni Bärmann f8e8d093c1 search fields for travel and honorary are using foreign keys now, with the notation of double underscores 2022-12-12 10:26:19 +00:00
Benni Bärmann f2d65e5934 honorary certificate model now has autocomplete field foreign key project too 2022-12-12 10:13:46 +00:00
Benni Bärmann fcb906c193 changed order of fields in admin panel of model project 2022-12-09 18:54:58 +00:00
Benni Bärmann cb930eceda deleted variable persons in admin model project 2022-12-09 18:31:38 +00:00
Benni Bärmann d2d9149a62 send end mails var in admin.model.project changed to boolean check field, also true is false now, so changed logic in sendmails.py 2022-12-09 17:58:37 +00:00
Benni Bärmann a6defcb627 admin model travel has now datefields instead of datetimefields for checkin and checkout 2022-12-09 17:25:41 +00:00
Benni Bärmann 3d591a39f7 now the | in datefield is also hidden via css 2022-12-09 17:20:03 +00:00
Benni Bärmann 0b044692d6 literature self_buy_giveData variable is now required in extern view 2022-12-09 16:55:26 +00:00
Benni Bärmann d09b97f72f model travel is now based on extern instead of intern, service id is displayed and a readonly field 2022-12-09 16:52:52 +00:00
Benni Bärmann fbad8873ba all service ids are readonly fields now 2022-12-09 16:33:52 +00:00
Benni Bärmann e814b7fa41 added search bar to foreign key choice field project in model travel 2022-12-08 21:36:48 +00:00
Benni Bärmann f35a788fd0 hotel in forms.py is now radioselect choicefield and required 2022-12-08 21:32:17 +00:00
Benni Bärmann 2cd2d9f110 fixed literature selfbuy variables in admin view 2022-12-08 20:21:36 +00:00
Benni Bärmann b5062dcc28 custom css is now only applied to travel form, not to all forms 2022-12-07 14:08:23 +00:00
Benni Bärmann 2fe292fda0 changed logic of generation of finId and pId, solved Travelform error, hotel variable travelmodel is not required anymore 2022-12-07 13:56:22 +00:00
Benni Bärmann 35f0dd84ab hidden for all 'today' shortcuts in datetimefields via css 2022-12-06 19:22:56 +00:00
Benni Bärmann b153b78048 added adult multiple choice radio button by changing admin.py and forms.py 2022-12-06 17:39:25 +00:00
Benni Bärmann 40ec564815 travel und project models now have date hierarchy based on project end 2022-12-06 16:48:02 +00:00
Benni Bärmann 76f8df70ee added a presave signal for travel model to update own field with foreign key project field 2022-12-06 16:19:02 +00:00
Benni Bärmann 5335865fcd rewrote the javascript part 2022-12-05 10:19:03 +00:00
Benni Bärmann b662011618 changed languages default to german, translated last labels (verbosename) for variables 2022-12-04 16:40:23 +00:00
Benni Bärmann 97525ad564 added link to Reisekosten in label choices in extern.html view 2022-12-02 17:14:03 +00:00
Benni Bärmann a50c8efd60 sort of label choices on extern.html view alphabetically, change of text when form was sent to communitys und engagement instead of Ideenfoerderung 2022-12-02 17:10:09 +00:00
Benni Bärmann 0085c5ff02 changed the data protection link in html mails 2022-12-02 16:20:55 +00:00
Benni Bärmann 4d7b48f8b8 admin search bar working now for all models, gave a 500 error because of wrong syntax in admin.py - searchfields 2022-12-02 16:04:11 +00:00
Benni Bärmann 4aa8d15f74 html format geändert 2022-12-01 15:49:30 +00:00
Benni Bärmann d2d48c1a82 added mail_state to all objects, added filters regarding sendmail.py 2022-11-30 00:09:10 +00:00
corsaronero 9b9209f2b5 conditional hiding of address textfield in literature form added 2022-11-21 15:30:01 +00:00
corsaronero b28c145454 changing saved value in database selfbuy_give_data to false when selfbuy true also in internview done() 2022-11-21 13:11:49 +00:00
corsaronero 2501bb0866 changed fields in Travel to required, changed saving of value of selfbuy_give_data when person wants to selfbuy to false 2022-11-21 13:09:12 +00:00
corsaronero 7a99176b23 changed sending of last mails in sendmails.py and in views.py 2022-11-18 12:42:29 +00:00
corsaronero 21cfd50972 sendmails is sending html regarding the informing of the organisator when not happened 2022-11-17 18:45:45 +00:00
corsaronero 43df9bd353 created html versions of all mail templates 2022-11-17 18:37:38 +00:00
corsaronero 5d436f9294 added intern_notes variable to all dbs, not excluded in extern view for all 2022-11-17 18:19:18 +00:00
corsaronero c3c5a44be5 added date hierarchy and overview in admin panel to all other forms in admin.py, also created variable intern_notes 2022-11-17 17:39:43 +00:00
corsaronero 687fdddb8e made mail.adult a required field 2022-11-17 16:46:58 +00:00
corsaronero ca7fbf6af7 intern url commented out in urls.py 2022-11-17 16:27:42 +00:00
corsaronero 4603dddb69 added the automated mail with the possibility to grant travel costs by link in email 2022-11-17 16:22:18 +00:00
corsaronero 08406d97d1 if not happened mail is now in html format, if not html then txt 2022-11-17 11:40:30 +00:00
corsaronero 372bd32395 buttons in input form displaying 'Weiter', if last step then displaying 'Absenden' 2022-11-17 11:04:23 +00:00
corsaronero 8d6be910f3 added two sendmails functions, that are executed when admins change status of ended project 2022-11-16 21:19:49 +00:00
corsaronero 8356460242 added templates for changed sendmail.txt 2022-11-15 17:01:58 +00:00
corsaronero fba8178d48 Anfang code der Funktion end of proj approved in sendmails.py 2022-11-15 16:57:01 +00:00
corsaronero 4c016a4a5a added dropdown agreement to send my data for buying literature for me 2022-11-11 11:54:26 +00:00
corsaronero 0d51dae174 pic_of_url hidden in all views 2022-11-11 09:34:09 +00:00
corsaronero 9167adeab5 added boolean field send_data_to_print with html formatted link to businesscard 2022-11-11 08:44:38 +00:00
corsaronero 54eca0197c notes field is now bigger, changed to Textfield analog. new entry url_of_pic, migrated, javascript to hide in businesscard if nopic is choice 2022-11-11 08:28:46 +00:00
corsaronero 29d20e040e added NOT choice, 'nicht stattgefunden', to project status button 2022-11-08 12:55:54 +00:00
corsaronero 792f8df588 dates in tabulatures, based on django style with almost no new code. only applied to projects change list page 2022-11-04 11:18:09 +00:00
corsaronero a5b7d92ec2 full search and display fields for Projects, Services also added fields 2022-11-03 17:02:39 +00:00
corsaronero ace7fde295 added search field in admin panel model Projects, added displayed fields almost like wanted 2022-11-03 16:37:18 +00:00
corsaronero 1bb189bcc4 Datenschutzbestimmungen und Förderrichtlinien öffnen nun auch in neuem Tab 2022-11-01 10:35:42 +00:00
corsaronero 018d6bbc1b links in choice field opening new tab now 2022-11-01 10:30:30 +00:00
145 changed files with 2670 additions and 112 deletions

4
.gitignore vendored Normal file → Executable file
View File

@ -1,7 +1,9 @@
# secret passwords and so
/secrets.json
/staticfiles
/foerderbarometer/settings.py
# /foerderbarometer/settings.py
/foerderbarometer/*settings*
/foerderbarometer/input/settings.py
/nohup.out
/logfile
*~

0
LICENSE Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

0
TODO Normal file → Executable file
View File

0
foerderbarometer/__init__.py Normal file → Executable file
View File

0
foerderbarometer/asgi.py Normal file → Executable file
View File

151
foerderbarometer/settings.py_old Executable file
View File

@ -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'

9
foerderbarometer/settings_development.py Normal file → Executable file
View File

@ -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

0
foerderbarometer/settings_mariadb_development.py Normal file → Executable file
View File

11
foerderbarometer/settings_production.py Normal file → Executable file
View File

@ -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'
@ -108,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',

8
foerderbarometer/urls.py Normal file → Executable file
View File

@ -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
#)

0
foerderbarometer/wsgi.py Normal file → Executable file
View File

0
input/__init__.py Normal file → Executable file
View File

114
input/admin.py Normal file → Executable file
View File

@ -22,26 +22,114 @@ 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)
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
save_as = True
readonly_fields = ('pid','finance_id','project_of_year')
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')
fields = ('realname', 'email', 'granted', 'granted_date', 'mail_state', 'end_mail_send', 'survey_mail_send', 'survey_mail_date', 'name', 'description', 'pid', 'finance_id', 'start', 'end', 'otrs', 'plan', 'page', 'urls', 'group', 'location', 'participants_estimated', 'participants_real', 'insurance', 'insurance_technic', 'support', 'cost', 'account', 'granted_from', 'notes', 'intern_notes', 'status', 'project_of_year', '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):
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']
date_hierarchy = 'granted_date'
readonly_fields = ['service_id']
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'
readonly_fields = ['service_id']
@admin.register(Account)
class AccountAdmin(admin.ModelAdmin):
save_as = True
admin.site.register([
Account,
HonoraryCertificate,
Library,
IFG,
Travel,
Email,
BusinessCard,
List,
Literature,
])
@admin.register(HonoraryCertificate)
class HonoraryCertificateAdmin(admin.ModelAdmin):
save_as = True
search_fields = ['realname', 'granted', 'project__name', 'project__pid']
list_display = ('realname', 'granted','project')
date_hierarchy = 'granted_date'
autocomplete_fields = ['project']
@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'
readonly_fields = ['service_id']
@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'
readonly_fields = ['service_id']
@admin.register(Travel)
class TravelAdmin(admin.ModelAdmin):
save_as = True
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'
readonly_fields = ('project_end_quartal', 'project_end')
autocomplete_fields = ['project']
readonly_fields = ['service_id']
@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'
radio_fields = {'adult': admin.VERTICAL}
readonly_fields = ['service_id']
class Media:
js = ('dropdown/js/base.js',)
@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'
readonly_fields = ['service_id']
# commented out because of the individual registering to control displays in admin panel
#admin.site.register([
# Account,
# HonoraryCertificate,
# Library,
# IFG,
# Travel,
# Email,
# List,
# ])

0
input/apps.py Normal file → Executable file
View File

0
input/fixtures/accounts.json Normal file → Executable file
View File

91
input/forms.py Normal file → Executable file
View File

@ -22,22 +22,24 @@ 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(),}
class ExternForm(FdbForm):
choice = ChoiceField(choices=TYPE_CHOICES.items(), widget=RadioSelect,
label='Was möchtest Du beantragen?')
check = BooleanField(required=True,
label=format_html("Ich stimme den <a href='{}'>Datenschutzbestimmungen</a> und den <a href='{}'>Förderrichtlinen</a> zu",
label=format_html("Ich stimme den <a href='{}' target='_blank' rel='noopener'>Datenschutzbestimmungen</a> und den <a href='{}' target='_blank' rel='noopener'>Förderrichtlinen</a> zu",
DATAPROTECTION, FOERDERRICHTLINIEN))
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',
'HON': 'Ehrenamtsbescheinigung, Akkreditierung oder Redaktionsbestätigung',
@ -49,31 +51,60 @@ 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')
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
# 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')
exclude = ('granted', 'granted_date', 'survey_mail_send', 'realname', 'email', 'survey_mail_date', 'project', 'request_url', 'payed_for_hotel_by', 'payed_for_travel_by', 'intern_notes', 'mail_state' )
widgets = {'checkin': AdminDateWidget(),
'checkout': AdminDateWidget(),}
fields = ['project_name', 'transport', 'travelcost', 'checkin', 'checkout', 'hotel', 'notes']
hotel = ChoiceField(label='Hotelzimmer benötigt:', choices=HOTEL_CHOICES.items(), widget=RadioSelect())
class Media:
css = {
'all': ('css/dateFieldNoNowShortcutInTravels.css',)
}
class LibraryForm(FdbForm):
class Meta:
model = Library
fields = ['cost', 'library', 'duration', 'notes']
fields = ['cost', 'library', 'duration', 'notes', 'survey_mail_send']
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
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', 'survey_mail_send', 'mail_state']
class CheckForm(FdbForm):
@ -82,23 +113,63 @@ class CheckForm(FdbForm):
label=format_html("Ich stimme den <a href='{}'>Nutzungsbedingungen</a> zu",
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_data', 'selfbuy_give_data']
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
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
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
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
fields = ['domain', 'address', 'other']
fields = ['domain', 'address', 'other', 'adult']
exclude = ['intern_notes', 'survey_mail_send', 'mail_state']
class Media:
js = ('dropdown/js/mail.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
self.fields['send_data_to_print'].required = True
class Meta:
model = BusinessCard
fields = ['project', 'data', 'variant', 'sent_to']
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/businessCard.js',)
class ListForm(CheckForm):
class Meta:
model = List
fields = ['domain', 'address']
exclude = ['intern_notes', 'survey_mail_send','mail_state']

201
input/management/commands/sendmails.py Normal file → Executable file
View File

@ -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,\
@ -34,42 +35,188 @@ 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()
#print('survey mail would have been 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.')
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')
mail_template = get_template('input/if_end_of_project.txt')
for project in old:
context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX
try:
send_mail('Projektende erreicht',
mail_template.render(context),
IF_EMAIL,
[IF_EMAIL],
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()
#print('end of project mail would have been sent')
#send_mail('Projektende erreicht',
# mail_template.render(context),
# IF_EMAIL,
# [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.'))
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 = True)\
.filter(mail_state = 'INF')
txt_mail_template = get_template('input/if_end_of_project_approved.txt')
html_mail_template = get_template('input/if_end_of_project_approved.html')
txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt')
html_informMail_template = get_template('input/if_end_of_project_orginformed.html')
# send the mail to project.email, which would be the mail of the volunteer filling out the form
for project in approved_end:
context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX
try:
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()
#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_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),
# 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.mail_state = 'CLOSE'
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.'))
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 = True)\
.filter(mail_state = 'INF')
html_mail_template = get_template('input/if_not_of_project_approved.html')
txt_mail_template = get_template('input/if_not_of_project_approved.txt')
txt_informMail_template = get_template('input/if_end_of_project_orginformed.txt')
html_informMail_template = get_template('input/if_end_of_project_orginformed.html')
# send the mail to project.email, which would be the mail of the volunteer that filled out the form
for project in approved_notHappened:
context = {'project': project}
context['URLPREFIX'] = settings.URLPREFIX
try:
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()
#print('if not of project approved end mail would have been sent')
#send_mail('Projektende erreicht',
# mail_template.render(context),
# IF_EMAIL,
# [project.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()
#print('if not of project approved end mail orginformed would have been sent')
#send_mail('Projektorganisator*in wurde informiert',
# informMail_template.render(context),
# IF_EMAIL,
# [IF_EMAIL],
# fail_silently=False)
project.end_mail_send = True
project.mail_state = 'CLOSE'
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'):
mytype=type
myname = name
@ -85,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'))
@ -97,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):
@ -105,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):
@ -113,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):
@ -121,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):
@ -136,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):
@ -149,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
@ -158,6 +313,8 @@ class Command(BaseCommand):
'''the main function which is called by the custom command'''
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()

0
input/migrations/0001_initial.py Normal file → Executable file
View File

0
input/migrations/0002_auto_20200922_1340.py Normal file → Executable file
View File

0
input/migrations/0003_volonteer.py Normal file → Executable file
View File

0
input/migrations/0004_project_contact.py Normal file → Executable file
View File

0
input/migrations/0005_auto_20200930_1015.py Normal file → Executable file
View File

0
input/migrations/0006_honorarycertificate.py Normal file → Executable file
View File

0
input/migrations/0007_library.py Normal file → Executable file
View File

0
input/migrations/0008_ifg.py Normal file → Executable file
View File

0
input/migrations/0009_project_pid.py Normal file → Executable file
View File

0
input/migrations/0010_auto_20201007_0732.py Normal file → Executable file
View File

0
input/migrations/0011_auto_20201007_0743.py Normal file → Executable file
View File

0
input/migrations/0012_auto_20201007_0754.py Normal file → Executable file
View File

0
input/migrations/0013_library_type.py Normal file → Executable file
View File

0
input/migrations/0014_auto_20201020_0714.py Normal file → Executable file
View File

0
input/migrations/0015_auto_20201021_0721.py Normal file → Executable file
View File

0
input/migrations/0016_project_account.py Normal file → Executable file
View File

0
input/migrations/0017_auto_20201021_1145.py Normal file → Executable file
View File

0
input/migrations/0018_auto_20201021_1147.py Normal file → Executable file
View File

0
input/migrations/0019_auto_20201021_1148.py Normal file → Executable file
View File

0
input/migrations/0020_project_project_end_mail.py Normal file → Executable file
View File

0
input/migrations/0021_auto_20201022_0934.py Normal file → Executable file
View File

0
input/migrations/0022_auto_20201022_1233.py Normal file → Executable file
View File

0
input/migrations/0023_auto_20201022_1400.py Normal file → Executable file
View File

0
input/migrations/0024_travel.py Normal file → Executable file
View File

0
input/migrations/0025_auto_20201026_1048.py Normal file → Executable file
View File

0
input/migrations/0026_auto_20201026_1214.py Normal file → Executable file
View File

0
input/migrations/0027_businesscard_email_list.py Normal file → Executable file
View File

0
input/migrations/0028_auto_20201027_1131.py Normal file → Executable file
View File

0
input/migrations/0029_auto_20201027_1247.py Normal file → Executable file
View File

0
input/migrations/0030_auto_20201027_1337.py Normal file → Executable file
View File

0
input/migrations/0031_auto_20201028_1402.py Normal file → Executable file
View File

0
input/migrations/0032_auto_20201029_1213.py Normal file → Executable file
View File

0
input/migrations/0033_auto_20201029_1338.py Normal file → Executable file
View File

0
input/migrations/0034_auto_20201102_0913.py Normal file → Executable file
View File

0
input/migrations/0035_auto_20201102_0944.py Normal file → Executable file
View File

0
input/migrations/0036_auto_20201102_1049.py Normal file → Executable file
View File

0
input/migrations/0037_auto_20201102_1054.py Normal file → Executable file
View File

0
input/migrations/0038_auto_20201102_1055.py Normal file → Executable file
View File

0
input/migrations/0039_auto_20201102_1212.py Normal file → Executable file
View File

0
input/migrations/0040_auto_20201102_1302.py Normal file → Executable file
View File

0
input/migrations/0041_auto_20201102_1318.py Normal file → Executable file
View File

0
input/migrations/0042_auto_20201102_1319.py Normal file → Executable file
View File

0
input/migrations/0043_auto_20201102_1320.py Normal file → Executable file
View File

0
input/migrations/0044_auto_20201103_1545.py Normal file → Executable file
View File

0
input/migrations/0044_auto_20201116_1531.py Normal file → Executable file
View File

0
input/migrations/0045_auto_20201116_1557.py Normal file → Executable file
View File

0
input/migrations/0046_auto_20201117_1542.py Normal file → Executable file
View File

0
input/migrations/0047_auto_20201117_1546.py Normal file → Executable file
View File

0
input/migrations/0048_auto_20201118_1503.py Normal file → Executable file
View File

0
input/migrations/0049_auto_20201118_1509.py Normal file → Executable file
View File

0
input/migrations/0050_auto_20201118_1512.py Normal file → Executable file
View File

0
input/migrations/0051_auto_20201118_1521.py Normal file → Executable file
View File

0
input/migrations/0052_auto_20201118_1524.py Normal file → Executable file
View File

0
input/migrations/0053_auto_20201118_1531.py Normal file → Executable file
View File

0
input/migrations/0054_auto_20201118_1702.py Normal file → Executable file
View File

0
input/migrations/0055_merge_20201118_1734.py Normal file → Executable file
View File

0
input/migrations/0056_auto_20201217_1215.py Normal file → Executable file
View File

0
input/migrations/0057_auto_20210104_0937.py Normal file → Executable file
View File

0
input/migrations/0058_auto_20210412_0946.py Normal file → Executable file
View File

0
input/migrations/0059_auto_20210412_1142.py Normal file → Executable file
View File

0
input/migrations/0060_concreteextern.py Normal file → Executable file
View File

0
input/migrations/0061_concretevolunteer.py Normal file → Executable file
View File

0
input/migrations/0062_auto_20211103_1155.py Normal file → Executable file
View File

View File

@ -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', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Zugang_zu_Fachliteratur#Bibliotheksstipendium" target="_blank" rel="noopener">Bibliotheksstipendium</a>'), ('ELIT', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Zugang_zu_Fachliteratur#eLiteraturstipendium" target="_blank" rel="noopener">eLiteraturstipendium</a>'), ('MAIL', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/E-Mail-Adressen_und_Visitenkarten#E-Mail-Adressen" target="_blank" rel="noopener">E-Mail-Adresse</a>'), ('IFG', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Gebührenerstattungen_für_Behördenanfragen" target="_blank" rel="noopener">Kostenübernahme IFG-Anfrage</a>'), ('LIT', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Zugang_zu_Fachliteratur#Literaturstipendium" target="_blank" rel="noopener">Literaturstipendium</a>'), ('LIST', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/E-Mail-Adressen_und_Visitenkarten#Mailinglisten" target="_blank" rel="noopener">Mailingliste</a>'), ('SOFT', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/Software-Stipendien" target="_blank" rel="noopener">Softwarestipendium</a>'), ('VIS', '<a href="https://de.wikipedia.org/wiki/Wikipedia:Förderung/E-Mail-Adressen_und_Visitenkarten#Visitenkarten" target="_blank" rel="noopener">Visitenkarten</a>')], default='BIB', max_length=4),
),
migrations.AlterField(