from models import Module, Attribute from repositories import ModuleRepository, AttributeRepository from schemas.module import * from services.mixins import * from utils.exceptions import ForbiddenException class ModuleService( ServiceGetAllMixin[Module, ModuleSchema], ServiceCreateMixin[Module, CreateModuleRequest, ModuleSchema], ServiceUpdateMixin[Module, UpdateModuleCommonInfoRequest], ServiceDeleteMixin[Module], ): schema_class = ModuleSchema entity_updated_msg = "Модуль успешно обновлен" entity_deleted_msg = "Модуль успешно удален" def __init__(self, session: AsyncSession): self.repository = ModuleRepository(session) async def get_with_attributes(self) -> GetAllWithAttributesResponse: result = await self.repository.get_with_attributes_as_tuples() modules = self._build_modules_with_attributes(result) return GetAllWithAttributesResponse(items=list(modules.values())) async def get_by_id_with_attributes(self, pk: int) -> GetByIdWithAttributesResponse: result = await self.repository.get_with_attributes_as_tuple_by_id(pk) modules = self._build_modules_with_attributes(result) module = next(iter(modules.values()), None) if module is None: raise ObjectNotFoundException(f"Модуль с ID {pk} не найден") return GetByIdWithAttributesResponse(entity=module) @staticmethod def _build_modules_with_attributes( result: list[tuple], ) -> dict[int, ModuleWithAttributesSchema]: module_attrs_dict: dict[int, ModuleWithAttributesSchema] = {} for module, attribute, attribute_label in result: new_attr = None if attribute: original_label = attribute.label label = attribute_label.label if attribute_label else original_label attr_values = { **attribute.__dict__, "label": label, "original_label": original_label, } new_attr = ModuleAttributeSchema(**attr_values) module_schema = module_attrs_dict.get(module.id) if not module_schema: module_data = module.__dict__ del module_data["attributes"] module_schema = ModuleWithAttributesSchema( **module_data, attributes=[new_attr] if new_attr else [], ) module_attrs_dict[module.id] = module_schema elif new_attr: module_schema.attributes.append(new_attr) return module_attrs_dict async def is_soft_delete(self, module: Module) -> bool: if module.is_built_in: raise ForbiddenException("Нельзя менять встроенный модуль") return True async def add_attribute(self, request: AddAttributeRequest) -> AddAttributeResponse: module, attribute = await self._get_module_and_attr_from_request(request) await self.repository.add_attribute_to_module(module, attribute) return AddAttributeResponse(message="Аттрибут успешно добавлен к модулю") async def delete_attribute( self, request: DeleteAttributeRequest ) -> DeleteAttributeResponse: module, attribute = await self._get_module_and_attr_from_request(request) await self.repository.delete_attribute_from_module(module, attribute) return DeleteAttributeResponse(message="Аттрибут успешно удален из модуля") async def _get_module_and_attr_from_request( self, request: AddAttributeRequest | DeleteAttributeRequest ) -> tuple[Module, Attribute]: module = await self.repository.get_by_id(request.module_id) if module.is_built_in: raise ForbiddenException("Нельзя менять встроенный модуль") attr_repo = AttributeRepository(self.repository.session) attribute = await attr_repo.get_by_id(request.attribute_id) return module, attribute