diff --git a/src/infra/publication.py b/src/infra/publication.py index b07df6d..fb28357 100644 --- a/src/infra/publication.py +++ b/src/infra/publication.py @@ -1,16 +1,25 @@ from datetime import timedelta import logging from sqlalchemy import String, Text, ForeignKey, Engine, Interval, UniqueConstraint -from sqlalchemy.orm import Mapped, mapped_column, relationship, Session +from sqlalchemy.orm import Mapped, mapped_column, relationship, Session, joinedload from src.infra.db import Base -from src.services.publications import Publication, Order, Entry, Sequence, PublicationProfile, PublicationRepo +from src.services.publications import ( + Publication, + Order, + Entry, + Sequence, + PublicationProfile, + PublicationRepo, + OrderProfile, +) class PublicationEntryModel(Base): __tablename__ = 'publication_entry' id: Mapped[int] = mapped_column(primary_key=True) + title: Mapped[str] = mapped_column(String(256)) text: Mapped[str] = mapped_column(Text()) sequences: Mapped[list['PublicationSequenceModel']] = relationship(back_populates='entry') @@ -55,13 +64,13 @@ class PublicationModel(Base): def model_to_entry(db_pub_entry: PublicationEntryModel) -> Entry: - return Entry(id=db_pub_entry.id, text=db_pub_entry.text) + return Entry(id=db_pub_entry.id, text=db_pub_entry.text, title=db_pub_entry.title) def model_to_sequence(db_pub_position: PublicationSequenceModel) -> Sequence: return Sequence( position=db_pub_position.position, - entry=model_to_entry(db_pub_position.entry), + entry=model_to_entry(db_pub_position.entry).to_profile(), duration=db_pub_position.duration, ) @@ -74,13 +83,20 @@ def model_to_order(db_pub_order: PublicationOrderModel) -> Order: ) +def model_to_order_profile(db_pub_order: PublicationOrderModel) -> OrderProfile: + return OrderProfile( + id=db_pub_order.id, + title=db_pub_order.title, + ) + + def model_to_publication(db_pub: PublicationModel) -> Publication: return Publication( id=db_pub.id, title=db_pub.title, description=db_pub.description, by_line=db_pub.by_line, - orders=list(map(model_to_order, db_pub.orders)), + orders=list(map(lambda m: model_to_order_profile(m), db_pub.orders)), ) @@ -96,7 +112,7 @@ class PublicationRepoImpl(PublicationRepo): def get_publication_by_id(self, pub_id) -> Publication | None: with Session(self._db) as session: - publication = session.get(PublicationModel, pub_id) + publication = session.get(PublicationModel, pub_id, options=[joinedload(PublicationModel.orders)]) if publication: return model_to_publication(publication) @@ -111,3 +127,22 @@ class PublicationRepoImpl(PublicationRepo): def get_all_publications(self) -> list[PublicationProfile]: with Session(self._db) as session: return list(map(model_to_publication_profile, session.query(PublicationModel).all())) + + def get_full_order(self, order_id: int) -> Order | None: + with Session(self._db) as session: + order = session.get( + PublicationOrderModel, order_id, options=[joinedload(PublicationOrderModel.sequence_entries)] + ) + + if order: + return model_to_order(order) + + def get_full_entry(self, entry_id: int) -> Entry | None: + with Session(self._db) as session: + order = session.get( + PublicationEntryModel, + entry_id, + ) + + if order: + return model_to_entry(order) diff --git a/src/services/publications/__init__.py b/src/services/publications/__init__.py index 451db29..b19e688 100644 --- a/src/services/publications/__init__.py +++ b/src/services/publications/__init__.py @@ -1,5 +1,14 @@ -from .data import Publication, PublicationProfile, Order, Sequence, Entry +from .data import Publication, PublicationProfile, Order, Sequence, Entry, OrderProfile from .service import PublicationService from .repo import PublicationRepo -__all__ = ['Publication', 'PublicationProfile', 'Order', 'Sequence', 'Entry', 'PublicationService', 'PublicationRepo'] +__all__ = [ + 'Publication', + 'PublicationProfile', + 'Order', + 'OrderProfile', + 'Sequence', + 'Entry', + 'PublicationService', + 'PublicationRepo', +] diff --git a/src/services/publications/data.py b/src/services/publications/data.py index 7d2bf59..c29a563 100644 --- a/src/services/publications/data.py +++ b/src/services/publications/data.py @@ -2,25 +2,44 @@ from datetime import timedelta from dataclasses import dataclass, field +@dataclass +class EntryProfile: + id: int + title: str + + @dataclass class Entry: id: int + title: str text: str + def to_profile(self) -> EntryProfile: + return EntryProfile(self.id, self.title) + @dataclass class Sequence: position: int - entry: Entry + entry: EntryProfile duration: timedelta | None +@dataclass +class OrderProfile: + id: int + title: str + + @dataclass class Order: id: int title: str sequence_entries: list[Sequence] + def to_profile(self) -> OrderProfile: + return OrderProfile(id=self.id, title=self.title) + @dataclass class PublicationProfile: @@ -35,7 +54,7 @@ class Publication: title: str description: str by_line: str - orders: list[Order] = field(default_factory=list) + orders: list[OrderProfile] = field(default_factory=list) # Rather than using a subclass I think this makes sense def to_profile(self) -> PublicationProfile: diff --git a/src/services/publications/repo.py b/src/services/publications/repo.py index 56502c6..0494fec 100644 --- a/src/services/publications/repo.py +++ b/src/services/publications/repo.py @@ -1,6 +1,6 @@ import abc -from .data import Publication, PublicationProfile +from .data import Publication, PublicationProfile, Order, Entry class PublicationRepo(abc.ABC): @@ -15,3 +15,11 @@ class PublicationRepo(abc.ABC): @abc.abstractmethod def get_all_publications(self) -> list[PublicationProfile]: pass + + @abc.abstractmethod + def get_full_order(self, order_id: int) -> Order | None: + pass + + @abc.abstractmethod + def get_full_entry(self, entry_id: int) -> Entry | None: + pass