"""This module declareds the pydantic schema representation for devices.""" from datetime import datetime from abc import ABC from decimal import Decimal from pydantic import BaseModel, validator from backend.models.records import AvpuScore, RespirationScore class AbstractRecordCreate(BaseModel, ABC): """Base class containing fields common to all vitals records during creation.""" measured: datetime device_id: int @validator('measured') def assert_measured_is_valid(cls, measured: datetime) -> datetime: if measured >= datetime.now(): raise ValueError("Time of measurement cannot be in the future.") return measured class AbstractRecord(BaseModel, ABC): """Base class containing fields common to all vitals records for display.""" id: int measured: datetime device_id: int @validator('measured') def assert_measured_is_valid(cls, measured: datetime) -> datetime: if measured >= datetime.now(): raise ValueError("Time of measurement cannot be in the future.") return measured class AbstractHeartRateRecord(BaseModel, ABC): value: int @validator('value') def assert_value_is_valid(cls, value): if value < 0: raise ValueError("Value cannot be negative.") if value >= 32767: raise ValueError("Value is too large.") return value class HeartRateRecordCreate(AbstractRecordCreate, AbstractHeartRateRecord): pass class HeartRateRecord(AbstractRecord, AbstractHeartRateRecord): pass class AbstractAvpuScoreRecord(BaseModel, ABC): value: AvpuScore class AvpuScoreRecordCreate(AbstractRecordCreate, AbstractAvpuScoreRecord): pass class AvpuScoreRecord(AbstractRecord, AbstractAvpuScoreRecord): pass class AbstractBodyTemperatureRecord(BaseModel, ABC): value: Decimal @validator('value') def assert_value_is_valid(cls, value: Decimal) -> Decimal: if value < 0: raise ValueError("Value cannot be negative.") if value >= 100: raise ValueError("Value cannot exceed '99.99'.") if len(value.as_tuple().digits) > 4: raise ValueError("Value can have at most two digits after the decimal point.") return value class BodyTemperatureRecordCreate(AbstractRecordCreate, AbstractBodyTemperatureRecord): pass class BodyTemperatureRecord(AbstractRecord, AbstractBodyTemperatureRecord): pass class AbstractBloodPressureRecord(BaseModel, ABC): value_systolic: int value_diastolic: int @validator('value_systolic') def assert_value_systolic_is_valid(cls, value_systolic): if value_systolic < 0: raise ValueError("Value (systolic) cannot be negative.") if value_systolic >= 32767: raise ValueError("Value (systolic) is too large.") return value_systolic @validator('value_diastolic') def assert_value_diastolic_is_valid(cls, value_diastolic): if value_diastolic < 0: raise ValueError("Value (diastolic) cannot be negative.") if value_diastolic >= 32767: raise ValueError("Value (diastolic) is too large.") return value_diastolic class BloodPressureRecordCreate(AbstractRecordCreate, AbstractBloodPressureRecord): pass class BloodPressureRecord(AbstractRecord, AbstractBloodPressureRecord): pass class AbstractBloodOxygenRecord(BaseModel, ABC): value: Decimal @validator('value') def assert_value_is_valid(cls, value: Decimal) -> Decimal: if value < 0: raise ValueError("Value cannot be negative.") if value > 100: raise ValueError("Value cannot exceed '100.00'.") if len(value.as_tuple().digits) > 5: raise ValueError("Value can have at most two digits after the decimal point.") return value class BloodOxygenRecordCreate(AbstractRecordCreate, AbstractBloodOxygenRecord): pass class BloodOxygenRecord(AbstractRecord, AbstractBloodOxygenRecord): pass class AbstractRespirationScoreScoreRecord(BaseModel, ABC): value: RespirationScore class RespirationScoreScoreRecordCreate(AbstractRecordCreate, AbstractRespirationScoreScoreRecord): pass class RespirationScoreScoreRecord(AbstractRecord, AbstractRespirationScoreScoreRecord): pass