diff --git a/app/services/movie_service.py b/app/services/movie_service.py index 7cd6b09..879c0aa 100644 --- a/app/services/movie_service.py +++ b/app/services/movie_service.py @@ -47,6 +47,18 @@ async def get_movie_detail(session: AsyncSession, movie_aurora_id: str) -> Movie cast, crew = split_credits(credits_) + company_out: list[CompanyBriefOut] = [] + for company, _role in companies: + logos = await polymorphic.get_artwork(session, "company", company.id, ArtworkType.LOGO) + company_out.append( + CompanyBriefOut( + id=aurora_id("company", str(company.id)), + name=company.name, + company_type=company.company_type.value, + logo_path=primary_artwork_path(logos, ArtworkType.LOGO), + ) + ) + return MovieDetailOut( id=aurora_id("movie", str(movie.id)), title=movie.title, @@ -67,15 +79,7 @@ async def get_movie_detail(session: AsyncSession, movie_aurora_id: str) -> Movie keywords=[KeywordOut(id=aurora_id("keyword", str(k.id)), name=k.name) for k in keywords], cast=cast, crew=crew, - companies=[ - CompanyBriefOut( - id=aurora_id("company", str(company.id)), - name=company.name, - company_type=company.company_type.value, - logo_path=None, - ) - for company, _role in companies - ], + companies=company_out, collection=( CollectionBriefOut( id=aurora_id("collection", str(movie.collection.id)), name=movie.collection.name diff --git a/app/services/tv_service.py b/app/services/tv_service.py index 2300282..d6e2d63 100644 --- a/app/services/tv_service.py +++ b/app/services/tv_service.py @@ -53,6 +53,16 @@ async def _season_brief(session: AsyncSession, season) -> SeasonBriefOut: ) +async def _company_brief(session: AsyncSession, company) -> CompanyBriefOut: + logos = await polymorphic.get_artwork(session, "company", company.id, ArtworkType.LOGO) + return CompanyBriefOut( + id=aurora_id("company", str(company.id)), + name=company.name, + company_type=company.company_type.value, + logo_path=primary_artwork_path(logos, ArtworkType.LOGO), + ) + + async def get_series_detail(session: AsyncSession, series_aurora_id: str) -> SeriesDetailOut: series_id = _resolve_id(series_aurora_id, "series", SeriesNotFoundError) series = await tv_repository.get_series_by_id(session, series_id) @@ -75,6 +85,8 @@ async def get_series_detail(session: AsyncSession, series_aurora_id: str) -> Ser _, creators = split_credits([c for c in credits_ if c.department == "Creator"]) season_briefs = [await _season_brief(session, s) for s in seasons] + network_briefs = [await _company_brief(session, c) for c, _role in networks] + company_briefs = [await _company_brief(session, c) for c, _role in companies] return SeriesDetailOut( id=aurora_id("series", str(series.id)), @@ -96,18 +108,8 @@ async def get_series_detail(session: AsyncSession, series_aurora_id: str) -> Ser creators=creators, cast=cast, crew=crew, - networks=[ - CompanyBriefOut( - id=aurora_id("company", str(c.id)), name=c.name, company_type=c.company_type.value - ) - for c, _role in networks - ], - companies=[ - CompanyBriefOut( - id=aurora_id("company", str(c.id)), name=c.name, company_type=c.company_type.value - ) - for c, _role in companies - ], + networks=network_briefs, + companies=company_briefs, seasons=season_briefs, images=to_images_out(artwork), videos=[to_video_out(v) for v in videos], diff --git a/tests/integration/test_movie_ingestion.py b/tests/integration/test_movie_ingestion.py index 9b94729..1b0e916 100644 --- a/tests/integration/test_movie_ingestion.py +++ b/tests/integration/test_movie_ingestion.py @@ -11,6 +11,7 @@ import pytest from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession +from app.core.ids import aurora_id from app.models.artwork import Artwork from app.models.company import Company from app.models.credit import Credit @@ -18,6 +19,7 @@ from app.models.genre import Genre from app.models.movie import Movie from app.models.provider import ProviderRecord from app.providers.base import MetadataProvider +from app.services import movie_service from app.services.ingestion.movie_ingestion import ingest_movie from tests.unit.test_normalizer import FAKE_MOVIE @@ -128,3 +130,21 @@ async def test_ingest_movie_ingests_company_logo(db_session: AsyncSession): assert logo.artwork_type.value == "logo" assert logo.is_primary is True assert logo.original_url.endswith("/village-roadshow-logo.png") + + +@pytest.mark.asyncio +async def test_movie_detail_surfaces_company_logo_path(db_session: AsyncSession): + """The ingested logo must actually reach the API response -- movie_service + used to hardcode companies[].logo_path = None instead of looking up the + company's artwork, so ingestion could succeed while the API still showed + logo_path: None for every company.""" + + provider = FakeTMDbProvider(FAKE_MOVIE) + movie_id = await ingest_movie(db_session, provider, "603") + await db_session.commit() + + detail = await movie_service.get_movie_detail(db_session, aurora_id("movie", str(movie_id))) + + roadshow = next(c for c in detail.companies if c.name == "Village Roadshow Pictures") + assert roadshow.logo_path is not None + assert roadshow.logo_path.endswith("/village-roadshow-logo.png") diff --git a/tests/integration/test_series_ingestion.py b/tests/integration/test_series_ingestion.py index ed34b4f..b288042 100644 --- a/tests/integration/test_series_ingestion.py +++ b/tests/integration/test_series_ingestion.py @@ -11,8 +11,10 @@ import pytest from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession +from app.core.ids import aurora_id from app.models.tv import Episode, Season, Series from app.providers.base import MetadataProvider, ProviderNotFoundError +from app.services import tv_service from app.services.ingestion.series_ingestion import ingest_season, ingest_series from tests.unit.test_normalizer import FAKE_SEASON, FAKE_SERIES @@ -115,3 +117,23 @@ async def test_ingest_season_is_idempotent(db_session: AsyncSession): ) # Re-running must not duplicate episode rows. assert len(episodes) == 2 + + +@pytest.mark.asyncio +async def test_series_detail_surfaces_network_logo_path(db_session: AsyncSession): + """Same class of bug as movie companies: tv_service used to build + networks[]/companies[] without ever looking up their logo artwork, so + logo_path was always None regardless of what ingestion had stored.""" + + provider = FakeTMDbSeriesProvider(FAKE_SERIES, FAKE_SEASON) + series_id = await ingest_series(db_session, provider, "1396") + await db_session.commit() + + detail = await tv_service.get_series_detail(db_session, aurora_id("series", str(series_id))) + + amc = next(n for n in detail.networks if n.name == "AMC") + assert amc.logo_path is not None + assert amc.logo_path.endswith("/amc-logo.png") + + gran_via = next(c for c in detail.companies if c.name == "Gran Via Productions") + assert gran_via.logo_path is None