import pickle from typing import Optional from sqlalchemy import select, and_ from card_attributes.exceptions import CardAttributeException from card_attributes.handlers.base_handler import BaseHandler from models import CardAttribute, Attribute, Card from .card_attributes_query_handler import CardAttributesQueryHandler class CardAttributesCommandHandler(BaseHandler): async def _create_card_attribute(self, card_id: int, attribute_id: int, value): card_attribute = CardAttribute( card_id=card_id, attribute_id=attribute_id, ) card_attribute.set_value(value) self.session.add(card_attribute) await self.session.flush() async def _set_attribute_after_creation(self, card_id: int, project_attr: Attribute, attributes: Optional[dict]): if attributes and project_attr.name in attributes: passed_value = attributes[project_attr.name] return await self._create_card_attribute(card_id, project_attr.id, passed_value) if project_attr.default_value: default_value = pickle.loads(project_attr.default_value) return await self._create_card_attribute(card_id, project_attr.id, default_value) if project_attr.is_nullable: return await self._create_card_attribute(card_id, project_attr.id, None) raise CardAttributeException("Required value was not provided") async def set_attributes_after_creation(self, card: Card, attributes: Optional[dict] = None): query_handler = CardAttributesQueryHandler(self.session) project_attrs = await query_handler.get_attributes_for_project(card.board_id) try: for project_attr in project_attrs: await self._set_attribute_after_creation(card.id, project_attr, attributes) except CardAttributeException: raise async def _set_card_attribute(self, card_id: int, attribute_name: str, value): query_handler = CardAttributesQueryHandler(self.session) attribute = await query_handler.get_attr_by_name(attribute_name) if not attribute: raise CardAttributeException(f"Attribute [{attribute_name}] not found") stmt = ( select(CardAttribute) .where( and_( CardAttribute.card_id == card_id, CardAttribute.attribute_id == attribute.id, ) ) ) card_attribute: Optional[CardAttribute] = (await self.session.scalars(stmt)).one_or_none() if not card_attribute: await self._create_card_attribute(card_id, attribute.id, value) else: card_attribute.set_value(value) async def set_attr_for_each_in_group(self, group_id: int, attribute_name: str, value): query_handler = CardAttributesQueryHandler(self.session) card_ids: list[int] = await query_handler.get_card_ids_by_group_id(group_id) for card_id in card_ids: await self._set_card_attribute(card_id, attribute_name, value) async def set_attributes(self, card: Card, attributes: Optional[dict] = None): query_handler = CardAttributesQueryHandler(self.session) project_attrs: list[Attribute] = await query_handler.get_attributes_for_project(card.board_id) try: for attr_name, attr_value in attributes.items(): attr = next(attr for attr in project_attrs if attr.name == attr_name) if attr: if attr.is_applicable_to_group and card.group: await self.set_attr_for_each_in_group(card.group.id, attr_name, attr_value) else: await self._set_card_attribute(card.id, attr_name, attr_value) except CardAttributeException: raise