async def create_for_affiliate( cls, affiliate_dni: str, consultation_data: ConsultationDTO) -> Consultation: """ Creates a new consultation for the given affiliate and returns it's id. """ # Get petitioner object affiliate = await AffiliateDAO.find(affiliate_dni) if not affiliate: raise BusinessError( f'There is no affiliate with DNI {affiliate_dni}.', 404) # Get patient object patient = await AffiliateDAO.find(consultation_data.patient_dni) if not patient: raise BusinessError( f'There is no affiliate with DNI {patient.dni}.', 404) # If there is an ongoing call, return it's id consultation = await ConsultationDAO.affiliate_required_consultation( affiliate_dni) if consultation: return consultation # Create new consultation and store consultation_id = str(uuid.uuid4()) consultation = Consultation(id=consultation_id, affiliate_dni=affiliate_dni, patient=patient, symptoms=ast.literal_eval( consultation_data.symptoms), reason=consultation_data.reason, patient_dni=consultation_data.patient_dni) await ConsultationDAO.store(consultation) # Return id for response return consultation
async def start_call(cls, doctor_id: str) -> str: """ Returns a call ID if there is any for the given doctor. """ doctor = await DoctorDAO.find_by_id(doctor_id) if not doctor: raise BusinessError(f'There is no doctor with ID {doctor_id}.', 404) # There could be a consultation in progress (in which case we would return that same call_id) consultation = await ConsultationDAO.doctor_consultation_in_progress( doctor_id) if consultation: return consultation.call_id # If it is a new consultation, then we need to create the call consultation = await ConsultationDAO.next_consultation_waiting_call( doctor_id) # There may be no affiliate to talk with at the moment if not consultation: raise BusinessError( f'There is no consultation waiting for the given doctor.', 404) # Create a call id for the consultation call_id = str(uuid.uuid4()) # Notify start of call to affiliate via socket socket_id = consultation.socket_id await SocketManager.notify_call_start(call_id, socket_id) # Notify start of call to affiliate via push notification affiliate = await AffiliateDAO.find(consultation.affiliate_dni) # TODO -> This if shouldn't be necessary, but it'll be here temporarily to avoid bugs if affiliate.device_id: NotificationService.notify_call_start(affiliate.device_id, doctor.last_name, affiliate.first_name) # Update consultation with new call id and IN_PROGRESS status consultation.status = ConsultationStatus.IN_PROGRESS consultation.call_id = call_id await ConsultationDAO.store(consultation) # Return the id of the call return call_id
async def add(cls, doctor: Doctor): # Check if doctor with given dni exists if await DoctorDAO.find_by_dni(doctor.dni): raise BusinessError( f'Doctor with DNI {doctor.dni} already exists.', 409) # Check if doctor with given licence exists if await DoctorDAO.find_by_licence(doctor): raise BusinessError( f'Doctor with licence {doctor.licence} already exists.', 409) # Assign id and store new doctor doctor.id = str(uuid4()) await DoctorDAO.store(doctor)
def map_modification(request_body: dict, resource_id: str) -> ExampleResource: # Check if the request contains all needed fields if not resource_id: raise BusinessError('Resource ID is compulsory for this service.', 400) if not request_body: raise BusinessError( 'Tried to update doctor with an empty patch body.', 400) # Create model object only with the elements that were received resource = ExampleResource(id=resource_id) if 'name' in request_body: resource.name = request_body['name'] if 'value' in request_body: resource.value = request_body['value'] return resource
def map_modification(request_body: dict, doctor_id: str) -> Doctor: # Check if the request contains all needed fields if not doctor_id: raise BusinessError('Doctor ID is compulsory for this service.', 400) if not request_body: raise BusinessError('Tried to update doctor with an empty patch body.', 400) # Create model object only with the elements that were received doctor = Doctor(id=doctor_id) if 'dni' in request_body: doctor.dni = request_body['dni'] if 'licence' in request_body: doctor.licence = request_body['licence'] if 'first_name' in request_body: doctor.first_name = request_body['first_name'] if 'last_name' in request_body: doctor.last_name = request_body['last_name'] if 'email' in request_body: doctor.email = request_body['email'] if 'centers' in request_body: doctor.centers = request_body['centers'] if 'specialties' in request_body: doctor.specialties = request_body['specialties'] if 'availability_times' in request_body: doctor.availability_times = request_body['availability_times'] return doctor
async def add(cls, resource: ExampleResource): # Check if resource with given id exists if await ExampleDAO.find(resource.id): raise BusinessError( f'Resource with ID {resource.id} already exists.', 409) # Store new resource await ExampleDAO.store(resource)
async def retrieve(cls, resource_id: str) -> ExampleResource: """ Returns the doctor object associated to the given ID, if existent. """ resource = await ExampleDAO.find(resource_id) if not resource: raise BusinessError(f'There is no resource with id {resource_id}.', 404) return resource
async def update(cls, resource: ExampleResource): # Check if the resource to be modified exists if not await ExampleDAO.find(resource.id): raise BusinessError(f'There is no resource with id {resource.id}.', 404) # Modify resource await ExampleDAO.store(resource)
async def retrieve(cls, doctor_id: str) -> Doctor: """ Returns the doctor object associated to the given ID, if existent. """ doctor = await DoctorDAO.find_by_id(doctor_id) if not doctor: raise BusinessError(f'There is no doctor with id {doctor_id}.', 404) return doctor
async def do_request(cls): """ Example method to show how to call an external service. """ try: client_response = await ExampleClientConnector.get_info_from_client() except ExampleClientError: raise BusinessError(f'Failed to retrieve the information from the client.') # Here you could do something with the response received from the client return client_response
def map(request_body: dict) -> ConsultationDTO: for field in ['patient_dni', 'symptoms']: if field not in request_body: raise BusinessError(f'Invalid request. Missing field "{field}".', 400) return ConsultationDTO( symptoms=request_body['symptoms'], patient_dni=request_body['patient_dni'], reason=request_body.get('reason') )
async def update_information(cls, doctor: Doctor): # Check if doctor to be modified exists db_doctor = await DoctorDAO.find_by_id(doctor.id) if not db_doctor: raise BusinessError(f'There is no doctor with id {doctor.id}.', 404) # Check if doctor with given dni exists if doctor.dni and db_doctor.dni != doctor.dni and await DoctorDAO.find_by_dni( doctor.dni): raise BusinessError( f'Doctor with DNI {doctor.dni} already exists.', 409) # Check if doctor with given licence exists if doctor.licence and db_doctor.licence != doctor.licence and await DoctorDAO.find_by_licence( doctor): raise BusinessError( f'Doctor with licence {doctor.licence} already exists.', 409) # Assign id and store new doctor await DoctorDAO.store(doctor)
async def next_consultation(cls, doctor_id) -> Tuple[Consultation, Affiliate]: """ Returns a consultation that is waiting for a doctor. """ doctor = await DoctorDAO.find_by_id(doctor_id) if not doctor: raise BusinessError(f'There are no doctors with ID {doctor_id}.', 404) consultation = await QueueManager.pop(doctor.specialties) if not consultation: raise BusinessError( 'There are no consultations waiting for the given doctor.', 404) # Update information consultation.doctor_id = doctor_id consultation.status = ConsultationStatus.WAITING_CALL await ConsultationDAO.store(consultation) # Get associated affiliate affiliate = await AffiliateDAO.find(consultation.affiliate_dni) # Return id return consultation, affiliate
def map(request_body: dict) -> AuthData: # Check correctness of request for field in ['user_id', 'password']: if field not in request_body: raise BusinessError( f'Failed to map incoming request. Missing field with ID {field}', 400) # Do mapping return AuthData(user_id=request_body['user_id'], password=request_body['password'], device_id=request_body.get('token'))
async def delete(self, resource_id): try: if not resource_id: raise BusinessError('No resource ID specified for deletion.') await ExampleCRUDService.remove(resource_id) # This service only returns an HTTP 200 self.make_response(status_code=200) except BusinessError as be: self.make_error_response(be.status, be.message) except RuntimeError: self.make_error_response(500, self.INTERNAL_ERROR_MESSAGE)
async def get_doctor_consultations( cls, doctor_id: str) -> Tuple[List[Consultation], List[Affiliate]]: """ Returns all finished consultation of the given doctor. """ if not await DoctorDAO.find_by_id(doctor_id): raise BusinessError(f'There is no doctor with ID {doctor_id}.', 404) consultations = await ConsultationDAO.all_doctor_consultations( doctor_id) affiliates = [ await AffiliateDAO.find(consultation.patient_dni) for consultation in consultations ] return consultations, affiliates
async def all_consultations( cls, affiliate_dni: str) -> Tuple[List[Consultation], List[Doctor]]: """ Returns all the past consultations of the given affiliate. """ if not await AffiliateDAO.find(affiliate_dni): raise BusinessError( f'There is no affiliate with DNI {affiliate_dni}.', 404) consultations = await ConsultationDAO.all_affiliate_consultations( affiliate_dni) doctors = [ await DoctorDAO.find_by_id(consultation.doctor_id) for consultation in consultations ] return consultations, doctors
async def authenticate(cls, auth_data: AuthData) -> Tuple[AuthData, object]: # Retrieve auth data from database fetched_data = await AuthenticationDAO.find(auth_data) # Check if user exists if not fetched_data: raise BusinessError(f'Unknown user with id {auth_data.user_id}', 404) # Validate password if fetched_data.password != auth_data.password: raise BusinessError( f'Invalid password for user {auth_data.user_id}', 413) if fetched_data.role == 'doctor': user_info = await DoctorDAO.find_by_dni(auth_data.user_id) elif fetched_data.role == 'affiliate': user_info = await AffiliateDAO.find(auth_data.user_id) await AffiliateDAO.store_device_id(user_info.dni, auth_data.device_id) else: # TODO -> This is for admin users user_info = None # Return related data found in database return fetched_data, user_info
async def put_doctors_opinion(cls, doctor_id: str, consultation_id: str, opinion: ConsultationOpinion): """ Update a consultation with prescription and indications. """ consultation = await cls.__get_doctor_consultation( doctor_id, consultation_id) # Check that the consultation belongs to the doctor if not consultation.doctor_id == doctor_id: raise BusinessError( f'Failed to match doctor ID to consultation ID.', 400) # Update and store consultation.prescription = opinion.prescription consultation.indications = opinion.indications consultation.status = ConsultationStatus.FINISHED await ConsultationDAO.store(consultation)
async def doctor_consultation( cls, doctor_id: str, consultation_id: str) -> Tuple[Consultation, Doctor, Affiliate]: """ Get consultation and check if doctor and consultation are related. """ consultation = await cls.__get_doctor_consultation( doctor_id, consultation_id) # Check that the consultation belongs to the affiliate if not consultation.doctor_id == doctor_id: raise BusinessError( f'Failed to match affiliate DNI to consultation ID.', 404) # Get consultation doctor doctor = await DoctorDAO.find_by_id(consultation.doctor_id) # Get consultation patient patient = await AffiliateDAO.find(consultation.patient_dni) # Return both objects for mapping return consultation, doctor, patient
def map_creation(request_body: dict) -> Doctor: # Check if the request contains all needed fields for field in Doctor.fields(): if field not in request_body and field != 'id': raise BusinessError(f'Invalid resource creation request. Missing field {field}.', 400) # Create model object return Doctor( dni=request_body['dni'], licence=request_body['licence'], first_name=request_body['first_name'], last_name=request_body['last_name'], email=request_body['email'], centers=request_body['centers'], specialties=request_body['specialties'], availability_times=request_body['availability_times'] )
async def __get_doctor_consultation(cls, doctor_id: str, consultation_id: str) -> Consultation: if not await DoctorDAO.find_by_id(doctor_id): raise BusinessError(f'There is no doctor with ID {doctor_id}.', 404) return await cls.__get_consultation(consultation_id)
async def __get_affiliate_consultation( cls, affiliate_dni: str, consultation_id: str) -> Consultation: if not await AffiliateDAO.find(affiliate_dni): raise BusinessError( f'There is no affiliate with DNI {affiliate_dni}.', 404) return await cls.__get_consultation(consultation_id)
async def remove(cls, doctor_id: str): # Check if doctor with given id exists if not await DoctorDAO.find_by_id(doctor_id): raise BusinessError(f'There is no doctor with id {doctor_id}.', 404) await DoctorDAO.delete(doctor_id)
async def remove(cls, resource_id: str): # Check if doctor with given id exists if not await ExampleDAO.find(resource_id): raise BusinessError(f'There is no resource with id {resource_id}.', 404) await ExampleDAO.delete(resource_id)
def _parse_body(self): try: return MappingUtils.decode_request_body(self.request.body) except RuntimeError: raise BusinessError(f'Invalid request body {self.request.body}', 400)
async def __get_consultation(cls, consultation_id: str) -> Consultation: consultation = await ConsultationDAO.find(consultation_id) if not consultation: raise BusinessError( f'There is no consultation with ID {consultation_id}.', 404) return consultation
async def get(self, consultation_id): doctor_id = self.get_argument('doctor', None, True) if not doctor_id: raise BusinessError('Missing query parameter "doctor".', 400) await self.wrap_coroutine(self.__next_consultation, **{'doctor_id': doctor_id})