""" Handlers. Requests are redirected to handlers, which are responsible for getting information from the URL and passing it down to the logic layer. The way each layer talks to each other is through Response objects which defines the type status of the data and the data itself. Please note: the Orchard uses the term handlers over views as convention for clarity See: deliveryhistory.response for more details. """ from flask import g from flask import jsonify from flask import request from werkzeug.exceptions import HTTPException from deliveryhistory import config from deliveryhistory import response from deliveryhistory.api import app from deliveryhistory.logic import delivery_history, delivery_report, masters from deliveryhistory.util import handler_util from deliveryhistory.validation import validators @app.route(config.HEALTH_CHECK, methods=['GET']) def health(): """Check the health of the application.""" return jsonify({'status': 'ok'}) @app.route('/masters/', methods=['GET']) @handler_util.validate_header(validators.HEADER_VALIDATOR) def get_delivery_history(partner_id): """Get delivery history for a given partner and ISRCs. Args: partner_id (str): Id of a content partner Request parameters: isrc (str): comma-separated list of ISRCs Returns: flask.Response: list of delivery history record """ isrcs = request.args.get('isrcs', '').strip().split(',') log_message = ( 'GET /masters/: partner_id={0}; ' 'isrcs={1}' ).format(partner_id, isrcs) g.log.info(log_message) history = masters.get_delivery_history(partner_id, isrcs) return response.flaskify(history, encoder=handler_util.DatetimeEncoder) @app.route('/delivered_stores_count', methods=['GET']) @handler_util.validate_request_args(validators.DELIVER_STORES_ARGS_VALIDATOR) def get_delivered_stores_count(): """Get number of stores delivered for a given list of UPCs. Request parameters: upcs (str): comma-separated list of UPCs Returns: flask.Response: list of delivery history records """ upcs = request.args.get('upcs', '').strip().split(',') items = delivery_report.get_delivered_stores_count(upcs) return response.flaskify( response.Response({'items': items}), encoder=handler_util.DatetimeEncoder) @app.route('/delivered_stores_details/', methods=['GET']) @handler_util.validate_header(validators.HEADER_VALIDATOR) def get_delivered_stores_details(upc): """Get delivery history details for a UPC. Args: upc (str): a given UPC Request parameters: store_id (str, optional): filter results to a specific store delivery_info (bool, optional): when true, include delivery_type and delivery_status fields Returns: flask.Response: list of delivery history record """ store_id = request.args.get('store_id') delivery_info = request.args.get('delivery_info', '').lower() == 'true' log_message = ( 'GET /delivered_stores_details/: upc={0}; store_id={1}; delivery_info={2}' ).format(upc, store_id, delivery_info) g.log.info(log_message) items = delivery_report.get_delivered_stores_details( upc, store_id=store_id, delivery_info=delivery_info) return response.flaskify( response.Response({'items': items}), encoder=handler_util.DatetimeEncoder) @app.route('/masters', methods=['POST']) @handler_util.validate_header(validators.HEADER_VALIDATOR) @handler_util.validate_body(validators.RECORDS_VALIDATOR) def post_delivery_history(): """Save delivery history records. Request body: items (json): List of delivery history records to save Returns: flask.Response: number of records created """ records = request.json g.log.info('POST /masters') result = masters.save_delivery_history(records['items']) return response.flaskify(result) @app.errorhandler(Exception) def exception_handler(error): """Handle error when uncaught exceptions. Note: Exception will also be sent to Sentry if config.SENTRY is set. Returns: flask.Response: A 500 response with JSON 'code' & 'message' payload. """ message = ( 'The server encountered an internal error ' 'and was unable to complete your request.') g.log.exception(error) if isinstance(error, HTTPException): return response.flaskify(response.create_error_response( code=error.name, message=error.description, status=error.code )) return response.flaskify(response.create_fatal_response(message)) @app.route('/delivery_history', methods=['POST']) @handler_util.validate_header(validators.OA_USER_HEADER_VALIDATOR) def import_delivery_history(): """Import delivery history.""" data = request.get_json() if delivery_history.import_delivery_history(data): return response.flaskify( response.Response('Delivery history imported successfully.')) return response.flaskify( response.Response('Delivery history failed to import.'))