from apollo_utils.service.schemas.fields.datetime import DateStringField from apollo_utils.service.schemas.fields.string import CustomStringField from apollo_utils.service.schemas.mixins.dsp import get_dsp_mixin from apollo_utils.service.schemas.mixins.isrc import IsrcListRequiredMixin, IsrcRequiredMixin from apollo_utils.service.schemas.mixins.market import MarketDefaultWWGlobalWWMixin from apollo_utils.service.schemas.mixins.search import SearchNoneLowerMixin from marshmallow import fields from server.constants import DSP_SPOTIFY_APPLE from server.schemas.base.chart import ChartBreakdownDefaultDailyMixin, ChartBreakdownListDefaultAllMixin, \ ChartTypeDefaultRegionalMixin, ChartTypeListDefaultAllMixin from server.schemas.base.pagination import PaginationResultMixin, get_pagination_mixin from server.schemas.base.schemas import RequestSchema, Schema class ChartStats: class Request( RequestSchema, IsrcListRequiredMixin, MarketDefaultWWGlobalWWMixin, ChartBreakdownDefaultDailyMixin, ChartTypeDefaultRegionalMixin, get_dsp_mixin(DSP_SPOTIFY_APPLE, required=False, data_key="vendor", missing=DSP_SPOTIFY_APPLE.SPOTIFY), ): pass class Response(Schema): isrc = fields.String(attribute="public_meta.isrc") entry_date = DateStringField(attribute="lifetime_metrics.earliest_position_date") peak_position = fields.Integer(attribute="lifetime_metrics.min_position") current_position = fields.Function( lambda item, context: ( item["lifetime_metrics"]["latest_position"] if context["date"] == item["lifetime_metrics"]["latest_position_date"] else None ) ) class ChartSummary: class Request( RequestSchema, IsrcRequiredMixin, SearchNoneLowerMixin, get_dsp_mixin(DSP_SPOTIFY_APPLE, required=True, data_key="vendor"), get_pagination_mixin(page_offset=None, page_limit=None), ): """Schema for validating chart summary query params.""" sort_by = fields.String(missing=None) class Response(Schema, PaginationResultMixin): """Response schema for chart summary.""" class ChartTrackSummaryOutputItem(Schema): added_date = DateStringField() change = fields.Integer() vendor = fields.String() country_name = fields.String() country_code = fields.String() date = DateStringField() position = fields.Integer() streams = fields.Integer() is_new = fields.Boolean(default=False, missing=False) is_re_enter = fields.Boolean(default=False, missing=False) rank = fields.Integer() peak_position = fields.Integer() items = fields.List(fields.Nested(ChartTrackSummaryOutputItem)) top_market = fields.String() class ChartTrackSummary: class Request( RequestSchema, ChartBreakdownListDefaultAllMixin, ChartTypeListDefaultAllMixin, get_dsp_mixin(DSP_SPOTIFY_APPLE, required=True), ): """Schema for validating charts tracks summary query params.""" include_empty = fields.Boolean(missing=True) class Response(Schema): """Response schema for charts tracks summary.""" class ChartItem(Schema): listType = CustomStringField(attribute="chart_meta.type", title=True) timeWindow = CustomStringField(attribute="chart_meta.breakdown", title=True) entryDate = DateStringField(attribute="lifetime_metrics.earliest_position_date", default=None) entryPosition = fields.Integer(attribute="lifetime_metrics.earliest_position", default=None) peakDate = DateStringField(attribute="lifetime_metrics.min_position_date", default=None) peakPosition = fields.Integer(attribute="lifetime_metrics.min_position", default=None) latestDate = DateStringField(attribute="lifetime_metrics.latest_position_date", default=None) latestPosition = fields.Integer(attribute="lifetime_metrics.latest_position", default=None) currentPosition = fields.Integer(attribute="metrics.position", default=None) previousPosition = fields.Function( lambda item: ( item["metrics"]["previous_position"] if "metrics" in item and not item["metrics"].get("is_entry", True) else None ) ) latestUpdateDate = DateStringField(attribute="metrics.date", default=None) items = fields.Dict(keys=fields.String(required=True), values=fields.Nested(ChartItem))