from django.db import models from django.contrib.auth.models import User from django.conf import settings from PIL import Image from django.utils import timezone # MAKE EMAIL UNIQUE from django.contrib.auth.models import User, Group, Permission from django.contrib.contenttypes.models import ContentType import datetime # UNIQUE and NO BLANK fields while user-registration User._meta.get_field('email')._unique = True User._meta.get_field('email').blank = False User._meta.get_field('first_name').blank = False User._meta.get_field('last_name').blank = False # PATH FOR AGENCYPIC def picturepath_agency(instance, filename): # file will be uploaded to MEDIA_URL/agency_// return 'agencydata/agency_{0}/agencystats/{1}'.format(instance.pk, filename) # PATH FOR PROFILEPICS def picturepath_user(instance, filename): return 'agencydata/agency_{0}/agencystats/profilepics/{1}'.format(instance.agency.pk, filename) ''' Class AgencyNetworkPreperation Regelt den Join-Prozess einer Agentur in einen Verbund, um Anfrage und Status der Anfrage zu prüfen. Kommt nur zum tragen, wenn ein AgenturVerbund auf publicjoin=False ist! ''' class AgencyNetworkPreperation(models.Model): target_network = models.ForeignKey("AgencyNetwork", on_delete=models.CASCADE) wanted_agency = models.ForeignKey("Agency", on_delete=models.PROTECT, blank=True) status = models.IntegerField() ''' Class AgencyNetwork Bildet einen Agenturverbund ab ''' class AgencyNetwork(models.Model): name = models.CharField(default="", max_length=200) adminagencys = models.ManyToManyField("Agency", related_name="AdministrationAgencys") creator = models.ForeignKey(User, on_delete=models.PROTECT, blank=True) creator_agency = models.ForeignKey("Agency", on_delete=models.PROTECT, blank=True) created_on = models.DateTimeField(default=timezone.now) lastactivity = models.DateTimeField(default=timezone.now) members = models.ManyToManyField("Agency", related_name="MemberAgencys", blank=True) sharemembers = models.ManyToManyField("Agency", related_name="ShareMemberAgencys", blank=True) publicjoin = models.BooleanField(default=False) networkid = models.CharField(default="", max_length=30) standards = models.ManyToManyField("standards.Standards", related_name="sharedstandards", blank=True) def __str__(self): return f'{self.name}' ''' Class Agency Speichert alle Infos für die Agency, darunter später auch die Aufgaben und Bereiche Bezug normale User: Erhalten bei Erstellung durch den Administrator automatisch die aktuelle agency: request.user.profile.agency --> Dahinter ist das Agency-Objekt! ''' class Agency(models.Model): name = models.CharField(default="", max_length=200) inhaber = models.CharField(default="", max_length=200, blank=True) street = models.CharField(default="", max_length=200, blank=True) city = models.CharField(default="", max_length=200, blank=True) plz = models.CharField(default="", max_length=5, blank=True) agency_email = models.EmailField(default="", blank=True) phone = models.CharField(default="", max_length=50, blank=True) agencypic = models.ImageField(default='ag_default.jpg', upload_to=picturepath_agency, blank=True) # MONEY #balance = models.FloatField(default=0.0, max_length=9, blank=True) #nextdebiting = models.DateTimeField(default=timezone.now, blank=True) #monthlyprice = models.FloatField(default=25.0, max_length=9, blank=True) # Payment-Status # 0 = Normal, Agentur muss ganz normal bezahlen # 1 = Agentur ist kostenlos dabei! paymentstatus = models.IntegerField(default=0, null=True) # ID für die Verbindung mit Lexoffice lexofficeid = models.CharField(default="", max_length=200, blank=True) # Bezahlplan 1,3,6,12 Monate #0 = Kein Bezahkplan ausgewählt paymentplan = models.IntegerField(default=0, null=True, blank=True) # Registrierdatum der Agentur registerdate = models.DateField(default=timezone.now, null=True) payment_address = models.EmailField(default=None, blank=True, null=True) # agb = models.BooleanField(default=False) contract = models.BooleanField(default=False) # MODULEEINSTELLUNGEN FÜR DIE AGENTUR module_news = models.BooleanField(default=True) module_organizer = models.BooleanField(default=True) module_files = models.BooleanField(default=True) module_organigramm = models.BooleanField(default=True) # Steckbrief dynamisch aus Standard dynamicprofile = models.BooleanField(default=True) module_messages = models.BooleanField(default=True) module_chat = models.BooleanField(default=True) # KOSTENPFLICHTIGE MODULE # Abwesenheits- und Zeiterfassung # Modul aktiv/deaktiviert module_timemanagement = models.BooleanField(default=False) module_timemanagement_price = models.FloatField(default=10.0, max_length=9, blank=True) # Zeiterfassung Ja/Nein #module_timemanagement_ze = models.BooleanField(default=False) vve = models.CharField(default="", max_length=200, blank=True) # RECOVERDIR module_recoverdir = models.BooleanField(default=False) def __str__(self): return f'{self.name}' # Hier wird definiert, welche Parameter in der URL übertragen werden inkl. Bezeichner #def get_absolute_url(self): # return reverse('agency-update', kwargs={'pk':self.pk}) @property def get_photo_url(self): if self.agencypic and hasattr(self.agencypic, 'url'): return self.agencypic.url else: return settings.MEDIA_URL + "ag_default.jpg" # Speichern der Rechnungs-ID von LexOffice class AgencyBills(models.Model): lexid = models.CharField(max_length=200, default="", null=True, blank=True) agency = models.ForeignKey(Agency, on_delete=models.PROTECT) billtype = models.CharField(default="", max_length=200) billdate = models.DateField(default=timezone.now) billnumber = models.CharField(default="", max_length=200) billstatus = models.CharField(default="", max_length=200, null=True, blank=True) start = models.DateField(default=timezone.now) end = models.DateField(default=timezone.now) plan = models.CharField(default="", max_length=20) usercount = models.IntegerField(default=0) def __str__(self): return f'{self.lexid}' ''' Class AgencyJob ''' class AgencyJob(models.Model): name = models.CharField(default="", max_length=80) agency = models.ForeignKey(Agency, on_delete=models.PROTECT) def __str__(self): return f'{self.name}' ''' Class Profile Klasse für die Zusatzinfos eines Nutzers. - Vorname - Nachname - Email - Bild - Telefonnummer - Fest - Mobil - Funktion - Auswahlfelder - Außendienst/Innendienst/Azubi - Rollen - Bereiche - Aufgaben ''' class Profile(models.Model): # Wenn der User gelöscht wird, wird auch das Profil gelöscht user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True, default=None) parent = models.ForeignKey(User, on_delete=models.PROTECT, blank=True, null=True, related_name='parent_user') phoneland = models.CharField(max_length=60, blank=True) phonemobile = models.CharField(max_length=60, blank=True) phone_public = models.BooleanField(default=False) # Wenn die Funktion gelöscht wird, wird die FUNC auf NULL gesetzt func = models.ForeignKey("AgencyJob", blank=True, null=True, default=None, on_delete=models.SET_NULL) # Wenn dieses Profil gelöscht wird, wird NICHT die Agency geslöscht agency = models.ForeignKey(Agency, on_delete=models.PROTECT) image = models.ImageField(default='default.jpg', upload_to=picturepath_user, blank=True) compfunc = models.CharField(max_length=60, blank=True) visible = models.BooleanField(default=True) persnumber = models.CharField(default="", max_length=50, blank=True) # TOOLTIPPS showtooltips = models.BooleanField(default=True) # NOTIFICATIONS #NEWS # Mitteilung bei neuen News innerhalb der Agentur news_mail = models.BooleanField(default=True) news_push = models.BooleanField(default=True) #STANDARDS # Benutzerstandard wurde veröffentlicht user_standard_public_mail = models.BooleanField(default=False) user_standard_public_push = models.BooleanField(default=True) #STANDARDS # Neue Standards agency_new_standard_mail = models.BooleanField(default=False) agency_new_standard_push = models.BooleanField(default=True) # GROUPS # Neuer Gruppe zugeordnet add_new_group_mail = models.BooleanField(default=False) add_new_group_push = models.BooleanField(default=True) # TASKS # Einer neuen Tätigkeit zugewiesen add_task_mail = models.BooleanField(default=False) add_task_push = models.BooleanField(default=True) # MESSAGES # Mitteilungen user_messages_mail = models.BooleanField(default=True) user_messages_push = models.BooleanField(default=True) # ONLINESTATUS ''' 0 = ONLINE - green 1 = BESCHAFTIGT - red 2 = ABWESEND - orange 3 = OFFLINE - grey ''' onlinestatus = models.IntegerField(default=0) def __str__(self): return f'{self.user.last_name}' # Hier Path für Templates des Models mit Parametern def get_absolute_url(self): return reverse('users-update', kwargs={'pk':self.pk}) # Erst Oberklasse speichern, dann Bild verkleinern ''' def save(self, **kwargs): super().save() if self.image: img = Image.open(self.image.path) # Bildspeichergröße if(img.height > 300 or img.width > 300): output_size = (300,300) img.thumbnail(output_size) img.save(self.image.path) baseheight = 560 hpercent = (baseheight / float(img.size[1])) wsize = int((float(img.size[0]) * float(hpercent))) img = img.resize((wsize, baseheight), Image.ANTIALIAS) img.save(self.image.path) ''' @property def get_photo_url(self): if self.image and hasattr(self.image, 'url'): return self.image.url else: return settings.MEDIA_URL + "default.jpg" class UserTime(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True, default=None) # TIME ELEMENTS wd_mo = models.FloatField(default=0.0) wd_tu = models.FloatField(default=0.0) wd_we = models.FloatField(default=0.0) wd_th = models.FloatField(default=0.0) wd_fr = models.FloatField(default=0.0) wd_sa = models.FloatField(default=0.0) wd_so = models.FloatField(default=0.0) loose_holidedate = models.CharField(default="30.04.", max_length=6) startdate = models.DateField(default=None, blank=True, null=True) usetime = models.BooleanField(default=False) usetime_start = models.DateField(default=None, blank=True, null=True) ''' UserNotifications Beherbergt alle Benachrichtigungseinstellungen für die User. Ehemals direkt im User-Model gepflegt, aber da es zu viele sind hierher umgezogen ''' class UserNotifications(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True, default=None) # NOTIFICATIONS # STANDARDS standard_created_mail = models.BooleanField(default=False) standard_created_push = models.BooleanField(default=True) standard_update_mail = models.BooleanField(default=False) standard_update_push = models.BooleanField(default=True) standard_delete_mail = models.BooleanField(default=False) standard_delete_push = models.BooleanField(default=True) # Wenn neue Standards erstellt wurden, erhalten alle User mit entsprechenden Recht eine Info, dass neue, unveröffentlichte Standards vorhanden sind standard_created_unpub_mail = models.BooleanField(default=False) standard_created_unpub_push = models.BooleanField(default=True) # NEWS news_created_mail = models.BooleanField(default=True) news_created_push = models.BooleanField(default=True) # FILES filedir_created_mail = models.BooleanField(default=False) filedir_created_push = models.BooleanField(default=True) filedir_update_mail = models.BooleanField(default=False) filedir_update_push = models.BooleanField(default=True) filedir_delete_mail = models.BooleanField(default=False) filedir_delete_push = models.BooleanField(default=True) # Quicklinks ql_created_mail = models.BooleanField(default=False) ql_created_push = models.BooleanField(default=True) ql_update_mail = models.BooleanField(default=False) ql_update_push = models.BooleanField(default=True) ql_delete_mail = models.BooleanField(default=False) ql_delete_push = models.BooleanField(default=True) # Contacts contact_created_mail = models.BooleanField(default=False) contact_created_push = models.BooleanField(default=True) contact_update_mail = models.BooleanField(default=False) contact_update_push = models.BooleanField(default=True) contact_delete_mail = models.BooleanField(default=False) contact_delete_push = models.BooleanField(default=True) # Password password_created_mail = models.BooleanField(default=False) password_created_push = models.BooleanField(default=True) password_update_mail = models.BooleanField(default=False) password_update_push = models.BooleanField(default=True) password_delete_mail = models.BooleanField(default=False) password_delete_push = models.BooleanField(default=True) # MESSAGES message_received_mail = models.BooleanField(default=False) message_received_push = models.BooleanField(default=True) # TASKS task_activity_mail = models.BooleanField(default=False) task_activity_push = models.BooleanField(default=True) # CHAT # Diese Einstellung sorgt dafür, dass User eine Mail/Push erhalten, wenn neue Chatnachrichten vorhanden sind. chat_received_mail = models.BooleanField(default=False) chat_received_push = models.BooleanField(default=True) # Benachrichtigunge, wenn es Raumaktivitäten gab chat_room_activity_mail = models.BooleanField(default=False) chat_room_activity_push = models.BooleanField(default=True) # TIMEMANAGEMENT # Wenn neue Abwesenheitsanfragen kommen, Rechte werden gecheckt und dann wird gesendet absence_created_mail = models.BooleanField(default=True) absence_created_push = models.BooleanField(default=True) # Info, ob ein Nutzer als Vertreter eingesetzt worden ist. absence_user_is_rep_mail = models.BooleanField(default=True) absence_user_is_rep_push = models.BooleanField(default=True) # Info, ob ein Nutzer als Vertreter eingesetzt worden ist REMINDER CronJob zwei Tage vorher absence_user_is_rep_reminder_mail = models.BooleanField(default=True) absence_user_is_rep_reminder_push = models.BooleanField(default=True) # Info an den User, wenn seine Zeitdaten verändert wurden time_data_changed_mail = models.BooleanField(default=True) time_data_changed_push = models.BooleanField(default=True) # GRUPPEN group_activity_mail = models.BooleanField(default=False) group_activity_push = models.BooleanField(default=True) group_rights_mail = models.BooleanField(default=False) group_rights_push = models.BooleanField(default=True) # AGENCYNETWORK # Neuer Standard im Verbund agn_standard_created_mail = models.BooleanField(default=False) agn_standard_created_push = models.BooleanField(default=True) # Neuer Agenturstandard wurde von anderer Agentur übernommen agn_standard_copied_mail = models.BooleanField(default=False) agn_standard_copied_push = models.BooleanField(default=True) # Neuer Kommentar zu einem Standard aus meinem Verbund agn_standard_comment_mail = models.BooleanField(default=False) agn_standard_comment_push = models.BooleanField(default=True) # Reaktion auf einen Kommentar von mir agn_standard_comment_react_mail = models.BooleanField(default=False) agn_standard_comment_react_push = models.BooleanField(default=True) # Änderungen eigener Mitgliedsanfragen in anderen Verbünden agn_own_change_mail = models.BooleanField(default=False) agn_own_change_push = models.BooleanField(default=True) # Änderungen anderer Mitgliedschaften (Beitrittsanfragen!) agn_other_change_mail = models.BooleanField(default=False) agn_other_change_push = models.BooleanField(default=True) class UserYearAbsenceInfo(models.Model): agency = models.ForeignKey(Agency, on_delete=models.PROTECT, default=None) user = models.ForeignKey(User, on_delete=models.CASCADE) year = models.IntegerField() days_inuse = models.FloatField(default=0.0) days = models.FloatField(default=24.0) restdays = models.FloatField(default=0.0) ''' CLASS AgencyGroup Hier werden die Gruppen mit der Agency verbunden ''' class AgencyGroup(models.Model): group = models.OneToOneField(Group, on_delete=models.CASCADE) agency = models.ForeignKey(Agency, on_delete=models.PROTECT) agencygroupname = models.CharField(max_length=60, blank=True) savefordel = models.BooleanField(default=False) is_admin = models.BooleanField(default=False) class Meta: permissions = [ ('agencyinfo', 'Agenturinformationen verändern'), ('agencynetwork', 'Agenturverbund bearbeiten'), ('usermanager', 'Mitarbeiter bearbeiten'), ('groupmanager', 'Gruppen bearbeiten'), ('structuremanager', 'Struktur bearbeiten'), ('standardmanager', 'Standards bearbeiten und freischalten'), ('modulenews', 'News bearbeiten und veröffentlichen'), ('modulesconfig', 'Module verwalten'), ('moduleorganizer', 'Organizer bearbeiten'), ('filesmanager', 'Dateien bearbeiten'), ('filedirmanager', 'Ordner bearbeiten'), ('filesviewer', 'Dateien lesen'), ('absencemanager', 'Abwesenheiten verwalten'), ('recoverdirmanager', 'Notfallhilfe verwalten') ] # SUBCLASS class UserFullName(User): class Meta: proxy = True def __unicode__(self): return "placeholder" def __str__(self): return f'{self.first_name + " " + self.last_name}'