from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.db import models class EntityFieldConfig(models.Model): entity_type = models.CharField(max_length=100) field_name = models.CharField(max_length=100) is_hidden = models.BooleanField(default=False) display_label = models.CharField(max_length=200, blank=True) sort_order = models.PositiveSmallIntegerField(default=0) class Meta: unique_together = ('entity_type', 'field_name') verbose_name = 'Feldkonfiguration' verbose_name_plural = 'Feldkonfigurationen' def __str__(self): return f'{self.entity_type}.{self.field_name}' class CustomAttribute(models.Model): DATA_TYPE_CHOICES = [ ('text', 'Text'), ('number', 'Zahl'), ('date', 'Datum'), ('boolean', 'Ja/Nein'), ('url', 'URL'), ('email', 'E-Mail'), ] content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') key = models.CharField(max_length=100) label = models.CharField(max_length=200) value = models.TextField(blank=True) data_type = models.CharField(max_length=20, choices=DATA_TYPE_CHOICES, default='text') sort_order = models.PositiveSmallIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['sort_order', 'created_at'] indexes = [models.Index(fields=['content_type', 'object_id'])] def __str__(self): return f'{self.label}: {self.value}' class Freigabe(models.Model): TYP_CHOICES = [ ('teilnahme', 'Teilnahme-Freigabe'), ('ablehnung', 'Ablehnungs-Freigabe'), ('recht', 'Rechtliche Freigabe'), ('preis', 'Preis-Freigabe'), ('abgabe', 'Abgabe-Freigabe'), ('standarddokument', 'Standarddokument-Freigabe'), ('referenz', 'Referenz-Freigabe'), ] STATUS_CHOICES = [ ('erteilt', 'Erteilt'), ('abgelehnt', 'Abgelehnt'), ('ausstehend', 'Ausstehend'), ] content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') freigabe_typ = models.CharField(max_length=30, choices=TYP_CHOICES) freigebende_person = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name='erteilte_freigaben' ) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='erteilt') kommentar = models.TextField(blank=True) timestamp = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['-timestamp'] verbose_name = 'Freigabe' verbose_name_plural = 'Freigaben' def __str__(self): return f'{self.get_freigabe_typ_display()} — {self.status}' class FlexibleModel(models.Model): custom_attributes = GenericRelation(CustomAttribute) freigaben = GenericRelation(Freigabe) def get_hidden_fields(self): model_name = self._meta.model_name return set( EntityFieldConfig.objects.filter( entity_type=model_name, is_hidden=True ).values_list('field_name', flat=True) ) def get_visible_field_names(self): hidden = self.get_hidden_fields() return [ f.name for f in self._meta.get_fields() if hasattr(f, 'column') and not f.name.startswith('_') and f.name not in hidden ] class Meta: abstract = True