"""Logic to handle generating a Single Product Overview page.""" from multiprocessing.pool import ThreadPool from oto.response import ( Response, create_error_response, create_not_found_response, ) from reporting.constants import error from reporting.models import ows_permissions, persister from reporting.utils import single_product_overview as utils def _make_request(request_item): """Make a request as part of a multi-thread series of requests. Args: request_item: a dictionary containing a function and parameters. Returns: Result of calling the given function with the given parameters. """ return request_item.get('function_to_call')(*request_item.get('params')) def get_monthly_trend(local_product_cd, territory): """Get monthly trend information for a single product. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. Returns: oto.Response: Monthly sales report data. """ supply_chain_id = utils.territory_to_supply_chain(territory) if not supply_chain_id: return create_not_found_response() return persister.get_physical_product_monthly_trend( local_product_cd, supply_chain_id ) def get_product_overview(local_product_cd, territory): """Get metadata, inventory and rtd information for a single product. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. Returns: oto.Response: Monthly sales report data. """ supply_chain_id = utils.territory_to_supply_chain(territory) if not supply_chain_id: return create_not_found_response() return persister.get_product_overview(local_product_cd, supply_chain_id) def get_overview(local_product_cd, territory): """Get complete product overview. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. Returns: oto.Response: Monthly sales report data. """ params = [local_product_cd, territory] request_list = [ {'function_to_call': get_product_overview, 'params': params}, {'function_to_call': get_monthly_trend, 'params': params}, ] with ThreadPool(len(request_list)) as pool: response_list = pool.map(_make_request, request_list) for response in response_list: if not response: return response final_message = {} for response in response_list: final_message.update(response.message) return Response(message=final_message) def _get_account_by_product(local_product_cd, territory): """Look up the vendor and subaccount that own a product. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. Returns: oto.Response: response with 'vendor_id'/'subaccount_id' in message. """ supply_chain_id = utils.territory_to_supply_chain(territory) if not supply_chain_id: return create_not_found_response() return persister.get_account_by_product(local_product_cd, supply_chain_id) def product_belongs_to_account( local_product_cd, territory, account_type, account_id ): """Check that a vendor has ownership the product. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. account_type (str): account type. account_id (int) Returns: oto.Response: response indicating access to product is authorized. """ account_by_product_info = _get_account_by_product( local_product_cd, territory ) if not account_by_product_info: return account_by_product_info vendor_id = str(account_by_product_info.message.get('vendor_id')) subaccount_id = str(account_by_product_info.message.get('subaccount_id')) if account_type == 'vendor': if not vendor_id == account_id: return create_error_response( error.ERROR_CODE_UNAUTHORIZED, error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) if account_type == 'subaccount': if not subaccount_id == account_id: return create_error_response( error.ERROR_CODE_UNAUTHORIZED, error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) return Response() def product_belongs_to_profile( local_product_cd, territory, profile_type, profile_id ): """Check that a profile has label access to the product's owner. Args: local_product_cd (str): local identifier for a product. ex:'ESO012012' territory (str): territory abbreviation. ex: CA or US. profile_type (str): Orchard profile type, ex: 'Label'. profile_id (str): Orchard profile id. Returns: oto.Response: response indicating access to product is authorized. """ account_by_product_info = _get_account_by_product( local_product_cd, territory ) if not account_by_product_info: return account_by_product_info vendor_id = str(account_by_product_info.message.get('vendor_id')) subaccount_id = str(account_by_product_info.message.get('subaccount_id')) permissions_response = ows_permissions.get_label_resources( profile_type, profile_id ) if not permissions_response: return permissions_response permissions = permissions_response.message if permissions.get('full_access'): return Response() vendor_ids = {str(v) for v in permissions.get('vendor_ids') or []} subaccount_ids = {str(s) for s in permissions.get('subaccount_ids') or []} if vendor_id in vendor_ids or subaccount_id in subaccount_ids: return Response() return create_error_response( error.ERROR_CODE_UNAUTHORIZED, error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, )