from django.db.models.signals import post_save, pre_delete, m2m_changed, pre_save from django.contrib.auth.models import User, Group from django.dispatch import receiver from .models import Profile, Agency, AgencyGroup, AgencyNetworkPreperation, UserYearAbsenceInfo, UserTime, UserNotifications from news.models import News from django.contrib.auth.models import Permission from notificsys.models import UserNotification from django.core.mail import send_mail from django.template.loader import render_to_string from tasks.models import Tasks from cloud.models import DataFile, DataDir import os from django.conf import settings from django.utils import timezone from standards.models import Standards from django.contrib.auth.signals import user_logged_in, user_logged_out from timemanagement.models import Workday, Breaks, AbsenceReason, FreeDays, Absence from datetime import date import datetime, json from django.utils import timezone import requests, csv, os from django.templatetags.static import static from django.conf import settings from datetime import date import channels.layers from asgiref.sync import async_to_sync from django.contrib.auth.decorators import login_required from datetime import timedelta from django.core.signals import request_started from channels_presence.models import Room from channels_presence.models import Presence from channels_presence.signals import presence_changed from organizer.models import * def loadingFreeDays(plz, year): # Getting land file_path = os.path.join(settings.STATIC_ROOT, 'users/extra/plz_short.csv') land = False with open(file_path, 'rt') as csvfile: filecsv = csv.reader(csvfile, delimiter=';') for row in filecsv: if str(row[1] == str(plz)): land = row[6] break; if(land != False): URL = "https://feiertage-api.de/api/" PARAMS = {'jahr':year,'nur_land':land} r = requests.get(url = URL, params = PARAMS) return r.json() else: return False # CHECK SOMETHING WHEN USER LOGGED IN @receiver(signal=user_logged_out, sender=User) def checkForFreeDays(sender, user, request, **kwargs): user.profile.onlinestatus = 3 user.save() # CHECK SOMETHING WHEN USER LOGGED IN @receiver(signal=user_logged_in, sender=User) def checkDefaultAbsenceReasons(sender, user, request, **kwargs): user.profile.onlinestatus = 0 user.save() ar = AbsenceReason.objects.filter(agency=user.profile.agency) if(len(ar) == 0): new_ar_holidays = AbsenceReason(agency=user.profile.agency, name="Urlaub", color="#0099BC", need_confirm=True, need_rep=True, is_holiday=True) new_ar_holidays.save() new_ar_specialholidays = AbsenceReason(agency=user.profile.agency, name="Sonderurlaub", need_confirm=True, need_rep=True, is_holiday=False, color="#F39C12") new_ar_specialholidays.save() new_ar_ill = AbsenceReason(agency=user.profile.agency, name="Krankheit", color="#E74C3C", need_confirm=False, need_rep=False, is_holiday=False) new_ar_ill.save() new_ar_school = AbsenceReason(agency=user.profile.agency, name="Berufsschule", color="#16A085", need_confirm=False, need_rep=False, is_holiday=False) new_ar_school.save() new_ar_education = AbsenceReason(agency=user.profile.agency, name="Fortbildung", color="#2ECC71", need_confirm=True, need_rep=True, is_holiday=False) new_ar_education.save() new_ar_time = AbsenceReason(agency=user.profile.agency, name="Gleitzeit", color="#9B59B6", need_confirm=True, need_rep=False, is_holiday=False) new_ar_time.save() today = date.today() # FREEDAYS LADEN if len(FreeDays.objects.filter(agency=user.profile.agency, year=today.year+2)) == 0: tempdays = loadingFreeDays(user.profile.agency.plz, today.year+2) if(tempdays != False): for k in tempdays.keys(): tempdate = tempdays[k]["datum"].split("-") FreeDays(agency=user.profile.agency, name=k, day=datetime.datetime(int(tempdate[0]),int(tempdate[1]),int(tempdate[2])), year=date.today().year+2).save() # CHECK FOR YEARS # NO YEARS FOUND if len(UserYearAbsenceInfo.objects.filter(agency=user.profile.agency)) == 0: # CREATE DATA FOR EVERY USER uina = User.objects.filter(profile__agency=user.profile.agency) for u in uina: UserYearAbsenceInfo(agency=user.profile.agency, user=u, year=today.year).save() UserYearAbsenceInfo(agency=user.profile.agency, user=u, year=today.year+1).save() UserYearAbsenceInfo(agency=user.profile.agency, user=u, year=today.year+2).save() pass # CREATE DATE FOR YEAR PLUS 2 elif len(UserYearAbsenceInfo.objects.filter(agency=user.profile.agency, year=today.year+2)) == 0: uina = User.objects.filter(profile__agency=user.profile.agency) for u in uina: UserYearAbsenceInfo(agency=user.profile.agency, user=u, year=today.year+2).save() ''' FUNKTION ZUM SENDEN VON MAILS AUS EINEM SIGNAL ''' def sendMailNoti(notificationtext, user_touched, linktarget=""): username = user_touched.first_name + " " + user_touched.last_name msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext, 'linktarget' : linktarget}) send_mail( 'Agentur-Benachrichtigung', 'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext, 'noreply@digitale-agentur.com', [user_touched.email], html_message=msg_html, fail_silently=True ) # Deletes all Notifications added to to delete news @receiver(pre_delete, sender=News) def del_news_notifications(sender, instance, **kwargs): UserNotification.objects.filter(elementid=instance.pk).delete() #USER SIGNAL @receiver(post_save, sender=User) def save_profile(sender, instance, **kwargs): instance.profile.save() # SIGNALS FOR GROUPS # Signal für das Ändern von Gruppenrechten @receiver(signal=m2m_changed, sender=Group.permissions.through) def adjust_group_notifications_permission(instance, action, reverse, model, pk_set, using, *args, **kwargs): group_touched = AgencyGroup.objects.get(group=instance) # Rechte wurden hinzugefügt if(action == "post_add"): users_in_group = instance.user_set.all() for user in users_in_group: if(user.usernotifications.group_rights_mail): notificationtext = "Die Gruppe " + group_touched.agencygroupname + " hat neue Rechte erhalten." sendMailNoti(notificationtext, user) if(user.usernotifications.group_rights_push): newnotification = UserNotification(touser=user, notificationtext="Die Gruppe " + group_touched.agencygroupname + " hat neue Rechte erhalten.", notificationtype="groupchanges") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Gruppenaktivität | Die Gruppe " + group_touched.agencygroupname + " hat neue Rechte erhalten."}) # Rechte wurden entfernt elif(action == "post_remove"): users_in_group = instance.user_set.all() for user in users_in_group: if(user.usernotifications.group_rights_mail): notificationtext = "Der Gruppe " + group_touched.agencygroupname + " wurden Rechte entzogen." sendMailNoti(notificationtext, user) if(user.usernotifications.group_rights_push): newnotification = UserNotification(touser=user, notificationtext="Der Gruppe " + group_touched.agencygroupname + " wurden Rechte entzogen.", notificationtype="groupchanges") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Gruppenaktivität | Der Gruppe " + group_touched.agencygroupname + " wurden Rechte entzogen."}) # Signal, wenn ein Nutzer aus der Gruppe entfernt/hinzugefügt wird @receiver(signal=m2m_changed, sender=User.groups.through) def adjust_group_notifications(instance, action, reverse, model, pk_set, using, *args, **kwargs): if isinstance(instance, Group): group_touched = AgencyGroup.objects.get(group=instance) userid = list(pk_set)[0] user_touched = User.objects.get(pk=userid) # PUSH NOTIFICATION FOR GROUOPCHANGES AND WEBSOCKET if(user_touched.usernotifications.group_activity_push): if(action == 'post_remove'): newnotification = UserNotification(touser=user_touched, notificationtext="Sie wurden aus der Gruppe " + group_touched.agencygroupname + " entfernt.", notificationtype="groupchanges") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user_touched.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Gruppenaktivität | Sie wurden aus der Gruppe " + group_touched.agencygroupname + " entfernt."}) # A USER WAS ADDED TO A GROUP elif(action == 'post_add'): newnotification = UserNotification(touser=user_touched, notificationtext="Sie wurden zur Gruppe " + group_touched.agencygroupname + " hinzugefügt.", notificationtype="groupchanges") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user_touched.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Gruppenaktivität | Sie wurden zur Gruppe " + group_touched.agencygroupname + " hinzugefügt."}) # E-MAILNOTIFICATIONS FOR GROUPCHANGES if(user_touched.usernotifications.group_activity_mail): notificationtext = "" if(action == 'post_remove'): notificationtext = "Sie wurden aus der Gruppe " + group_touched.agencygroupname + " entfernt." username = user_touched.first_name + " " + user_touched.last_name msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext}) send_mail( 'Agentur-Benachrichtigung', 'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext, 'noreply@digitale-agentur.com', [user_touched.email], html_message=msg_html, fail_silently=True ) # A USER WAS ADDED TO A GROUP elif(action == 'post_add'): notificationtext = "Sie wurden zur Gruppe " + group_touched.agencygroupname + " hinzugefügt." username = user_touched.first_name + " " + user_touched.last_name msg_html = render_to_string('notificsys/notification_mail.html', {'username': username, 'notificationtext' : notificationtext}) send_mail( 'Agentur-Benachrichtigung', 'Hallo ' + user_touched.first_name + ' ' + user_touched.last_name + '! ' + notificationtext, 'noreply@digitale-agentur.com', [user_touched.email], html_message=msg_html, fail_silently=True ) # SIGNALS FOR STANDARDS # DELETE @receiver(pre_delete, sender=Standards) def delete_standard(sender, instance, **kwargs): newNotifiyPush(2, instance, " es wurde ein neuer Agenturstandard gelöscht: ", "Agenturstandard gelöscht: ", "Standards | ", "", "") # SAVE AND UPDATE @receiver(post_save, sender=Standards) def save_standard(sender, instance, **kwargs): targeturl = settings.BASE_URL + "standards/standard/" + str(instance.pk) + "/single" # NEW STANDARD if(kwargs["created"] and len(instance.name) > 0): if(instance.public): newNotifiyPush(0, instance, " es wurde ein neuer Agenturstandard erstellt: ", "Neuer Agenturstandard: ", "Standards | ", "newstandard", targeturl) else: usersofagency = User.objects.filter(profile__agency__pk=instance.agency.pk) for user in usersofagency: if(user.has_perm("users.standardmanager") and user.usernotifications.standard_created_unpub_push): newnotification = UserNotification(touser=user, notificationtext="Neuer unveröffentlichter Agenturstandard: " + instance.name, notificationtype="newstandard", elementid=instance.pk) newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Standards | Neuer unveröffentlichter Agenturstandard: " + instance.name}) if(user.has_perm("users.standardmanager") and user.usernotifications.standard_created_unpub_mail): notificationtext = " es wurde ein neuer unveröffentlichter Agenturstandard erstellt: " + instance.name sendMailNoti(notificationtext, user) # Standard wurde aktualisiert else: newNotifiyPush(1, instance, " es wurde ein neuer Agenturstandard aktualisiert: ", "Agenturstandard aktualisiert: ", "Standards | ", "newstandard", targeturl) # SIGNAL FOR NEWS @receiver(post_save, sender=News) def save_news(sender, instance, **kwargs): if(kwargs["created"]): targeturl = settings.BASE_URL + "news/news/" + str(instance.pk) + "/single" # Prüfung, ob die News SOFORT online geht oder später if(instance.go_online_on < timezone.now() and instance.agnotify): newNotifiyPush(0, instance, " es gibt neue Agenturnews: ", "Neue Agenturnews: ", "News | ", "", targeturl) else: instance.agnotify = False instance.save() # SIGNALS FOR TASK @receiver(signal=m2m_changed, sender=Tasks.usersfield.through) def adjust_group_notifications_task(instance, action, reverse, model, pk_set, using, *args, **kwargs): # A USER WAS TOUCHED ATT HIS TASKS user_touched = User.objects.get(pk=list(pk_set)[0]) taskname = instance.name # PUSH NOTIFICATION FOR GROUOPCHANGES if(user_touched.usernotifications.task_activity_push): if(action == 'post_remove'): newnotification = UserNotification(touser=user_touched, notificationtext="Sie wurden von der Tätigkeit " + taskname + " entfernt.", notificationtype="taskchange") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user_touched.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Tätigkeitsbereich | Sie wurden von der Tätigkeitn " + instance.name + " entfernt."}) # A USER WAS ADDED TO A GROUP elif(action == 'post_add'): newnotification = UserNotification(touser=user_touched, notificationtext="Sie wurden der Tätigkeit " + taskname + " zugeordnet.", notificationtype="taskchange") newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user_touched.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__Tätigkeitsbereich | Sie wurden der Tätigkeitn " + instance.name + " zugeordnet."}) # E-MAILNOTIFICATIONS FOR GROUPCHANGES if(user_touched.usernotifications.task_activity_mail): notificationtext = "" if(action == 'post_remove'): notificationtext = "Sie wurden von der Tätigkeit " + taskname + " entfernt." sendMailNoti(notificationtext, user_touched) # A USER WAS ADDED TO A GROUP elif(action == 'post_add'): notificationtext = "Sie wurden der Tätigkeit " + taskname + " zugeordnet." sendMailNoti(notificationtext, user_touched) ''' newNotifiyPush @param: instance - Objekt des Signals mode - Modus 0 --> CREATED, 1 --> UPDATE, 3 --> DELETE mailtext - Text in der Benachrichtigung zB " es gibt neue Ordner: " notifytext - Text in der PUSH-Nachricht zB "Neuer Ordner: " pushtext - Typ bei PUSH (hinter pushnotification__) zB "Ordner | " + notifytext notifytype - Typ für Verlinkung targeturl - URL für Verlinkung, Default = "" ''' def newNotifiyPush(mode, instance, mailtext, notifytext, pushtext, notifytype, targeturl=""): usersofagency = User.objects.filter(profile__agency__pk=instance.agency.pk) # CREATED if(mode == 0): for user in usersofagency: if(user.usernotifications.filedir_created_mail): notificationtext = mailtext + instance.name sendMailNoti(notificationtext, user, targeturl) if(user.usernotifications.filedir_created_push): newnotification = UserNotification(touser=user, notificationtext=notifytext + instance.name, notificationtype="", elementid=instance.pk) newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__"+ pushtext + notifytext + instance.name}) # UPDATED elif(mode == 1): for user in usersofagency: if(user.usernotifications.filedir_update_mail): notificationtext = mailtext + instance.name sendMailNoti(notificationtext, user, targeturl) if(user.usernotifications.filedir_update_push): newnotification = UserNotification(touser=user, notificationtext=notifytext + instance.name, notificationtype="", elementid=instance.pk) newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__" + pushtext + notifytext + instance.name}) #DELETE elif(mode == 2): usersofagency = User.objects.filter(profile__agency__pk=instance.agency.pk) for user in usersofagency: if(user.usernotifications.filedir_delete_mail): notificationtext = mailtext + instance.name sendMailNoti(notificationtext, user, targeturl) if(user.usernotifications.filedir_delete_push): newnotification = UserNotification(touser=user, notificationtext=notifytext + instance.name, notificationtype="", elementid=instance.pk) newnotification.save() channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)("user_" + str(user.pk), {'type' : 'pushhandler', 'pushtext' : "pushnotification__" + pushtext + notifytext + instance.name}) # DIRS @receiver(post_save, sender=DataDir) def save_dir(sender, instance, **kwargs): if(kwargs["created"] and len(instance.name) > 0): newNotifiyPush(0, instance, " es gibt neue Ordner: ", "Neuer Ordner: ", "Ordner | ", "", "") elif(len(instance.name) > 0): newNotifiyPush(1, instance, " Ordner wurden aktualisiert: ", "Aktualisierter Ordner: ", "Ordner | ", "", "") @receiver(pre_delete, sender=DataDir) def del_dir(sender, instance, **kwargs): newNotifiyPush(2, instance, " ein Ordner wurde gelöscht: ", "Ordner gelöscht: ", "Ordner | ", "", "") # Signals for FILES @receiver(post_save, sender=DataFile) def save_file(sender, instance, **kwargs): if(kwargs["created"] and len(instance.name) > 0): newNotifiyPush(0, instance, " es gibt eine neue Datei: ", "Neue Datei: ", "Dateien | ", "", "") elif(len(instance.name) > 0): newNotifiyPush(1, instance, " Datei wurde aktualisiert: ", "Aktualisierter Datei: ", "Dateien | ", "", "") @receiver(pre_delete, sender=DataFile) def del_file(sender, instance, **kwargs): newNotifiyPush(2, instance, " eine Datei wurde gelöscht: ", "Datei gelöscht: ", "Dateien | ", "", "") # QUICKLINKS @receiver(post_save, sender=QuickLinks) def save_ql(sender, instance, **kwargs): if(kwargs["created"] and len(instance.name) > 0): newNotifiyPush(0, instance, " es gibt einen neuen Quicklink: ", "Neuer Quicklink: ", "Quicklinks | ", "", "") elif(len(instance.name) > 0): newNotifiyPush(1, instance, " Quicklink wurde aktualisiert: ", "Aktualisierter Quicklink: ", "Quicklinks | ", "", "") @receiver(pre_delete, sender=QuickLinks) def del_ql(sender, instance, **kwargs): newNotifiyPush(2, instance, " ein Quicklink wurde gelöscht: ", "Quicklink gelöscht: ", "Quicklinks | ", "", "") # CONTACTS @receiver(post_save, sender=AGContacts) def save_contact(sender, instance, **kwargs): if(kwargs["created"] and len(instance.name) > 0): newNotifiyPush(0, instance, " es gibt einen neuen Kontakt: ", "Neuer Kontakt: ", "Kontakte | ", "", "") elif(len(instance.name) > 0): newNotifiyPush(1, instance, " Kontakt wurde aktualisiert: ", "Aktualisierter Kontakt: ", "Kontakte | ", "", "") @receiver(pre_delete, sender=AGContacts) def del_contact(sender, instance, **kwargs): newNotifiyPush(2, instance, " ein Kontakt wurde gelöscht: ", "Kontakt gelöscht: ", "Kontakte | ", "", "") # PASSWORDS @receiver(post_save, sender=AGPassword) def save_password(sender, instance, **kwargs): if(kwargs["created"] and len(instance.name) > 0): newNotifiyPush(0, instance, " es gibt ein neues Passwort: ", "Neues Passwort: ", "Passwörter | ", "", "") elif(len(instance.name) > 0): newNotifiyPush(1, instance, " Passwort wurde aktualisiert: ", "Aktualisiertes Passwort: ", "Passwörter | ", "", "") @receiver(pre_delete, sender=AGPassword) def del_password(sender, instance, **kwargs): newNotifiyPush(2, instance, " ein Passwort wurde gelöscht: ", "Passwort gelöscht: ", "Passwörter | ", "", "") # Join eines Agenturverbunds @receiver(signal=post_save, sender=AgencyNetworkPreperation) def save_agjoin_prep(sender, instance, **kwargs): newnotification = UserNotification(touser=instance.target_network.creator, notificationtext="Eine Agentur möchte Ihrem Verbund beitreten.", notificationtype="wantedag", elementid=instance.pk) newnotification.save() # REQUEST MAIN STUFF @receiver(signal=request_started) def receiver_function(sender, **kwargs): # DELETES ALL PRESENCE-OBJECTS LOWER THAN 15 MINUTES now_minus = datetime.datetime.now() - datetime.timedelta(minutes=2) Presence.objects.filter(last_seen__lt=now_minus).delete() users = User.objects.all() for user in users: user_notification = [] try: user_notification = UserNotifications.objects.get(user=user) except: if(len(user_notification) == 0): user_notification = UserNotifications(user=user) user_notification.save() # PRESENCE CHANGED @receiver(signal=presence_changed) def update_presence_live(sender, **kwargs): channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)(str(kwargs["room"]), {'type' : 'update_presence_live'}) ''' ABWESENHEIT BERECHNUNG UND SPEICHERUNG DER NEUEN URLAUBSTAGE - VERWEIS AUF timemenagement.views ''' @receiver(signal=post_save, sender=Absence) def save_newabsence(sender, instance, **kwargs): post_save.disconnect(save_newabsence, sender=sender) if(instance.reason.is_holiday): newdata = getFinalHolidayData(instance) abinfo = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year))[0] abinfo_lastyear = "" abinfo_nextyear = "" is_lastyear = False abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year-1)) if(len(abinfo_lastyear) > 0): is_lastyear = True abinfo_lastyear = abinfo_lastyear[0] is_nextyear = False abinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year+1)) if(len(abinfo_nextyear) > 0): is_nextyear = True abinfo_nextyear = abinfo_nextyear[0] multiple_info_needays = False if(hasattr(newdata[3], "__len__")): multiple_info_needays = True # Gleiches Jahr MIT Rest if(multiple_info_needays and newdata[3][2] == False): # Rest ist positiv, daher bleibt rest übrig, rest wird in absence gespeichert und vom rest des Jahres-Restes abgezogen # Rest ist positiv, damit bleibt Rest übrig if(newdata[3][0] > 0): instance.holidays_rest = abinfo.restdays - newdata[3][0] instance.save() abinfo.restdays = newdata[3][0] abinfo.save() # Rest ist negativ elif(newdata[3][0] < 0): instance.holidays_rest = (abinfo.restdays - newdata[3][0]) - newdata[3][0]*(-1) instance.holidays_normal = newdata[3][0]*(-1) instance.save() abinfo.restdays = 0 abinfo.days_inuse = abinfo.days_inuse + newdata[3][0]*(-1) abinfo.save() # Rest ist Urlaubsdauer else: instance.holidays_rest = abinfo.restdays instance.save() #abinfo.days_inuse = abinfo.days_inuse + abinfo.restdays abinfo.restdays = 0 abinfo.save() # Gleiches Jahr ohne Rest elif(not multiple_info_needays): abinfo.days_inuse = abinfo.days_inuse + newdata[3] abinfo.save() instance.holidays_normal = newdata[3] instance.save() # Mehrere Jahre elif(multiple_info_needays and newdata[3][2] == True): abinfo.days_inuse = abinfo.days_inuse + newdata[3][0] abinfo.save() abinfo_nextyear.days_inuse = abinfo_nextyear.days_inuse + newdata[3][1] abinfo_nextyear.restdays = abinfo_nextyear.restdays - newdata[3][3] abinfo_nextyear.save() # Hier werden alle benötigten Tage von Vor- und Nächstem Jahr gespeichert instance.holidays_normal = newdata[3][0] instance.holidays_rest = 0 instance.holidays_normal_next = newdata[3][1] instance.holidays_rest_next = newdata[3][3] instance.save() else: print("Absence-Object is no holiday...") post_save.connect(save_newabsence, sender=sender) @receiver(signal=pre_delete, sender=Absence) def delete_absence(sender, instance, **kwargs): if(instance.reason.is_holiday): newdata = getFinalHolidayData(instance) abinfo = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year))[0] abinfo_lastyear = "" abinfo_nextyear = "" is_lastyear = False abinfo_lastyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year-1)) if(len(abinfo_lastyear) > 0): is_lastyear = True abinfo_lastyear = abinfo_lastyear[0] is_nextyear = False abinfo_nextyear = list(UserYearAbsenceInfo.objects.filter(user=instance.user, year=instance.start.year+1)) if(len(abinfo_nextyear) > 0): is_nextyear = True abinfo_nextyear = abinfo_nextyear[0] multiple_info_needays = False if(hasattr(newdata[3], "__len__")): multiple_info_needays = True # Mehrere Jahre oder nicht if(instance.start.year != instance.end.year): abinfo.days_inuse = abinfo.days_inuse - instance.holidays_normal abinfo.save() abinfo_nextyear.days_inuse = abinfo_nextyear.days_inuse - instance.holidays_normal_next abinfo_nextyear.restdays = abinfo_nextyear.restdays + instance.holidays_rest_next abinfo_nextyear.save() else: # Gleiches Jahr MIT Rest abinfo.days_inuse = abinfo.days_inuse - instance.holidays_normal abinfo.restdays = abinfo.restdays + instance.holidays_rest abinfo.save() else: print("Absence-Object is no holiday...") def getFinalHolidayData(abscence): user = abscence.user usertimedata = UserTime.objects.get(user=user) today = date.today() start_day_obj = abscence.start end_day_obj = abscence.end try: holidayloose_date = datetime.date(start_day_obj.year, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0])) except: holidayloose_date = datetime.date(2020, int(usertimedata.loose_holidedate.split(".")[1]), int(usertimedata.loose_holidedate.split(".")[0])) #start_half = abscence.start_ishalf #end_half = abscence.end_ishalf start_half = False if abscence.startday_info == "1" or abscence.startday_info == "2": start_half = True end_half = False if abscence.endday_info == "1" or abscence.endday_info == "2": end_half = True choosenyear = abscence.start.year yeardata = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear))[0] holiday_thisyear = 0 holiday_lastyear = yeardata.restdays holiday_nextyear = 0 try: holiday_nextyear = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear+1))[0].days - list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear+1))[0].days_inuse holiday_nextyear_rest = list(UserYearAbsenceInfo.objects.filter(user=user, agency=user.profile.agency, year=choosenyear+1))[0].restdays except: holiday_nextyear = yeardata.days # Urlaub innerhalb eines Jahres inkl. Prüfung auf Resturlaubsanspruch if(end_day_obj.year == start_day_obj.year): # Startt des Urlaubs NACH Verfallsdatum - nur aktuelles JAhr und die Zahl interessiert if(start_day_obj > holidayloose_date): need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1) holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days else: need_days = (calculateHolidays(user, start_day_obj, end_day_obj, start_half, end_half))*(-1) # Kein Resturlaub if(yeardata.restdays == 0.0): holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days # Resturlaub vorhanden, berechne mit Resturlaub else: holiday_lastyear = yeardata.restdays holiday_thisyear = yeardata.days - yeardata.days_inuse temp_holiday = holiday_lastyear - need_days if(temp_holiday < 0): holiday_lastyear = 0 holiday_thisyear = yeardata.days - yeardata.days_inuse + temp_holiday need_days = [temp_holiday, holiday_thisyear, False] else: holiday_lastyear = yeardata.restdays - need_days need_days = [temp_holiday, holiday_lastyear, False] # Urlaub geht über das nächstes Jahr hinweg else: two_years = True holiday_lastyear = yeardata.restdays date_splitter = datetime.date(end_day_obj.year, 1, 1) need_days_this = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1) need_days_next = (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) need_days = (calculateHolidays(user, start_day_obj, date_splitter, start_half, False))*(-1) + (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) holiday_thisyear = yeardata.days - yeardata.days_inuse - need_days_this days_nextyear_normal = 0 days_nextyear_rest = 0 # Urlaub nächstes Jahr MIT und OHNE Rest if(holiday_nextyear_rest == 0.0): holiday_nextyear = holiday_nextyear - (calculateHolidays(user, date_splitter, end_day_obj, False, end_half))*(-1) else: temprest = holiday_nextyear_rest - need_days_next # Rest reicht! if(temprest >= 0): holiday_nextyear_rest = temprest days_nextyear_normal = 0 days_nextyear_rest = need_days_next # Rest reicht nicht else: holiday_nextyear_rest = 0 holiday_nextyear += temprest days_nextyear_rest = need_days_next + temprest days_nextyear_normal = temprest * -1 # TAGE NORMAL, TAGE NEXT NORMAL, TRUE für 2jahre, TAGE NEXT REST need_days = [need_days_this, days_nextyear_normal, True, days_nextyear_rest] data = [ holiday_thisyear, holiday_lastyear, holiday_nextyear, need_days ] return data def calculateHolidays(user, start, end, start_half, end_half): restdays = 0 allfreedays = FreeDays.objects.filter(agency=user.profile.agency) if(end == start): if(start_half): return restdays - 0.5 else: return restdays - 1 else: if(end < start): return False else: counter = 0 if(start_half): counter -= 0.5 if(end_half): counter -= 0.5 weekdays = [6,7] freedaycounter = 0 for dt in daterange(start, end): if dt.isoweekday() not in weekdays: counter += 1 for freeday in allfreedays.all(): if(dt == freeday.day): freedaycounter += 1 if(dt.isoweekday() == 1): if user.usertime.wd_mo == 0.0: freedaycounter += 1 elif(dt.isoweekday() == 2): if user.usertime.wd_tu == 0.0:# freedaycounter += 1 elif(dt.isoweekday() == 3): if user.usertime.wd_we == 0.0: freedaycounter += 1 elif(dt.isoweekday() == 4): if user.usertime.wd_th == 0.0: freedaycounter += 1 elif(dt.isoweekday() == 5): if user.usertime.wd_fr == 0.0: freedaycounter += 1 return restdays - counter + freedaycounter # Gibt die Woche als Wochentage zurück def daterange(date1, date2): for n in range(int ((date2 - date1).days)+1): yield date1 + timedelta(n)