"""Revenue utility functions tests.""" from copy import deepcopy from decimal import Decimal from unittest.mock import patch from pytest import fixture from api.utils import revenue def transaction_types(): """Patch.dict override spec. This is the unit test TX id mapping.""" return { 1: 'foo', 2: 'bar', 3: 'baz', 41: 'transactional_theatrical'} @fixture def breakdown(): """Initial breakdown data.""" return { 'actuals': { 'transactional': Decimal(10), 'movies': Decimal(10), 'transactional_theatrical': None}, 'projected': { 'transactional': Decimal(20), 'movies': Decimal(11), 'transactional_theatrical': Decimal(15)}} @fixture def actuals(): """Raw actuals for breakdowns (date omitted because it's not used).""" return [ {'transaction_type_id': 1, 'amount': Decimal(10), 'store_id': 11}, {'transaction_type_id': 9, 'amount': Decimal(30), 'store_id': 11}, {'transaction_type_id': 11, 'amount': Decimal(30), 'store_id': 12}, {'transaction_type_id': 14, 'amount': Decimal(40), 'store_id': 18}, {'transaction_type_id': 41, 'amount': None, 'store_id': 11}] @fixture def projected(): """Raw projections for breakdowns (date omitted because it's not used).""" return [ {'transaction_type_id': 1, 'amount': Decimal(15), 'store_id': 12}, {'transaction_type_id': 2, 'amount': Decimal(65), 'store_id': 11}, {'transaction_type_id': 9, 'amount': Decimal(35), 'store_id': 13}, {'transaction_type_id': 11, 'amount': Decimal(35), 'store_id': 11}, {'transaction_type_id': 41, 'amount': Decimal(15), 'store_id': 13}] @patch.dict( 'api.utils.revenue.BREAKDOWN_TRANSACTION_TYPES', transaction_types(), clear=True) @patch('api.utils.revenue.get_store_name_by_id') @patch('api.utils.revenue.store_slug') def test_transactional_group_breakdown( store_slug, get_store_name_by_id, breakdown, actuals, projected): """Test transactional breakdown logic function.""" term_licenses_labels = {} get_store_name_by_id.return_value = ('Netflix',) store_slug.return_value = 'term_license_netflix' expected = { 'actuals': { 'foo': Decimal(10), 'bar': Decimal(0), 'movies': Decimal(10), 'transactional_theatrical': Decimal(0), 'term_license_netflix': Decimal(40)}, 'projected': { 'foo': Decimal(25), 'bar': Decimal(65), 'movies': Decimal(11), 'transactional_theatrical': Decimal(15), 'term_license_netflix': None}} results, term_licenses_labels = revenue.transactional_group_breakdown( breakdown, actuals, projected, term_licenses_labels) assert results == expected assert term_licenses_labels == { 'term_license_netflix': 'Term License - Netflix'} @patch.dict( 'api.utils.revenue.BREAKDOWN_TRANSACTION_TYPES', transaction_types(), clear=True) @patch('api.utils.revenue.get_store_name_by_id') @patch('api.utils.revenue.store_slug') def test_transactional_group_breakdown_zeros( store_slug, get_store_name_by_id, breakdown, actuals, projected): """Test transactional breakdown logic function with zero values.""" term_licenses_labels = {} get_store_name_by_id.return_value = ('Netflix',) store_slug.return_value = 'term_license_netflix' actuals.append({'transaction_type_id': 3, 'amount': Decimal(0)}) projected.append({'transaction_type_id': 3, 'amount': Decimal(0)}) expected = { 'actuals': { 'foo': Decimal(10), 'bar': Decimal(0), 'movies': Decimal(10), 'transactional_theatrical': Decimal(0), 'term_license_netflix': Decimal(40)}, 'projected': { 'foo': Decimal(25), 'bar': Decimal(65), 'movies': Decimal(11), 'transactional_theatrical': Decimal(15), 'term_license_netflix': None}} results, term_licenses_labels = revenue.transactional_group_breakdown( breakdown, actuals, projected, term_licenses_labels) assert results == expected assert term_licenses_labels == { 'term_license_netflix': 'Term License - Netflix'} @patch.dict( 'api.utils.revenue.BREAKDOWN_TRANSACTION_TYPES', transaction_types(), clear=True) @patch('api.utils.revenue.get_store_name_by_id') @patch('api.utils.revenue.store_slug') def test_transactional_group_breakdown_projected_value( store_slug, get_store_name_by_id, breakdown, actuals, projected): """Test transactional breakdown logic function with only projections.""" term_licenses_labels = {} get_store_name_by_id.return_value = ('Netflix',) store_slug.return_value = 'term_license_netflix' actuals.append({'transaction_type_id': 3, 'amount': Decimal(0)}) projected.append({'transaction_type_id': 3, 'amount': Decimal(10)}) expected = { 'actuals': { 'foo': Decimal(10), 'bar': Decimal(0), 'baz': Decimal(0), 'movies': Decimal(10), 'transactional_theatrical': Decimal(0), 'term_license_netflix': Decimal(40)}, 'projected': { 'foo': Decimal(25), 'bar': Decimal(65), 'baz': Decimal(10), 'movies': Decimal(11), 'transactional_theatrical': Decimal(15), 'term_license_netflix': None}} results, term_licenses_labels = revenue.transactional_group_breakdown( breakdown, actuals, projected, term_licenses_labels) assert results == expected assert term_licenses_labels == { 'term_license_netflix': 'Term License - Netflix'} def test_add_to_revenue(digital_revenue_buckets, cable_non_analytics_buckets): """Test add_cable_to_revenue function.""" digital_original = deepcopy(digital_revenue_buckets) cable_original = deepcopy(cable_non_analytics_buckets) expected_raw = digital_original['raw'] + cable_original['raw'] revenue.add_cable_to_revenue( digital_revenue_buckets, cable_non_analytics_buckets) assert digital_revenue_buckets['raw'] == expected_raw assert digital_revenue_buckets['bucket']['theatrical'] == \ digital_original['bucket']['theatrical'] expected_transactional = digital_revenue_buckets['bucket']['transactional'] original_transactional = digital_original['bucket']['transactional'] cable_transactional = cable_original['bucket']['transactional'] for date, amount in expected_transactional.items(): expected_amount = original_transactional.get(date, Decimal(0)) \ + cable_transactional.get(date, Decimal(0)) assert amount == expected_amount def test_get_clear_store_name(): """Test the get_clear_store_name function call.""" labels = ( ('Term License - Netflix', 'Netflix'), ('Term License - Iflix (VHDO)', 'Iflix'), ('Term License - DirecTV (US 4K Channel) (SVOD, Broadcast)', 'DirecTV (US 4K Channel)')) for label, store_name in labels: assert store_name == revenue.get_clear_store_name(label) def test_breakdown_label(): """Test the breakdown_label function call.""" stores = ( ('Netflix', 'Term License - Netflix'), ('Iflix', 'Term License - Iflix'), ('Vooks', 'Term License - Vooks')) for store_name, label in stores: assert label == revenue.breakdown_label(store_name)