Files
dashboard-cpsp/backend/apps/farms/models.py
T

144 lines
4.1 KiB
Python

from datetime import date
from django.core.exceptions import ValidationError
from django.db import models
from wagtail.admin.panels import FieldPanel
from wagtail.snippets.models import register_snippet
from apps.accounts.models import User
@register_snippet
class Site(models.Model):
site_id = models.BigAutoField(primary_key=True)
site_name = models.CharField(max_length=30)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sites")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
panels = [
FieldPanel("site_name"),
FieldPanel("user"),
]
class Meta:
db_table = "sites"
ordering = ["site_name"]
def __str__(self) -> str:
return self.site_name
@register_snippet
class Kandang(models.Model):
kandang_id = models.BigAutoField(primary_key=True)
kandang_name = models.CharField(max_length=30)
site = models.ForeignKey(Site, on_delete=models.CASCADE, related_name="kandangs")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
panels = [
FieldPanel("kandang_name"),
FieldPanel("site"),
]
class Meta:
db_table = "kandang"
ordering = ["kandang_name"]
def __str__(self) -> str:
return self.kandang_name
@register_snippet
class Flock(models.Model):
flock_id = models.BigAutoField(primary_key=True)
flock_name = models.CharField(max_length=30)
cycle = models.ForeignKey(
"Cycle",
on_delete=models.CASCADE,
related_name="flocks",
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
panels = [
FieldPanel("flock_name"),
FieldPanel("cycle"),
]
class Meta:
db_table = "flock"
ordering = ["flock_name"]
def __str__(self) -> str:
return self.flock_name
@register_snippet
class Cycle(models.Model):
STATUS_ACTIVE = "active"
STATUS_CLOSED = "closed"
STATUS_CHOICES = [
(STATUS_ACTIVE, "Active"),
(STATUS_CLOSED, "Closed"),
]
cycle_id = models.BigAutoField(primary_key=True)
total_days = models.IntegerField()
start_date = models.DateField()
end_date = models.DateField()
doc_in_weight = models.IntegerField()
doc_in_count = models.IntegerField()
feed_initial_balance = models.IntegerField(default=0)
status = models.CharField(
max_length=30, choices=STATUS_CHOICES, default=STATUS_ACTIVE, db_index=True
)
kandang = models.ForeignKey(Kandang, on_delete=models.CASCADE, related_name="cycles")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
panels = [
FieldPanel("kandang"),
FieldPanel("total_days"),
FieldPanel("start_date"),
FieldPanel("end_date"),
FieldPanel("doc_in_weight"),
FieldPanel("doc_in_count"),
FieldPanel("feed_initial_balance"),
FieldPanel("status"),
]
class Meta:
db_table = "cycles"
ordering = ["-start_date"]
constraints = [
models.CheckConstraint(
check=models.Q(end_date__gte=models.F("start_date")),
name="chk_cycles_date_range",
)
]
def __str__(self) -> str:
return f"Cycle #{self.pk} ({self.status})"
def clean(self) -> None:
if self.end_date and self.start_date and self.end_date < self.start_date:
raise ValidationError({"end_date": "Must be on or after start_date"})
@property
def current_day(self) -> int:
from apps.operations.services.visibility import visible_through_date
effective = visible_through_date()
if effective < self.start_date:
return 0
elapsed = (effective - self.start_date).days + 1
return min(max(elapsed, 1), self.total_days)
@property
def visible_through_date(self) -> date:
from apps.operations.services.visibility import visible_through_date as cutoff_date
return cutoff_date()