feat: add animal registry schema and models
Add database tables for animal tracking: - animal_registry: main snapshot table with all animal attributes - live_animals_by_location: denormalized view for fast roster queries - animal_aliases: merge tracking for when animals are discovered to be same Includes Pydantic models and comprehensive tests for all constraints. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
61
src/animaltrack/models/animals.py
Normal file
61
src/animaltrack/models/animals.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# ABOUTME: Pydantic models for animal tracking tables.
|
||||
# ABOUTME: Includes Animal, LiveAnimal, and AnimalAlias for registry system.
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from animaltrack.events.enums import AnimalStatus, LifeStage, Origin, ReproStatus, Sex
|
||||
|
||||
|
||||
class Animal(BaseModel):
|
||||
"""Full animal record from animal_registry table.
|
||||
|
||||
Represents the current state of an animal including all attributes,
|
||||
location, and lifecycle status.
|
||||
"""
|
||||
|
||||
animal_id: str = Field(..., min_length=26, max_length=26)
|
||||
species_code: str
|
||||
identified: bool = False
|
||||
nickname: str | None = None
|
||||
sex: Sex
|
||||
repro_status: ReproStatus
|
||||
life_stage: LifeStage
|
||||
status: AnimalStatus
|
||||
location_id: str = Field(..., min_length=26, max_length=26)
|
||||
origin: Origin
|
||||
born_or_hatched_at: int | None = None
|
||||
acquired_at: int | None = None
|
||||
first_seen_utc: int
|
||||
last_event_utc: int
|
||||
|
||||
|
||||
class LiveAnimal(BaseModel):
|
||||
"""Animal record from live_animals_by_location table.
|
||||
|
||||
Denormalized view of active animals for fast roster queries.
|
||||
Only includes animals with status='alive'.
|
||||
"""
|
||||
|
||||
animal_id: str = Field(..., min_length=26, max_length=26)
|
||||
location_id: str = Field(..., min_length=26, max_length=26)
|
||||
species_code: str
|
||||
identified: bool = False
|
||||
nickname: str | None = None
|
||||
sex: Sex
|
||||
repro_status: ReproStatus
|
||||
life_stage: LifeStage
|
||||
first_seen_utc: int
|
||||
last_move_utc: int | None = None
|
||||
tags: list[str] = []
|
||||
|
||||
|
||||
class AnimalAlias(BaseModel):
|
||||
"""Merge tracking record from animal_aliases table.
|
||||
|
||||
When two animals are discovered to be the same individual,
|
||||
one becomes an alias pointing to the survivor.
|
||||
"""
|
||||
|
||||
alias_animal_id: str = Field(..., min_length=26, max_length=26)
|
||||
survivor_animal_id: str = Field(..., min_length=26, max_length=26)
|
||||
merged_at_utc: int
|
||||
Reference in New Issue
Block a user