63 lines
2.1 KiB
Python
63 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.extensions import db
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
return datetime.now(timezone.utc)
|
|
|
|
|
|
class Person(db.Model):
|
|
__tablename__ = "people"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
full_name: Mapped[str] = mapped_column(String(160), nullable=False, index=True)
|
|
employee_id: Mapped[str] = mapped_column(String(80), unique=True, index=True, nullable=False)
|
|
notes: Mapped[str | None] = mapped_column(Text)
|
|
active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, nullable=False)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
default=utcnow,
|
|
onupdate=utcnow,
|
|
nullable=False,
|
|
)
|
|
|
|
face_encodings: Mapped[list["FaceEncoding"]] = relationship(
|
|
back_populates="person",
|
|
cascade="all, delete-orphan",
|
|
lazy="selectin",
|
|
)
|
|
attendance_events = relationship(
|
|
"AttendanceEvent",
|
|
back_populates="person",
|
|
cascade="all, delete-orphan",
|
|
lazy="selectin",
|
|
)
|
|
|
|
|
|
class FaceEncoding(db.Model):
|
|
__tablename__ = "face_encodings"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
person_id: Mapped[int] = mapped_column(ForeignKey("people.id"), nullable=False, index=True)
|
|
image_slot: Mapped[int] = mapped_column(default=1, nullable=False)
|
|
vector_json: Mapped[str] = mapped_column(Text, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, nullable=False)
|
|
|
|
person: Mapped[Person] = relationship(back_populates="face_encodings")
|
|
|
|
@property
|
|
def vector(self) -> list[float]:
|
|
return json.loads(self.vector_json)
|
|
|
|
@vector.setter
|
|
def vector(self, value: list[float]) -> None:
|
|
self.vector_json = json.dumps([float(item) for item in value])
|