示例#1
0
def get_api_data(url, body, token):
    """ This function use to get data from API.

    Args:
        url (string): required api url.
        body (dict): required request body

        Returns:
        json: The return value. """

    # Initialize return value.
    return_value = {"statusCode": None, "body": None}
    try:
        headers = {"Content-Type": "application/json", "Authorization": token}
        response = requests.post(url, data=json.dumps(body), headers=headers)
        return_value["body"] = response
        return_value["statusCode"] = response.status_code
        if response.status_code == 200:
            logger.info("Successfully called %s with response code of %s", url,
                        response.status_code)
        else:
            logger.error("Error calling %s, response code was: %s", url,
                         response.status_code)
    except RequestException as ex:
        return_value["statusCode"] = 500
        return_value["body"] = str(RequestException)
        logger.error("Error calling %s, error was %s", url, str(ex))
    return return_value
示例#2
0
def re_handler(event, context):
    """ This handler function return recommendation acording to vacated shift, shifter parameter.

        Args:
        event["body"] (dict): request body to get recommendation.

        Returns:
        json: The return value. """

    logger.debug("Received new event: %s", repr(event))
    response = {
        'statusCode': None,
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': str(context) + str(event)
    }
    vacated_params = event['body']
    if vacated_params:
        vacated_params = json.loads(vacated_params)
        result = recommendations(vacated_params)
        response['statusCode'] = result['statusCode']
        response['body'] = json.dumps(result)
    else:
        response['body'] = "Unprocessable Entity"
        response['statusCode'] = 422
        logger.error("Unable to parse request paramaters")
    logger.debug("Lambda Response: %s", repr(response))
    return response
def recommendations(vacated_params):
    """ This function used to get recommended shifter according to request params.

    Args:
    vacated_params (dict): vacated shift and shifter data.

    Returns:
    dict: (List of recommended shifter) The return value. """

    # Initialize return value
    return_value = {"statusCode": None, "message": None, "body": None}
    try:
        patterns = ConfigLoaders.get_organizationsetting(
            vacated_params["jobProviderId"])
        qualified_shifter = get_qualified_shifter(
            vacated_params, patterns["disqualify_structures"])
        return_value = get_recommended_shifter(qualified_shifter,
                                               vacated_params,
                                               patterns['scoring_structures'])
    except BaseException as ex:
        logger.error("Error in recommendation function. %s", str(ex))
        return_value['statusCode'] = 500
        return_value["message"] = "Internal server error!"
        return_value['body'] = []
    return return_value
    def day_overtime_risk(instance):
        """ This function used to filter shifter shift and vacated shift over time risk for same day.

        Args:
            instance (dict): {
                shifter_day_hour: shifter shift duration from start to end.
                vacated_hour: vacated shift duration from start to end.
                disqualify_params: params for filter overtime risk for the same day.
            }

        Returns:
            boolean: The filter status. """
        # Initialize return value.
        return_value = "qualified"
        try:
            shifter_shift_hour = instance["shifter_day_hour"]
            vacated_shift_hour = instance["vacated_hour"]
            disqualify_params = instance["disqualify_params"]
            shift_duration_count = shifter_shift_hour + vacated_shift_hour
            if shift_duration_count > disqualify_params["day_overtime_range"]:
                logger.info("Disqualified Reason: day_overtime_risk")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in day_overtime_risk: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
    def week_overtime_risk(instance):
        """ This function used to filter shifter shift and vacated shift over time risk for a week.

        Args:
        instance (dict): {
            shifter_week_hour: Total conformed shift duration hour in week.
            vacated_hour: vacated shift duration from start to end.
            disqualify_params: params for filter week over time risk.

        Returns:
            boolean: The filter status. """
        # Initialize return value.
        return_value = "qualified"
        try:
            shifter_week_hour = instance["shifter_week_hour"]
            vacated_shift_hour = instance["vacated_hour"]
            disqualify_params = instance["disqualify_params"]
            week_duration = shifter_week_hour + vacated_shift_hour
            if week_duration > disqualify_params["week_overtime_range"]:
                logger.info("Disqualified Reason: week_overtime_risk")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in week_overtime_risk: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
    def shift_overlap(instance):
        """ This function used to filter shifter shift time and vacated shift time overlap each other.

        Args:
            instance (dict): {
                shifter_hour_list: List of hours between shifter start and end time.
                vacated_hour_list: List of hours between vacated start and end time.
                disqualify_params: Status to filter Example: True/False
            }

        Returns:
            boolean: The disqualify status. """
        # Initialize return value.
        return_value = "qualified"
        try:
            disqualify_params = instance["disqualify_params"]
            overlap = []
            if disqualify_params:
                shifter_hour_list = instance["shifter_hour_list"]
                vacated_hour_list = instance["vacated_hour_list"]
                overlap = [
                    value for value in shifter_hour_list
                    if value in vacated_hour_list
                ]
            if overlap:
                logger.info("Disqualified Reason: shift_overlap")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error("Disqualified Reason: EXCEPTION in shift_overlap: %s",
                         str(ex))
            return_value = "disqualified"
        return return_value
示例#7
0
    def openconnection(connection_key):
        """ This function return connection object acording to connection params.

        Args:
        connection_key (dic): have following keys { username, host, password,
        port, authentication_source, db_name }.

        Returns:
        Object: The return value. """

        return_value = {"statusCode": None, "message": None, "body": None}
        try:
            # Initialize connection string.
            mongo_port = int(27017)
            try:
                mongo_port = int(connection_key["port"])
            except ValueError:
                logger.error(
                    "Mongo DB Port should be an integer. Provided value was: %s",
                    connection_key["port"])
            connection_kwargs = {
                'username': connection_key['username'],
                'host': connection_key['host'],
                'password': connection_key['password'],
                'port': mongo_port,
                'authentication_source': connection_key['authSource']
            }
            # Get connection.
            connect(connection_key['db_name'], **connection_kwargs)
            # Get connection object.
            connection = get_connection()
            # Get database.
            database = get_db()
            if database.name == connection_key['db_name']:
                logger.info("Database connected successfully.")
                return_value["statusCode"] = 200
                return_value["message"] = "Success"
                return_value["body"] = connection
        except BaseException as exceptions:
            message = str(exceptions)
            logger.error("Database connection failed!: %s", message)
            return_value["statusCode"] = 500
            return_value["message"] = "Internal server error!"
            return_value["body"] = None
        return return_value
def get_shifters_from_db(vacated_params, disqualify_params):
    """ This function used to get filtered shifters data from database.

    Args:
    vacated_params (dict): Vacated shift, shifter data.
    disqualify_params (dict): paramiters to filter data

    Returns:
    dict: The return value. """
    # Initialize return value.
    return_value = {"statusCode": None, "message": None, "body": None}
    try:
        # Check if class Shifters has no objects member.
        if 'objects' not in dir(Shifters):
            # Assign objects member.
            Shifters.objects = QuerySetManager()
        # Initialize database connection
        response = DbConnection.openconnection(CONNECTION_KEY)
        if response["statusCode"] == 200:
            # Get data from database
            result = Shifters.objects.get_shifters(
                vacated_params, disqualify_params).to_json(indent=0)
            shifters = json.loads(result)
            if shifters:
                logger.info("Get shifters data from database success.")
                return_value["statusCode"] = 200
                return_value["message"] = "Seccess"
                return_value["body"] = shifters
            else:
                logger.info("Shifters not found in database!")
                return_value["statusCode"] = 404
                return_value["message"] = "Shifters not found in database!"
                return_value["body"] = []
        else:
            return_value = response
    except BaseException as ex:
        logger.error("Error retrieving data from MongoDB. %s", repr(ex))
        return_value["statusCode"] = 500
        return_value["message"] = "Internal server error!"
        return_value["body"] = []
    return return_value
def get_disqualify_status(disqualify_instances):
    """ This function used to perform disqualify filter and return status.

    Args:
    disqualify_instances (List): list of all filter function and associated params.

    Returns:
    List: The status of disqualify filter. """
    # Initialize qualify shifter
    disqualify_status = []
    try:
        for method, inputs in disqualify_instances.items():
            status = FILTER.execute(method, inputs)
            logger.debug("QualityFilter %s returned status of: %s", method,
                         status)
            disqualify_status.append(status)
        return disqualify_status
    except BaseException as exceptions:
        message = str(exceptions)
        logger.error("Error while getting disqualify status: %s", message)
        return None
示例#10
0
    def position_filter(instance):
        """ This function used to filter shift position completed for vacated shift.

        Args:
        shifter (dict): shifter, vacated shift data.

        Returns:
        boolean: The return value. """
        # Initialize return value.
        return_value = "qualified"
        try:
            completed_position_count = instance["completed_position_count"]
            completed_position_range = instance["completed_position_range"]
            if completed_position_count == completed_position_range:
                logger.info("Disqualified Reason: position_filter")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in position_filter: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
示例#11
0
    def reliability_filter(instance):
        """ This function used to check reliability of shifter on the basis of nowshow count.

        Args:
        shifter (dict): shifter, vacated shift data.

        Returns:
        boolean: The return value. """
        # Initialize return value.
        return_value = "qualified"
        try:
            noshow_count = instance["noshowcount"]
            noshow_range = instance["noshow_range"]
            if noshow_count >= noshow_range:
                logger.info("Disqualified Reason: reliability_filter")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in reliability_filter: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
示例#12
0
def save_shifter(data):
    """ This function used to save shifter data into database.

    Args:
    data (dict): Shifter data.

    Returns:
    dict: The return value. """

    # Initialize return value
    return_value = {"statusCode": None, "body": None}

    try:
        response = DbConnection.openconnection(CONNECTION_KEY)
        if response["statusCode"] == 200:
            # Initialize shifter object.
            shifter = Shifters(
                id=data['id'],
                shifterid=data['id'],
                existingshifterjpid=data['existingshifterjpid'],
                position=data['position'],
                location=[float(data['longitude']),
                          float(data['latitude'])],
                rating=data['rating'],
                shifteravailability=data['shifteravailability'])
            # To save shifter data in database.
            shifter.save()
            logger.info("Saved data successfully")
            return_value["statusCode"] = 200
            return_value["body"] = "Success"
        else:
            return_value = response
    except BaseException as exceptions:
        message = str(exceptions)
        logger.error("Shifter data not saved! Error: %s", message)
        return_value["statusCode"] = 500
        return_value["body"] = message
    return return_value
示例#13
0
    def duration_difference(instance):
        """ This function used to filter shifter shift and vacated shift difference time risk.

        Args:
        instance (dict): shifter, vacated shift data.

        Returns:
        boolean: The return value. """
        # Initialize return value
        return_value = "qualified"
        try:
            duration_difference_list = instance["duration_difference_list"]
            disqualify_params = instance["duration_difference_range"]
            for difference in duration_difference_list:
                if difference <= disqualify_params:
                    logger.info("Disqualified Reason: duration_difference")
                    return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in duration_difference: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
示例#14
0
def save_shift(data):
    """ This function used to save shift data into database.

    Args:
    data (dict): Shift data.

    Returns:
    dict: The return value. """

    # Initialize return value
    return_value = {"statusCode": None, "body": None}

    try:
        # Initialize database connection
        response = DbConnection.openconnection(CONNECTION_KEY)
        if response["statusCode"] == 200:
            # Initialize shift object.
            shift = Shifts(
                id=data['shiftid'],
                shiftid=data['shiftid'],
                jobproviderid=data['jobproviderid'],
                location=[float(data['longitude']),
                          float(data['latitude'])],
                shiftdetail=data["shiftdetail"])
            # To save shift data in database.
            shift.save()
            logger.info("Saved data successfully")
            return_value["statusCode"] = 200
            return_value["body"] = "Success"
        else:
            return_value = response
    except BaseException as exceptions:
        message = str(exceptions)
        logger.error("Shift data not saved! Error: %s", message)
        return_value["statusCode"] = 500
        return_value["body"] = message
    return return_value
示例#15
0
    def recommended_filter(instance):
        """ This function used to filter shifter recommended on the basis of recommended count.

        Args:
        shifter (dict): shifter, vacated shift data.

        Returns:
        boolean: The return value. """
        # Initialize return value.
        return_value = "qualified"
        try:
            recommended_count = instance["recommendedcount"]
            invited_count = instance["invitedcount"]
            recommended_range = instance["recommended_range"]
            invited_range = instance["invited_range"]
            if recommended_count >= recommended_range and invited_count == invited_range:
                logger.info("Disqualified Reason: recommend_filter")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in recommend_filter: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
示例#16
0
    def flexibility_filter(instance):
        """ This function used to check flexibility of shifter on the basis of invited and accepted count.

        Args:
        instance (dict): shifter, vacated shift data.

        Returns:
        boolean: The return value. """
        # Initialize return value.
        return_value = "qualified"
        try:
            invited_count = instance["invitedcount"]
            accepted_count = instance["acceptedcount"]
            accepted_range = instance["accepted_range"]
            invited_range = instance["invited_range"]
            if invited_count >= invited_range and accepted_count == accepted_range:
                logger.info("Disqualified Reason: day_overtime_risk")
                return_value = "disqualified"
        except BaseException as ex:
            logger.error(
                "Disqualified Reason: EXCEPTION in flexibility_filter: %s",
                str(ex))
            return_value = "disqualified"
        return return_value
示例#17
0
def sqs(body):
    """ This function used to call dal api and save response into mongo db according
    to request params.

    Notes: 'This function use helper function to save shift and shifter data

    Args:
    body (dict): required for call dal api.

    Returns:
    dict: The return value. """

    # initialize return value.
    return_value = {"statusCode": None, "body": None}

    try:
        # Initialize request body to call dal api.
        request_body = {"ID": body['Id'], "Type": body['nType']}
        # To parse as string and log the request body comming from sqs.
        request_body_string = str(body)
        logger.debug("Request body from sqs %s", request_body_string)
        # To call dal api and store response in result variable.
        result = get_api_data(DAL_URL['base_url'], request_body,
                              DAL_URL["token"])
        # To check if dal api call success.
        if result["statusCode"] == 200:
            logger.info("DAL api called success for type %s", body['nType'])
            data = result["body"].json()
            if data['data']:
                data = data['data'][0]
                logger.info("Get data from dal api succeeded")
                # To switch according to type.
                if body['nType'] == 'shifter':
                    # Call shifter function to save shifter data.
                    response = save_shifter(data)
                    return_value = response
                elif body['nType'] == 'shift':
                    # Call shift function to save shift data.
                    response = save_shift(data)
                    return_value = response
            else:
                logger.error("Response %s %s.", data["status"],
                             data["message"])
                return_value["statusCode"] = data['status']
                return_value["body"] = data['message']
        else:
            logger.error("Error during call dal api!")
            return_value = result
    except BaseException as exceptions:
        message = str(exceptions)
        logger.error("Error ! %s", message)
        return_value['statusCode'] = 500
        return_value['body'] = message
    return return_value
示例#18
0
def get_shifter_volatile_data(shifters, vacated_params):
    """ This function is used to get shifters voatile data from dal api.

    Args:
    shifters (List): List of filtered shifter data.

    Returns:
    dict: The return value. """
    # Initialize return value.
    return_value = {"statusCode": None, "message": None, "body": {}}
    try:
        # Initialize request body for call dal api type: "qualify".
        shifter_ids_list = []
        for shifter in shifters:
            shifter_ids_list.append(shifter["shifterid"])
        shifter_ids = ", ".join(shifter_ids_list)
        request_body = {
            "ID": shifter_ids,
            "Type": "qualify",
            "VacatedShiftDate": vacated_params["startTime"]
        }
        result = get_api_data(DAL_URL['base_url'], request_body,
                              DAL_URL["token"])
        # To check if dal api call success.
        if result["statusCode"] == 200:
            logger.info("DAL api called successfully for type qualify.")
            data = result["body"].json()
            # To check data found.
            if data["data"]:
                logger.info("Shifters volatile data get success.")
                return_value["statusCode"] = 200
                return_value["message"] = "Success"
                return_value["body"] = data["data"]
            else:
                logger.error("Shifters volatile data not found!")
                return_value["statusCode"] = data['status']
                return_value["message"] = "Shifters volatile data not found!"
                return_value["body"] = []
        else:
            logger.error("Error calling DAL http response was: %s",
                         result["statusCode"])
            return_value["statusCode"] = result["statusCode"]
            return_value["message"] = "Internal server error!"
            return_value["body"] = []
    except BaseException as exceptions:
        message = str(exceptions)
        logger.error("Error while gatting shifters volatile data %s", message)
        return_value["statusCode"] = 500
        return_value["message"] = "Internal server error!"
        return_value["body"] = []
    return return_value
示例#19
0
def get_qualified_shifter(vacated_params, patterns):
    """ This function used to get qualified shifter.

    Args:
    vacated_params (dict): vacated shifter, shift data.

    Returns:
    dict: The return value. """

    # Initialize return value.
    return_value = {"statusCode": None, "message": None, "body": None}
    # Initialize array to store list of shifter with volatile data.
    shifters_data = []
    try:
        # To get filtered shifter from database.
        shifter_from_db = get_shifters_from_db(vacated_params,
                                               patterns["static_data_filter"])
        shifter_volatile_data = get_shifter_volatile_data(
            shifter_from_db["body"], vacated_params)
        shifters_data = get_combined_shifter(shifter_from_db,
                                             shifter_volatile_data)
        if shifters_data["statusCode"] == 200:
            qualified_shifter = []
            instance_builder = DisqualifyInstanceBuilder()
            logger.info(
                "Getting qualified shifter for shiftId: %s and positionId: %s",
                vacated_params["shiftId"], vacated_params["positionId"])
            for data in shifters_data["body"]:
                logger.info(LOG_HEADER, data["shifterid"])
                instances = {}
                inputs = {"shifter": data, "vacated_params": vacated_params}
                for method, pattern in patterns["volatile_data_filter"].items(
                ):
                    instance = instance_builder.execute(
                        method, inputs, pattern)
                    if instance and instance != "Invalid":
                        instances.update(instance)
                filter_status = get_disqualify_status(instances)
                if "disqualified" not in filter_status:
                    instances.clear()
                    filter_status.clear()
                    qualified_shifter.append(data)
            if qualified_shifter:
                return_value["statusCode"] = 200
                return_value["message"] = "Success"
                return_value["body"] = qualified_shifter
                logger.info("Shifter is qualified")
            else:
                return_value["statusCode"] = 404
                return_value[
                    "message"] = "No qualified shifters found for this shift"
                return_value["body"] = []
                logger.info("Shifter was not qualified for the vacated shift")
        else:
            return_value = shifters_data
    except AttributeError as ex:
        return_value["statusCode"] = 500
        return_value["message"] = "Internal server error!"
        return_value["body"] = []
        logger.error("Error %s", repr(ex))
    return return_value