Files
AudiOhm/backend/alembic/versions/001_add_library_tables.py
T
root 801e6a050b prod: UI Optimisée mise en production
- Documentation archivée et réorganisée
- Backend: Ajout tests, migrations, library service, rate limiting
- Frontend: Suppression Flutter, focus sur interface web HTML/JS
- Tailwind CSS ajouté pour le style
- Améliorations UX et corrections bugs

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-01-20 09:56:39 +00:00

198 lines
5.6 KiB
Python

"""Add library tables (listening_history, liked_tracks)
Revision ID: 001_add_library_tables
Revises:
Create Date: 2025-01-19 17:51: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 = '001_add_library_tables'
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 listening_history and liked_tracks tables with indexes."""
# Create listening_history table
op.create_table(
'listening_history',
sa.Column(
'id',
postgresql.UUID(as_uuid=True),
primary_key=True,
nullable=False,
server_default=sa.text('gen_random_uuid()')
),
sa.Column(
'user_id',
postgresql.UUID(as_uuid=True),
sa.ForeignKey('users.id', ondelete='CASCADE'),
nullable=False
),
sa.Column(
'track_id',
postgresql.UUID(as_uuid=True),
sa.ForeignKey('tracks.id', ondelete='CASCADE'),
nullable=False
),
sa.Column(
'played_for',
sa.Integer(),
nullable=False,
server_default='0',
comment='Duration played in seconds'
),
sa.Column(
'completed',
sa.Boolean(),
nullable=False,
server_default='false',
comment='Whether the track was played to completion'
),
sa.Column(
'source',
sa.String(length=50),
nullable=True,
comment='Playback source (library, playlist, search, etc.)'
),
sa.Column(
'played_at',
sa.DateTime(),
nullable=False,
server_default=sa.text('CURRENT_TIMESTAMP')
),
sa.Column(
'created_at',
sa.DateTime(),
nullable=False,
server_default=sa.text('CURRENT_TIMESTAMP')
),
comment='Listening history representing user track listening records'
)
# Create indexes for listening_history
op.create_index(
'ix_listening_history_id',
'listening_history',
['id']
)
op.create_index(
'ix_listening_history_user_id',
'listening_history',
['user_id']
)
op.create_index(
'ix_listening_history_track_id',
'listening_history',
['track_id']
)
op.create_index(
'ix_listening_history_played_at',
'listening_history',
['played_at']
)
op.create_index(
'ix_listening_history_user_played',
'listening_history',
['user_id', 'played_at']
)
op.create_index(
'ix_listening_history_user_track',
'listening_history',
['user_id', 'track_id']
)
# Create liked_tracks table
op.create_table(
'liked_tracks',
sa.Column(
'id',
postgresql.UUID(as_uuid=True),
primary_key=True,
nullable=False,
server_default=sa.text('gen_random_uuid()')
),
sa.Column(
'user_id',
postgresql.UUID(as_uuid=True),
sa.ForeignKey('users.id', ondelete='CASCADE'),
nullable=False
),
sa.Column(
'track_id',
postgresql.UUID(as_uuid=True),
sa.ForeignKey('tracks.id', ondelete='CASCADE'),
nullable=False
),
sa.Column(
'notes',
sa.String(length=1000),
nullable=True,
comment='User notes about the track'
),
sa.Column(
'created_at',
sa.DateTime(),
nullable=False,
server_default=sa.text('CURRENT_TIMESTAMP')
),
sa.Column(
'updated_at',
sa.DateTime(),
nullable=False,
server_default=sa.text('CURRENT_TIMESTAMP')
),
comment='Liked tracks representing user favorited tracks'
)
# Create indexes for liked_tracks
op.create_index(
'ix_liked_tracks_id',
'liked_tracks',
['id']
)
op.create_index(
'ix_liked_tracks_user_id',
'liked_tracks',
['user_id']
)
op.create_index(
'ix_liked_tracks_track_id',
'liked_tracks',
['track_id']
)
op.create_index(
'ix_liked_tracks_user_track',
'liked_tracks',
['user_id', 'track_id'],
unique=True
)
def downgrade() -> None:
"""Drop liked_tracks and listening_history tables."""
# Drop liked_tracks table first (no foreign keys depend on it)
op.drop_index('ix_liked_tracks_user_track', table_name='liked_tracks')
op.drop_index('ix_liked_tracks_track_id', table_name='liked_tracks')
op.drop_index('ix_liked_tracks_user_id', table_name='liked_tracks')
op.drop_index('ix_liked_tracks_id', table_name='liked_tracks')
op.drop_table('liked_tracks')
# Drop listening_history table
op.drop_index('ix_listening_history_user_track', table_name='listening_history')
op.drop_index('ix_listening_history_user_played', table_name='listening_history')
op.drop_index('ix_listening_history_played_at', table_name='listening_history')
op.drop_index('ix_listening_history_track_id', table_name='listening_history')
op.drop_index('ix_listening_history_user_id', table_name='listening_history')
op.drop_index('ix_listening_history_id', table_name='listening_history')
op.drop_table('listening_history')