forked from jamesp/sasa-membership
Add UTC datetime helpers to attempt to fix running issue
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
"""Add ESP RFID attendance tables
|
||||
|
||||
Revision ID: 8d2b0c4a1f7e
|
||||
Revises: 2e8a0f9d4b31
|
||||
Create Date: 2026-05-05 11:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision: str = "8d2b0c4a1f7e"
|
||||
down_revision: Union[str, None] = "2e8a0f9d4b31"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"esp_readers",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("device_id", sa.String(length=100), nullable=False),
|
||||
sa.Column("name", sa.String(length=255), nullable=False),
|
||||
sa.Column("location", sa.String(length=255), nullable=True),
|
||||
sa.Column("reader_type", sa.Enum("checkin_checkout", name="espreadertype"), nullable=False),
|
||||
sa.Column("api_key_hash", sa.String(length=255), nullable=False),
|
||||
sa.Column("is_active", sa.Boolean(), nullable=False),
|
||||
sa.Column("last_seen_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("notes", sa.Text(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index(op.f("ix_esp_readers_device_id"), "esp_readers", ["device_id"], unique=True)
|
||||
op.create_index(op.f("ix_esp_readers_id"), "esp_readers", ["id"], unique=False)
|
||||
|
||||
op.create_table(
|
||||
"rfid_cards",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("uid", sa.String(length=100), nullable=False),
|
||||
sa.Column("user_id", sa.Integer(), nullable=True),
|
||||
sa.Column("label", sa.String(length=255), nullable=True),
|
||||
sa.Column("is_active", sa.Boolean(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index(op.f("ix_rfid_cards_id"), "rfid_cards", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_cards_uid"), "rfid_cards", ["uid"], unique=True)
|
||||
op.create_index(op.f("ix_rfid_cards_user_id"), "rfid_cards", ["user_id"], unique=False)
|
||||
|
||||
op.create_table(
|
||||
"rfid_taps",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("reader_id", sa.Integer(), nullable=False),
|
||||
sa.Column("card_id", sa.Integer(), nullable=True),
|
||||
sa.Column("user_id", sa.Integer(), nullable=True),
|
||||
sa.Column("card_uid", sa.String(length=100), nullable=False),
|
||||
sa.Column("action", sa.Enum("check_in", "check_out", "denied", "unknown", name="esptapaction"), nullable=False),
|
||||
sa.Column("accepted", sa.Boolean(), nullable=False),
|
||||
sa.Column("message", sa.String(length=255), nullable=True),
|
||||
sa.Column("raw_payload", sa.Text(), nullable=True),
|
||||
sa.Column("tapped_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["card_id"], ["rfid_cards.id"]),
|
||||
sa.ForeignKeyConstraint(["reader_id"], ["esp_readers.id"]),
|
||||
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index(op.f("ix_rfid_taps_card_id"), "rfid_taps", ["card_id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_taps_card_uid"), "rfid_taps", ["card_uid"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_taps_id"), "rfid_taps", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_taps_reader_id"), "rfid_taps", ["reader_id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_taps_tapped_at"), "rfid_taps", ["tapped_at"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_taps_user_id"), "rfid_taps", ["user_id"], unique=False)
|
||||
|
||||
op.create_table(
|
||||
"attendance_sessions",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("user_id", sa.Integer(), nullable=False),
|
||||
sa.Column("reader_id", sa.Integer(), nullable=False),
|
||||
sa.Column("check_in_tap_id", sa.Integer(), nullable=False),
|
||||
sa.Column("check_out_tap_id", sa.Integer(), nullable=True),
|
||||
sa.Column("checked_in_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("checked_out_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("checkout_source", sa.Enum("user", "system", name="attendancecheckoutsource"), nullable=True),
|
||||
sa.Column("system_flag_reason", sa.String(length=255), nullable=True),
|
||||
sa.Column("duration_seconds", sa.Integer(), nullable=True),
|
||||
sa.Column("is_open", sa.Boolean(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["check_in_tap_id"], ["rfid_taps.id"]),
|
||||
sa.ForeignKeyConstraint(["check_out_tap_id"], ["rfid_taps.id"]),
|
||||
sa.ForeignKeyConstraint(["reader_id"], ["esp_readers.id"]),
|
||||
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index(op.f("ix_attendance_sessions_checked_in_at"), "attendance_sessions", ["checked_in_at"], unique=False)
|
||||
op.create_index(op.f("ix_attendance_sessions_checked_out_at"), "attendance_sessions", ["checked_out_at"], unique=False)
|
||||
op.create_index(op.f("ix_attendance_sessions_id"), "attendance_sessions", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_attendance_sessions_is_open"), "attendance_sessions", ["is_open"], unique=False)
|
||||
op.create_index(op.f("ix_attendance_sessions_reader_id"), "attendance_sessions", ["reader_id"], unique=False)
|
||||
op.create_index(op.f("ix_attendance_sessions_user_id"), "attendance_sessions", ["user_id"], unique=False)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(op.f("ix_attendance_sessions_user_id"), table_name="attendance_sessions")
|
||||
op.drop_index(op.f("ix_attendance_sessions_reader_id"), table_name="attendance_sessions")
|
||||
op.drop_index(op.f("ix_attendance_sessions_is_open"), table_name="attendance_sessions")
|
||||
op.drop_index(op.f("ix_attendance_sessions_id"), table_name="attendance_sessions")
|
||||
op.drop_index(op.f("ix_attendance_sessions_checked_out_at"), table_name="attendance_sessions")
|
||||
op.drop_index(op.f("ix_attendance_sessions_checked_in_at"), table_name="attendance_sessions")
|
||||
op.drop_table("attendance_sessions")
|
||||
op.drop_index(op.f("ix_rfid_taps_user_id"), table_name="rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_taps_tapped_at"), table_name="rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_taps_reader_id"), table_name="rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_taps_id"), table_name="rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_taps_card_uid"), table_name="rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_taps_card_id"), table_name="rfid_taps")
|
||||
op.drop_table("rfid_taps")
|
||||
op.drop_index(op.f("ix_rfid_cards_user_id"), table_name="rfid_cards")
|
||||
op.drop_index(op.f("ix_rfid_cards_uid"), table_name="rfid_cards")
|
||||
op.drop_index(op.f("ix_rfid_cards_id"), table_name="rfid_cards")
|
||||
op.drop_table("rfid_cards")
|
||||
op.drop_index(op.f("ix_esp_readers_id"), table_name="esp_readers")
|
||||
op.drop_index(op.f("ix_esp_readers_device_id"), table_name="esp_readers")
|
||||
op.drop_table("esp_readers")
|
||||
@@ -0,0 +1,81 @@
|
||||
"""Add ESP provisioning and RFID write jobs
|
||||
|
||||
Revision ID: c4f1d2a9b8e6
|
||||
Revises: 8d2b0c4a1f7e
|
||||
Create Date: 2026-05-05 12:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision: str = "c4f1d2a9b8e6"
|
||||
down_revision: Union[str, None] = "8d2b0c4a1f7e"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"esp_readers",
|
||||
sa.Column(
|
||||
"provisioning_status",
|
||||
sa.Enum("pending", "approved", "provisioned", "rejected", name="espreaderprovisioningstatus"),
|
||||
nullable=False,
|
||||
server_default="provisioned",
|
||||
),
|
||||
)
|
||||
op.add_column("esp_readers", sa.Column("registration_token_hash", sa.String(length=255), nullable=True))
|
||||
op.add_column("esp_readers", sa.Column("can_write_cards", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
op.add_column("esp_readers", sa.Column("firmware_version", sa.String(length=100), nullable=True))
|
||||
op.add_column("esp_readers", sa.Column("approved_at", sa.DateTime(), nullable=True))
|
||||
op.add_column("esp_readers", sa.Column("provisioned_at", sa.DateTime(), nullable=True))
|
||||
op.alter_column("esp_readers", "api_key_hash", existing_type=sa.String(length=255), nullable=True)
|
||||
|
||||
op.create_table(
|
||||
"rfid_card_write_jobs",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("reader_id", sa.Integer(), nullable=False),
|
||||
sa.Column("user_id", sa.Integer(), nullable=False),
|
||||
sa.Column("card_id", sa.Integer(), nullable=True),
|
||||
sa.Column("label", sa.String(length=255), nullable=False),
|
||||
sa.Column("status", sa.Enum("pending", "claimed", "completed", "failed", "cancelled", name="rfidwritejobstatus"), nullable=False),
|
||||
sa.Column("requested_by_user_id", sa.Integer(), nullable=False),
|
||||
sa.Column("card_uid", sa.String(length=100), nullable=True),
|
||||
sa.Column("write_payload", sa.Text(), nullable=True),
|
||||
sa.Column("claimed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("completed_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("error_message", sa.String(length=500), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), nullable=False),
|
||||
sa.ForeignKeyConstraint(["card_id"], ["rfid_cards.id"]),
|
||||
sa.ForeignKeyConstraint(["reader_id"], ["esp_readers.id"]),
|
||||
sa.ForeignKeyConstraint(["requested_by_user_id"], ["users.id"]),
|
||||
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_card_id"), "rfid_card_write_jobs", ["card_id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_card_uid"), "rfid_card_write_jobs", ["card_uid"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_id"), "rfid_card_write_jobs", ["id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_reader_id"), "rfid_card_write_jobs", ["reader_id"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_status"), "rfid_card_write_jobs", ["status"], unique=False)
|
||||
op.create_index(op.f("ix_rfid_card_write_jobs_user_id"), "rfid_card_write_jobs", ["user_id"], unique=False)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_user_id"), table_name="rfid_card_write_jobs")
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_status"), table_name="rfid_card_write_jobs")
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_reader_id"), table_name="rfid_card_write_jobs")
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_id"), table_name="rfid_card_write_jobs")
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_card_uid"), table_name="rfid_card_write_jobs")
|
||||
op.drop_index(op.f("ix_rfid_card_write_jobs_card_id"), table_name="rfid_card_write_jobs")
|
||||
op.drop_table("rfid_card_write_jobs")
|
||||
op.alter_column("esp_readers", "api_key_hash", existing_type=sa.String(length=255), nullable=False)
|
||||
op.drop_column("esp_readers", "provisioned_at")
|
||||
op.drop_column("esp_readers", "approved_at")
|
||||
op.drop_column("esp_readers", "firmware_version")
|
||||
op.drop_column("esp_readers", "can_write_cards")
|
||||
op.drop_column("esp_readers", "registration_token_hash")
|
||||
op.drop_column("esp_readers", "provisioning_status")
|
||||
@@ -0,0 +1,25 @@
|
||||
"""Add pending ESP API key delivery
|
||||
|
||||
Revision ID: e7a9c2b1d4f0
|
||||
Revises: c4f1d2a9b8e6
|
||||
Create Date: 2026-05-05 13:30:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision: str = "e7a9c2b1d4f0"
|
||||
down_revision: Union[str, None] = "c4f1d2a9b8e6"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("esp_readers", sa.Column("pending_api_key", sa.String(length=255), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("esp_readers", "pending_api_key")
|
||||
Reference in New Issue
Block a user