from django.db import models from apps.core.models import TimeStampedModel, UUIDModel class StepExecution(UUIDModel, TimeStampedModel): class State(models.TextChoices): PENDING = "pending", "Pending" READY = "ready", "Ready" IN_PROGRESS = "in_progress", "In progress" PAUSED = "paused", "Paused" WAITING = "waiting", "Waiting" COMPLETED = "completed", "Completed" FAILED = "failed", "Failed" REJECTED = "rejected", "Rejected" SKIPPED = "skipped", "Skipped" CANCELLED = "cancelled", "Cancelled" REWORK_REQUIRED = "rework_required", "Rework required" order = models.ForeignKey("orders.ProcessingOrder", on_delete=models.CASCADE, related_name="step_executions") step = models.ForeignKey("workflows.WorkflowStep", on_delete=models.PROTECT) state = models.CharField(max_length=20, choices=State.choices, default=State.PENDING) attempt = models.PositiveIntegerField(default=1) assigned_to = models.ForeignKey( "accounts.User", null=True, blank=True, on_delete=models.SET_NULL, related_name="assigned_steps" ) started_at = models.DateTimeField(null=True, blank=True) completed_at = models.DateTimeField(null=True, blank=True) notes = models.TextField(blank=True) measurements = models.JSONField(default=dict, blank=True) # For rework history: a rework execution points back to the failed one. parent = models.ForeignKey( "self", null=True, blank=True, on_delete=models.SET_NULL, related_name="rework_children" ) class Meta: ordering = ["created_at"] constraints = [ models.UniqueConstraint(fields=["order", "step", "attempt"], name="uniq_step_execution_attempt") ] def __str__(self) -> str: return f"{self.order.order_number} / {self.step.key} (attempt {self.attempt})"