M34: enforce domain integrity in PostgreSQL

This commit is contained in:
NuklearRabbit
2026-08-10 22:28:38 +02:00
parent 82a933f6cd
commit c7492bf6ad
8 changed files with 161 additions and 5 deletions
+6 -1
View File
@@ -1,7 +1,7 @@
import uuid
from datetime import datetime
from sqlalchemy import DateTime, String
from sqlalchemy import CheckConstraint, DateTime, Index, String
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column
@@ -13,6 +13,11 @@ ACTOR_TYPES = ("user", "service", "system")
class AuditEvent(UUIDPrimaryKeyMixin, Base):
__tablename__ = "audit_events"
__table_args__ = (
CheckConstraint("actor_type IN ('user','service','system')", name="ck_audit_actor_type"),
Index("ix_audit_action_occurred", "action", "occurred_at"),
Index("ix_audit_entity", "entity_type", "entity_id"),
)
actor_type: Mapped[str] = mapped_column(String(20), nullable=False)
actor_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
+17 -1
View File
@@ -1,7 +1,7 @@
import uuid
from datetime import datetime
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String
from sqlalchemy import Boolean, CheckConstraint, DateTime, ForeignKey, Index, Integer, String
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column
@@ -13,6 +13,22 @@ BOOKING_STATUSES = ("reserved", "active", "returned", "cancelled", "blocked")
class Booking(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "bookings"
__table_args__ = (
CheckConstraint(
"status IN ('reserved','active','returned','cancelled','blocked')",
name="ck_bookings_status",
),
CheckConstraint("ends_at > starts_at", name="ck_bookings_time_window"),
CheckConstraint(
"start_odometer_km IS NULL OR start_odometer_km >= 0",
name="ck_bookings_start_odometer",
),
CheckConstraint(
"end_odometer_km IS NULL OR end_odometer_km >= 0",
name="ck_bookings_end_odometer",
),
Index("ix_bookings_vehicle_status_window", "vehicle_id", "status", "starts_at", "ends_at"),
)
public_ref: Mapped[str] = mapped_column(String(20), unique=True, nullable=False)
customer_id: Mapped[uuid.UUID] = mapped_column(
+14 -1
View File
@@ -2,7 +2,7 @@ import uuid
from datetime import datetime
from typing import TYPE_CHECKING
from sqlalchemy import DateTime, ForeignKey, String
from sqlalchemy import CheckConstraint, DateTime, ForeignKey, Index, String
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -25,6 +25,19 @@ ISSUE_STATUSES = ("open", "deferred", "resolved", "rejected")
class DataQualityIssue(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "data_quality_issues"
__table_args__ = (
CheckConstraint(
"rule_type IN ('possible_duplicate_customer','missing_required_field',"
"'odometer_regression','booking_overlap','vehicle_status_conflict')",
name="ck_data_quality_rule_type",
),
CheckConstraint("severity IN ('low','medium','high')", name="ck_data_quality_severity"),
CheckConstraint(
"status IN ('open','deferred','resolved','rejected')",
name="ck_data_quality_status",
),
Index("ix_data_quality_work_queue", "status", "due_at", "severity"),
)
public_ref: Mapped[str] = mapped_column(String(20), unique=True, nullable=False)
rule_type: Mapped[str] = mapped_column(String(40), nullable=False)
+9 -1
View File
@@ -1,7 +1,7 @@
import uuid
from datetime import datetime
from sqlalchemy import DateTime, Integer, String, Text
from sqlalchemy import CheckConstraint, DateTime, Index, Integer, String, Text
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column
@@ -32,6 +32,14 @@ def is_demo_scenario_failure(event: "OutboxEvent") -> bool:
class OutboxEvent(TimestampMixin, Base):
__tablename__ = "outbox_events"
__table_args__ = (
CheckConstraint(
"delivery_status IN ('pending','delivering','succeeded','failed')",
name="ck_outbox_delivery_status",
),
CheckConstraint("attempts >= 0", name="ck_outbox_attempts"),
Index("ix_outbox_delivery_next_attempt", "delivery_status", "next_attempt_at"),
)
event_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
+11 -1
View File
@@ -1,4 +1,4 @@
from sqlalchemy import Boolean, Integer, String
from sqlalchemy import Boolean, CheckConstraint, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from app.core.db import Base
@@ -9,6 +9,16 @@ OPERATIONAL_STATUSES = ("available", "rented", "cleaning", "maintenance", "block
class Vehicle(UUIDPrimaryKeyMixin, TimestampMixin, Base):
__tablename__ = "vehicles"
__table_args__ = (
CheckConstraint(
"operational_status IN ('available','rented','cleaning','maintenance','blocked')",
name="ck_vehicles_operational_status",
),
CheckConstraint("model_year BETWEEN 1900 AND 2100", name="ck_vehicles_model_year"),
CheckConstraint("odometer_km >= 0", name="ck_vehicles_odometer"),
CheckConstraint("next_service_km >= 0", name="ck_vehicles_next_service"),
CheckConstraint("version >= 1", name="ck_vehicles_version"),
)
public_ref: Mapped[str] = mapped_column(String(20), unique=True, nullable=False)
make: Mapped[str] = mapped_column(String(80), nullable=False)