Files
bellsystems-cp/backend/shared/orm.py

47 lines
2.2 KiB
Python

from datetime import datetime, timezone
from sqlalchemy import BigInteger, Column, DateTime, Index, String, Text
from sqlalchemy.dialects.postgresql import JSONB
from database.postgres import Base
def _now():
return datetime.now(timezone.utc)
class MigrationRun(Base):
"""Tracks every migration script execution — what ran, when, row counts, success/failure."""
__tablename__ = "_migration_runs"
id = Column(BigInteger, primary_key=True, autoincrement=True)
script_name = Column(String(256), nullable=False)
ran_at = Column(DateTime(timezone=True), nullable=False, default=_now)
source_rows = Column(BigInteger, nullable=False, default=0)
dest_rows = Column(BigInteger, nullable=False, default=0)
success = Column(String(8), nullable=False, default="ok") # 'ok' | 'error'
notes = Column(Text)
class AuditLog(Base):
"""Staff action audit trail — all create/update/delete/command events."""
__tablename__ = "audit_log"
__table_args__ = (
Index("idx_audit_actor", "actor_id", "occurred_at"),
Index("idx_audit_entity", "entity_type", "entity_id", "occurred_at"),
Index("idx_audit_action", "action", "occurred_at"),
Index("idx_audit_occurred", "occurred_at"),
)
id = Column(BigInteger, primary_key=True, autoincrement=True)
occurred_at = Column(DateTime(timezone=True), nullable=False, default=_now)
actor_id = Column(String(128), nullable=False)
actor_name = Column(String(255), nullable=False)
action = Column(String(64), nullable=False)
# CREATE | UPDATE | DELETE | COMMAND | PUBLISH | UNPUBLISH |
# LOGIN | LOGOUT | PERMISSION_CHANGE | STATUS_CHANGE
entity_type = Column(String(64), nullable=False)
# customer | order | device | melody | product | staff | ticket | note | quotation | ...
entity_id = Column(String(128), nullable=False)
entity_label = Column(String(500)) # denormalised human name
changes = Column(JSONB) # {"field": {"old": x, "new": y}} — null for CREATE/DELETE
meta = Column(JSONB) # extra context: ip_address, command_name, etc.