src.offers.postgresql_offers_repository_adapter

PostgreSQL adapter for the offers repository.

 1"""PostgreSQL adapter for the offers repository."""
 2
 3from typing import override
 4
 5from psycopg.rows import class_row
 6
 7from src.lib.postgresql_base import PostgreSQLRepositoryBase
 8from .models import Offer
 9from .offers_repository_port import OffersRepositoryPort
10
11
12class PostgreSQLOffersRepositoryAdapter(PostgreSQLRepositoryBase, OffersRepositoryPort):
13    """Adapter that stores offers in a PostgreSQL database."""
14
15    def __init__(self, connection_string: str) -> None:
16        """Initialise with a PostgreSQL connection string.
17
18        Args:
19            connection_string: PostgreSQL connection string.
20        """
21        PostgreSQLRepositoryBase.__init__(self, connection_string)
22        self._init_db()
23
24    def _init_db(self) -> None:
25        """Initialize the database table for offers."""
26        self.execute(
27            """
28            CREATE TABLE IF NOT EXISTS offers (
29                offer_id TEXT PRIMARY KEY,
30                award_id TEXT NOT NULL
31            )
32            """
33            # TODO add indexes for offer_id and award_id
34        )
35
36    @override
37    def store(self, offer: Offer) -> None:
38        """Persist an offer in PostgreSQL.
39
40        Args:
41            offer: The offer to store.
42        """
43        self.execute(
44            """
45            INSERT INTO offers (offer_id, award_id)
46            VALUES (%s, %s)
47            ON CONFLICT (offer_id) DO UPDATE
48            SET award_id = EXCLUDED.award_id
49            """,
50            (
51                offer.offer_id,
52                offer.award_id,
53            ),
54        )
55
56    @override
57    def get(self, offer_id: str) -> Offer:
58        """Retrieve an offer by its identifier.
59
60        Args:
61            offer_id: The unique offer identifier.
62
63        Returns:
64            The matching Offer.
65
66        Raises:
67            KeyError: When no offer with the given id exists.
68        """
69        with self.conn() as conn:
70            row = (
71                conn.cursor(row_factory=class_row(Offer))
72                .execute(
73                    """
74                SELECT offer_id, award_id, null AS uri
75                FROM offers
76                WHERE offer_id = %(id)s
77                """,
78                    {"id": offer_id},
79                )
80                .fetchone()
81            )
82
83        if row is None:
84            raise KeyError(f"Offer with id {offer_id} not found")
85
86        return row
13class PostgreSQLOffersRepositoryAdapter(PostgreSQLRepositoryBase, OffersRepositoryPort):
14    """Adapter that stores offers in a PostgreSQL database."""
15
16    def __init__(self, connection_string: str) -> None:
17        """Initialise with a PostgreSQL connection string.
18
19        Args:
20            connection_string: PostgreSQL connection string.
21        """
22        PostgreSQLRepositoryBase.__init__(self, connection_string)
23        self._init_db()
24
25    def _init_db(self) -> None:
26        """Initialize the database table for offers."""
27        self.execute(
28            """
29            CREATE TABLE IF NOT EXISTS offers (
30                offer_id TEXT PRIMARY KEY,
31                award_id TEXT NOT NULL
32            )
33            """
34            # TODO add indexes for offer_id and award_id
35        )
36
37    @override
38    def store(self, offer: Offer) -> None:
39        """Persist an offer in PostgreSQL.
40
41        Args:
42            offer: The offer to store.
43        """
44        self.execute(
45            """
46            INSERT INTO offers (offer_id, award_id)
47            VALUES (%s, %s)
48            ON CONFLICT (offer_id) DO UPDATE
49            SET award_id = EXCLUDED.award_id
50            """,
51            (
52                offer.offer_id,
53                offer.award_id,
54            ),
55        )
56
57    @override
58    def get(self, offer_id: str) -> Offer:
59        """Retrieve an offer by its identifier.
60
61        Args:
62            offer_id: The unique offer identifier.
63
64        Returns:
65            The matching Offer.
66
67        Raises:
68            KeyError: When no offer with the given id exists.
69        """
70        with self.conn() as conn:
71            row = (
72                conn.cursor(row_factory=class_row(Offer))
73                .execute(
74                    """
75                SELECT offer_id, award_id, null AS uri
76                FROM offers
77                WHERE offer_id = %(id)s
78                """,
79                    {"id": offer_id},
80                )
81                .fetchone()
82            )
83
84        if row is None:
85            raise KeyError(f"Offer with id {offer_id} not found")
86
87        return row

Adapter that stores offers in a PostgreSQL database.

PostgreSQLOffersRepositoryAdapter(connection_string: str)
16    def __init__(self, connection_string: str) -> None:
17        """Initialise with a PostgreSQL connection string.
18
19        Args:
20            connection_string: PostgreSQL connection string.
21        """
22        PostgreSQLRepositoryBase.__init__(self, connection_string)
23        self._init_db()

Initialise with a PostgreSQL connection string.

Args: connection_string: PostgreSQL connection string.

@override
def store(self, offer: src.offers.models.Offer) -> None:
37    @override
38    def store(self, offer: Offer) -> None:
39        """Persist an offer in PostgreSQL.
40
41        Args:
42            offer: The offer to store.
43        """
44        self.execute(
45            """
46            INSERT INTO offers (offer_id, award_id)
47            VALUES (%s, %s)
48            ON CONFLICT (offer_id) DO UPDATE
49            SET award_id = EXCLUDED.award_id
50            """,
51            (
52                offer.offer_id,
53                offer.award_id,
54            ),
55        )

Persist an offer in PostgreSQL.

Args: offer: The offer to store.

@override
def get(self, offer_id: str) -> src.offers.models.Offer:
57    @override
58    def get(self, offer_id: str) -> Offer:
59        """Retrieve an offer by its identifier.
60
61        Args:
62            offer_id: The unique offer identifier.
63
64        Returns:
65            The matching Offer.
66
67        Raises:
68            KeyError: When no offer with the given id exists.
69        """
70        with self.conn() as conn:
71            row = (
72                conn.cursor(row_factory=class_row(Offer))
73                .execute(
74                    """
75                SELECT offer_id, award_id, null AS uri
76                FROM offers
77                WHERE offer_id = %(id)s
78                """,
79                    {"id": offer_id},
80                )
81                .fetchone()
82            )
83
84        if row is None:
85            raise KeyError(f"Offer with id {offer_id} not found")
86
87        return row

Retrieve an offer by its identifier.

Args: offer_id: The unique offer identifier.

Returns: The matching Offer.

Raises: KeyError: When no offer with the given id exists.