Files
openapi-first/openapi_first/templates/vet_app/data.py

357 lines
13 KiB
Python

"""
In-memory data store for the Veterinary Clinic example.
This module is NOT thread-safe and is intended for demos and scaffolds only.
It provides minimal, process-local data stores for the five veterinary
clinic entities. Each store exposes standard CRUD operations backed by
a simple dictionary.
This module intentionally avoids:
- persistence
- concurrency guarantees
- transactional semantics
- validation beyond what Pydantic provides
This module is not part of the ``openapi_first`` library API surface.
"""
from datetime import date, datetime, timezone
from models import (
Parent, ParentCreate,
Vet, VetCreate,
Treatment, TreatmentCreate,
Procedure, ProcedureNotes,
Pet, PetCreate,
Appointment, AppointmentCreate,
)
def _now():
return datetime.now(timezone.utc).isoformat()
# ---------------------------------------------------------------------------
# Parents
# ---------------------------------------------------------------------------
_parents: dict[int, Parent] = {}
_parents_next_id = 1
def list_parents() -> list[Parent]:
return list(_parents.values())
def get_parent(parent_id: int) -> Parent:
return _parents[parent_id]
def create_parent(payload: ParentCreate) -> Parent:
global _parents_next_id
now = _now()
parent = Parent(
id=_parents_next_id,
name=payload.name,
email=payload.email,
phone=payload.phone,
metadata={"createdOn": now, "updatedOn": now} if payload.metadata else None,
)
_parents[_parents_next_id] = parent
_parents_next_id += 1
return parent
def update_parent(parent_id: int, payload: ParentCreate) -> Parent:
if parent_id not in _parents:
raise KeyError(parent_id)
now = _now()
current = _parents[parent_id]
updated = Parent(
id=parent_id,
name=payload.name,
email=payload.email,
phone=payload.phone if payload.phone is not None else current.phone,
metadata={"createdOn": current.metadata["createdOn"] if current.metadata else None, "updatedOn": now},
)
_parents[parent_id] = updated
return updated
def delete_parent(parent_id: int) -> None:
del _parents[parent_id]
# ---------------------------------------------------------------------------
# Vets
# ---------------------------------------------------------------------------
_vets: dict[int, Vet] = {}
_vets_next_id = 1
def list_vets() -> list[Vet]:
return list(_vets.values())
def get_vet(vet_id: int) -> Vet:
return _vets[vet_id]
def create_vet(payload: VetCreate) -> Vet:
global _vets_next_id
now = _now()
vet = Vet(
id=_vets_next_id,
name=payload.name,
specialty=payload.specialty,
email=payload.email,
phone=payload.phone,
metadata={"createdOn": now, "updatedOn": now} if payload.metadata else None,
)
_vets[_vets_next_id] = vet
_vets_next_id += 1
return vet
def update_vet(vet_id: int, payload: VetCreate) -> Vet:
if vet_id not in _vets:
raise KeyError(vet_id)
now = _now()
current = _vets[vet_id]
updated = Vet(
id=vet_id,
name=payload.name,
specialty=payload.specialty if payload.specialty is not None else current.specialty,
email=payload.email,
phone=payload.phone if payload.phone is not None else current.phone,
metadata={"createdOn": current.metadata["createdOn"] if current.metadata else None, "updatedOn": now},
)
_vets[vet_id] = updated
return updated
def delete_vet(vet_id: int) -> None:
del _vets[vet_id]
# ---------------------------------------------------------------------------
# Treatments
# ---------------------------------------------------------------------------
_treatments: dict[int, Treatment] = {}
_treatments_next_id = 1
def list_treatments() -> list[Treatment]:
return list(_treatments.values())
def get_treatment(treatment_id: int) -> Treatment:
return _treatments[treatment_id]
def create_treatment(payload: TreatmentCreate) -> Treatment:
global _treatments_next_id
now = _now()
treatment = Treatment(
id=_treatments_next_id,
label=payload.label,
description=payload.description,
metadata={"createdOn": now, "updatedOn": now} if payload.metadata else None,
)
_treatments[_treatments_next_id] = treatment
_treatments_next_id += 1
return treatment
def update_treatment(treatment_id: int, payload: TreatmentCreate) -> Treatment:
if treatment_id not in _treatments:
raise KeyError(treatment_id)
now = _now()
current = _treatments[treatment_id]
updated = Treatment(
id=treatment_id,
label=payload.label,
description=payload.description if payload.description is not None else current.description,
metadata={"createdOn": current.metadata["createdOn"] if current.metadata else None, "updatedOn": now},
)
_treatments[treatment_id] = updated
return updated
def delete_treatment(treatment_id: int) -> None:
del _treatments[treatment_id]
# ---------------------------------------------------------------------------
# Pets
# ---------------------------------------------------------------------------
_pets: dict[int, Pet] = {}
_pets_next_id = 1
def list_pets() -> list[Pet]:
return list(_pets.values())
def get_pet(pet_id: int) -> Pet:
return _pets[pet_id]
def create_pet(payload: PetCreate) -> Pet:
global _pets_next_id
now = _now()
parents = [_parents[pid] for pid in payload.parent_ids]
pet = Pet(
id=_pets_next_id,
name=payload.name,
species=payload.species,
age=payload.age,
weight=payload.weight,
birthDate=payload.birthDate,
photo=payload.photo,
parents=parents,
metadata={"createdOn": now, "updatedOn": now} if payload.metadata else None,
)
_pets[_pets_next_id] = pet
_pets_next_id += 1
return pet
def update_pet(pet_id: int, payload: PetCreate) -> Pet:
if pet_id not in _pets:
raise KeyError(pet_id)
now = _now()
parents = [_parents[pid] for pid in payload.parent_ids]
current = _pets[pet_id]
updated = Pet(
id=pet_id,
name=payload.name,
species=payload.species,
age=payload.age if payload.age is not None else current.age,
weight=payload.weight if payload.weight is not None else current.weight,
birthDate=payload.birthDate if payload.birthDate is not None else current.birthDate,
photo=payload.photo if payload.photo is not None else current.photo,
parents=parents,
metadata={"createdOn": current.metadata["createdOn"] if current.metadata else None, "updatedOn": now},
)
_pets[pet_id] = updated
return updated
def delete_pet(pet_id: int) -> None:
del _pets[pet_id]
# ---------------------------------------------------------------------------
# Appointments
# ---------------------------------------------------------------------------
_appointments: dict[int, Appointment] = {}
_appointments_next_id = 1
def list_appointments() -> list[Appointment]:
return list(_appointments.values())
def get_appointment(appointment_id: int) -> Appointment:
return _appointments[appointment_id]
def create_appointment(payload: AppointmentCreate) -> Appointment:
global _appointments_next_id
now = _now()
appointment = Appointment(
id=_appointments_next_id,
date=payload.date,
notes=payload.notes,
procedures=payload.procedures,
pet=_pets[payload.pet_id],
vet=_vets[payload.vet_id],
treatment=_treatments[payload.treatment_id],
metadata={"createdOn": now, "updatedOn": now} if payload.metadata else None,
)
_appointments[_appointments_next_id] = appointment
_appointments_next_id += 1
return appointment
def update_appointment(appointment_id: int, payload: AppointmentCreate) -> Appointment:
if appointment_id not in _appointments:
raise KeyError(appointment_id)
now = _now()
current = _appointments[appointment_id]
updated = Appointment(
id=appointment_id,
date=payload.date,
notes=payload.notes if payload.notes is not None else current.notes,
procedures=payload.procedures,
pet=_pets.get(payload.pet_id, current.pet),
vet=_vets.get(payload.vet_id, current.vet),
treatment=_treatments.get(payload.treatment_id, current.treatment),
metadata={"createdOn": current.metadata["createdOn"] if current.metadata else None, "updatedOn": now},
)
_appointments[appointment_id] = updated
return updated
def delete_appointment(appointment_id: int) -> None:
del _appointments[appointment_id]
# ---------------------------------------------------------------------------
# Seed data — populate stores so the UI isn't empty on startup
# ---------------------------------------------------------------------------
def _seed_data():
now = _now()
meta = {"createdOn": now, "updatedOn": now}
global _parents_next_id, _vets_next_id, _treatments_next_id
global _pets_next_id, _appointments_next_id
_parents[1] = Parent(id=1, name="Alice Johnson", email="alice@example.com", phone="555-0101", metadata=meta)
_parents[2] = Parent(id=2, name="Bob Smith", email="bob@example.com", phone="555-0102", metadata=meta)
_parents[3] = Parent(id=3, name="Carol Williams", email="carol@example.com", phone="555-0103", metadata=meta)
_parents[4] = Parent(id=4, name="Dave Brown", email="dave@example.com", phone="555-0104", metadata=meta)
_parents_next_id = 5
_vets[1] = Vet(id=1, name="Sarah Connor", specialty="Surgery", email="sarah@clinic.com", phone="555-0201", metadata=meta)
_vets[2] = Vet(id=2, name="James Wilson", specialty="Dentistry", email="james@clinic.com", phone="555-0202", metadata=meta)
_vets[3] = Vet(id=3, name="Emily Davis", specialty="General Practice", email="emily@clinic.com", phone="555-0203", metadata=meta)
_vets_next_id = 4
_treatments[1] = Treatment(id=1, label="Annual Checkup", description="Full physical examination", metadata=meta)
_treatments[2] = Treatment(id=2, label="Vaccination", description="Core vaccines for common diseases", metadata=meta)
_treatments[3] = Treatment(id=3, label="Dental Cleaning", description="Scaling, polishing, and oral exam", metadata=meta)
_treatments[4] = Treatment(id=4, label="Spay/Neuter", description="Surgical sterilization", metadata=meta)
_treatments[5] = Treatment(id=5, label="Blood Panel", description="Complete blood count and chemistry", metadata=meta)
_treatments_next_id = 6
_pets[1] = Pet(id=1, name="Max", species="dog", age=4, weight=25.5, birthDate=date(2022, 3, 15), parents=[_parents[1]], metadata=meta)
_pets[2] = Pet(id=2, name="Luna", species="cat", age=2, weight=4.2, birthDate=date(2024, 1, 10), parents=[_parents[1], _parents[2]], metadata=meta)
_pets[3] = Pet(id=3, name="Charlie", species="dog", age=7, weight=18.0, birthDate=date(2019, 8, 22), parents=[_parents[2]], metadata=meta)
_pets[4] = Pet(id=4, name="Bella", species="bird", age=1, weight=0.3, birthDate=date(2025, 5, 1), parents=[_parents[3]], metadata=meta)
_pets[5] = Pet(id=5, name="Rocky", species="dog", age=3, weight=30.0, birthDate=date(2023, 11, 5), parents=[_parents[4]], metadata=meta)
_pets_next_id = 6
_appointments[1] = Appointment(id=1, date=datetime(2026, 6, 18, 9, 0, tzinfo=timezone.utc), notes="Annual checkup",
procedures=[Procedure(name="Physical Exam", cost=50.0), Procedure(name="Heart Rate", notes=ProcedureNotes(summary="Normal rhythm"))],
pet=_pets[1], vet=_vets[1], treatment=_treatments[1], metadata=meta)
_appointments[2] = Appointment(id=2, date=datetime(2026, 6, 18, 10, 30, tzinfo=timezone.utc), notes="Dental cleaning",
procedures=[Procedure(name="Scaling", cost=80.0), Procedure(name="Polishing", cost=40.0, notes=ProcedureNotes(summary="High-speed polish"))],
pet=_pets[2], vet=_vets[2], treatment=_treatments[3], metadata=meta)
_appointments[3] = Appointment(id=3, date=datetime(2026, 6, 19, 11, 0, tzinfo=timezone.utc), notes="Vaccination booster",
procedures=[Procedure(name="DHPP Vaccine", cost=35.0), Procedure(name="Rabies Vaccine", cost=45.0)],
pet=_pets[3], vet=_vets[3], treatment=_treatments[2], metadata=meta)
_appointments[4] = Appointment(id=4, date=datetime(2026, 6, 20, 14, 0, tzinfo=timezone.utc), notes="Follow-up after surgery",
procedures=[Procedure(name="Pre-op Exam", cost=30.0), Procedure(name="Surgery", cost=200.0), Procedure(name="Post-op Care", cost=50.0)],
pet=_pets[5], vet=_vets[1], treatment=_treatments[4], metadata=meta)
_appointments_next_id = 5
_seed_data()