87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
|
|
"""
|
|||
|
|
Datenmodell – Templates, Jobs, Log-Einträge.
|
|||
|
|
"""
|
|||
|
|
import uuid
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
from django.conf import settings
|
|||
|
|
from django.db import models
|
|||
|
|
|
|||
|
|
|
|||
|
|
def template_upload_path(instance, filename: str) -> str:
|
|||
|
|
return f"templates/{instance.id}/{Path(filename).name}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def csv_upload_path(instance, filename: str) -> str:
|
|||
|
|
return f"jobs/{instance.id}/recipients/{Path(filename).name}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def result_upload_path(instance, filename: str) -> str:
|
|||
|
|
return f"jobs/{instance.id}/result/{Path(filename).name}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class LetterTemplate(models.Model):
|
|||
|
|
"""DOCX-Vorlage mit Jinja-Platzhaltern."""
|
|||
|
|
|
|||
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|||
|
|
name = models.CharField(max_length=200)
|
|||
|
|
description = models.TextField(blank=True)
|
|||
|
|
file = models.FileField(upload_to=template_upload_path)
|
|||
|
|
placeholders = models.JSONField(default=list, blank=True,
|
|||
|
|
help_text="Aus dem DOCX extrahierte Variablen.")
|
|||
|
|
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT,
|
|||
|
|
related_name="templates")
|
|||
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|||
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["-created_at"]
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return self.name
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MailMergeJob(models.Model):
|
|||
|
|
class Status(models.TextChoices):
|
|||
|
|
PENDING = "pending", "Wartet"
|
|||
|
|
RUNNING = "running", "Läuft"
|
|||
|
|
DONE = "done", "Fertig"
|
|||
|
|
FAILED = "failed", "Fehlgeschlagen"
|
|||
|
|
|
|||
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|||
|
|
template = models.ForeignKey(LetterTemplate, on_delete=models.PROTECT,
|
|||
|
|
related_name="jobs")
|
|||
|
|
recipients_csv = models.FileField(upload_to=csv_upload_path)
|
|||
|
|
status = models.CharField(max_length=20, choices=Status.choices,
|
|||
|
|
default=Status.PENDING)
|
|||
|
|
result_pdf = models.FileField(upload_to=result_upload_path, null=True, blank=True)
|
|||
|
|
total_rows = models.PositiveIntegerField(default=0)
|
|||
|
|
processed_rows = models.PositiveIntegerField(default=0)
|
|||
|
|
error_message = models.TextField(blank=True)
|
|||
|
|
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT,
|
|||
|
|
related_name="jobs")
|
|||
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|||
|
|
started_at = models.DateTimeField(null=True, blank=True)
|
|||
|
|
finished_at = models.DateTimeField(null=True, blank=True)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["-created_at"]
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return f"Job {self.id} ({self.template.name})"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class JobLogEntry(models.Model):
|
|||
|
|
class Level(models.TextChoices):
|
|||
|
|
INFO = "info", "Info"
|
|||
|
|
WARNING = "warning", "Warnung"
|
|||
|
|
ERROR = "error", "Fehler"
|
|||
|
|
|
|||
|
|
job = models.ForeignKey(MailMergeJob, on_delete=models.CASCADE, related_name="logs")
|
|||
|
|
level = models.CharField(max_length=10, choices=Level.choices, default=Level.INFO)
|
|||
|
|
message = models.TextField()
|
|||
|
|
timestamp = models.DateTimeField(auto_now_add=True)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["timestamp"]
|