diff --git a/app/api/v1/playlists.py b/app/api/v1/playlists.py index c86faeb..93bdb8c 100644 --- a/app/api/v1/playlists.py +++ b/app/api/v1/playlists.py @@ -62,11 +62,11 @@ async def get_main_playlist( @router.get("/current") async def get_current_playlist( - current_user: Annotated[User, Depends(get_current_active_user_flexible)], + current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], ) -> PlaylistResponse: - """Get the user's current playlist (falls back to main playlist).""" - playlist = await playlist_service.get_current_playlist(current_user.id) + """Get the global current playlist (falls back to main playlist).""" + playlist = await playlist_service.get_current_playlist() return PlaylistResponse.from_playlist(playlist) @@ -105,13 +105,19 @@ async def update_playlist( playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], ) -> PlaylistResponse: """Update a playlist.""" + if current_user.id is None: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="User ID not available", + ) + playlist = await playlist_service.update_playlist( playlist_id=playlist_id, user_id=current_user.id, name=request.name, description=request.description, genre=request.genre, - is_current=request.is_current, + is_current=None, # is_current is not handled by this endpoint ) return PlaylistResponse.from_playlist(playlist) @@ -212,21 +218,21 @@ async def reorder_playlist_sounds( @router.put("/{playlist_id}/set-current") async def set_current_playlist( playlist_id: int, - current_user: Annotated[User, Depends(get_current_active_user_flexible)], + current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], ) -> PlaylistResponse: - """Set a playlist as the current playlist.""" - playlist = await playlist_service.set_current_playlist(playlist_id, current_user.id) + """Set a playlist as the global current playlist.""" + playlist = await playlist_service.set_current_playlist_global(playlist_id) return PlaylistResponse.from_playlist(playlist) @router.delete("/current") async def unset_current_playlist( - current_user: Annotated[User, Depends(get_current_active_user_flexible)], + current_user: Annotated[User, Depends(get_current_active_user_flexible)], # noqa: ARG001 playlist_service: Annotated[PlaylistService, Depends(get_playlist_service)], ) -> MessageResponse: - """Unset the current playlist.""" - await playlist_service.unset_current_playlist(current_user.id) + """Unset the global current playlist.""" + await playlist_service.unset_current_playlist_global() return MessageResponse(message="Current playlist unset successfully") diff --git a/app/repositories/playlist.py b/app/repositories/playlist.py index 53a7f56..f7bda68 100644 --- a/app/repositories/playlist.py +++ b/app/repositories/playlist.py @@ -66,6 +66,18 @@ class PlaylistRepository(BaseRepository[Playlist]): logger.exception("Failed to get current playlist for user: %s", user_id) raise + async def get_global_current_playlist(self) -> Playlist | None: + """Get the global current playlist (app-wide).""" + try: + statement = select(Playlist).where( + Playlist.is_current == True, # noqa: E712 + ) + result = await self.session.exec(statement) + return result.first() + except Exception: + logger.exception("Failed to get global current playlist") + raise + async def search_by_name( self, query: str, user_id: int | None = None, ) -> list[Playlist]: diff --git a/app/services/playlist.py b/app/services/playlist.py index a571a45..a21335a 100644 --- a/app/services/playlist.py +++ b/app/services/playlist.py @@ -54,9 +54,9 @@ class PlaylistService: return main_playlist - async def get_current_playlist(self, user_id: int) -> Playlist: - """Get the user's current playlist, fallback to main playlist.""" - current_playlist = await self.playlist_repo.get_current_playlist(user_id) + async def get_current_playlist(self) -> Playlist: + """Get the global current playlist, fallback to main playlist.""" + current_playlist = await self.playlist_repo.get_global_current_playlist() if current_playlist: return current_playlist @@ -317,6 +317,30 @@ class PlaylistService: user_id, ) + # Global current playlist methods + async def set_current_playlist_global(self, playlist_id: int) -> Playlist: + """Set a playlist as the global current playlist (app-wide).""" + playlist = await self.get_playlist_by_id(playlist_id) + + # Unset any existing current playlist globally + await self._unset_global_current_playlist() + + # Set new current playlist + playlist = await self.playlist_repo.update(playlist, {"is_current": True}) + logger.info("Set playlist %s as global current playlist", playlist_id) + return playlist + + async def unset_current_playlist_global(self) -> None: + """Unset the global current playlist (main playlist becomes fallback).""" + await self._unset_global_current_playlist() + logger.info("Unset global current playlist, main playlist is now fallback") + + async def _unset_global_current_playlist(self) -> None: + """Unset any current playlist globally.""" + current_playlist = await self.playlist_repo.get_global_current_playlist() + if current_playlist: + await self.playlist_repo.update(current_playlist, {"is_current": False}) + async def _unset_current_playlist(self, user_id: int) -> None: """Unset the current playlist for a user.""" current_playlist = await self.playlist_repo.get_current_playlist(user_id) diff --git a/tests/api/v1/test_playlist_endpoints.py b/tests/api/v1/test_playlist_endpoints.py index c47efd3..b2d8e9d 100644 --- a/tests/api/v1/test_playlist_endpoints.py +++ b/tests/api/v1/test_playlist_endpoints.py @@ -358,14 +358,14 @@ class TestPlaylistEndpoints: assert data["genre"] == "jazz" @pytest.mark.asyncio - async def test_update_playlist_set_current( + async def test_update_playlist_basic_fields( self, authenticated_client: AsyncClient, test_session: AsyncSession, test_user: User, ) -> None: - """Test PUT /api/v1/playlists/{id} - set playlist as current.""" - # Create test playlists within this test + """Test PUT /api/v1/playlists/{id} - update basic fields only.""" + # Create test playlist user_id = test_user.id test_playlist = Playlist( user_id=user_id, @@ -377,25 +377,13 @@ class TestPlaylistEndpoints: is_deletable=True, ) test_session.add(test_playlist) - - # Note: main_playlist doesn't need to be current=True for this test - # The service logic handles current playlist management - main_playlist = Playlist( - user_id=None, - name="Main Playlist", - description="Main playlist", - is_main=True, - is_current=False, - is_deletable=False, - ) - test_session.add(main_playlist) await test_session.commit() await test_session.refresh(test_playlist) # Extract ID before HTTP request playlist_id = test_playlist.id - payload = {"is_current": True} + payload = {"name": "Updated Playlist", "description": "Updated description"} response = await authenticated_client.put( f"/api/v1/playlists/{playlist_id}", json=payload, @@ -403,7 +391,10 @@ class TestPlaylistEndpoints: assert response.status_code == 200 data = response.json() - assert data["is_current"] is True + assert data["name"] == "Updated Playlist" + assert data["description"] == "Updated description" + # is_current should remain unchanged (not handled by this endpoint) + assert data["is_current"] is False @pytest.mark.asyncio async def test_delete_playlist_success(