Esempio n. 1
0
def get_volunteer_mission(
    uuid: pydantic.UUID4,
    db: Session = Depends(get_db),
    volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission = crud.get_mission_by_uuid(db, uuid)
    if not mission:
        raise HTTPException(status.HTTP_404_NOT_FOUND,
                            detail="No such mission")

    volunteer_mission_statuses = crud.get_all_volunteer_mission_statuses(
        db, mission)
    if any(s == models.VolunteerMissionState.accepted
           for s in volunteer_mission_statuses):
        check_volunteer_mission(db,
                                mission,
                                volunteer,
                                in_state=models.VolunteerMissionState.accepted)
    else:
        check_volunteer_mission(db, mission, volunteer)

    if mission.state.name == models.MissionState.approved.name:
        return schemas.SlimMissionResponse(
            **mission.__dict__,
            distance=utils.distance_to_string(
                volunteer.calculate_distance_from(mission.elder_address)))
    elif mission.state.name in {
            models.MissionState.acquired.name, models.MissionState.started.name
    }:
        return schemas.VolunteerMission(**mission.to_dict())
    else:
        raise HTTPException(status.HTTP_403_FORBIDDEN,
                            detail="Mission is not longer required volunteer")
Esempio n. 2
0
def complete_mission(
    uuid: pydantic.UUID4,
    db: Session = Depends(get_db),
    volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission = crud.get_mission_by_uuid(db, uuid)
    check_volunteer_mission(db, mission, volunteer)
    crud.set_mission_state(db, mission, models.MissionState.completed)
Esempio n. 3
0
def change_mission_state(state_request: schemas.ChangeMissionStateRequest, background_tasks: BackgroundTasks,
                         db: Session = Depends(get_db),
                         volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission = crud.get_mission_by_uuid(db, _uuid=state_request.mission_id)
    if not mission:
        raise HTTPException(status.HTTP_404_NOT_FOUND, detail=schemas.MissionNotFound.description())
    if not has_role_or_above(volunteer, models.VolunteerRole.coordinator) \
            and volunteer.role != models.VolunteerRole.call_center:
        crud.check_volunteer_mission(db, mission, volunteer, models.VolunteerMissionState.accepted)

    handle_mission_state_changed(db, mission, state_request.mission_state, state_request.error_state, background_tasks,
                                 state_before_changed=mission.state)
Esempio n. 4
0
def schedule_mission(request: schemas.ScheduleMissionRequest,
                     background_tasks: BackgroundTasks,
                     db: Session = Depends(get_db),
                     volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission = crud.get_mission_by_uuid(db, _uuid=request.mission_id)
    if not mission:
        raise HTTPException(status.HTTP_404_NOT_FOUND, detail=schemas.MissionNotFound.description())
    if not has_role_or_above(volunteer, models.VolunteerRole.coordinator):
        check_volunteer_mission(db, mission, volunteer, VolunteerMissionState.accepted)

    crud.set_mission_schedule(db, mission, request.schedule_date, request.preferred_hours)
    background_tasks.add_task(crud.set_mission_approved_task, mission.uuid)
    return mission.to_dict()
Esempio n. 5
0
def update_mission(update_mission_request: schemas.UpdateMission,
                   background_tasks: BackgroundTasks,
                   db: Session = Depends(get_db),
                   coordinator: models.Volunteer = Depends(get_current_active_coordinator_volunteer)):
    mission_before_update = crud.get_mission_by_uuid(db, _uuid=update_mission_request.uuid)
    mission_state_before_update: models.MissionState = mission_before_update.state
    if update_mission_request.owner_id:
        coordinator = crud.get_volunteer_by_id(db, update_mission_request.owner_id)
    crud.update_mission(db, update_mission_request, coordinator)
    handle_mission_state_changed(db, mission_before_update,
                                 update_mission_request.state,
                                 update_mission_request.error_state,
                                 background_tasks,
                                 state_before_changed=mission_state_before_update)
Esempio n. 6
0
def decline_mission(
    uuid: pydantic.UUID4,
    decline_request: schemas.DeclineMissionRequest,
    background_tasks: BackgroundTasks,
    db: Session = Depends(get_db),
    volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission: models.Mission = crud.get_mission_by_uuid(db, uuid)
    if not mission:
        raise HTTPException(status.HTTP_404_NOT_FOUND,
                            detail="No such mission")

    crud.handle_decline_mission(db, mission.uuid, volunteer.id,
                                decline_request.reason, background_tasks)

    return schemas.SlimMissionResponse(**mission.to_dict(),
                                       distance=utils.distance_to_string(
                                           volunteer.calculate_distance_from(
                                               mission.elder_address)))
Esempio n. 7
0
def event_loop():
    while True:
        logger.info('Starting worker Iteration')
        timesleep.sleep(config.WORKER_INTERVAL_SECONDS)
        tasks: List[models.ScheduledTasks] = pull_tasks()
        logger.info(f'Pulled {len(tasks)} tasks')
        for task in tasks:
            # TODO: Format safer
            task.executed_at = models.get_utc_now()
            # Get mission id from endpoint column
            mission_uuid = task.endpoint.split('/')[3].split('?')[0]
            mission: models.Mission = crud.get_mission_by_uuid(
                db, mission_uuid)
            # Don't do anything if mission state is not approved
            if mission.state != models.MissionState.approved:
                logger.info(
                    f'mission {mission.uuid} status is not approved and was changed to {mission.state.name}'
                )
                task.failure_description = f'{mission.uuid} is not in state approved'
                continue
            if number_of_completed_tasks(
                    task) < config.MAX_SEARCHING_VOLUNTEERS_ATTEMPTS:
                add_next_task_time(task)
            # Set the MissionErrorState to no volunteers found
            else:
                crud.set_mission_error(
                    db, mission, models.MissionErrorState.no_volunteers_found)
                continue
            request_url = f'http://localhost{config.API_V1_STR}{task.endpoint}'
            logger.info(f'Running {request_url}')
            response = requests.get(url=request_url)
            # Valid response
            if response.status_code == status.HTTP_200_OK:
                task.completed_at = models.get_utc_now()
            # Error occurred
            else:
                task.failed_at = models.get_utc_now()
                task.failure_description = f'{response.status_code}: {response.text}'
        db.commit()
        logger.info('Iteration is finished')
Esempio n. 8
0
def verify_mission(mission_uuid: UUID4,
                   internal_token: str,
                   db: Session = Depends(get_db)):
    if internal_token != config.INTERNAL_API_TOKEN:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED,
                            detail="Not allowed to call this API")
    try:
        mission: models.Mission = crud.get_mission_by_uuid(db, mission_uuid)
        # If mission doesn't exists any more raise exception
        if not mission:
            raise HTTPException(
                status.HTTP_404_NOT_FOUND,
                detail=f"Mission {mission_uuid} no longer exists.")
        # If mission state is not approved (approved meaning it's waiting for volunteers) we want to return
        if mission.state != models.MissionState.approved:
            return f"Mission state ({mission.state.name}) doesn't need more volunteers lookup"
        # Ask for the second group since if we came here the first group doesn't respond
        return search.search_and_notify_nearby_volunteers(db, mission)

    except Exception as e:
        raise HTTPException(
            status.HTTP_400_BAD_REQUEST,
            detail=f"Exception raised while handling this task: {str(e)}")
Esempio n. 9
0
def accept_mission(
    uuid: pydantic.UUID4,
    db: Session = Depends(get_db),
    volunteer: models.Volunteer = Depends(get_current_active_volunteer)):
    mission = crud.get_mission_by_uuid(db, uuid)
    if not mission:
        raise HTTPException(status.HTTP_404_NOT_FOUND,
                            detail="No such mission")
    try:
        crud.accept_mission_for_volunteer(db, volunteer, mission)
    except MissionAlreadyAccepted:
        raise HTTPException(
            status.HTTP_405_METHOD_NOT_ALLOWED,
            detail="Mission was already accepted by another volunteer")
    except Exception as e:
        raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)

    db.refresh(volunteer)
    db.refresh(mission)
    return schemas.MissionStartedResponse(
        **mission.__dict__,
        elder_address=dict(address_str=mission.elder_address_str,
                           address_lat=mission.elder_address_lat,
                           address_lng=mission.elder_address_lng))