예제 #1
0
def get_products(token):
    """
    Get a list of products from the ERP system.

    :param token:   The ERP Loopback session token.

    :return:        The list of existing products.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Products' % get_service_url('lw-erp')
    headers = {'cache-control': "no-cache", 'Authorization': token}

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving products',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #2
0
def get_distribution_center(token, dc_id):
    """
    Get a distribution center from the ERP system.

    :param token:   The ERP Loopback session token.
    :param dc_id:   The ID of the distribution center to be retrieved.

    :return:        The retrieved distribution center.
    """

    # Create and format request to ERP
    url = '%s/api/v1/DistributionCenters/%s' % (get_service_url('lw-erp'),
                                                str(dc_id))
    headers = {'cache-control': "no-cache", 'Authorization': token}
    headers.update(get_apic_credentials())

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving distribution center',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Distribution center does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #3
0
def get_retailer_inventory(token, retailer_id):
    """
    Get a retailer from the ERP system.

    :param token:       The ERP Loopback session token.
    :param retailer_id: The ID of the retailer for which inventory is to be be retrieved.

    :return:        The retrieved retailer's inventory.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Retailers/%s/inventories' % (get_service_url('lw-erp'),
                                                  str(retailer_id))
    headers = {'cache-control': "no-cache", 'Authorization': token}

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving retailer inventory',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Retailer does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #4
0
def delete_demo_by_guid(guid):
    """
    Delete a demo from the ERP system by guid.

    :param guid:    The demo's guid.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Demos/%s' % (get_service_url('lw-erp'), guid)
    headers = get_apic_credentials()

    try:
        response = requests.request("DELETE", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error deleting demo',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Demo does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return
예제 #5
0
def delete_shipment(token, shipment_id):
    """
    Delete a shipment from the ERP system.

    :param token:       The ERP Loopback session token.
    :param shipment_id: The ID of the shipment to be deleted.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Shipments/%s' % (get_service_url('lw-erp'),
                                      str(shipment_id))
    headers = {'cache-control': "no-cache", 'Authorization': token}
    headers.update(get_apic_credentials())

    try:
        response = requests.request("DELETE", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error deleting shipment',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Shipment does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return
예제 #6
0
def get_demo_by_guid(guid):
    """
    Retrieve a demo from the ERP system by guid.

    :param guid:    The demo's guid.

    :return:        An instance of the Demo.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Demos/findByGuid/%s' % (get_service_url('lw-erp'), guid)
    headers = {'cache-control': "no-cache"}

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving demo',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Demo does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
def logout(token):
    """
    Log a user out of the system.

    :param token:   The ERP Loopback session token
    """

    # Create and format request to ERP
    url = '%s/api/v1/Users/logout' % get_service_url('lw-erp')
    headers = {'content-type': "application/json", 'Authorization': token}

    try:
        response = requests.request("POST", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating new user for demo',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 500:
        raise ResourceDoesNotExistException(
            'Session does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return
def create_user(guid, retailer_id):
    """
    Create a new user in the ERP system.

    :param guid:        The demo's guid
    :param retailer_id: Retailer the user will be associated with.

    :return:            The created User model.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Demos/%s/createUser' % (get_service_url('lw-erp'), guid)
    headers = {'content-type': "application/json", 'cache-control': "no-cache"}
    payload = dict()
    payload['retailerId'] = retailer_id
    payload_json = json.dumps(payload)

    try:
        response = requests.request("POST",
                                    url,
                                    data=payload_json,
                                    headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating new user for demo',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Demo or retailer does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #9
0
def login(guid, user_id):
    """
    Authenticate a user against the ERP system.

    :param guid:        The demo guid being logged in for.
    :param user_id:     The user_id for which to log in.
    :return:            Auth data returned by ERP system
    """

    # Create and format request to ERP
    url = '%s/api/v1/Demos/%s/loginAs' % (get_service_url('lw-erp'), guid)
    headers = {
        'content-type': "application/json",
        'cache-control': "no-cache"
    }
    payload = dict()
    payload['userId'] = int(user_id)
    payload_json = json.dumps(payload)

    try:
        response = requests.request("POST", url, data=payload_json, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating new user for demo', internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 404:
        raise ResourceDoesNotExistException('Demo or user does not exist',
                                            internal_details=json.loads(response.text).get('error').get('message'))

    login_response = json.loads(response.text)
    return {
        'loopback_token': login_response.get('token').get('id'),
        'user': login_response.get('user'),
        'guid': guid
    }
예제 #10
0
def get_shipments(token, retailer_id=None, dc_id=None, status=None):
    """
    Get a list of shipments from the ERP system.

    :param token:       The ERP Loopback session token.
    :param status:      Status of the shipments to be retrieved.
    :param retailer_id: Retailer of the shipments to be retrieved.
    :param dc_id:       Distribution center of the shipments to be retrieved.

    :return:         The list of existing shipments.
    """

    # Add filters if corresponding inputs are present
    status_query = ""
    if status is not None:
        status_query = add_query_filter(status_query,
                                        "where",
                                        "=",
                                        status,
                                        property_name="status")
    if retailer_id is not None:
        status_query = add_query_filter(status_query,
                                        "where",
                                        "=",
                                        retailer_id,
                                        property_name="toId")
    if dc_id is not None:
        status_query = add_query_filter(status_query,
                                        "where",
                                        "=",
                                        dc_id,
                                        property_name="fromId")

    # Create and format request to ERP
    url = '%s/api/v1/Shipments%s' % (get_service_url('lw-erp'), status_query)
    headers = {'cache-control': "no-cache", 'Authorization': token}
    headers.update(get_apic_credentials())

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving shipments',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #11
0
def get_recommendations(demoGuid):
    """
    Get recommendations
    """

    try:
        payload = dict()
        payload['demoGuid'] = demoGuid
        response = call_openwhisk('retrieve', payload)
    except Exception as e:
        raise APIException('KO', internal_details=str(e))

    return response
예제 #12
0
def get_service_url(service_name):
    """
    Retrieves the URL of the service being called based on the environment
    that the controller is currently being run.

    :param service_name:    Name of the service being retrieved
    :return:                The endpoint of the input service name
    """

    if service_name == 'lw-erp':
        return env['ERP_SERVICE']
    else:
        raise APIException('Unrecognized service invocation')
예제 #13
0
def get_observations(latitude, longitude):
    """
    Return observations for the given location
    """

    try:
        payload = dict()
        payload['latitude'] = latitude
        payload['longitude'] = longitude
        response = call_openwhisk('observations', payload)
    except Exception as e:
        raise APIException('KO', internal_details=str(e))

    return response
예제 #14
0
def acknowledge_recommendation(demoGuid, recommendationId):
    """
    Acknowledge the given recommendation
    """

    try:
        payload = dict()
        payload['demoGuid'] = demoGuid
        payload['recommendationId'] = recommendationId
        response = call_openwhisk('acknowledge', payload)
    except Exception as e:
        raise APIException('KO', internal_details=str(e))

    return response
예제 #15
0
def get_service_url(service_name):
    """
    Retrieves the URL of the service being called based on the environment
    that the controller is currently being run.

    :param service_name:    Name of the service being retrieved
    :return:                The endpoint of the input service name
    """

    # Use the Service Discovery service if Prod and toggle is on
    if Config.SD_STATUS == 'ON' and env.get('VCAP_SERVICES') is not None:
        try:
            creds = loads(
                env['VCAP_SERVICES'])['service_discovery'][0]['credentials']
            locator = ServiceLocator(creds['url'], creds['auth_token'])
            service_instances = loads(
                locator.get_services(
                    service_name=service_name,
                    status='UP',
                    tags=env['LOGISTICS_WIZARD_ENV']))['instances']
            if len(service_instances) == 0:
                raise APIException('Dependent service not available')
            return 'https://%s' % service_instances[0]['endpoint']['value']
        except Exception as e:
            if isinstance(e, Exception):
                e = e.message
            raise APIException('Cannot get dependent service',
                               user_details=str(e),
                               internal_details=str(e))
    # Otherwise, get the service endpoint from an env var
    else:
        if service_name == 'lw-erp':
            return env['ERP_SERVICE']
        elif service_name == 'lw-recommendation':
            return env['RECOMMENDATION_SERVICE']
        else:
            raise APIException('Unrecognized service invocation')
예제 #16
0
def create_shipment(token, shipment):
    """
    Create a shipment in the ERP system.

    :param token:       The ERP Loopback session token.
    :param shipment:    The shipment object to be created.

    :return:         The created shipment.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Shipments' % get_service_url('lw-erp')
    headers = {
        'content-type': "application/json",
        'cache-control': "no-cache",
        'Authorization': token
    }
    headers.update(get_apic_credentials())

    shipment_json = json.dumps(shipment)

    try:
        response = requests.request("POST",
                                    url,
                                    data=shipment_json,
                                    headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating shipment',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 400:
        raise ValidationException(
            'Bad shipment data',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 422:
        raise UnprocessableEntityException(
            'Required data for shipment is either absent or invalid',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #17
0
    def exception_handler(e):
        """
        Handle any exception thrown in the interface layer and return
        a JSON response with the error details. Wraps python exceptions
        with a generic exception message.

        :param e:  The raised exception.
        :return:   A Flask response object.
        """
        if not isinstance(e, APIException):
            exc = APIException(u'Server Error', internal_details=unicode(e))
        else:
            exc = e
        current_app.logger.error(exc)
        return Response(json.dumps(compose_error(exc, e)),
                        status=exc.status_code,
                        mimetype='application/json')
예제 #18
0
def trigger_simulation(demoGuid):
    """
    Trigger a simulation in the given demo
    Creates a Snow Storm in the DC area
    """

    try:
        payload = dict()
        payload['demoGuid'] = demoGuid
        event = dict()
        event = json.loads(open('./sample_event.json').read())
        payload['event'] = event
        response = call_openwhisk('recommend', payload)
    except Exception as e:
        raise APIException('KO', internal_details=str(e))

    return response
예제 #19
0
def create_demo():
    """
    Create a new demo session in the ERP system.

    :return:         The created Demo model.
    """

    # Create and format request to ERP
    url = '%s/api/v1/Demos' % get_service_url('lw-erp')
    headers = {'content-type': "application/json", 'cache-control': "no-cache"}

    try:
        response = requests.request("POST", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating new Demo',
                           internal_details=str(e))

    return response.text
예제 #20
0
def get_shipment(token, shipment_id, include_items=None):
    """
    Get a shipment from the ERP system.

    :param token:           The ERP Loopback session token.
    :param shipment_id:     The ID of the shipment to be retrieved.
    :param include_items:   Indicates if items are to be returned with shipment.

    :return:         The retrieved shipment.
    """

    # Add filters if corresponding inputs are present
    status_query = ""
    if include_items != "0":
        status_query = add_query_filter(status_query, "include", "=", "items")

    # Create and format request to ERP
    url = '%s/api/v1/Shipments/%s%s' % (get_service_url('lw-erp'),
                                        str(shipment_id), status_query)
    headers = {'cache-control': "no-cache", 'Authorization': token}
    headers.update(get_apic_credentials())

    try:
        response = requests.request("GET", url, headers=headers)
    except Exception as e:
        raise APIException('ERP threw error retrieving shipment',
                           internal_details=str(e))

    # Check for possible errors in response
    if response.status_code == 401:
        raise AuthenticationException(
            'ERP access denied',
            internal_details=json.loads(
                response.text).get('error').get('message'))
    elif response.status_code == 404:
        raise ResourceDoesNotExistException(
            'Shipment does not exist',
            internal_details=json.loads(
                response.text).get('error').get('message'))

    return response.text
예제 #21
0
def create_demo(demo_name, user_email=None):
    """
    Create a new demo session in the ERP system.

    :param demo_name:   Name of the demo being created.
    :param user_email:  Email of the user creating the demo.

    :return:         The created Demo model.
    """

    # Check email
    if user_email is not None and validate_email(user_email) == False:
        raise UnprocessableEntityException("Invalid email address")

    # Create and format request to ERP
    url = '%s/api/v1/Demos' % get_service_url('lw-erp')
    headers = {'content-type': "application/json", 'cache-control': "no-cache"}
    payload = dict()
    payload['name'] = demo_name
    payload_json = json.dumps(payload)

    try:
        response = requests.request("POST",
                                    url,
                                    data=payload_json,
                                    headers=headers)
    except Exception as e:
        raise APIException('ERP threw error creating new Demo',
                           internal_details=str(e))

    # Commenting out synchronous email sending until one-off tasks are enabled
    # if user_email:
    #     demo = json.loads(response.text)
    #     subject = "Your Logistics Wizard session has been created - Demo #" + \
    #               demo.get('guid')[-6:].upper()
    #     message = messaging_service.compose_msg('welcome.html', (demo.get('guid'),
    #                                                              demo.get('users')[0].get('username'),
    #                                                              str(demo.get('users')[0].get('id'))))
    #     messaging_service.send_email(user_email, subject, message, 'html')

    return response.text
예제 #22
0
def load_admin_data():
    """
    Load all data relative to the currently logged in user

    :return: {
        "shipments": [{Shipments}],
        "retailers": [{Retailer}],
        "distribution_centers": [{Distribution Center}]
    }
    """

    # Specify functions and corresponding arguments to call to retrieve ERP data
    loopback_token = g.auth['loopback_token']
    erp_calls = [(shipment_service.get_shipments, loopback_token),
                 (distribution_center_service.get_distribution_centers,
                  loopback_token),
                 (retailer_service.get_retailers, loopback_token)]
    pool = Pool(processes=len(erp_calls))

    # Asynchronously make calls and then wait on all processes to finish
    try:
        results = pool.map(async_helper, erp_calls)
    except Exception as e:
        raise APIException('Error retrieving admin data view',
                           internal_details=str(e))
    pool.close()
    pool.join()

    # Send back serialized results to client
    return Response(json.dumps({
        "shipments": json.loads(results[0]),
        "distribution-centers": json.loads(results[1]),
        "retailers": json.loads(results[2])
    }),
                    status=200,
                    mimetype='application/json')