satupeta-main/migrations/versions/20241203_1200_initial_schema.py

356 lines
19 KiB
Python
Raw Normal View History

2026-01-27 02:11:58 +00:00
"""initial schema
Revision ID: initial_schema
Revises:
Create Date: 2024-12-03 12:00:00.000000
"""
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 = 'initial_schema'
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:
# Create categories table
op.create_table('categories',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(), nullable=True),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('thumbnail', sa.String(), nullable=True),
sa.Column('count_mapset', sa.Integer(), server_default='0', nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('order', sa.Integer(), server_default='0', nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_categories_id', 'categories', ['id'])
# Create classifications table
op.create_table('classifications',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=20), nullable=False),
sa.Column('is_open', sa.Boolean(), nullable=True),
sa.Column('is_limited', sa.Boolean(), nullable=True),
sa.Column('is_secret', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_classifications_id', 'classifications', ['id'])
# Create map_projection_systems table
op.create_table('map_projection_systems',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=50), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_map_projection_systems_id', 'map_projection_systems', ['id'])
# Create news table
op.create_table('news',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(), nullable=True),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('thumbnail', sa.String(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_news_id', 'news', ['id'])
# Create organizations table
op.create_table('organizations',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('thumbnail', sa.String(length=255), nullable=True),
sa.Column('address', sa.String(length=255), nullable=True),
sa.Column('phone_number', sa.String(length=15), nullable=True),
sa.Column('email', sa.String(length=100), nullable=True),
sa.Column('website', sa.String(length=255), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='true', nullable=True),
sa.Column('is_deleted', sa.Boolean(), server_default='false', nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('modified_at', sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_organizations_id', 'organizations', ['id'])
# Create regionals table
op.create_table('regionals',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('code', sa.String(length=10), nullable=False),
sa.Column('name', sa.String(length=50), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('thumbnail', sa.String(length=255), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_regionals_id', 'regionals', ['id'])
# Create roles table
op.create_table('roles',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=20), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_roles_id', 'roles', ['id'])
# Create users table (depends on roles and organizations)
op.create_table('users',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(), nullable=False),
sa.Column('email', sa.String(), nullable=False),
sa.Column('profile_picture', sa.String(), nullable=True),
sa.Column('username', sa.String(), nullable=False),
sa.Column('password', sa.String(), nullable=False),
sa.Column('position', sa.String(), nullable=True),
sa.Column('role_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('employee_id', sa.String(), nullable=True),
sa.Column('organization_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('modified_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['organization_id'], ['organizations.id'], ),
sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('username')
)
op.create_index('ix_users_id', 'users', ['id'])
# Create credentials table (depends on users)
op.create_table('credentials',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(), nullable=True),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('encrypted_data', sa.Text(), nullable=False),
sa.Column('encryption_iv', sa.String(length=255), nullable=False),
sa.Column('credential_type', sa.String(length=50), nullable=False),
sa.Column('credential_metadata', postgresql.JSON(astext_type=sa.Text()), nullable=True),
sa.Column('created_by', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('last_used_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('last_used_by', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('is_default', sa.Boolean(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['last_used_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_credentials_id', 'credentials', ['id'])
# Create files table (depends on users)
op.create_table('files',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('filename', sa.String(length=255), nullable=False),
sa.Column('object_name', sa.String(length=512), nullable=False),
sa.Column('content_type', sa.String(length=100), nullable=False),
sa.Column('size', sa.Integer(), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('url', sa.String(length=1024), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('modified_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('object_name')
)
op.create_index('ix_files_filename', 'files', ['filename'])
op.create_index('ix_files_id', 'files', ['id'])
# Create refresh_tokens table (depends on users)
op.create_table('refresh_tokens',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('token', sa.String(length=255), nullable=False),
sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('revoked', sa.Boolean(), server_default='false', nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_refresh_tokens_id', 'refresh_tokens', ['id'])
op.create_index('ix_refresh_tokens_token', 'refresh_tokens', ['token'])
op.create_index('ix_refresh_tokens_user_id', 'refresh_tokens', ['user_id'])
# Create map_sources table (depends on credentials)
op.create_table('map_sources',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=50), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('credential_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('url', sa.Text(), nullable=True),
sa.ForeignKeyConstraint(['credential_id'], ['credentials.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_map_sources_id', 'map_sources', ['id'])
# Create mapsets table (depends on multiple tables)
op.create_table('mapsets',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('scale', sa.String(length=29), nullable=False),
sa.Column('layer_url', sa.Text(), nullable=True),
sa.Column('metadata_url', sa.Text(), nullable=True),
sa.Column('category_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('classification_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('regional_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('projection_system_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('producer_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('status_validation', sa.String(length=20), nullable=True),
sa.Column('data_status', sa.String(length=20), nullable=False),
sa.Column('data_update_period', sa.String(length=20), nullable=False),
sa.Column('data_version', sa.String(length=20), nullable=False),
sa.Column('coverage_level', sa.String(length=20), nullable=True),
sa.Column('coverage_area', sa.String(length=20), nullable=True),
sa.Column('is_popular', sa.Boolean(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=True),
sa.Column('is_deleted', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('created_by', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('layer_type', sa.String(length=20), nullable=True),
sa.Column('view_count', sa.Integer(), server_default='0', nullable=False),
sa.Column('download_count', sa.Integer(), server_default='0', nullable=False),
sa.Column('order', sa.Integer(), server_default='0', nullable=False),
sa.ForeignKeyConstraint(['category_id'], ['categories.id'], ),
sa.ForeignKeyConstraint(['classification_id'], ['classifications.id'], ),
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['producer_id'], ['organizations.id'], ),
sa.ForeignKeyConstraint(['projection_system_id'], ['map_projection_systems.id'], ),
sa.ForeignKeyConstraint(['regional_id'], ['regionals.id'], ),
sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_mapsets_id', 'mapsets', ['id'])
# Create mapset_access table (depends on mapsets, users, and organizations)
op.create_table('mapset_access',
sa.Column('id', sa.String(), nullable=False),
sa.Column('mapset_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('organization_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('granted_by', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('can_read', sa.Boolean(), nullable=True),
sa.Column('can_write', sa.Boolean(), nullable=True),
sa.Column('can_delete', sa.Boolean(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['granted_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['mapset_id'], ['mapsets.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['organization_id'], ['organizations.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
)
# Create mapset_histories table (depends on mapsets and users)
op.create_table('mapset_histories',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('mapset_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('validation_type', sa.String(length=50), nullable=False),
sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('timestamp', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['mapset_id'], ['mapsets.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_mapset_histories_id', 'mapset_histories', ['id'])
op.create_index('ix_mapset_histories_mapset_id', 'mapset_histories', ['mapset_id'])
# Create source_usages table (depends on map_sources and mapsets)
op.create_table('source_usages',
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('source_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('mapset_id', postgresql.UUID(as_uuid=True), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.ForeignKeyConstraint(['mapset_id'], ['mapsets.id'], ),
sa.ForeignKeyConstraint(['source_id'], ['map_sources.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_source_usages_id', 'source_usages', ['id'])
# Create feedback table (independent)
op.create_table('feedback',
sa.Column('id', sa.Integer(), nullable=False, autoincrement=True),
sa.Column('datetime', sa.DateTime(), nullable=True),
sa.Column('score', sa.Integer(), nullable=True),
sa.Column('tujuan_tercapai', sa.Boolean(), nullable=True),
sa.Column('tujuan_ditemukan', sa.Boolean(), nullable=True),
sa.Column('tujuan', sa.String(length=255), nullable=True),
sa.Column('sektor', sa.String(length=255), nullable=True),
sa.Column('email', sa.String(length=255), nullable=True),
sa.Column('saran', sa.Text(), nullable=True),
sa.Column('source_url', sa.String(length=255), nullable=True),
sa.Column('source_access', sa.String(length=255), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('gender', sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
def downgrade() -> None:
# Drop tables in reverse order to respect foreign key constraints
op.drop_table('feedback')
op.drop_index('ix_source_usages_id', table_name='source_usages')
op.drop_table('source_usages')
op.drop_index('ix_mapset_histories_mapset_id', table_name='mapset_histories')
op.drop_index('ix_mapset_histories_id', table_name='mapset_histories')
op.drop_table('mapset_histories')
op.drop_table('mapset_access')
op.drop_index('ix_mapsets_id', table_name='mapsets')
op.drop_table('mapsets')
op.drop_index('ix_map_sources_id', table_name='map_sources')
op.drop_table('map_sources')
op.drop_index('ix_refresh_tokens_user_id', table_name='refresh_tokens')
op.drop_index('ix_refresh_tokens_token', table_name='refresh_tokens')
op.drop_index('ix_refresh_tokens_id', table_name='refresh_tokens')
op.drop_table('refresh_tokens')
op.drop_index('ix_files_id', table_name='files')
op.drop_index('ix_files_filename', table_name='files')
op.drop_table('files')
op.drop_index('ix_credentials_id', table_name='credentials')
op.drop_table('credentials')
op.drop_index('ix_users_id', table_name='users')
op.drop_table('users')
op.drop_index('ix_roles_id', table_name='roles')
op.drop_table('roles')
op.drop_index('ix_regionals_id', table_name='regionals')
op.drop_table('regionals')
op.drop_index('ix_organizations_id', table_name='organizations')
op.drop_table('organizations')
op.drop_index('ix_news_id', table_name='news')
op.drop_table('news')
op.drop_index('ix_map_projection_systems_id', table_name='map_projection_systems')
op.drop_table('map_projection_systems')
op.drop_index('ix_classifications_id', table_name='classifications')
op.drop_table('classifications')
op.drop_index('ix_categories_id', table_name='categories')
op.drop_table('categories')