BuyingAgent/backend/app/sources/base.py

86 lines
2.1 KiB
Python
Raw Normal View History

from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal
from typing import Any, Protocol
from uuid import UUID
@dataclass(frozen=True)
class SourceProduct:
source_key: str
external_id: str
id: UUID
category: str
brand: str
name: str
model: str | None
variants: tuple["SourceVariant", ...]
@dataclass(frozen=True)
class SourceVariant:
id: UUID
name: str
manufacturer_sku: str | None
identifiers: dict[str, Any]
attributes: tuple["SourceAttribute", ...]
@dataclass(frozen=True)
class SourceAttribute:
id: UUID
attribute: str
raw_value: Any
normalized_value: Any
unit: str | None
normalization_status: str
normalizer_version: str
confidence: Decimal
source_reference: str
observed_at: datetime
normalization_error: str | None = None
@dataclass(frozen=True)
class SourceOffer:
id: UUID
variant_id: UUID
external_id: str
seller: str
url: str | None
market: str
currency: str
condition: str
@dataclass(frozen=True)
class SourcePriceObservation:
id: UUID | None
external_offer_id: str
external_observation_id: str
observed_at: datetime
item_price: Decimal
shipping_price: Decimal | None
currency: str
availability: str
raw_payload: Any
confidence: Decimal
class ProductSource(Protocol):
source_key: str
def get_product(self, external_id: str) -> SourceProduct: ...
def get_offers(self, external_product_id: str) -> list[SourceOffer]: ...
def get_price_history(self, external_offer_id: str) -> list[SourcePriceObservation]: ...
class DiscoverySourceAdapter(Protocol):
source_key: str
def discover_taxonomy(self, category_ref: str) -> dict[str, Any]: ...
def build_query(self, criteria: list[dict[str, Any]], mappings: list[dict[str, Any]]) -> dict[str, Any]: ...
def fetch_results(self, query: dict[str, Any], pagination: dict[str, Any]) -> dict[str, Any]: ...
def parse_results(self, response: dict[str, Any]) -> list[dict[str, Any]]: ...
def normalize_result(self, result: dict[str, Any]) -> dict[str, Any]: ...