from typing import Optional from fastapi import HTTPException from sqlalchemy.ext.asyncio import AsyncSession from starlette import status from datetime import date from app.application.appointment_types_repository import AppointmentTypesRepository from app.application.appointments_repository import AppointmentsRepository from app.application.patients_repository import PatientsRepository from app.application.users_repository import UsersRepository from app.domain.entities.appointment import AppointmentEntity from app.domain.models import Appointment from app.infrastructure.appointment_types_service import AppointmentTypesService from app.infrastructure.patients_service import PatientsService from app.infrastructure.users_service import UsersService class AppointmentsService: def __init__(self, db: AsyncSession): self.appointments_repository = AppointmentsRepository(db) self.appointment_types_repository = AppointmentTypesRepository(db) self.users_repository = UsersRepository(db) self.patients_repository = PatientsRepository(db) async def get_all_appointments(self, start_date: date | None = None, end_date: date | None = None) -> list[ AppointmentEntity]: appointments = await self.appointments_repository.get_all(start_date=start_date, end_date=end_date) return [self.model_to_entity(appointment) for appointment in appointments] async def get_appointments_by_doctor_id(self, doctor_id: int, start_date: date | None = None, end_date: date | None = None) -> Optional[list[AppointmentEntity]]: doctor = await self.users_repository.get_by_id(doctor_id) if not doctor: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Доктор с таким ID не найден', ) appointments = await self.appointments_repository.get_by_doctor_id(doctor_id, start_date=start_date, end_date=end_date) return [self.model_to_entity(appointment) for appointment in appointments] async def get_upcoming_appointments_by_doctor_id(self, doctor_id: int) -> Optional[list[AppointmentEntity]]: doctor = await self.users_repository.get_by_id(doctor_id) if not doctor: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Доктор с таким ID не найден', ) appointments = await self.appointments_repository.get_upcoming_by_doctor_id(doctor_id) return [self.model_to_entity(appointment) for appointment in appointments] async def get_appointments_by_patient_id(self, patient_id: int, start_date: date | None = None, end_date: date | None = None) -> Optional[list[AppointmentEntity]]: patient = await self.patients_repository.get_by_id(patient_id) if not patient: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пациент с таким ID не найден', ) appointments = await self.appointments_repository.get_by_patient_id(patient_id, start_date=start_date, end_date=end_date) return [self.model_to_entity(appointment) for appointment in appointments] async def create_appointment(self, appointment: AppointmentEntity, doctor_id: int) -> Optional[AppointmentEntity]: patient = await self.patients_repository.get_by_id(appointment.patient_id) if not patient: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пациент с таким ID не найден', ) doctor = await self.users_repository.get_by_id(doctor_id) if not doctor: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Доктор/пользователь с таким ID не найден', ) appointment.doctor_id = doctor_id appointment_type = await self.appointment_types_repository.get_by_id(appointment.type_id) if not appointment_type: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Тип приема с таким ID не найден', ) appointment_model = self.entity_to_model(appointment) await self.appointments_repository.create(appointment_model) return self.model_to_entity(appointment_model) async def update_appointment(self, appointment_id: int, appointment: AppointmentEntity) -> Optional[ AppointmentEntity ]: appointment_model = await self.appointments_repository.get_by_id(appointment_id) if not appointment_model: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Прием не найден") patient = await self.patients_repository.get_by_id(appointment.patient_id) if not patient: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Пациент с таким ID не найден', ) doctor = await self.users_repository.get_by_id(appointment.doctor_id) if not doctor: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Доктор/пользователь с таким ID не найден', ) appointment_type = await self.appointment_types_repository.get_by_id(appointment.type_id) if not appointment_type: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail='Тип приема с таким ID не найден', ) appointment_model.results = appointment.results appointment_model.days_until_the_next_appointment = appointment.days_until_the_next_appointment appointment_model.appointment_datetime = appointment.appointment_datetime appointment_model.patient_id = appointment.patient_id appointment_model.doctor_id = appointment.doctor_id appointment_model.type_id = appointment.type_id await self.appointments_repository.update(appointment_model) return self.model_to_entity(appointment_model) @staticmethod def entity_to_model(appointment: AppointmentEntity) -> Appointment: appointment_model = Appointment( results=appointment.results, days_until_the_next_appointment=appointment.days_until_the_next_appointment, appointment_datetime=appointment.appointment_datetime, patient_id=appointment.patient_id, doctor_id=appointment.doctor_id, type_id=appointment.type_id, ) if appointment.id is not None: appointment_model.id = appointment.id return appointment_model @staticmethod def model_to_entity(appointment: Appointment) -> AppointmentEntity: appointment_entity = AppointmentEntity( id=appointment.id, results=appointment.results, days_until_the_next_appointment=appointment.days_until_the_next_appointment, appointment_datetime=appointment.appointment_datetime, patient_id=appointment.patient_id, doctor_id=appointment.doctor_id, type_id=appointment.type_id, ) if appointment.patient is not None: appointment_entity.patient = PatientsService.model_to_entity(appointment.patient) if appointment.doctor is not None: appointment_entity.doctor = UsersService.model_to_entity(appointment.doctor) if appointment.type is not None: appointment_entity.type = AppointmentTypesService.model_to_entity(appointment.type) return appointment_entity