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
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
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
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
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
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
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 }
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
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
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')
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
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
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')
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
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')
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
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
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
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
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')