Publish curated MobilityOps source snapshot
This commit is contained in:
commit
7adc072f5e
317 files changed
+48851
No files matched your search
@@ -0,0 +1,28 @@
|
||||
"""idempotency request fingerprint
|
||||
|
||||
Revision ID: 0a4c1d2e3f5b
|
||||
Revises: c24f6a9d013e
|
||||
Create Date: 2026-08-16 22:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "0a4c1d2e3f5b"
|
||||
down_revision: Union[str, None] = "c24f6a9d013e"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"idempotency_records",
|
||||
sa.Column("request_fingerprint", sa.String(length=64), nullable=True),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column("idempotency_records", "request_fingerprint")
|
||||
@@ -0,0 +1,27 @@
|
||||
"""enforce one open issue per detected condition
|
||||
|
||||
Revision ID: 4f2b9c8d7e61
|
||||
Revises: 0a4c1d2e3f5b
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "4f2b9c8d7e61"
|
||||
down_revision = "0a4c1d2e3f5b"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_index(
|
||||
"uq_data_quality_one_open_condition",
|
||||
"data_quality_issues",
|
||||
["rule_type", "entity_type", "entity_id"],
|
||||
unique=True,
|
||||
postgresql_where=sa.text("status = 'open'"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("uq_data_quality_one_open_condition", table_name="data_quality_issues")
|
||||
@@ -0,0 +1,25 @@
|
||||
"""outbox last_error_code
|
||||
|
||||
Revision ID: 799d8800e241
|
||||
Revises: e7b08389f47f
|
||||
Create Date: 2026-08-03 10:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '799d8800e241'
|
||||
down_revision: Union[str, None] = 'e7b08389f47f'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column('outbox_events', sa.Column('last_error_code', sa.String(length=60), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column('outbox_events', 'last_error_code')
|
||||
@@ -0,0 +1,28 @@
|
||||
"""add optional external OIDC identity
|
||||
|
||||
Revision ID: a81d0ce9f662
|
||||
Revises: f43d829ab610
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "a81d0ce9f662"
|
||||
down_revision = "f43d829ab610"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("users", sa.Column("identity_provider", sa.String(80), nullable=True))
|
||||
op.add_column("users", sa.Column("external_subject", sa.String(255), nullable=True))
|
||||
op.create_unique_constraint(
|
||||
"uq_user_external_identity", "users", ["identity_provider", "external_subject"]
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint("uq_user_external_identity", "users", type_="unique")
|
||||
op.drop_column("users", "external_subject")
|
||||
op.drop_column("users", "identity_provider")
|
||||
@@ -0,0 +1,25 @@
|
||||
"""operational user credentials
|
||||
|
||||
Revision ID: b7c7b536df85
|
||||
Revises: 799d8800e241
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "b7c7b536df85"
|
||||
down_revision = "799d8800e241"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("users", sa.Column("email", sa.String(length=320), nullable=True))
|
||||
op.add_column("users", sa.Column("password_hash", sa.String(length=512), nullable=True))
|
||||
op.create_unique_constraint("uq_users_email", "users", ["email"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint("uq_users_email", "users", type_="unique")
|
||||
op.drop_column("users", "password_hash")
|
||||
op.drop_column("users", "email")
|
||||
@@ -0,0 +1,24 @@
|
||||
"""add explicit customer anonymisation state
|
||||
|
||||
Revision ID: b913a72e8c14
|
||||
Revises: a81d0ce9f662
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "b913a72e8c14"
|
||||
down_revision = "a81d0ce9f662"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column("customers", sa.Column("anonymized_at", sa.DateTime(timezone=True)))
|
||||
op.create_index("ix_customers_anonymized_at", "customers", ["anonymized_at"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_customers_anonymized_at", table_name="customers")
|
||||
op.drop_column("customers", "anonymized_at")
|
||||
@@ -0,0 +1,68 @@
|
||||
"""add domain constraints and operational indexes
|
||||
|
||||
Revision ID: c24f6a9d013e
|
||||
Revises: b913a72e8c14
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "c24f6a9d013e"
|
||||
down_revision = "b913a72e8c14"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
checks = (
|
||||
("bookings", "ck_bookings_status", "status IN ('reserved','active','returned','cancelled','blocked')"),
|
||||
("bookings", "ck_bookings_time_window", "ends_at > starts_at"),
|
||||
("bookings", "ck_bookings_start_odometer", "start_odometer_km IS NULL OR start_odometer_km >= 0"),
|
||||
("bookings", "ck_bookings_end_odometer", "end_odometer_km IS NULL OR end_odometer_km >= 0"),
|
||||
("vehicles", "ck_vehicles_operational_status", "operational_status IN ('available','rented','cleaning','maintenance','blocked')"),
|
||||
("vehicles", "ck_vehicles_model_year", "model_year BETWEEN 1900 AND 2100"),
|
||||
("vehicles", "ck_vehicles_odometer", "odometer_km >= 0"),
|
||||
("vehicles", "ck_vehicles_next_service", "next_service_km >= 0"),
|
||||
("vehicles", "ck_vehicles_version", "version >= 1"),
|
||||
("data_quality_issues", "ck_data_quality_rule_type", "rule_type IN ('possible_duplicate_customer','missing_required_field','odometer_regression','booking_overlap','vehicle_status_conflict')"),
|
||||
("data_quality_issues", "ck_data_quality_severity", "severity IN ('low','medium','high')"),
|
||||
("data_quality_issues", "ck_data_quality_status", "status IN ('open','deferred','resolved','rejected')"),
|
||||
("outbox_events", "ck_outbox_delivery_status", "delivery_status IN ('pending','delivering','succeeded','failed')"),
|
||||
("outbox_events", "ck_outbox_attempts", "attempts >= 0"),
|
||||
("audit_events", "ck_audit_actor_type", "actor_type IN ('user','service','system')"),
|
||||
)
|
||||
for table, name, condition in checks:
|
||||
op.create_check_constraint(name, table, condition)
|
||||
|
||||
op.create_index("ix_bookings_vehicle_status_window", "bookings", ["vehicle_id", "status", "starts_at", "ends_at"])
|
||||
op.create_index("ix_data_quality_work_queue", "data_quality_issues", ["status", "due_at", "severity"])
|
||||
op.create_index("ix_outbox_delivery_next_attempt", "outbox_events", ["delivery_status", "next_attempt_at"])
|
||||
op.create_index("ix_audit_action_occurred", "audit_events", ["action", "occurred_at"])
|
||||
op.create_index("ix_audit_entity", "audit_events", ["entity_type", "entity_id"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_audit_entity", table_name="audit_events")
|
||||
op.drop_index("ix_audit_action_occurred", table_name="audit_events")
|
||||
op.drop_index("ix_outbox_delivery_next_attempt", table_name="outbox_events")
|
||||
op.drop_index("ix_data_quality_work_queue", table_name="data_quality_issues")
|
||||
op.drop_index("ix_bookings_vehicle_status_window", table_name="bookings")
|
||||
for table, name in (
|
||||
("audit_events", "ck_audit_actor_type"),
|
||||
("outbox_events", "ck_outbox_attempts"),
|
||||
("outbox_events", "ck_outbox_delivery_status"),
|
||||
("data_quality_issues", "ck_data_quality_status"),
|
||||
("data_quality_issues", "ck_data_quality_severity"),
|
||||
("data_quality_issues", "ck_data_quality_rule_type"),
|
||||
("vehicles", "ck_vehicles_version"),
|
||||
("vehicles", "ck_vehicles_next_service"),
|
||||
("vehicles", "ck_vehicles_odometer"),
|
||||
("vehicles", "ck_vehicles_model_year"),
|
||||
("vehicles", "ck_vehicles_operational_status"),
|
||||
("bookings", "ck_bookings_end_odometer"),
|
||||
("bookings", "ck_bookings_start_odometer"),
|
||||
("bookings", "ck_bookings_time_window"),
|
||||
("bookings", "ck_bookings_status"),
|
||||
):
|
||||
op.drop_constraint(name, table, type_="check")
|
||||
@@ -0,0 +1,184 @@
|
||||
"""initial schema
|
||||
|
||||
Revision ID: c9498525abb5
|
||||
Revises:
|
||||
Create Date: 2026-08-01 20:50:05.997864
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'c9498525abb5'
|
||||
down_revision: Union[str, None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('audit_events',
|
||||
sa.Column('actor_type', sa.String(length=20), nullable=False),
|
||||
sa.Column('actor_id', sa.UUID(), nullable=True),
|
||||
sa.Column('actor_label', sa.String(length=120), nullable=False),
|
||||
sa.Column('action', sa.String(length=80), nullable=False),
|
||||
sa.Column('entity_type', sa.String(length=30), nullable=False),
|
||||
sa.Column('entity_id', sa.UUID(), nullable=True),
|
||||
sa.Column('correlation_id', sa.UUID(), nullable=False),
|
||||
sa.Column('before_json', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('after_json', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('metadata_json', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('occurred_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('customers',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('first_name', sa.String(length=80), nullable=False),
|
||||
sa.Column('last_name', sa.String(length=80), nullable=False),
|
||||
sa.Column('email', sa.String(length=200), nullable=True),
|
||||
sa.Column('phone', sa.String(length=40), nullable=True),
|
||||
sa.Column('postal_code', sa.String(length=20), nullable=True),
|
||||
sa.Column('city', sa.String(length=120), nullable=True),
|
||||
sa.Column('date_of_birth', sa.Date(), nullable=True),
|
||||
sa.Column('merged_into_customer_id', sa.UUID(), nullable=True),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['merged_into_customer_id'], ['customers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
op.create_table('data_quality_issues',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('rule_type', sa.String(length=40), nullable=False),
|
||||
sa.Column('entity_type', sa.String(length=30), nullable=False),
|
||||
sa.Column('entity_id', sa.UUID(), nullable=False),
|
||||
sa.Column('severity', sa.String(length=10), nullable=False),
|
||||
sa.Column('status', sa.String(length=20), nullable=False),
|
||||
sa.Column('evidence_json', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||
sa.Column('proposed_action_json', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||
sa.Column('detected_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('resolved_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('resolved_by', sa.String(length=120), nullable=True),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
op.create_table('outbox_events',
|
||||
sa.Column('event_id', sa.UUID(), nullable=False),
|
||||
sa.Column('event_type', sa.String(length=60), nullable=False),
|
||||
sa.Column('aggregate_type', sa.String(length=30), nullable=False),
|
||||
sa.Column('aggregate_id', sa.UUID(), nullable=False),
|
||||
sa.Column('payload_json', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||
sa.Column('occurred_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('delivery_status', sa.String(length=20), nullable=False),
|
||||
sa.Column('attempts', sa.Integer(), nullable=False),
|
||||
sa.Column('next_attempt_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('last_error', sa.Text(), nullable=True),
|
||||
sa.Column('external_run_id', sa.String(length=120), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.PrimaryKeyConstraint('event_id')
|
||||
)
|
||||
op.create_table('users',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('display_name', sa.String(length=120), nullable=False),
|
||||
sa.Column('role', sa.String(length=30), nullable=False),
|
||||
sa.Column('active', sa.Boolean(), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
op.create_table('vehicles',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('make', sa.String(length=80), nullable=False),
|
||||
sa.Column('model', sa.String(length=80), nullable=False),
|
||||
sa.Column('model_year', sa.Integer(), nullable=False),
|
||||
sa.Column('registration_number', sa.String(length=40), nullable=False),
|
||||
sa.Column('location', sa.String(length=120), nullable=False),
|
||||
sa.Column('operational_status', sa.String(length=20), nullable=False),
|
||||
sa.Column('odometer_km', sa.Integer(), nullable=False),
|
||||
sa.Column('next_service_km', sa.Integer(), nullable=False),
|
||||
sa.Column('active', sa.Boolean(), nullable=False),
|
||||
sa.Column('version', sa.Integer(), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref'),
|
||||
sa.UniqueConstraint('registration_number')
|
||||
)
|
||||
op.create_table('bookings',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('customer_id', sa.UUID(), nullable=False),
|
||||
sa.Column('vehicle_id', sa.UUID(), nullable=False),
|
||||
sa.Column('starts_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('ends_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('status', sa.String(length=20), nullable=False),
|
||||
sa.Column('start_odometer_km', sa.Integer(), nullable=True),
|
||||
sa.Column('end_odometer_km', sa.Integer(), nullable=True),
|
||||
sa.Column('requirements_complete', sa.Boolean(), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['customer_id'], ['customers.id'], ),
|
||||
sa.ForeignKeyConstraint(['vehicle_id'], ['vehicles.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
op.create_table('maintenance_records',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('vehicle_id', sa.UUID(), nullable=False),
|
||||
sa.Column('occurred_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('odometer_km', sa.Integer(), nullable=False),
|
||||
sa.Column('category', sa.String(length=60), nullable=False),
|
||||
sa.Column('summary', sa.Text(), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['vehicle_id'], ['vehicles.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
op.create_table('inspections',
|
||||
sa.Column('public_ref', sa.String(length=20), nullable=False),
|
||||
sa.Column('booking_id', sa.UUID(), nullable=False),
|
||||
sa.Column('vehicle_id', sa.UUID(), nullable=False),
|
||||
sa.Column('type', sa.String(length=20), nullable=False),
|
||||
sa.Column('fuel_level_percent', sa.Integer(), nullable=False),
|
||||
sa.Column('cleanliness_ok', sa.Boolean(), nullable=False),
|
||||
sa.Column('damage_reported', sa.Boolean(), nullable=False),
|
||||
sa.Column('technical_warning', sa.Boolean(), nullable=False),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('odometer_km', sa.Integer(), nullable=False),
|
||||
sa.Column('completed_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('completed_by', sa.String(length=120), nullable=True),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['booking_id'], ['bookings.id'], ),
|
||||
sa.ForeignKeyConstraint(['vehicle_id'], ['vehicles.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('public_ref')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('inspections')
|
||||
op.drop_table('maintenance_records')
|
||||
op.drop_table('bookings')
|
||||
op.drop_table('vehicles')
|
||||
op.drop_table('users')
|
||||
op.drop_table('outbox_events')
|
||||
op.drop_table('data_quality_issues')
|
||||
op.drop_table('customers')
|
||||
op.drop_table('audit_events')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,49 @@
|
||||
"""persist revoked sessions
|
||||
|
||||
Revision ID: d1f83bc64170
|
||||
Revises: b7c7b536df85
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "d1f83bc64170"
|
||||
down_revision = "b7c7b536df85"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"revoked_sessions",
|
||||
sa.Column("token_hash", sa.String(length=64), nullable=False),
|
||||
sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column("id", sa.Uuid(), nullable=False),
|
||||
sa.Column(
|
||||
"created_at",
|
||||
sa.DateTime(timezone=True),
|
||||
server_default=sa.text("now()"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.Column(
|
||||
"updated_at",
|
||||
sa.DateTime(timezone=True),
|
||||
server_default=sa.text("now()"),
|
||||
nullable=False,
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
op.create_index("ix_revoked_sessions_expires_at", "revoked_sessions", ["expires_at"])
|
||||
op.create_index(
|
||||
"ix_revoked_sessions_token_hash",
|
||||
"revoked_sessions",
|
||||
["token_hash"],
|
||||
unique=True,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("ix_revoked_sessions_token_hash", table_name="revoked_sessions")
|
||||
op.drop_index("ix_revoked_sessions_expires_at", table_name="revoked_sessions")
|
||||
op.drop_table("revoked_sessions")
|
||||
@@ -0,0 +1,41 @@
|
||||
"""idempotency records
|
||||
|
||||
Revision ID: e7b08389f47f
|
||||
Revises: c9498525abb5
|
||||
Create Date: 2026-08-01 21:24:35.472070
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'e7b08389f47f'
|
||||
down_revision: Union[str, None] = 'c9498525abb5'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('idempotency_records',
|
||||
sa.Column('idempotency_key', sa.String(length=128), nullable=False),
|
||||
sa.Column('booking_id', sa.UUID(), nullable=False),
|
||||
sa.Column('response_status', sa.Integer(), nullable=False),
|
||||
sa.Column('response_body', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['booking_id'], ['bookings.id'], ),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('idempotency_key')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('idempotency_records')
|
||||
# ### end Alembic commands ###
|
||||
@@ -0,0 +1,65 @@
|
||||
"""add ownership and SLA deadlines to data quality issues
|
||||
|
||||
Revision ID: f43d829ab610
|
||||
Revises: d1f83bc64170
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "f43d829ab610"
|
||||
down_revision = "d1f83bc64170"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column(
|
||||
"data_quality_issues",
|
||||
sa.Column("due_at", sa.DateTime(timezone=True), nullable=True),
|
||||
)
|
||||
op.add_column(
|
||||
"data_quality_issues",
|
||||
sa.Column("assigned_to_user_id", sa.Uuid(), nullable=True),
|
||||
)
|
||||
op.create_foreign_key(
|
||||
"fk_data_quality_issues_assigned_user",
|
||||
"data_quality_issues",
|
||||
"users",
|
||||
["assigned_to_user_id"],
|
||||
["id"],
|
||||
ondelete="SET NULL",
|
||||
)
|
||||
op.create_index("ix_data_quality_issues_due_at", "data_quality_issues", ["due_at"])
|
||||
op.create_index(
|
||||
"ix_data_quality_issues_assigned_to_user_id",
|
||||
"data_quality_issues",
|
||||
["assigned_to_user_id"],
|
||||
)
|
||||
op.execute(
|
||||
"""
|
||||
UPDATE data_quality_issues
|
||||
SET due_at = detected_at + CASE severity
|
||||
WHEN 'high' THEN interval '4 hours'
|
||||
WHEN 'low' THEN interval '3 days'
|
||||
ELSE interval '1 day'
|
||||
END
|
||||
WHERE status = 'open' AND due_at IS NULL
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index(
|
||||
"ix_data_quality_issues_assigned_to_user_id",
|
||||
table_name="data_quality_issues",
|
||||
)
|
||||
op.drop_index("ix_data_quality_issues_due_at", table_name="data_quality_issues")
|
||||
op.drop_constraint(
|
||||
"fk_data_quality_issues_assigned_user",
|
||||
"data_quality_issues",
|
||||
type_="foreignkey",
|
||||
)
|
||||
op.drop_column("data_quality_issues", "assigned_to_user_id")
|
||||
op.drop_column("data_quality_issues", "due_at")
|
||||
Reference in new issue
Block a user