from typing import Union from sqlalchemy import select, update, insert, delete from sqlalchemy.orm import joinedload from models import Service, ServiceCategory, ServicePriceRange, ServicesKit, services_kit_services from services.base import BaseService from schemas.service import * class ServiceService(BaseService): async def get_all(self) -> ServiceGetAllResponse: query = await (self.session .scalars(select(Service) .options(joinedload(Service.category)) .order_by(Service.category_id, Service.id))) services = [] for service in query.all(): services.append(ServiceSchema.model_validate(service)) return ServiceGetAllResponse(services=services) async def create(self, request: ServiceCreateRequest) -> ServiceCreateResponse: try: raw_service = request.service service_dict = raw_service.model_dump() service_dict['category_id'] = raw_service.category.id del service_dict['id'] del service_dict['category'] del service_dict['price_ranges'] service = Service(**service_dict) self.session.add(service) await self.session.flush() price_ranges = request.service.price_ranges for price_range in price_ranges: price_range_dict = price_range.model_dump() price_range_dict['service_id'] = service.id del price_range_dict['id'] price_range_obj = ServicePriceRange(**price_range_dict) self.session.add(price_range_obj) await self.session.commit() return ServiceCreateResponse(ok=True, message="Услуга успешно создана") except Exception as e: return ServiceCreateResponse(ok=False, message=f"Неудалось создать услугу, ошибка: {e}") async def update(self, request: ServiceUpdateRequest) -> ServiceUpdateResponse: try: raw_service = request.data service = await (self.session.get(Service, raw_service.id)) if not service: return ServiceUpdateResponse(ok=False, message="Услуга не найдена") service_dict = raw_service.dict() service_dict['category_id'] = raw_service.category.id del service_dict['category'] del service_dict['price_ranges'] await self.session.execute( update(Service) .where(Service.id == raw_service.id) .values(**service_dict) ) # checking if old price ranges are still in the request request_price_range_ids = [price_range.id for price_range in raw_service.price_ranges if price_range.id] price_ranges_to_delete = [] for price_range in service.price_ranges: if price_range.id not in request_price_range_ids: price_ranges_to_delete.append(price_range) for price_range in price_ranges_to_delete: await self.session.delete(price_range) await self.session.flush() for price_range in raw_service.price_ranges: price_range_dict = price_range.dict() price_range_dict['service_id'] = raw_service.id if price_range.id: await self.session.execute( update(ServicePriceRange) .where(ServicePriceRange.id == price_range.id) .values(**price_range_dict) ) else: del price_range_dict['id'] price_range_obj = ServicePriceRange(**price_range_dict) self.session.add(price_range_obj) await self.session.commit() return ServiceUpdateResponse(ok=True, message="Услуга успешно обновлена") except Exception as e: return ServiceUpdateResponse(ok=False, message=f"Неудалось обновить услугу, ошибка: {e}") async def delete(self, request: ServiceDeleteRequest) -> ServiceDeleteResponse: try: service = await (self.session .scalar(select(Service) .filter(Service.id == request.service_id))) if not service: return ServiceDeleteResponse(ok=False, message="Услуга не найдена") await self.session.delete(service) await self.session.commit() return ServiceDeleteResponse(ok=True, message="Услуга успешно удалена") except Exception as e: return ServiceDeleteResponse(ok=False, message=f"Неудалось удалить услугу, ошибка: {e}") async def create_category(self, request: ServiceCreateCategoryRequest) -> ServiceCreateCategoryResponse: try: raw_category = request.category category_dict = raw_category.model_dump() del category_dict['id'] category = ServiceCategory(**category_dict) self.session.add(category) await self.session.commit() return ServiceCreateCategoryResponse(ok=True, message="Категория успешно создана") except Exception as e: return ServiceCreateCategoryResponse(ok=False, message=f"Неудалось создать категорию, ошибка: {e}") async def get_all_categories(self) -> ServiceGetAllCategoriesResponse: query = await (self.session .scalars(select(ServiceCategory) .order_by(ServiceCategory.id))) categories = [] for category in query.all(): categories.append(ServiceCategorySchema.model_validate(category)) return ServiceGetAllCategoriesResponse(categories=categories) async def get_kit_by_name(self, name: str) -> Optional[ServicesKit]: return await self.session.scalar(select(ServicesKit).where(ServicesKit.name == name)) async def get_kit_by_id(self, kit_id: int) -> Optional[ServicesKit]: return await self.session.scalar(select(ServicesKit).where(ServicesKit.id == kit_id)) async def get_all_kits(self) -> GetAllServicesKitsResponse: stmt = ( select( ServicesKit ) .order_by( ServicesKit.id.desc() ) ) kits = (await self.session.scalars(stmt)).all() kits_schemas = GetServiceKitSchema.from_orm_list(kits) return GetAllServicesKitsResponse(services_kits=kits_schemas) async def create_kit(self, request: CreateServicesKitRequest) -> CreateServicesKitResponse: try: if await self.get_kit_by_name(request.data.name): return CreateServicesKitResponse(ok=False, message='Набор услуг с таким названием уже существует') base_fields = request.data.model_dump_parent() kit = ServicesKit(**base_fields) self.session.add(kit) await self.session.flush() # Appending services insert_data = [] for service_id in request.data.services_ids: insert_data.append({ 'service_id': service_id, 'services_kit_id': kit.id }) if insert_data: await self.session.execute( insert(services_kit_services), insert_data ) await self.session.flush() await self.session.commit() return CreateServicesKitResponse(ok=True, message='Набор услуг успешно создан') except Exception as e: return CreateServicesKitResponse(ok=False, message=str(e)) async def update_kit(self, request: UpdateServicesKitRequest) -> UpdateServicesKitResponse: try: kit = await self.get_kit_by_id(request.data.id) if not kit: return UpdateServicesKitResponse(ok=False, message='Указанный набор услуг не существует') base_fields = request.data.model_dump_parent() stmt = update(ServicesKit).values(**base_fields).where(ServicesKit.id == request.data.id) await self.session.execute(stmt) await self.session.flush() # Deleting previous services stmt = ( delete( services_kit_services ).where( services_kit_services.c.services_kit_id == kit.id ) ) await self.session.execute(stmt) await self.session.flush() insert_data = [] for service_id in request.data.services_ids: insert_data.append({ 'service_id': service_id, 'services_kit_id': kit.id }) if insert_data: await self.session.execute( insert(services_kit_services), insert_data ) await self.session.flush() await self.session.commit() return UpdateServicesKitResponse(ok=True, message='Набор услуг успешно обновлен') except Exception as e: return UpdateServicesKitResponse(ok=False, message=str(e))