"""Test for logic application module.""" import uuid from unittest.mock import MagicMock, patch import pytest from owsresponse.response import Response from pythonfeatures.constants import split as split_constants from account.constants.features import FEATURES, THIRD_PARTY_PAYEE_OWNER from account.logic.application import vendor as vendor_app_logic from account.models import ( application as app_model, feature as feature_model, types, vendor as vendor_model, ) @pytest.fixture() def vendor_attributes_fixture() -> dict[str, types.VendorAttributes]: """Fixture for vendor attributes.""" return { '1ee1ebda-42f2-4183-84d2-25df213a7db6': { 'vendor_id': 34536, 'uuid': '1ee1ebda-42f2-4183-84d2-25df213a7db6', 'company_brand': {'id': 4, 'name': 'sme'}, 'migrated_to_abacus': False, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.FILM_RELEASE_BUILDER, FEATURES.ARTIST_BUILDER, FEATURES.MARKETPLACE, FEATURES.ACCOUNTING, FEATURES.VENDOR_IDENTIFIERS, FEATURES.ANALYTICS, FEATURES.ALL_TIME_ACCOUNTING, FEATURES.LOCALIZATIONS, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.FILM_TRANSPARENCY, FEATURES.SOURCE_OF_STREAM, FEATURES.PHYSICAL_UPC_GENERATION, FEATURES.WORKSTATION_PHYSICAL_REPORTING, FEATURES.ADVERTISING_CAMPAIGN_CONTROL, FEATURES.ORCHARD_ADVERTISING, FEATURES.ORCHARD_ADVERTISING_TIER_1, FEATURES.SHOW_GROSS_ACCOUNTING, FEATURES.FACEBOOK_ADVERTISING_BANNER, FEATURES.ORCHARDGO_BANNER, FEATURES.ORCHARDGO_NEW_BANNER, FEATURES.ORCHARDGO_SURVEY_BANNER, FEATURES.WORKSTATION_ANALYTICS_OVERVIEW, ], }, '42d022c2-50e4-4f5c-af30-f10dca6b8a50': { 'vendor_id': 57608, 'uuid': '42d022c2-50e4-4f5c-af30-f10dca6b8a50', 'company_brand': {'id': 5, 'name': 'awal'}, 'migrated_to_abacus': True, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.PHYSICAL_UPC_GENERATION, FEATURES.WORKSTATION_PHYSICAL_REPORTING, ], }, '7a0b3c99-05e3-4ddc-869a-11ceffc78f52': { 'vendor_id': 45068, 'uuid': '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', 'company_brand': {'id': 2, 'name': 'theorchard'}, 'migrated_to_abacus': True, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.ACCOUNTING, FEATURES.MARKETPLACE, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.PHYSICAL_UPC_GENERATION, FEATURES.WORKSTATION_PHYSICAL_REPORTING, ], }, '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e': { 'vendor_id': 24888, 'uuid': '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', 'company_brand': {'id': 2, 'name': 'theorchard'}, 'migrated_to_abacus': False, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.ARTIST_BUILDER, FEATURES.MARKETPLACE, FEATURES.ACCOUNTING, FEATURES.VENDOR_IDENTIFIERS, FEATURES.ANALYTICS, FEATURES.PERFORMANCE_RIGHTS, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.SOURCE_OF_STREAM, FEATURES.WORKSTATION_PHYSICAL_REPORTING, FEATURES.ADVERTISING_CAMPAIGN_CONTROL, FEATURES.ORCHARD_ADVERTISING, FEATURES.ORCHARDGO_BANNER, FEATURES.ORCHARDGO_NEW_BANNER, FEATURES.WORKSTATION_ANALYTICS_OVERVIEW, FEATURES.FANSIFTER, ], }, 'd0dabb7e-709b-46b6-b914-f01185ec2281': { 'vendor_id': 68226, 'uuid': 'd0dabb7e-709b-46b6-b914-f01185ec2281', 'company_brand': {'id': 1, 'name': 'knr'}, 'migrated_to_abacus': True, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.FILM_RELEASE_BUILDER, FEATURES.ARTIST_BUILDER, FEATURES.MARKETPLACE, FEATURES.ACCOUNTING, FEATURES.VENDOR_IDENTIFIERS, FEATURES.ANALYTICS, FEATURES.PERFORMANCE_RIGHTS, FEATURES.ALL_TIME_ACCOUNTING, FEATURES.LOCALIZATIONS, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.FILM_TRANSPARENCY, FEATURES.SOURCE_OF_STREAM, FEATURES.PHYSICAL_UPC_GENERATION, FEATURES.WORKSTATION_PHYSICAL_REPORTING, FEATURES.ADVERTISING_CAMPAIGN_CONTROL, FEATURES.ORCHARD_ADVERTISING, FEATURES.ORCHARD_ADVERTISING_TIER_1, FEATURES.SHOW_GROSS_ACCOUNTING, FEATURES.FACEBOOK_CAMPAIGN_BOOST, FEATURES.FACEBOOK_ADVERTISING_BANNER, FEATURES.ORCHARDGO_BANNER, FEATURES.ORCHARDGO_NEW_BANNER, FEATURES.ORCHARDGO_SURVEY_BANNER, FEATURES.DYI, FEATURES.WORKSTATION_ANALYTICS_OVERVIEW, ], }, 'ty96bb7e-546t-34b8-b914-f01185ec3311': { 'vendor_id': 35467, 'uuid': 'ty96bb7e-546t-34b8-b914-f01185ec3311', 'company_brand': {'id': 1, 'name': 'knr'}, 'features': [ FEATURES.FANSIFTER, ], }, 'yu90bb3f-546t-34b8-b914-sa4585ec7781': { 'vendor_id': 65483, 'uuid': 'yu90bb3f-546t-34b8-b914-sa4585ec7781', 'company_brand': {'id': 1, 'name': 'theorchard'}, 'features': [ FEATURES.ANALYTICS, ], }, 'up7rr4d-546t-34b8-b914-sa4585yu5634': { 'vendor_id': 9403, 'uuid': 'up7rr4d-546t-34b8-b914-sa4585yu5634', 'company_brand': {'id': 1, 'name': 'awal'}, 'features': [ FEATURES.FANSIFTER, FEATURES.FANSIFTER_AD_REPORTING, ], }, 'tre4r4d-546t-34b8-uy67-sa4585io9845': { 'vendor_id': 11111, 'uuid': 'tre4r4d-546t-34b8-uy67-sa4585io9845', 'company_brand': {'id': 1, 'name': 'sme'}, 'features': [ FEATURES.FANSIFTER, FEATURES.FANSIFTER_AD_CAMPAIGN_AUDIENCES, ], }, '90dfrt6-765f-78h7-kl89-sa4585re3434': { 'vendor_id': 89876, 'uuid': '90dfrt6-765f-78h7-kl89-sa4585re3434', 'company_brand': {'id': 1, 'name': 'theorchard'}, 'features': [ FEATURES.FANSIFTER, FEATURES.FANSIFTER_EMAIL_CAMPAIGNS, ], }, '87ghjt6-765f-78h7-kl89-sa4585re5439': { 'vendor_id': 767676, 'uuid': '87ghjt6-765f-78h7-kl89-sa4585re5439', 'company_brand': {'id': 1, 'name': 'awal'}, 'features': [ FEATURES.FANSIFTER, FEATURES.FANSIFTER_SMS_CAMPAIGNS, ], }, '5a97fa88-660a-11ef-abbe-120c1dfc8269': { 'vendor_id': 781872, 'uuid': '5a97fa88-660a-11ef-abbe-120c1dfc8269', 'company_brand': {'id': 10, 'name': 'altafonte'}, 'features': [ FEATURES.AUDIO_RELEASE_BUILDER, FEATURES.MUSIC_VIDEO_RELEASE_BUILDER, FEATURES.MARKETPLACE, FEATURES.PROJECT_MODE, FEATURES.PHYSICAL_PRODUCT_BUILDER, FEATURES.WORKSTATION_PHYSICAL_REPORTING, ], }, 'ff488e1c-497a-40f9-b639-2da554e3ace9': { 'vendor_id': 999001, 'uuid': 'ff488e1c-497a-40f9-b639-2da554e3ace9', 'company_brand': {'id': 2, 'name': 'theorchard'}, 'features': [ FEATURES.SONGWHIP, FEATURES.AUDIO_RELEASE_BUILDER, ], }, '3a3e3e3e-3333-3333-3333-333333333333': { 'vendor_id': 888888, 'uuid': '3a3e3e3e-3333-3333-3333-333333333333', 'company_brand': {'id': 5, 'name': 'awal'}, 'migrated_to_abacus': True, 'owner': THIRD_PARTY_PAYEE_OWNER, 'features': [ FEATURES.ACCOUNTING, FEATURES.ANALYTICS, ], }, '4b4e4e4e-4444-4444-4444-444444444444': { 'vendor_id': 777777, 'uuid': '4b4e4e4e-4444-4444-4444-444444444444', 'company_brand': {'id': 5, 'name': 'awal'}, 'migrated_to_abacus': True, 'owner': THIRD_PARTY_PAYEE_OWNER, 'features': [FEATURES.ANALYTICS], }, } @patch('account.logic.application.vendor.get_insights_app_for_vendor') @patch('account.logic.application.vendor.get_ws_analytics_app_for_vendor') @patch('account.logic.application.vendor.get_ws_catalog_app_for_vendor') @patch('account.logic.application.vendor.get_customer_accounting_app_for_vendor') @patch('account.logic.application.vendor.get_collaborators_app_for_vendor') @patch('account.logic.application.vendor.get_banking_and_tax_app_for_vendor') @patch('account.logic.application.vendor.get_ws_marketing_app_for_vendor') @patch('account.logic.application.vendor.get_fansifter_app_for_vendor') @patch('account.logic.application.vendor.get_songwhip_app_for_vendor') @patch('account.logic.application.vendor.get_settings_app_for_vendor') def test_generate_vendor_app_check_map( mock_get_settings_app_for_vendor, mock_get_songwhip_app_for_vendor, mock_get_fansifter_app_for_vendor, mock_get_ws_marketing_app_for_vendor, mock_get_banking_and_tax_app_for_vendor, mock_get_collaborators_app_for_vendor, mock_get_customer_accounting_app_for_vendor, mock_get_ws_catalog_app_for_vendor, mock_get_ws_analytics_app_for_vendor, mock_get_insights_app_for_vendor, vendor_attributes_fixture, ): """Test generate_vendor_app_check_map.""" vendor_attributes = vendor_attributes_fixture['9cb8ec76-d1d2-4d42-a3ab-942967b34f4e'] app_check_map = vendor_app_logic.generate_vendor_app_check_map(vendor_attributes) # Ensure the map is a dictionary assert isinstance(app_check_map, dict) # Ensure the length of the map matches the length of ENABLED_APPLICATIONS assert len(app_check_map) == len(vendor_app_logic.ENABLED_APPLICATIONS) for app_id in vendor_app_logic.ENABLED_APPLICATIONS: assert app_id in app_check_map assert callable(app_check_map[app_id]) # Call the function and verify the correct mocked function is called app_check_map[app_id]() # Verify the correct function is called based on the app_id if app_id == app_model.WORKSTATION_CATALOG_APP: mock_get_ws_catalog_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.WORKSTATION_ANALYTICS_APP: mock_get_ws_analytics_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.INSIGHTS_APP: mock_get_insights_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.CUSTOMER_ACCOUNTING_APP: mock_get_customer_accounting_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.COLLABORATORS_APP: mock_get_collaborators_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.BANKING_TAX_APP: mock_get_banking_and_tax_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.WORKSTATION_MARKETING_APP: mock_get_ws_marketing_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.FANSIFTER_APP: mock_get_fansifter_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.SONGWHIP_APP: mock_get_songwhip_app_for_vendor.assert_called_with(vendor_attributes) elif app_id == app_model.SETTINGS_APP: mock_get_settings_app_for_vendor.assert_called_with(vendor_attributes) @pytest.mark.parametrize( 'vendor_uuid, expected_applications', [ pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', [ { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.theorchard.com', }, { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', ], 'url': 'https://fansifter.theorchard.com', }, { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.theorchard.com', }, { 'application_id': 'WORKSTATION_ANALYTICS_APP', 'roles': ['WORKSTATION_ANALYTICS_BASE_ROLE'], 'url': 'https://workstation.theorchard.com/analytics', }, { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.theorchard.com/catalog', }, { 'application_id': 'WORKSTATION_MARKETING_APP', 'roles': ['WORKSTATION_MARKETING_ROLE', 'WORKSTATION_ADVERTISING_ROLE'], 'url': 'https://workstation.theorchard.com/marketing2', }, { 'application_id': 'SETTINGS_APP', 'roles': ['SETTINGS_BASE_ROLE', 'WORKSTATION_ADMIN_ROLE'], 'url': 'https://settings.theorchard.com', }, ], id='theorchard', ), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', [ { 'application_id': 'BANKING_TAX_APP', 'roles': ['BANKING_TAX_BASE_ROLE'], 'url': 'https://documents.awal.com', }, { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.awal.com', }, { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.awal.com', }, { 'application_id': 'INSIGHTS_APP', 'roles': [ 'INSIGHTS_BASE_ROLE', ], 'url': 'https://insights.awal.com', }, { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.awal.com/catalog', }, { 'application_id': 'SETTINGS_APP', 'roles': ['SETTINGS_BASE_ROLE', 'WORKSTATION_ADMIN_ROLE'], 'url': 'https://settings.awal.com', }, ], id='awal', ), pytest.param( 'd0dabb7e-709b-46b6-b914-f01185ec2281', [ { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.kollectivenr.com', }, { 'application_id': 'SETTINGS_APP', 'roles': ['SETTINGS_BASE_ROLE'], 'url': 'https://settings.kollectivenr.com', }, ], id='knr', ), pytest.param( '3a3e3e3e-3333-3333-3333-333333333333', [ { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.awal.com', }, { 'application_id': 'BANKING_TAX_APP', 'roles': ['BANKING_TAX_BASE_ROLE'], 'url': 'https://documents.awal.com', }, ], id='3rd_party_payee_with_accounting', ), pytest.param( '4b4e4e4e-4444-4444-4444-444444444444', [], id='3rd_party_payee_without_accounting', ), ], ) @patch('account.logic.application.vendor.pythonfeatures.get_single_feature') @patch('account.logic.application.vendor.g') def test_get_enabled_vendor_applications_existing_vendor( mock_g, mock_get_single_feature, vendor_attributes_fixture, vendor_uuid, expected_applications, app_context, ): """Test get_enabled_vendor_applications for existing vendor.""" # Setup mocks for songwhip feature flag (control by default in these tests) mock_g.request_context = MagicMock() mock_response = MagicMock(message='control') mock_get_single_feature.return_value = mock_response applications = vendor_app_logic.get_enabled_vendor_applications( vendor_attributes_fixture[vendor_uuid] ) assert applications == expected_applications def test_get_vendor_applications_existing_vendor(monkeypatch, app_context): """Test get_vendor_applications for existing vendor.""" monkeypatch.setattr( vendor_model, 'lookup_vendor_and_company_brand_by_uuid', MagicMock( return_value=( { 'vendor_id': 45068, 'uuid': '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', 'migrated_to_abacus': True, }, {'id': 2, 'name': 'theorchard'}, ) ), ) monkeypatch.setattr( feature_model, 'get_enabled_features_for_vendor_with_session', MagicMock( return_value=[ {'feature_id': 1, 'feature_name': 'Audio Release Builder'}, {'feature_id': 2, 'feature_name': 'Music Video Release Builder'}, {'feature_id': 5, 'feature_name': 'Marketplace'}, {'feature_id': 6, 'feature_name': 'Accounting'}, {'feature_id': 13, 'feature_name': 'Project Mode'}, {'feature_id': 14, 'feature_name': 'Physical Product Builder'}, {'feature_id': 18, 'feature_name': 'Physical UPC Generation'}, {'feature_id': 19, 'feature_name': 'Workstation Physical Reporting'}, ] ), ) # Mock songwhip feature flag as disabled mock_response = MagicMock(message='control') monkeypatch.setattr( 'account.logic.application.vendor.pythonfeatures.get_single_feature', MagicMock(return_value=mock_response), ) monkeypatch.setattr( 'account.logic.application.vendor.g', MagicMock(request_context=MagicMock()), ) response = vendor_app_logic.get_vendor_applications('7a0b3c99-05e3-4ddc-869a-11ceffc78f52') assert isinstance(response, Response) assert response.status == 200 assert response.message == { 'applications': [ { 'application_id': 'BANKING_TAX_APP', 'roles': ['BANKING_TAX_BASE_ROLE'], 'url': 'https://documents.theorchard.com', }, { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.theorchard.com', }, { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.theorchard.com', }, { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.theorchard.com', }, { 'application_id': 'WORKSTATION_ANALYTICS_APP', 'roles': ['WORKSTATION_ANALYTICS_BASE_ROLE'], 'url': 'https://workstation.theorchard.com/analytics', }, { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.theorchard.com/catalog', }, { 'application_id': 'WORKSTATION_MARKETING_APP', 'roles': ['WORKSTATION_MARKETING_ROLE'], 'url': 'https://workstation.theorchard.com/marketing2', }, { 'application_id': 'SETTINGS_APP', 'roles': ['SETTINGS_BASE_ROLE', 'WORKSTATION_ADMIN_ROLE'], 'url': 'https://settings.theorchard.com', }, ] } def test_get_vendor_applications_non_existing_vendor(monkeypatch): """Test get_vendor_applications for non-existing vendor.""" monkeypatch.setattr( vendor_model, 'lookup_vendor_and_company_brand_by_uuid', MagicMock(return_value=None), ) response = vendor_app_logic.get_vendor_applications('bogus-uuid') assert isinstance(response, Response) assert response.status == 404 assert response.errors['message'] == 'Vendor not found' assert response.errors['code'] == 'not_found_error' @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.sonymusic.com', }, id='Sony Music', ), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.awal.com', }, id='AWAL', ), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.theorchard.com', }, id='The Orchard 1', ), pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', { 'application_id': 'INSIGHTS_APP', 'roles': ['INSIGHTS_BASE_ROLE'], 'url': 'https://insights.theorchard.com', }, id='The Orchard 2', ), pytest.param('d0dabb7e-709b-46b6-b914-f01185ec2281', None, id='KNR'), ], ) def test_get_insights_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_insights_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_insights_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', None, id='Sony Music', ), pytest.param('42d022c2-50e4-4f5c-af30-f10dca6b8a50', None, id='AWAL'), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'WORKSTATION_ANALYTICS_APP', 'roles': ['WORKSTATION_ANALYTICS_BASE_ROLE'], 'url': 'https://workstation.theorchard.com/analytics', }, id='The Orchard 1', ), pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', { 'application_id': 'WORKSTATION_ANALYTICS_APP', 'roles': ['WORKSTATION_ANALYTICS_BASE_ROLE'], 'url': 'https://workstation.theorchard.com/analytics', }, id='The Orchard 2', ), pytest.param('d0dabb7e-709b-46b6-b914-f01185ec2281', None, id='KNR'), pytest.param( '5a97fa88-660a-11ef-abbe-120c1dfc8269', { 'application_id': 'WORKSTATION_ANALYTICS_APP', 'roles': ['WORKSTATION_ANALYTICS_BASE_ROLE'], 'url': 'https://workstation.theorchard.com/analytics', }, id='Altafonte', ), ], ) def test_get_ws_analytics_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_ws_analytics_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_ws_analytics_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.sonymusic.com/catalog', }, id='Sony Music', ), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.awal.com/catalog', }, id='AWAL', ), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.theorchard.com/catalog', }, id='The Orchard 1', ), pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', { 'application_id': 'WORKSTATION_CATALOG_APP', 'roles': ['WORKSTATION_CATALOG_ROLE'], 'url': 'https://workstation.theorchard.com/catalog', }, id='The Orchard 2', ), pytest.param('d0dabb7e-709b-46b6-b914-f01185ec2281', None, id='KNR'), ], ) def test_get_ws_catalog_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_ws_catalog_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_ws_catalog_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', None, id='Sony Music', ), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.awal.com', }, id='AWAL', ), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.theorchard.com', }, id='The Orchard Migrated To Abacus', ), pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', None, id='The Orchard Not Migrated To Abacus', ), pytest.param( 'd0dabb7e-709b-46b6-b914-f01185ec2281', { 'application_id': 'CUSTOMER_ACCOUNTING_APP', 'roles': ['CUSTOMER_ACCOUNTING_BASE_ROLE'], 'url': 'https://accounting.kollectivenr.com', }, id='KNR', ), ], ) def test_get_customer_accounting_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_customer_accounting_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_customer_accounting_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.sonymusic.com', }, id='Sony Music', ), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.awal.com', }, id='AWAL', ), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.theorchard.com', }, id='The Orchard 1', ), pytest.param( '9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.theorchard.com', }, id='The Orchard 2', ), ], ) def test_get_collaborators_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_collaborators_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_collaborators_app_for_vendor(vendor_attributes) assert result == expected def test_get_collaborators_app_for_altafonte_vendor(): """Test get_collaborators_app_for_vendor for Altafonte vendor.""" vendor_attributes = { 'vendor_id': 12345, 'uuid': '12345-1234-1234-1234-1234567890ab', 'company_brand': {'id': 10, 'name': 'altafonte'}, 'migrated_to_abacus': True, # It doesn't have the FEATURES.ACCOUNTING feature but still gets the app 'features': [], } result = vendor_app_logic.get_collaborators_app_for_vendor(vendor_attributes) assert result == { 'application_id': 'COLLABORATORS_APP', 'roles': ['COLLABORATORS_BASE_ROLE'], 'url': 'https://collaborators.theorchard.com', } @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param('1ee1ebda-42f2-4183-84d2-25df213a7db6', None, id='Sony Music'), pytest.param( '42d022c2-50e4-4f5c-af30-f10dca6b8a50', { 'application_id': 'BANKING_TAX_APP', 'roles': ['BANKING_TAX_BASE_ROLE'], 'url': 'https://documents.awal.com', }, id='AWAL', ), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'BANKING_TAX_APP', 'roles': ['BANKING_TAX_BASE_ROLE'], 'url': 'https://documents.theorchard.com', }, id='The Orchard 1', ), pytest.param('9cb8ec76-d1d2-4d42-a3ab-942967b34f4e', None, id='The Orchard 2'), ], ) def test_get_banking_and_tax_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_banking_and_tax_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_banking_and_tax_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', { 'application_id': 'WORKSTATION_MARKETING_APP', 'roles': ['WORKSTATION_MARKETING_ROLE', 'WORKSTATION_ADVERTISING_ROLE'], 'url': 'https://workstation.sonymusic.com/marketing2', }, id='Sony Music', ), pytest.param('42d022c2-50e4-4f5c-af30-f10dca6b8a50', None, id='AWAL'), pytest.param( '7a0b3c99-05e3-4ddc-869a-11ceffc78f52', { 'application_id': 'WORKSTATION_MARKETING_APP', 'roles': ['WORKSTATION_MARKETING_ROLE'], 'url': 'https://workstation.theorchard.com/marketing2', }, id='The Orchard 1', ), pytest.param('d0dabb7e-709b-46b6-b914-f01185ec2281', None, id='KNR'), ], ) def test_get_ws_marketing_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_ws_marketing_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_ws_marketing_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, expected', [ pytest.param( 'ty96bb7e-546t-34b8-b914-f01185ec3311', { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', ], 'url': 'https://fansifter.kollectivenr.com', }, id='Only FANSIFTER feature', ), pytest.param( 'yu90bb3f-546t-34b8-b914-sa4585ec7781', None, id='No Fansifter associated features', ), pytest.param( 'up7rr4d-546t-34b8-b914-sa4585yu5634', { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', 'fansifter_can_create_ad_reports', ], 'url': 'https://fansifter.awal.com', }, id='FANSIFTER and FANSIFTER_AD_REPORTING features', ), pytest.param( 'tre4r4d-546t-34b8-uy67-sa4585io9845', { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', 'fansifter_can_share_ad_campaign_audiences', 'fansifter_can_connect_ad_accounts', ], 'url': 'https://fansifter.sonymusic.com', }, id='FANSIFTER and FANSIFTER_AD_CAMPAIGN_AUDIENCES features', ), pytest.param( '90dfrt6-765f-78h7-kl89-sa4585re3434', { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', 'fansifter_can_view_email_campaigns', 'fansifter_can_create_email_campaigns', ], 'url': 'https://fansifter.theorchard.com', }, id='FANSIFTER and FANSIFTER_EMAIL_CAMPAIGNS features', ), pytest.param( '87ghjt6-765f-78h7-kl89-sa4585re5439', { 'application_id': 'FANSIFTER_APP', 'roles': [ 'fansifter_can_view_fan_data', 'fansifter_can_view_sms_campaigns', 'fansifter_can_create_sms_campaigns', ], 'url': 'https://fansifter.awal.com', }, id='FANSIFTER and FANSIFTER_SMS_CAMPAIGNS features', ), ], ) def test_get_fansifter_app_for_vendor( vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, expected: types.TenantApplication | None, ): """Test get_fansifter_app_for_vendor.""" vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_fansifter_app_for_vendor(vendor_attributes) assert result == expected @pytest.mark.parametrize( 'vendor_uuid, feature_flag_enabled, expected', [ pytest.param( 'ff488e1c-497a-40f9-b639-2da554e3ace9', True, { 'application_id': 'SONGWHIP_APP', 'roles': ['songwhip_read'], 'url': 'https://songwhip.com', }, id='Feature flag enabled and SONGWHIP feature present', ), pytest.param( 'ff488e1c-497a-40f9-b639-2da554e3ace9', False, None, id='Feature flag disabled and SONGWHIP feature present', ), pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', True, None, id='Feature flag enabled but SONGWHIP feature absent', ), pytest.param( '1ee1ebda-42f2-4183-84d2-25df213a7db6', False, None, id='Feature flag disabled and SONGWHIP feature absent', ), ], ) @patch('account.logic.application.vendor.pythonfeatures.get_single_feature') @patch('account.logic.application.vendor.g') def test_get_songwhip_app_for_vendor( mock_g: MagicMock, mock_get_single_feature: MagicMock, vendor_attributes_fixture: dict[str, types.VendorAttributes], vendor_uuid: str, feature_flag_enabled: bool, expected: types.TenantApplication | None, app_context, ): """Test get_songwhip_app_for_vendor with different feature flag and feature combinations.""" # Setup mocks mock_g.request_context = MagicMock() mock_response = MagicMock() mock_response.message = split_constants.FEATURE_ENABLED if feature_flag_enabled else 'control' mock_get_single_feature.return_value = mock_response vendor_attributes = vendor_attributes_fixture[vendor_uuid] result = vendor_app_logic.get_songwhip_app_for_vendor(vendor_attributes) assert result == expected mock_get_single_feature.assert_called_once() @patch('account.models.vendor.lookup_vendors_and_company_brands_by_uuids') @patch('account.models.feature.get_enabled_features_for_vendors_with_session') @patch('account.models.feature.convert_features_to_list') @patch('account.logic.application.vendor.get_enabled_vendor_applications') def test_get_bulk_vendor_applications_success( mock_get_enabled_vendor_applications: MagicMock, mock_convert_features_to_list: MagicMock, mock_get_enabled_features_for_vendors_with_session: MagicMock, mock_lookup_vendors_and_company_brands_by_uuids: MagicMock, ) -> None: """Test get_bulk_vendor_applications with successful results.""" vendor_uuids = [ uuid.UUID('12345678-1234-1234-1234-123456789abc'), uuid.UUID('87654321-4321-4321-4321-cba987654321'), ] vendor_data_1 = { 'vendor_id': 123, 'uuid': '12345678-1234-1234-1234-123456789abc', 'migrated_to_abacus': True, } vendor_data_2 = { 'vendor_id': 456, 'uuid': '87654321-4321-4321-4321-cba987654321', 'migrated_to_abacus': True, } company_brand = {'id': 1, 'name': 'theorchard'} features = [FEATURES.ACCOUNTING] applications = [ { 'application_id': app_model.BANKING_TAX_APP, 'roles': [app_model.BANKING_TAX_BASE_ROLE], 'url': 'https://documents.theorchard.com', } ] mock_lookup_vendors_and_company_brands_by_uuids.return_value = { '12345678-1234-1234-1234-123456789abc': (vendor_data_1, company_brand), '87654321-4321-4321-4321-cba987654321': (vendor_data_2, company_brand), } mock_get_enabled_features_for_vendors_with_session.return_value = { 123: features, 456: features, } mock_convert_features_to_list.return_value = features mock_get_enabled_vendor_applications.return_value = applications result = vendor_app_logic.get_bulk_vendor_applications(vendor_uuids) assert 'vendors' in result assert len(result['vendors']) == 2 assert result['vendors'][0]['uuid'] == '12345678-1234-1234-1234-123456789abc' assert result['vendors'][1]['uuid'] == '87654321-4321-4321-4321-cba987654321' assert result['vendors'][0]['applications'] == applications assert result['vendors'][1]['applications'] == applications @patch('account.models.vendor.lookup_vendors_and_company_brands_by_uuids') @patch('account.models.feature.get_enabled_features_for_vendors_with_session') @patch('account.models.feature.convert_features_to_list') @patch('account.logic.application.vendor.get_enabled_vendor_applications') def test_get_bulk_vendor_applications_vendor_not_found( mock_get_enabled_vendor_applications: MagicMock, mock_convert_features_to_list: MagicMock, mock_get_enabled_features_for_vendors_with_session: MagicMock, mock_lookup_vendors_and_company_brands_by_uuids: MagicMock, ) -> None: """Test get_bulk_vendor_applications when vendor is not found.""" vendor_uuids = [ uuid.UUID('12345678-1234-1234-1234-123456789abc'), uuid.UUID('87654321-4321-4321-4321-cba987654321'), ] vendor_data = { 'vendor_id': 123, 'uuid': '12345678-1234-1234-1234-123456789abc', 'migrated_to_abacus': True, } company_brand = {'id': 1, 'name': 'theorchard'} features = [FEATURES.ACCOUNTING] applications = [ { 'application_id': app_model.BANKING_TAX_APP, 'roles': [app_model.BANKING_TAX_BASE_ROLE], 'url': 'https://documents.theorchard.com', } ] mock_lookup_vendors_and_company_brands_by_uuids.return_value = { '12345678-1234-1234-1234-123456789abc': (vendor_data, company_brand), } mock_get_enabled_features_for_vendors_with_session.return_value = { 123: features, } mock_convert_features_to_list.return_value = features mock_get_enabled_vendor_applications.return_value = applications result = vendor_app_logic.get_bulk_vendor_applications(vendor_uuids) assert 'vendors' in result assert len(result['vendors']) == 2 assert result['vendors'][0]['uuid'] == '12345678-1234-1234-1234-123456789abc' assert result['vendors'][1] is None @patch('account.models.vendor.lookup_vendors_and_company_brands_by_uuids') @patch('account.models.feature.get_enabled_features_for_vendors_with_session') @patch('account.models.feature.convert_features_to_list') @patch('account.logic.application.vendor.get_enabled_vendor_applications') def test_get_bulk_vendor_applications_features_not_found( mock_get_enabled_vendor_applications: MagicMock, mock_convert_features_to_list: MagicMock, mock_get_enabled_features_for_vendors_with_session: MagicMock, mock_lookup_vendors_and_company_brands_by_uuids: MagicMock, ) -> None: """Test get_bulk_vendor_applications when features are not found for a vendor.""" vendor_uuids = [ uuid.UUID('12345678-1234-1234-1234-123456789abc'), uuid.UUID('87654321-4321-4321-4321-cba987654321'), ] vendor_data_1 = { 'vendor_id': 123, 'uuid': '12345678-1234-1234-1234-123456789abc', 'migrated_to_abacus': True, } vendor_data_2 = { 'vendor_id': 456, 'uuid': '87654321-4321-4321-4321-cba987654321', 'migrated_to_abacus': True, } company_brand = {'id': 1, 'name': 'theorchard'} features = [FEATURES.ACCOUNTING] applications = [ { 'application_id': app_model.BANKING_TAX_APP, 'roles': [app_model.BANKING_TAX_BASE_ROLE], 'url': 'https://documents.theorchard.com', } ] # vendor 1 has features, vendor 2 doesn't mock_lookup_vendors_and_company_brands_by_uuids.return_value = { '12345678-1234-1234-1234-123456789abc': (vendor_data_1, company_brand), '87654321-4321-4321-4321-cba987654321': (vendor_data_2, company_brand), } mock_get_enabled_features_for_vendors_with_session.return_value = { 123: features, 456: None, # No features for vendor 2 } mock_convert_features_to_list.return_value = features mock_get_enabled_vendor_applications.return_value = applications result = vendor_app_logic.get_bulk_vendor_applications(vendor_uuids) assert 'vendors' in result assert len(result['vendors']) == 2 assert result['vendors'][0]['uuid'] == '12345678-1234-1234-1234-123456789abc' assert result['vendors'][1] is None # Should be None when features are None @patch('account.models.vendor.lookup_vendors_and_company_brands_by_uuids') @patch('account.models.feature.get_enabled_features_for_vendors_with_session') @patch('account.logic.application.vendor.pythonfeatures.get_single_feature') @patch('account.logic.application.vendor.g') def test_get_bulk_vendor_applications_mixed_scenarios( mock_g: MagicMock, mock_get_single_feature: MagicMock, mock_get_enabled_features_for_vendors_with_session: MagicMock, mock_lookup_vendors_and_company_brands_by_uuids: MagicMock, app_context, ) -> None: """Test get_bulk_vendor_applications with mixed scenarios.""" # Setup mocks for songwhip feature flag mock_g.request_context = MagicMock() mock_response = MagicMock(message='control') mock_get_single_feature.return_value = mock_response vendor_uuids = [ uuid.UUID('12345678-1234-1234-1234-123456789abc'), uuid.UUID('87654321-4321-4321-4321-cba987654321'), uuid.UUID('11111111-2222-3333-4444-555555555555'), ] vendor_data_1 = { 'vendor_id': 123, 'uuid': '12345678-1234-1234-1234-123456789abc', 'migrated_to_abacus': True, } vendor_data_3 = { 'vendor_id': 789, 'uuid': '11111111-2222-3333-4444-555555555555', 'migrated_to_abacus': True, } company_brand = {'id': 1, 'name': 'theorchard'} features = [{'feature_id': 6, 'feature_name': 'Accounting'}] mock_lookup_vendors_and_company_brands_by_uuids.return_value = { '12345678-1234-1234-1234-123456789abc': (vendor_data_1, company_brand), '11111111-2222-3333-4444-555555555555': (vendor_data_3, company_brand), } mock_get_enabled_features_for_vendors_with_session.return_value = { 123: features, 789: None, # No features for vendor 3 } result = vendor_app_logic.get_bulk_vendor_applications(vendor_uuids) assert 'vendors' in result assert len(result['vendors']) == 3 # Find the valid uuid in the response valid_entry = next( ( item for item in result['vendors'] if item and item['uuid'] == '12345678-1234-1234-1234-123456789abc' ), None, ) assert valid_entry is not None assert 'applications' in valid_entry # Count None entries for not found and no features none_count = sum(1 for item in result['vendors'] if item is None) assert none_count == 2