All checks were successful
Deploy to Production / deploy (push) Successful in 1m17s
- Add Alarm model with tenant/part/machine relationships and 3 indexes - Add alembic migration c5d6e7f8a9b0_add_alarms - Add alarms API: list (filter by ack/severity), summary, acknowledge - Auto-generate alarms on counter update (threshold warning, critical at 100%) - Duplicate alarm prevention for same part+alarm_type - Add alarms frontend page with active/acknowledged tabs, summary badges - 9 new tests (67/67 total passing) Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
"""add_alarms
|
|
|
|
Revision ID: c5d6e7f8a9b0
|
|
Revises: b4c5d6e7f8a9
|
|
Create Date: 2026-02-10 14:20:00.000000
|
|
|
|
"""
|
|
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
revision: str = "c5d6e7f8a9b0"
|
|
down_revision: Union[str, None] = "b4c5d6e7f8a9"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"alarms",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
|
|
sa.Column(
|
|
"tenant_id",
|
|
sa.String(50),
|
|
sa.ForeignKey("tenants.id"),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"equipment_part_id",
|
|
postgresql.UUID(as_uuid=True),
|
|
sa.ForeignKey("equipment_parts.id"),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"machine_id",
|
|
postgresql.UUID(as_uuid=True),
|
|
sa.ForeignKey("machines.id"),
|
|
nullable=False,
|
|
),
|
|
sa.Column("alarm_type", sa.String(30), nullable=False),
|
|
sa.Column("severity", sa.String(20), nullable=False),
|
|
sa.Column("message", sa.String(500), nullable=False),
|
|
sa.Column("lifecycle_pct_at_trigger", sa.Float, nullable=False),
|
|
sa.Column("is_acknowledged", sa.Boolean, default=False),
|
|
sa.Column(
|
|
"acknowledged_by",
|
|
postgresql.UUID(as_uuid=True),
|
|
sa.ForeignKey("users.id"),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"acknowledged_at",
|
|
postgresql.TIMESTAMP(timezone=True),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"created_at",
|
|
postgresql.TIMESTAMP(timezone=True),
|
|
server_default=sa.func.now(),
|
|
),
|
|
)
|
|
op.create_index("ix_alarms_tenant_ack", "alarms", ["tenant_id", "is_acknowledged"])
|
|
op.create_index("ix_alarms_tenant_severity", "alarms", ["tenant_id", "severity"])
|
|
op.create_index(
|
|
"ix_alarms_tenant_part", "alarms", ["tenant_id", "equipment_part_id"]
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_alarms_tenant_part", table_name="alarms")
|
|
op.drop_index("ix_alarms_tenant_severity", table_name="alarms")
|
|
op.drop_index("ix_alarms_tenant_ack", table_name="alarms")
|
|
op.drop_table("alarms")
|