import datetime import tldextract from pydantic import AnyHttpUrl, BaseModel, Field, field_validator from dmp.app_connections.enums import AppConnectionStatus from dmp.shopify.types import ShopifyStoreOrderBy # Always populate by name BaseModel.model_config["populate_by_name"] = True class ShopifyStoreConnectionCredentials(BaseModel): store_id: str = Field(alias="storeId") connect_card_uri: str = Field(alias="connectCardUri") class ShopifyStoreConnectionInput(BaseModel): vendor_id: int = Field(alias="vendorId") subaccount_id: int = Field(alias="subaccountId") global_participant_id: str | None = Field( None, alias="globalParticipantId", description="When provided, it's used as a default artist for all Products", ) shop_domain: str = Field(alias="shopDomain") redirect_uri: AnyHttpUrl = Field(alias="redirectUri") @field_validator("shop_domain") @classmethod def _setup_shop_domain(cls, v: str) -> str: ext = tldextract.extract(v) if not ext.domain or not ext.suffix: raise ValueError("Invalid shop domain") parts = [ext.subdomain, ext.domain, ext.suffix] return ".".join([part for part in parts if part]) class ReconnectShopifyStoreInput(BaseModel): redirect_uri: AnyHttpUrl = Field(alias="redirectUri") class ShopifyStore(BaseModel): id: str name: str | None shop_domain: str = Field(alias="shopDomain") custom_domain: str | None = Field(alias="customDomain") status: AppConnectionStatus vendor_id: int = Field(alias="vendorId") subaccount_id: int = Field(alias="subaccountId") global_participant_id: str | None = Field(alias="globalParticipantId") collections_count: int | None = Field(alias="collectionsCount") products_count: int | None = Field(alias="productsCount") artists_count: int | None = Field(alias="artistsCount") synced_at: datetime.datetime | None = Field(alias="syncedAt") class ShopifyCollection(BaseModel): id: int title: str products_count: int = Field(alias="productsCount") global_participant_id: str | None = Field(alias="globalParticipantId") class ShopifyStoreCollectionArtistAssociations(BaseModel): vendor_id: int = Field(alias="vendorId") subaccount_id: int = Field(alias="subaccountId") whole_store_products_count: int = Field(alias="wholeStoreProductsCount") shop_domain: str = Field(alias="shopDomain") whole_store_global_participant_id: str | None = Field( alias="wholeStoreGlobalParticipantId" ) collections: list[ShopifyCollection] class ShopifyCollectionArtistAssociationInput(BaseModel): collection_id: int = Field(alias="collectionId") global_participant_id: str = Field(alias="globalParticipantId") class ShopifyStoreCollectionArtistAssociationsInput(BaseModel): whole_store_global_participant_id: str | None = Field( None, alias="wholeStoreGlobalParticipantId" ) collections: list[ShopifyCollectionArtistAssociationInput] | None = None class ShopifyStoreArtist(BaseModel): global_participant_id: str = Field(alias="globalParticipantId") collections_count: int = Field(alias="collectionsCount") products_count: int = Field(alias="productsCount") class RefreshShopifyStoreInput(BaseModel): fivetran_connection_id: str = Field(alias="fivetranConnectorId") class SyncShopifyFivetranTablesInput(BaseModel): fivetran_connection_id: str = Field(alias="fivetranConnectorId") class GetShopifyMaxSpendInput(BaseModel): vendor_id: int = Field( alias="vendorId", description="Account vendor id", ) subaccount_id: int = Field( alias="subaccountId", description="Account subaccount id", ) global_participant_ids: list[str] = Field( alias="globalParticipantIds", description="Artist ids", ) class GetShopifyMaxSpendOutput(BaseModel): max_spend: float = Field(alias="maxSpend") class GetShopifyStoresInput(BaseModel): vendor_id: int | None = Field(None, alias="vendorId") subaccount_id: int | None = Field(None, alias="subaccountId") limit: int | None = Field(None) offset: int | None = Field(None) order_by: list[ShopifyStoreOrderBy] | None = Field(None, alias="orderBy")