from django.core.exceptions import ValidationError from django.db import models from django.db.models import Q import datetime from core.models.base import BaseModel from core.models.account import AccountAddress class Labor(BaseModel): """Labor records for accounts""" account_address = models.ForeignKey( AccountAddress, on_delete=models.PROTECT, related_name='labors', verbose_name="Account Service Address", null=True ) amount = models.DecimalField(max_digits=10, decimal_places=2) start_date = models.DateField() end_date = models.DateField(blank=True, null=True) class Meta: ordering = ['-start_date'] indexes = [ models.Index(fields=['account_address', 'start_date']), ] verbose_name = "Labor" verbose_name_plural = "Labors" def __str__(self): return f"{self.account_address.account.name} - {self.account_address.name} - ${self.amount}" def clean(self): super().clean() # Basic date validity if self.end_date and self.start_date > self.end_date: raise ValidationError({'end_date': "End date must be after start date"}) # Optional: amount validation if self.amount is None or self.amount < 0: raise ValidationError({'amount': "Amount must be a non-negative value"}) # Overlap prevention within the same account_address start = self.start_date end = self.end_date or datetime.date.max qs = Labor.objects.filter(account_address=self.account_address) if self.pk: qs = qs.exclude(pk=self.pk) overlaps = qs.filter( Q(end_date__isnull=True, start_date__lte=end) | Q(end_date__isnull=False, start_date__lte=end, end_date__gte=start) ) if overlaps.exists(): raise ValidationError("Labor rate dates overlap with an existing labor rate for this address.")