Files
enclava/plugins/zammad/migrations/versions/001_initial_zammad_schema.py
2025-08-22 18:02:37 +02:00

112 lines
5.0 KiB
Python

"""Initial Zammad plugin schema
Revision ID: 001
Revises:
Create Date: 2024-12-22 12:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID
# revision identifiers, used by Alembic.
revision = '001'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
"""Create initial Zammad plugin schema"""
# Create zammad_configurations table
op.create_table(
'zammad_configurations',
sa.Column('id', UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('user_id', sa.String(255), nullable=False),
sa.Column('name', sa.String(100), nullable=False),
sa.Column('zammad_url', sa.String(500), nullable=False),
sa.Column('api_token_encrypted', sa.Text(), nullable=False),
sa.Column('chatbot_id', sa.String(100), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False, server_default=sa.text('TRUE')),
sa.Column('ai_summarization_enabled', sa.Boolean(), nullable=False, server_default=sa.text('TRUE')),
sa.Column('auto_summarize', sa.Boolean(), nullable=False, server_default=sa.text('TRUE')),
sa.Column('sync_enabled', sa.Boolean(), nullable=False, server_default=sa.text('TRUE')),
sa.Column('sync_interval_hours', sa.Integer(), nullable=False, server_default=sa.text('2')),
sa.Column('created_at', sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('updated_at', sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
)
# Create zammad_tickets table
op.create_table(
'zammad_tickets',
sa.Column('id', UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('zammad_ticket_id', sa.String(50), nullable=False),
sa.Column('configuration_id', UUID(as_uuid=True), nullable=True),
sa.Column('title', sa.String(500), nullable=False),
sa.Column('body', sa.Text(), nullable=True),
sa.Column('status', sa.String(50), nullable=True),
sa.Column('priority', sa.String(50), nullable=True),
sa.Column('customer_id', sa.String(50), nullable=True),
sa.Column('group_id', sa.String(50), nullable=True),
sa.Column('ai_summary', sa.Text(), nullable=True),
sa.Column('last_synced', sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('created_at', sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('updated_at', sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.ForeignKeyConstraint(['configuration_id'], ['zammad_configurations.id'], ondelete='CASCADE'),
)
# Create indexes for performance
op.create_index('idx_zammad_configurations_user_id', 'zammad_configurations', ['user_id'])
op.create_index('idx_zammad_configurations_user_active', 'zammad_configurations', ['user_id', 'is_active'])
op.create_index('idx_zammad_tickets_zammad_id', 'zammad_tickets', ['zammad_ticket_id'])
op.create_index('idx_zammad_tickets_config_id', 'zammad_tickets', ['configuration_id'])
op.create_index('idx_zammad_tickets_status', 'zammad_tickets', ['status'])
op.create_index('idx_zammad_tickets_last_synced', 'zammad_tickets', ['last_synced'])
# Create updated_at trigger function if it doesn't exist
op.execute("""
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE 'plpgsql';
""")
# Create triggers to automatically update updated_at columns
op.execute("""
CREATE TRIGGER update_zammad_configurations_updated_at
BEFORE UPDATE ON zammad_configurations
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
""")
op.execute("""
CREATE TRIGGER update_zammad_tickets_updated_at
BEFORE UPDATE ON zammad_tickets
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
""")
def downgrade() -> None:
"""Drop Zammad plugin schema"""
# Drop triggers first
op.execute("DROP TRIGGER IF EXISTS update_zammad_tickets_updated_at ON zammad_tickets;")
op.execute("DROP TRIGGER IF EXISTS update_zammad_configurations_updated_at ON zammad_configurations;")
# Drop indexes
op.drop_index('idx_zammad_tickets_last_synced')
op.drop_index('idx_zammad_tickets_status')
op.drop_index('idx_zammad_tickets_config_id')
op.drop_index('idx_zammad_tickets_zammad_id')
op.drop_index('idx_zammad_configurations_user_active')
op.drop_index('idx_zammad_configurations_user_id')
# Drop tables (tickets first due to foreign key)
op.drop_table('zammad_tickets')
op.drop_table('zammad_configurations')
# Note: We don't drop the update_updated_at_column function as it might be used by other tables