"""Logic for Instant Grat.""" import datetime from oto import response from oto import status as response_code from backend.constants import error from backend.models import ows_product_digital from backend.models.instant_grats_persister import InstantGratPersister from backend.models.track_persister import TrackPersister from backend.utils import api as api_utils from backend.utils import grat_utils from backend.utils import logic as logic_utils def _validate_grat_dates(grats_data, product): preorder_date_str = product.get('preorder_date') sale_start_date_str = product.get('sale_start_date') if not preorder_date_str or not sale_start_date_str: return response.create_error_response( code=error.VALIDATION_ERROR_CODE, message=error.VALIDATION_ERROR_IG_PRODUCT_DATES_UNAVAILABLE_MSG) preorder_date = datetime.datetime.strptime(preorder_date_str, '%Y-%m-%d').date() sale_start_date = datetime.datetime.strptime(sale_start_date_str, '%Y-%m-%d').date() for grat in grats_data: ig_date = grat['date'].date() if not (preorder_date <= ig_date < sale_start_date): return response.create_error_response( code=error.VALIDATION_ERROR_CODE, message=error.VALIDATION_ERROR_IG_DATE_OUT_OF_RANGE_MSG) return None @logic_utils.verify_product_ownership def get_all_grats_by_product_id( product_id, account_id=None, account_type=None): """Get all instant grats based on a given product_id. Args: product_id (int): product_id of grats to retrieve. account_id (int): the user account id in the header. account_type (str): the user account type in the header. Returns: Response: A Response obj with grats JSON data. """ tracks_res = TrackPersister.get_all_by_product_id(product_id) tracks = tracks_res.message.get('items', []) tuids = [track['tuid'] for track in tracks] grats_res = InstantGratPersister.fetch_grats_by_list_of_tuids(tuids) if not grats_res: return grats_res formatted_grats = grat_utils.group_grats_by_tuid(grats_res.message) return response.Response({'items': formatted_grats}) @logic_utils.verify_product_ownership def delete_grat_by_store_id( product_id, track_id, store_id, account_id=None, account_type=None): """Delete instant grat based on a product_id, track_id and store_id. Args: product_id (int): The product primary key. track_id (int): The track primary key. store_id (int): The store primary key. account_id (int): the user account id in the header. account_type (str): the user account type in the header. Returns: Response: A Response obj with grats JSON data. """ tracks_res = TrackPersister.get_by_tuid(track_id) if not tracks_res: return tracks_res if tracks_res.message['product_id'] != product_id: return response.create_error_response( code=error.ERROR_MESSAGE_TRACK_NOT_FOUND, message=error.NO_SUCH_TRACKS_IN_PRODUCT_MSG.format(track_id)) return InstantGratPersister.delete_grats_by_track_ids([track_id], store_id) @logic_utils.verify_product_ownership def create_grats_for_product_id( product_id, grats_data, account_id=None, account_type=None, user_type=None, user_id=None): """Create new instant grats for a given product_id by list of grats data. Args: product_id (int): product_id of grats to retrieve. grats_data (dict): new grats data. account_id (int): the user account id in the header. account_type (str): the user account type in the header. user_type (str): type from orchard user id in the header (oa|alw). user_id (str): id from orchard user id in the header. Returns: Response: A Response obj with grats JSON data. """ grats_data = grats_data.get('items') tracks_res = TrackPersister.get_all_by_product_id(product_id) if not tracks_res: return tracks_res existing_tuids = { track['tuid'] for track in tracks_res.message.get('items', [])} provided_tuids = { grat['tuid'] for grat in grats_data} invalid_tuids = provided_tuids - existing_tuids if invalid_tuids: error_tuids = (str(tuid) for tuid in invalid_tuids) return response.create_error_response( code=error.VALIDATION_ERROR_CODE, message=error.NO_SUCH_TRACKS_IN_PRODUCT_MSG.format( ','.join(error_tuids))) product_res = ows_product_digital.get_product_by_product_id(product_id) if not product_res: return product_res date_error = _validate_grat_dates(grats_data, product_res.message) if date_error is not None: return date_error # TODO: Get list of allowed for grats stores from ows-carveouts and # validate list of provided store accordingly. for grat in grats_data: grat['user_id'] = user_id grat['user_type'] = user_type created_grats = InstantGratPersister.bulk_create_grats(grats_data) if not created_grats: return created_grats formatted_items = grat_utils.group_grats_by_tuid( created_grats.message.get('items')) return api_utils.create_get_list_response( formatted_items, status=response_code.CREATED) @logic_utils.verify_product_ownership def delete_all_grats_by_product_id( product_id, account_id=None, account_type=None): """Delete all instant grats based on a given product_id. Args: product_id (int): product_id of grats to delete. account_id (int): the user account id in the header. account_type (str): the user account type in the header. Returns: Response: A Response obj with grats JSON data. """ tracks_res = TrackPersister.get_all_by_product_id(product_id) tuids = [track['tuid'] for track in tracks_res.message.get('items', [])] return InstantGratPersister.delete_grats_by_track_ids(tuids) @logic_utils.verify_product_ownership def update_grats_by_product_id( product_id, grats_data, account_id=None, account_type=None): """Update provided instant grats based on a given product_id. Args: product_id (int): product_id of grats to delete. grats_data (dict): list of updated grats data. account_id (int): the user account id in the header. account_type (str): the user account type in the header. Returns: Response: A Response obj with grats JSON data. """ tracks_res = TrackPersister.get_all_by_product_id(product_id) tuids = [track['tuid'] for track in tracks_res.message.get('items', [])] if not tuids: return response.create_not_found_response( error.ERROR_MESSAGE_TRACK_NOT_FOUND) grats_update_data_list = grats_data.get('items') product_res = ows_product_digital.get_product_by_product_id(product_id) if not product_res: return product_res date_error = _validate_grat_dates(grats_update_data_list, product_res.message) if date_error is not None: return date_error updated_grats = InstantGratPersister.bulk_update_grats( tuids, grats_update_data_list) if not updated_grats: return updated_grats formatted_items = grat_utils.group_grats_by_tuid( updated_grats.message.get('items')) return api_utils.create_get_list_response( formatted_items, status=response_code.OK)