import datetime import decimal from dataclasses import dataclass from typing import Literal from pydantic import BaseModel, ConfigDict, Json from dmp.api.schemas import LabelId from dmp.fandata.enums import ( AcquisitionChannel, AgeRange, FanSegment, Gender, HeavyRotation, ) class FansShare(BaseModel): fans_share: decimal.Decimal class FansShareByArtist(FansShare): global_participant_id: str class ArtistAccount(BaseModel): vendor_id: int subaccount_id: int global_participant_id: str fans_count: int class FansSegmentValue(BaseModel): label: FanSegment value: int class FansShareByAgeRange(FansShare): age_range: AgeRange class FansShareByCountry(FansShare): country_code: str class FansShareByGender(FansShare): gender: Gender class FansShareByHeavyRotation(FansShare): heavy_rotation: HeavyRotation class SegmentCategoryValue(BaseModel): label: str value: float class SegmentCategorySeries(BaseModel): id: FanSegment count: int items: list[SegmentCategoryValue] class FansSummaryValue(BaseModel): id: str value: int change: int | None = None class FansCampaignValue(BaseModel): id: str name: str url: str | None = None channel: AcquisitionChannel value: int change: int | None = None date: datetime.date class FansTimeseriesValue(BaseModel): date: datetime.date value: int class FansTimeseries(BaseModel): id: str name: str | None = None channel: AcquisitionChannel | None = None items: list[FansTimeseriesValue] @property def last_value(self) -> int: return self.items[-1].value if len(self.items) > 0 else 0 class Label(BaseModel): vendor_id: int subaccount_id: int class Artist(BaseModel): name: str global_participant_id: str labels: Json[list[Label]] | list[Label] class ArtistCriteria(BaseModel): vendor_ids: list[int] | None = None subaccount_ids: list[int] | None = None search: str | None = None class ArtistFansCount(BaseModel): fans_count: int = 0 email_consent_fans_count: int = 0 ad_consent_fans_count: int = 0 sms_consent_fans_count: int = 0 model_config = ConfigDict(from_attributes=True) class FansSegmentExplained(BaseModel): segment: FanSegment explanation: str class SegmentCategory(BaseModel): segment_name: str category: str fans_share: float class SegmentCrmCampaign(BaseModel): segment_name: str campaign: str fans_share: float @dataclass(kw_only=True) class ArtistAccess: vendor_id: int | None subaccount_id: int | None is_global: bool type CampaignType = Literal["TEXT", "EMAIL"] class Participant(BaseModel): global_participant_id: str | None virtual_participant_id: str | None crm_mailing_list_id: str | None spotify_id: str | None name: str labels: Json[list[LabelId]] | list[LabelId]