Files
site/apps/api/app/modules/zootech/lab_models.py
T
2026-07-17 12:57:18 +03:00

214 lines
11 KiB
Python

"""Enterprise-scoped SQLAlchemy models for the zootech lab module."""
from __future__ import annotations
from datetime import UTC, datetime
from uuid import uuid4
from sqlalchemy import Boolean, DateTime, Float, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from app.db.base import Base
class _LabAuditMixin:
version: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
created_by: Mapped[str] = mapped_column(String(50), nullable=False, default="system")
updated_by: Mapped[str] = mapped_column(String(50), nullable=False, default="system")
class _LabTimestampMixin:
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(UTC)
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
default=lambda: datetime.now(UTC),
onupdate=lambda: datetime.now(UTC),
)
class _LabSoftDeleteMixin:
is_deleted: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
deleted_by: Mapped[str | None] = mapped_column(String(50), nullable=True)
def soft_delete(self, deleted_by_user: str = "system", **_: object) -> None:
if self.is_deleted:
return
self.is_deleted = True
self.deleted_at = datetime.now(UTC)
self.deleted_by = deleted_by_user
class ZootechLabAnimalProfile(_LabTimestampMixin, _LabSoftDeleteMixin, _LabAuditMixin, Base):
__tablename__ = "zootech_lab_animal_profile"
__table_args__ = (
UniqueConstraint("enterprise_id", "profile_key", name="uq_zootech_lab_profile_ent_key"),
UniqueConstraint("enterprise_id", "id", name="uq_zootech_lab_profile_ent_id"),
)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
profile_key: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
label: Mapped[str] = mapped_column(String(200), nullable=False)
ration_type: Mapped[str] = mapped_column(String(10), nullable=False, index=True)
mass_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
milk_yield_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
external_no: Mapped[int | None] = mapped_column(Integer, nullable=True)
norms_method: Mapped[str] = mapped_column(String(20), nullable=False, default="wesp")
norms_params_json: Mapped[str | None] = mapped_column(Text, nullable=True)
class ZootechLabProfileNorm(Base):
__tablename__ = "zootech_lab_profile_norm"
__table_args__ = (
UniqueConstraint("enterprise_id", "profile_id", "indicator_key", name="uq_zootech_lab_profile_norm"),
)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
profile_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
indicator_key: Mapped[str] = mapped_column(String(64), nullable=False)
min_value: Mapped[float | None] = mapped_column(Float, nullable=True)
max_value: Mapped[float | None] = mapped_column(Float, nullable=True)
class ZootechLabComponentNutrientValue(Base):
__tablename__ = "zootech_lab_component_nutrient_value"
__table_args__ = (
UniqueConstraint(
"enterprise_id",
"component_id",
"nutrient_key",
name="uq_zootech_lab_comp_nutrient",
),
)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
component_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
nutrient_key: Mapped[str] = mapped_column(String(80), nullable=False, index=True)
value: Mapped[float | None] = mapped_column(Float, nullable=True)
class ZootechLabRecipeRation(_LabTimestampMixin, _LabSoftDeleteMixin, _LabAuditMixin, Base):
__tablename__ = "zootech_lab_recipe_ration"
enterprise_id: Mapped[str] = mapped_column(String(36), primary_key=True)
recipe_id: Mapped[str] = mapped_column(String(36), primary_key=True)
animal_profile_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
calc_engine: Mapped[str | None] = mapped_column(String(20), nullable=True)
seed_source: Mapped[str | None] = mapped_column(String(32), nullable=True)
calculated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
class ZootechLabRationLine(_LabTimestampMixin, _LabSoftDeleteMixin, _LabAuditMixin, Base):
__tablename__ = "zootech_lab_ration_line"
__table_args__ = (UniqueConstraint("enterprise_id", "id", name="uq_zootech_lab_ration_line_ent_id"),)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
recipe_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
component_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
row_index: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
ingredient_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
daily_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
in_ration: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
in_compound: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
class ZootechLabRationCalcTotal(Base):
__tablename__ = "zootech_lab_ration_calc_total"
__table_args__ = (UniqueConstraint("enterprise_id", "id", name="uq_zootech_lab_calc_total_ent_id"),)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
recipe_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
scope: Mapped[str] = mapped_column(String(16), nullable=False, default="ration")
metric_key: Mapped[str] = mapped_column(String(32), nullable=False)
label: Mapped[str] = mapped_column(String(128), nullable=False, default="")
value: Mapped[float | None] = mapped_column(Float, nullable=True)
sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
class ZootechLabRationCalcIndicator(Base):
__tablename__ = "zootech_lab_ration_calc_indicator"
__table_args__ = (UniqueConstraint("enterprise_id", "id", name="uq_zootech_lab_calc_ind_ent_id"),)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
recipe_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
scope: Mapped[str] = mapped_column(String(16), nullable=False, default="ration")
indicator_key: Mapped[str | None] = mapped_column(String(64), nullable=True)
label: Mapped[str] = mapped_column(String(128), nullable=False, default="")
unit: Mapped[str] = mapped_column(String(32), nullable=False, default="")
min_value: Mapped[float | None] = mapped_column(Float, nullable=True)
max_value: Mapped[float | None] = mapped_column(Float, nullable=True)
content: Mapped[float | None] = mapped_column(Float, nullable=True)
diff: Mapped[float | None] = mapped_column(Float, nullable=True)
sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
class ZootechLabRationCompoundLine(Base):
__tablename__ = "zootech_lab_ration_compound_line"
__table_args__ = (UniqueConstraint("enterprise_id", "id", name="uq_zootech_lab_compound_line_ent_id"),)
enterprise_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
recipe_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
row_index: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
ingredient_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
daily_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
share_pct: Mapped[float | None] = mapped_column(Float, nullable=True)
# Global RACION reference tables (not enterprise-scoped).
class ZootechLabRacionNormyMoskwa(Base):
__tablename__ = "zootech_lab_racion_normy_moskwa"
__table_args__ = (UniqueConstraint("npitv", "pom", name="uq_zootech_lab_racion_moskwa_npitv_pom"),)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
npitv: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
pom: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
koef: Mapped[float | None] = mapped_column(Float, nullable=True)
popr_k_json: Mapped[str | None] = mapped_column(Text, nullable=True)
class ZootechLabRacionNormyMoskwaMeta(Base):
__tablename__ = "zootech_lab_racion_normy_moskwa_meta"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
meta_key: Mapped[str] = mapped_column(String(32), nullable=False, unique=True)
meta_json: Mapped[str | None] = mapped_column(Text, nullable=True)
class ZootechLabRacionNormyPiter(Base):
__tablename__ = "zootech_lab_racion_normy_piter"
__table_args__ = (
UniqueConstraint("npitv", "konc", "udoy", name="uq_zootech_lab_racion_piter_npitv_konc_udoy"),
)
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
npitv: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
konc: Mapped[float] = mapped_column(Float, nullable=False)
udoy: Mapped[float] = mapped_column(Float, nullable=False)
normy_json: Mapped[str | None] = mapped_column(Text, nullable=True)
class ZootechLabRacionNormyPiterMeta(Base):
__tablename__ = "zootech_lab_racion_normy_piter_meta"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
meta_key: Mapped[str] = mapped_column(String(32), nullable=False, unique=True)
meta_json: Mapped[str | None] = mapped_column(Text, nullable=True)
class ZootechLabRacionNormyInfo(Base):
__tablename__ = "zootech_lab_racion_normy_info"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
nperem: Mapped[int] = mapped_column(Integer, nullable=False, unique=True, index=True)
znachenie_json: Mapped[str | None] = mapped_column(Text, nullable=True)