57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
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.") |