from django.db import models from django.utils.translation import get_language, gettext_lazy as _ from .model_account import EmployeeProfile from .model_shared import REQUEST_STATUS_CHOICES, normalized_language_code class OnboardingRequest(models.Model): STATUS_CHOICES = REQUEST_STATUS_CHOICES full_name = models.CharField(max_length=255, verbose_name='Vorname und Nachname') gender = models.CharField(max_length=20, blank=True, choices=[('herr', _('Herr')), ('frau', _('Frau')), ('divers', _('Divers'))], verbose_name='Anrede') job_title = models.CharField(max_length=255, blank=True, verbose_name='Berufsbezeichnung') department = models.CharField(max_length=255, blank=True, verbose_name='Abteilung') work_email = models.EmailField(verbose_name='Gewünschte dienstliche E-Mail-Adresse') contract_start = models.DateField(verbose_name='Vertragsbeginn') employment_type = models.CharField(max_length=20, blank=True, choices=[('befristet', _('befristet')), ('unbefristet', _('unbefristet'))], verbose_name='Beschäftigungsverhältnis') employment_end_date = models.DateField(null=True, blank=True, verbose_name='Enddatum (nur bei befristet)') handover_date = models.DateField(null=True, blank=True, verbose_name='Gewünschtes Übergabedatum der Geräte') order_business_cards = models.BooleanField(default=False, verbose_name='Bestellung Visitenkarten') business_card_name = models.CharField(max_length=255, blank=True, verbose_name='Name (Visitenkarte)') business_card_title = models.CharField(max_length=255, blank=True, verbose_name='Titel (Visitenkarte)') business_card_email = models.EmailField(blank=True, verbose_name='E-Mailadresse (Visitenkarte)') business_card_phone = models.CharField(max_length=100, blank=True, verbose_name='Telefonnummer (Visitenkarte)') group_mailboxes_required = models.BooleanField(default=False, verbose_name='Gruppenpostfächer erforderlich?') group_mailboxes = models.TextField(blank=True, verbose_name='Gruppenpostfächer') needed_devices = models.TextField(blank=True, verbose_name='Benötigte Geräte und Gegenstände') needed_software = models.TextField(blank=True, verbose_name='Benötigte Software') needed_accesses = models.TextField(blank=True, verbose_name='Benötigte Zugänge') needed_workspace_groups = models.TextField(blank=True, verbose_name='Benötigte Gruppen im Workspace') additional_software_needed = models.BooleanField(default=False, verbose_name='Wird zusätzliche Software benötigt?') additional_software = models.TextField(blank=True, verbose_name='Zusätzlich gewünschte Software (ohne Garantie)') additional_hardware_needed = models.BooleanField(default=False, verbose_name='Wird zusätzliche Hardware benötigt?') additional_hardware = models.TextField(blank=True, verbose_name='Zusätzliche Hardware') additional_hardware_other = models.TextField(blank=True, verbose_name='Weitere Hardware (Freitext)') additional_access_needed = models.BooleanField(default=False, verbose_name='Werden weitere Zugänge benötigt?') additional_access_text = models.TextField(blank=True, verbose_name='Weitere Zugänge (Freitext)') needed_resources = models.TextField(blank=True, verbose_name='Benötigte Ressourcen') phone_number = models.CharField(max_length=100, blank=True, verbose_name='Telefon-Direktwahl') successor_required = models.BooleanField(default=False, verbose_name='Neue Mitarbeitende ist Nachfolge von?') successor_name = models.CharField(max_length=255, blank=True, verbose_name='Name der Vorgängerperson') inherit_phone_number = models.BooleanField(default=False, verbose_name='Telefonnummer von Vorgängerperson übernehmen') additional_notes = models.TextField(blank=True, verbose_name='Raum für zusätzliche Anmerkungen und Wünsche') onboarded_by_email = models.EmailField(blank=True, verbose_name='E-Mail der anfordernden Person') onboarded_by_name = models.CharField(max_length=255, blank=True, verbose_name='Name der anfordernden Person') agreement = models.TextField(blank=True, verbose_name='Vereinbarung') signature_url = models.URLField(blank=True, verbose_name='Unterschrift') signature_image = models.ImageField(upload_to='signatures/', blank=True, null=True, verbose_name='Unterschrift (Bilddatei)') personalized_text = models.TextField(blank=True, verbose_name='Personalisierter Text für PDF', help_text='Optionaler individueller Textblock im Onboarding PDF.') custom_field_values = models.JSONField(default=dict, blank=True) generated_pdf_path = models.CharField(max_length=500, blank=True) intro_pdf_path = models.CharField(max_length=500, blank=True) processing_status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='submitted') last_error = models.TextField(blank=True) preferred_language = models.CharField(max_length=10, blank=True, default='de', db_default='de') created_at = models.DateTimeField(auto_now_add=True) def __str__(self) -> str: return f'Onboarding #{self.id} - {self.full_name}' def save(self, *args, **kwargs): self.preferred_language = normalized_language_code(self.preferred_language) super().save(*args, **kwargs) class ScheduledWelcomeEmail(models.Model): STATUS_CHOICES = [ ('scheduled', _('Geplant')), ('paused', _('Pausiert')), ('cancelled', _('Abgebrochen')), ('sent', _('Gesendet')), ('failed', _('Fehlgeschlagen')), ] onboarding_request = models.OneToOneField(OnboardingRequest, on_delete=models.CASCADE) recipient_email = models.EmailField() send_at = models.DateTimeField() status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='scheduled') celery_task_id = models.CharField(max_length=100, blank=True) sent_at = models.DateTimeField(null=True, blank=True) last_error = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ['-send_at', '-id'] def __str__(self) -> str: return f'Welcome #{self.id} | {self.recipient_email} | {self.status}' class IntroChecklistItem(models.Model): SECTION_CHOICES = [ ('workplace', _('Geräte und Arbeitsplatz')), ('accounts', _('Konten und Berechtigungen')), ('software', _('Software und Tools')), ('process', _('Prozesse und Hinweise')), ] OPERATOR_CHOICES = [ ('always', _('Immer anzeigen')), ('contains', _('Enthält')), ('equals', _('Ist gleich')), ('is_true', _('Ist Ja / aktiv')), ('is_false', _('Ist Nein / inaktiv')), ] section = models.CharField(max_length=30, choices=SECTION_CHOICES) label = models.CharField(max_length=255) label_en = models.CharField(max_length=255, blank=True) sort_order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) condition_field = models.CharField(max_length=80, blank=True) condition_operator = models.CharField(max_length=20, choices=OPERATOR_CHOICES, default='always') condition_value = models.CharField(max_length=255, blank=True) class Meta: ordering = ['section', 'sort_order', 'label'] def __str__(self) -> str: return f'{self.get_section_display()}: {self.label}' def translated_label(self, language_code: str | None = None) -> str: lang = (language_code or get_language() or 'de').split('-')[0] if lang == 'en' and self.label_en.strip(): return self.label_en.strip() return self.label.strip() class OnboardingIntroductionSession(models.Model): STATUS_CHOICES = [('draft', _('Entwurf')), ('completed', _('Abgeschlossen'))] onboarding_request = models.OneToOneField(OnboardingRequest, on_delete=models.CASCADE) checklist_state = models.JSONField(default=dict, blank=True) notes = models.TextField(blank=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') completed_at = models.DateTimeField(null=True, blank=True) completed_by_name = models.CharField(max_length=255, blank=True) exported_pdf_path = models.CharField(max_length=500, blank=True) updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self) -> str: return f'Einweisung #{self.id} | {self.onboarding_request.full_name} | {self.status}' class OffboardingRequest(models.Model): STATUS_CHOICES = REQUEST_STATUS_CHOICES employee_profile = models.ForeignKey(EmployeeProfile, null=True, blank=True, on_delete=models.SET_NULL) full_name = models.CharField(max_length=255, verbose_name='Vorname und Nachname') work_email = models.EmailField(verbose_name='Dienstliche E-Mail-Adresse') department = models.CharField(max_length=255, blank=True, verbose_name='Abteilung') job_title = models.CharField(max_length=255, blank=True, verbose_name='Berufsbezeichnung') last_working_day = models.DateField(verbose_name='Letzter Arbeitstag') offboarding_reason = models.TextField(blank=True, verbose_name='Grund') notes = models.TextField(blank=True, verbose_name='Notizen') signature = models.CharField(max_length=255, blank=True, verbose_name='Unterschrift (Name)') requested_by_email = models.EmailField(verbose_name='E-Mail der anfordernden Person') requested_by_name = models.CharField(max_length=255, blank=True, verbose_name='Name der anfordernden Person') preferred_language = models.CharField(max_length=10, blank=True, default='de', db_default='de') generated_pdf_path = models.CharField(max_length=500, blank=True) custom_field_values = models.JSONField(default=dict, blank=True) processing_status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='submitted') last_error = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self) -> str: return f'Offboarding #{self.id} - {self.full_name}' def save(self, *args, **kwargs): self.preferred_language = normalized_language_code(self.preferred_language) super().save(*args, **kwargs)