from django.db import models from django.utils import timezone from apps.core.models import TimeStampedModel, UUIDModel def generate_order_number() -> str: year = timezone.now().year prefix = f"STN-{year}-" last = ( ProcessingOrder.objects.filter(order_number__startswith=prefix) .order_by("-order_number") .first() ) if last: try: seq = int(last.order_number.rsplit("-", 1)[1]) + 1 except (IndexError, ValueError): seq = 1 else: seq = 1 return f"{prefix}{seq:06d}" class ProcessingOrder(UUIDModel, TimeStampedModel): class Status(models.TextChoices): DRAFT = "draft", "Draft" AWAITING_CONFIRMATION = "awaiting_confirmation", "Awaiting confirmation" CONFIRMED = "confirmed", "Confirmed" PROCESSING = "processing", "Processing" COMPLETED = "completed", "Completed" CANCELLED = "cancelled", "Cancelled" order_number = models.CharField(max_length=32, unique=True, blank=True) customer = models.ForeignKey("accounts.Customer", on_delete=models.PROTECT, related_name="orders") reservation = models.OneToOneField( "reservations.Reservation", null=True, blank=True, on_delete=models.SET_NULL, related_name="order" ) # Workflow version is immutable per order — historical orders never change. workflow_version = models.ForeignKey( "workflows.WorkflowVersion", on_delete=models.PROTECT, related_name="orders" ) gross_weight_kg = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) tare_weight_kg = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) net_weight_kg = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) selected_step_keys = models.JSONField(default=list, blank=True) price_snapshot = models.JSONField(default=dict, blank=True) currency = models.CharField(max_length=8, default="IRR") status = models.CharField(max_length=24, choices=Status.choices, default=Status.DRAFT) confirmed_at = models.DateTimeField(null=True, blank=True) terms_accepted = models.BooleanField(default=False) class Meta: ordering = ["-created_at"] def save(self, *args, **kwargs): if not self.order_number: self.order_number = generate_order_number() super().save(*args, **kwargs) def __str__(self) -> str: return self.order_number or str(self.id)