# ============================================================================= # license_server/models.py — SQLAlchemy ORM models # ============================================================================= import uuid from datetime import datetime, timezone from sqlalchemy import Boolean, DateTime, Integer, String from sqlalchemy.orm import Mapped, mapped_column from .database import Base def _now() -> datetime: return datetime.now(timezone.utc) def _uuid() -> str: return str(uuid.uuid4()) class License(Base): """One row per serial number issued by AR Electronics.""" __tablename__ = "licenses" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) serial: Mapped[str] = mapped_column(String(20), unique=True, nullable=False, index=True) vessel: Mapped[str] = mapped_column(String(120), default="") issued_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now) is_active: Mapped[bool] = mapped_column(Boolean, default=True) notes: Mapped[str] = mapped_column(String(500), default="") class Activation(Base): """One row per successful hardware activation of a serial number.""" __tablename__ = "activations" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) activation_id: Mapped[str] = mapped_column(String(36), unique=True, default=_uuid, index=True) serial: Mapped[str] = mapped_column(String(20), nullable=False, index=True) hardware_id: Mapped[str] = mapped_column(String(64), nullable=False) app_version: Mapped[str] = mapped_column(String(20), default="") platform: Mapped[str] = mapped_column(String(20), default="") hostname: Mapped[str] = mapped_column(String(120), default="") activated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now) last_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now) vessel_slot: Mapped[int] = mapped_column(Integer, default=1) revoked: Mapped[bool] = mapped_column(Boolean, default=False) licensed_to: Mapped[str] = mapped_column(String(120), default="")