from oto import response from pricing.constants.warning import WARNING_ALBUM_PREORDER_PRICE_SUM_OF_IGS, WARNING_ALBUM_PREORDER_PRICE_SUM_OF_TRACKS from pricing.constants.warning import WARNING_ALBUM_PREORDER_PRICE_SUM_OF_IGS_MESSAGE, WARNING_ALBUM_PREORDER_PRICE_SUM_OF_TRACKS_MESSAGE from pricing.constants.pricing_family import AUDIO_ALBUM_PRICING_FAMILY_ID from pricing.constants.pricing_tier import MID_TIER_TRACK_PRICE_TIER_ID from pricing.models import orchard_pricing_tier_value from pricing.models import ows_track from pricing.models import product_pricing_override from pricing.logic import track_pricing_override def validate_product_by_id(product_id): """Validate a product. Args: product_id (int): the ID of a product. Returns: response.Response: validation warnings or success. """ result = {'valid': True, 'warnings': []} default_album_price_cents = orchard_pricing_tier_value.get_album_price_cents_by_product_id(product_id) default_track_price_cents = orchard_pricing_tier_value.get_track_price_cents_by_product_id(product_id) if default_album_price_cents and default_track_price_cents: product_overrides = product_pricing_override.get_by_product_id(product_id).message.get('items', []) album_overrides = [override for override in product_overrides if override.get('pricing_family_id') == AUDIO_ALBUM_PRICING_FAMILY_ID] album_override_prices_cents = _get_album_override_prices(album_overrides) album_price_cents = _get_highest_album_price(default_album_price_cents, album_override_prices_cents) track_overrides_data = track_pricing_override.get_track_pricing_overrides_for_product(product_id) track_overrides = track_overrides_data.message.get('items', []) number_of_tracks = track_overrides_data.message.get('total_track_count', 0) track_override_prices = _get_track_override_prices(track_overrides) track_override_prices_cents = track_override_prices.values() if not _validate_album_price_is_less_than_sum_of_track_prices( album_price_cents, default_track_price_cents, number_of_tracks, track_override_prices_cents): result['valid'] = False result['warnings'].append({ 'warning_code': WARNING_ALBUM_PREORDER_PRICE_SUM_OF_TRACKS, 'warning_message': WARNING_ALBUM_PREORDER_PRICE_SUM_OF_TRACKS_MESSAGE}) ig_tracks = ows_track.get_ig_tracks_by_product_id(product_id) if ig_tracks.status == 200: ig_tracks_items = ig_tracks.message.get('items', []) ig_track_prices_cents = _get_ig_track_prices(ig_tracks_items, default_track_price_cents, track_override_prices) if not _validate_album_price_is_greater_than_sum_of_ig_tracks( album_price_cents, ig_track_prices_cents): result['valid'] = False result['warnings'].append({ 'warning_code': WARNING_ALBUM_PREORDER_PRICE_SUM_OF_IGS, 'warning_message': WARNING_ALBUM_PREORDER_PRICE_SUM_OF_IGS_MESSAGE}) return response.Response(result) def _validate_album_price_is_less_than_sum_of_track_prices( album_price_cents, regular_track_price_cents, track_count, override_track_prices_cents): """Validate that the album price is strictly lower than the sum of the individual prices of all tracks. Args: album_price_cents (int): the price of the album in cents. regular_track_price_cents (int): the regular price of a track in cents. track_count (int): the number of tracks in the album. override_track_prices_cents (list): list of overridden track prices in cents. """ total_track_price = regular_track_price_cents * track_count for price in override_track_prices_cents: total_track_price += price - regular_track_price_cents if album_price_cents >= total_track_price: return False return True def _validate_album_price_is_greater_than_sum_of_ig_tracks( album_price_cents, ig_track_prices_cents): """Validate that the album price is greater than the sum of the instant grat track prices plus one mid-tier track. Args: album_price_cents (int): the price of the album in cents. ig_track_prices_cents (list): list of instant grat track prices in cents. """ mid_tier_track_price = orchard_pricing_tier_value.get_price_value_by_tier_id( MID_TIER_TRACK_PRICE_TIER_ID) total_ig_track_price_plus_one_mid_tier = sum(ig_track_prices_cents) + mid_tier_track_price if album_price_cents < total_ig_track_price_plus_one_mid_tier: return False return True def _get_album_override_prices(album_overrides): """Get the album override prices in cents. Args: album_overrides (list): list of album overrides. Returns: list: list of album override prices in cents. """ album_override_prices = [] album_override_tier_ids = set() for override in album_overrides: album_override_tier_ids.add(override['orchard_pricing_tier_id']) if album_override_tier_ids: album_override_prices = orchard_pricing_tier_value.get_price_values_by_tier_id( album_override_tier_ids) return album_override_prices def _get_highest_album_price(album_price_cents, album_override_prices_cents): """Get the highest album price in cents. Args: album_price_cents (int): the price of the album in cents. album_override_prices_cents (list): list of album override prices in cents. Returns: int: the highest album price in cents. """ if not album_override_prices_cents: return album_price_cents highest_album_price = max(album_price_cents, max(album_override_prices_cents)) return highest_album_price def _get_track_override_prices(track_overrides): """Get the track override prices in cents. Args: track_overrides (list): list of track overrides. Returns: dict: dict of track override prices in cents and the track tuid. """ track_override_prices = {} for override in track_overrides: track_override_prices[override['track_id']] = \ orchard_pricing_tier_value.get_price_value_by_tier_id( override['orchard_pricing_tier_id']) return track_override_prices def _get_ig_track_prices(ig_tracks, track_default_price_cents, track_override_prices): """Get the prices for any instant grat tracks. Args: ig_tracks (list): list of ig tracks. track_default_price_cents (int): default track price in cents track_override_prices (dict): dict of track override prices Returns: list: list of prices for the ig tracks """ ig_track_prices = [] for track in ig_tracks: price = track_override_prices.get(track['tuid']) ig_track_prices.append(price if price is not None else track_default_price_cents) return ig_track_prices