diff --git a/app/repositories.py b/app/repositories.py index af6b577..0d38f45 100644 --- a/app/repositories.py +++ b/app/repositories.py @@ -1,3 +1,4 @@ +import operator from typing import TYPE_CHECKING from advanced_alchemy.repository import SQLAlchemyAsyncRepository @@ -17,6 +18,9 @@ class BaseRepository(SQLAlchemyAsyncRepository[models.Deck]): repository_type = BaseRepository + async def list_decks(self) -> Sequence[models.Deck]: + return await self.get_many(order_by=models.Deck.id.asc()) + async def fetch_with_cards(self, deck_id: int) -> models.Deck: return await self.get_one( models.Deck.id == deck_id, @@ -31,12 +35,13 @@ class BaseRepository(SQLAlchemyAsyncRepository[models.Card]): repository_type = BaseRepository async def list_for_deck(self, deck_id: int) -> Sequence[models.Card]: - return await self.get_many(models.Card.deck_id == deck_id) + return await self.get_many(models.Card.deck_id == deck_id, order_by=models.Card.id.asc()) async def add_cards(self, deck_id: int, cards: list[schemas.CardCreate]) -> Sequence[models.Card]: return await self.create_many([models.Card(**card.model_dump(), deck_id=deck_id) for card in cards]) async def upsert_cards(self, deck_id: int, cards: list[schemas.Card]) -> Sequence[models.Card]: - return await self.upsert_many( + upserted = await self.upsert_many( [models.Card(**card.model_dump(exclude={"deck_id"}), deck_id=deck_id) for card in cards], ) + return sorted(upserted, key=operator.attrgetter("id")) diff --git a/app/use_cases/list_decks.py b/app/use_cases/list_decks.py index f1f2cce..6628382 100644 --- a/app/use_cases/list_decks.py +++ b/app/use_cases/list_decks.py @@ -16,6 +16,6 @@ class ListDecksUseCase: @postgres_retry async def __call__(self) -> Sequence[models.Deck]: async with self.transaction: - decks: typing.Final = await self.decks_repository.get_many() + decks: typing.Final = await self.decks_repository.list_decks() await self.transaction.commit() return decks diff --git a/tests/test_cards.py b/tests/test_cards.py index 43d8b3e..2118284 100644 --- a/tests/test_cards.py +++ b/tests/test_cards.py @@ -119,3 +119,19 @@ async def test_update_cards(client: AsyncClient) -> None: for x in cards: assert x.pop("deck_id") == deck.id assert cards == updated_data + + +async def test_cards_ordered_by_id_after_update(client: AsyncClient) -> None: + deck = await factories.DeckModelFactory.create_async() + card1, card2 = await factories.CardModelFactory.create_batch_async(size=2, deck_id=deck.id) + + response = await client.put( + f"/api/decks/{deck.id}/cards/", + json=[{"id": card2.id, "front": "card2 updated"}, {"id": card1.id, "front": "card1 updated"}], + ) + assert response.status_code == status.HTTP_200_OK + assert [x["id"] for x in response.json()["items"]] == [card1.id, card2.id] + + response = await client.get(f"/api/decks/{deck.id}/cards/") + assert response.status_code == status.HTTP_200_OK + assert [x["id"] for x in response.json()["items"]] == [card1.id, card2.id] diff --git a/tests/test_decks.py b/tests/test_decks.py index 5686fa0..3952093 100644 --- a/tests/test_decks.py +++ b/tests/test_decks.py @@ -45,6 +45,17 @@ async def test_list_decks_omits_cards(client: AsyncClient) -> None: assert "cards" not in item +async def test_list_decks_ordered_by_id_after_update(client: AsyncClient) -> None: + deck1, deck2 = await factories.DeckModelFactory.create_batch_async(size=2) + + response = await client.put(f"/api/decks/{deck1.id}/", json={"name": "deck1 updated"}) + assert response.status_code == status.HTTP_200_OK + + response = await client.get("/api/decks/") + assert response.status_code == status.HTTP_200_OK + assert [x["id"] for x in response.json()["items"]] == [deck1.id, deck2.id] + + async def test_get_one_deck(client: AsyncClient) -> None: deck = await factories.DeckModelFactory.create_async() card = await factories.CardModelFactory.create_async(deck_id=deck.id)