"""Tests for physical product logic.""" from datetime import datetime from freezegun import freeze_time from oto import response from ows_product_physical.constant import error from ows_product_physical.constant import field from ows_product_physical.logic import ownership from ows_product_physical.logic import product_physical from ows_product_physical.models import ows_assets from ows_product_physical.models import ows_carveouts from ows_product_physical.models import ows_project from ows_product_physical.models import ows_salesgoals from ows_product_physical.models import persister def mock_sales_goals(mocker, first_week_estimate): """Mock sales goals.""" mocker.patch.object( ows_salesgoals, 'get_goals', return_value=response.Response( status=200, message={ 'sales_goals': {'first_week_estimate': first_week_estimate}, 'target_market_goals': [ { 'country': {'country_id': 2}, 'first_week_estimate': 10000, }, { 'country': {'country_id': 1}, 'first_week_estimate': first_week_estimate, }, ] }), autospec=True) def mock_carveouts_success(mocker): """Mock carveouts success.""" mocker.patch.object( ows_carveouts, 'get_release_carveouts_for_upc', return_value=response.Response( status=200, message={}), autospec=True) def mock_common_dependencies(mocker): """Mocks common dependencies with successful outcomes.""" mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=200), autospec=True) mocker.patch.object( ows_project, 'get_project_by_id', return_value=response.Response( message={'vendor_id': 'ABC123'}, status=200)) mocker.patch.object( persister, 'update_product_status', return_value=response.Response( status=201), autospec=True) mocker.patch.object( ows_assets, 'get_artwork_asset', return_value=response.Response( status=200), autospec=True) def test_update_product_status_product_fetch_fail(mocker): """Test update product status product fetch fail.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.create_error_response( code='whatever', message='whatever', status=404), autospec=True) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=200), autospec=True) mocker.patch.object( ows_project, 'get_project_by_id', return_value=response.Response( message={'vendor_id': 'ABC123'}, status=200)) mocker.patch.object( persister, 'update_product_status', return_value=response.Response( status=201), autospec=True) result = product_physical.update_product_status(1234, {}, None, None) assert result.status == 404 assert persister.get_product_by_id.called assert not ownership.check_project_ownership.called assert not ows_project.get_project_by_id.called assert not persister.update_product_status.called def test_update_product_status_ownership_fail(mocker): """Test update product status ownership fail.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'upc': 1234}), autospec=True) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.create_error_response( code='whatever', message='whatever', status=403), autospec=True) mocker.patch.object( ows_project, 'get_project_by_id', return_value=response.Response( message={'vendor_id': 'ABC123'}, status=200)) mocker.patch.object( persister, 'update_product_status', return_value=response.Response( status=201), autospec=True) result = product_physical.update_product_status(1234, {}, None, None) assert result.status == 403 assert persister.get_product_by_id.called assert ownership.check_project_ownership.called assert not ows_project.get_project_by_id.called assert not persister.update_product_status.called def test_update_product_status_project_fetch_fail(mocker): """Test update product status project fetch fail.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'display_upc': '012'}), autospec=True) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=200), autospec=True) mocker.patch.object( ows_project, 'get_project_by_id', return_value=response.create_error_response( code='whatever', message='whatever', status=404), autospec=True) mocker.patch.object( persister, 'update_product_status', return_value=response.Response( status=201), autospec=True) result = product_physical.update_product_status(1234, {}, None, None) assert result.status == 404 assert persister.get_product_by_id.called assert ownership.check_project_ownership.called assert ows_project.get_project_by_id.called assert not persister.update_product_status.called def test_update_product_status_fails_without_upc__display_upc_enabled(mocker): """Test product status update returns an error if upc is missing.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234}), autospec=True) mocker.spy(persister, 'update_product_status') update_status_response = product_physical.update_product_status( 1234, {}, None, None) assert update_status_response.status == 400 assert update_status_response.errors assert not persister.update_product_status.called def test_update_product_status_failure_when_based_off_supply_chain_date( mocker, feature_engine): """Test product status update returns 400 when sale date is invalid.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'sale_start_date': '2017-10-26', 'discount': 'power', 'display_upc': '012'})) mock_common_dependencies(mocker) mock_carveouts_success(mocker) mock_sales_goals(mocker, 1000) mocker.spy(product_physical, '_validate_sale_start_date') with freeze_time(datetime(2017, 8, 28)): update_status_response = product_physical.update_product_status( 1234, {}, None, None) assert product_physical._validate_sale_start_date.called assert update_status_response.status == 400 error_code = update_status_response.errors.get('code') error_message = update_status_response.errors.get('message') assert field.SALE_START_DATE in error_message assert error_code == 'release_status_sale_start_date_us_error' def test_update_product_status_failure_when_based_off_supply_chain_discount( mocker): """Test product status update returns 400 when sale date is invalid.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'sale_start_date': '2017-10-26', 'display_upc': '012'})) mock_common_dependencies(mocker) mock_carveouts_success(mocker) update_status_response = product_physical.update_product_status( 1234, {}, None, None) assert update_status_response.status == 400 error_code = update_status_response.errors.get('code') error_message = update_status_response.errors.get('message') assert error_code == error.DISCOUNT_ERROR assert error_message.get('discount') == \ 'When in the US supply chain you must supply the discount policy.' def test_update_product_status_failure_when_based_off_supply_chain_first_week( mocker, feature_engine): """Test product status update returns 400 when sale date is invalid.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'sale_start_date': '2017-10-26', 'discount': 'power', 'display_upc': '012'})) mock_common_dependencies(mocker) mock_sales_goals(mocker, 0) mock_carveouts_success(mocker) update_status_response = product_physical.update_product_status( 1234, {}, None, None) assert update_status_response.status == 400 error_code = update_status_response.errors.get('code') error_message = update_status_response.errors.get('message') assert error_code == error.FIRST_WEEK_ESTIMATE_ERROR assert error_message.get('first_week_sale_estimate') == \ 'When in the US supply chain you must supply the first week estimate.' def test_update_product_status_when_supply_chain_first_week_territory( mocker): """Test product status update returns 400 when sale date is invalid.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'sale_start_date': '2017-10-26', 'discount': 'power', 'display_upc': '012'})) mock_common_dependencies(mocker) mock_sales_goals(mocker, 0) mock_carveouts_success(mocker) update_status_response = product_physical.update_product_status( 1234, {}, None, None) assert update_status_response.status == 400 error_code = update_status_response.errors.get('code') error_message = update_status_response.errors.get('message') assert error_code == error.FIRST_WEEK_ESTIMATE_ERROR assert error_message.get('first_week_sale_estimate') == \ 'When in the US supply chain you must supply the first week estimate.' def test_update_product_status_japan_distribution(mocker): """Test product status update when distributing in japan only.""" mocker.patch.object( persister, 'get_product_by_id', return_value=response.Response( message={'product_id': 1234, 'sale_start_date': '2017-10-26', 'discount': 'power', 'display_upc': '012', 'japan_distribution': 'yes_only'})) mocker.patch.object( product_physical, '_validate_sale_start_date', return_value=True) mock_common_dependencies(mocker) mock_sales_goals(mocker, 0) mock_carveouts_success(mocker) update_status_response = product_physical.update_product_status( 1234, {}, None, None) persister.update_product_status.assert_called_once() assert update_status_response.status == 201