from apollo_utils.service.schemas.base import RequestSchema from collections import Counter from marshmallow import Schema, ValidationError, fields, validate, validates_schema from server.constants.favorites import FAVORITES_TAG_PER_ACCOUNT_MAX_COUNT from server.schemas.accounts.favorites import FavoriteEntityTypeListNoneMixin, FavoriteEntityTypeRequiredMixin from server.schemas.mixins import CreatedUpdatedAtMixin class FavoritesTagBaseResponse(Schema): id = fields.Int() subtype_1 = fields.String(data_key="entity_type") name = fields.Function(lambda o: o.data.get("name")) order = fields.Function(lambda o: o.data.get("order")) class FavoritesTagResponse(CreatedUpdatedAtMixin, FavoritesTagBaseResponse): id = fields.Int() subtype_1 = fields.String(data_key="entity_type") name = fields.Function(lambda o: o.data.get("name")) order = fields.Function(lambda o: o.data.get("order")) class FavoritesTagsItemsResponse(Schema): items = fields.List(fields.Nested(FavoritesTagResponse)) class FavoritesTagsCreate: class Request(FavoriteEntityTypeRequiredMixin, RequestSchema): name = fields.Str(validate=validate.Length(min=1), required=True) order = fields.Integer( required=True, validate=validate.Range(min=0, max=(FAVORITES_TAG_PER_ACCOUNT_MAX_COUNT - 1)) ) class FavoritesTagsUpdate: class Request(FavoriteEntityTypeRequiredMixin, RequestSchema): class TagItem(RequestSchema): id = fields.Int(required=True) name = fields.Str(validate=validate.Length(min=1), required=False) order = fields.Int( required=False, validate=validate.Range(min=0, max=(FAVORITES_TAG_PER_ACCOUNT_MAX_COUNT - 1)) ) @validates_schema def validate_tag(self, data, **kwargs): if not data.get("name") and data.get("order") is None: raise ValidationError(f"At least one of 'name', 'order' should be passed for {data['id']}.") data = fields.List(fields.Nested(TagItem, required=True), validate=validate.Length(min=1)) @validates_schema def validate_tag_names(self, data, **kwargs): names = [t.get("name") for t in data["data"] if t.get("name") is not None] if len(names) != len(set(names)): raise ValidationError( f"Duplicated names are not allowed: {[k for k, v in Counter(names).items() if v > 1]}" ) class FavoritesTagsDeleteRequest(RequestSchema): id = fields.Int(required=True) class FavoritesTagsGet: class Request(FavoriteEntityTypeListNoneMixin, RequestSchema): pass class FavoritesTagsSet: class Request(RequestSchema): tag_id = fields.Int(allow_none=True, required=True) favorites_id = fields.List(fields.Int(required=True), validate=validate.Length(min=1), required=True)