"""Test for scheduled product updates CRUD operations.""" from datetime import date, datetime import pytest from oto import status as http_status from sqlalchemy.exc import SQLAlchemyError from tests.unit.testutils import db from timed_release.connectors.sql import db_session from timed_release.constants.error import ERROR_MESSAGE_SCHEDULE_NOT_FOUND from timed_release.models import scheduled_update @db.test_schema def test_upsert_updates(): """Test that existing records are updated.""" update = db.insert_scheduled_update_data()[0] product_id = update['product_id'] orchard_identity_id = '03e83149-3c7f-4587-940b-ce83dec34bc8' data = { 'delivery_store_ids': [268], 'schedule_datetime': '2023-02-11T00:00:00.000Z', 'process_at_datetime': '2023-02-10T23:00:00Z', 'schedule_time_offset': '01:00', 'update': { 'sale_start_date': '2023-03-03' } } result = scheduled_update.upsert(product_id, data, orchard_identity_id) assert result.message == { 'product_id': product_id, 'schedule_datetime': '2023-02-11T00:00:00Z', 'schedule_time_offset': '01:00', 'process_at_datetime': '2023-02-10T23:00:00Z', 'delivery_store_ids': [268], 'scheduled_by': '03e83149-3c7f-4587-940b-ce83dec34bc8', 'source': 'oa', 'update': { 'sale_start_date': '2023-03-03' }, 'user_timezone': 'america/new_york' } assert result.status == 200 @db.test_schema def test_upsert_inserts(): """Test that non-existing records are inserted.""" product_id = 456 orchard_identity_id = '03e83149-3c7f-4587-940b-ce83dec34bc8' data = { 'delivery_store_ids': [268], 'schedule_datetime': '2023-02-11T00:00:00.000Z', 'process_at_datetime': '2023-02-10T23:00:00Z', 'schedule_time_offset': '01:00', 'update': { 'sale_start_date': '2023-03-03' } } result = scheduled_update.upsert(product_id, data, orchard_identity_id) assert result.message == { 'product_id': product_id, 'schedule_datetime': '2023-02-11T00:00:00Z', 'schedule_time_offset': '01:00', 'process_at_datetime': '2023-02-10T23:00:00Z', 'delivery_store_ids': [268], 'scheduled_by': '03e83149-3c7f-4587-940b-ce83dec34bc8', 'source': 'oa', 'update': { 'sale_start_date': '2023-03-03' }, 'user_timezone': None } assert result.status == 201 @db.test_schema def test_delete(): """Test that deletes are deleted.""" update = db.insert_scheduled_update_data()[0] product_id = update['product_id'] with db_session() as session: scheduled_update.delete(product_id) assert scheduled_update._get(product_id, session=session) is None @db.test_schema def test_get_scheduled_update(): """Test that get returns scheduled updates data.""" product_id = 123 db.insert_scheduled_update_data() result = scheduled_update.get(product_id) assert result.message == { 'product_id': product_id, 'schedule_datetime': '2023-03-02T00:00:00Z', 'schedule_time_offset': '00:00', 'process_at_datetime': '2023-03-02T00:00:00Z', 'delivery_store_ids': [1, 2, 3], 'scheduled_by': 'b211c821-8b5f-40bd-91a6-d139fb9a95f6', 'source': 'oa', 'update': { 'sale_start_date': '2023-03-03' }, 'user_timezone': 'america/new_york' } assert result.status == 200 @db.test_schema def test_get_scheduled_update_not_found(): """Test that get returns 404 with error message.""" product_id = 100 db.insert_scheduled_update_data() result = scheduled_update.get(product_id) assert result.status == 404 assert result.message == \ ERROR_MESSAGE_SCHEDULE_NOT_FOUND.format(product_id) @db.test_schema def test_get_unsupported_stores_timed_release_ws_success(): """Test to get timed release data by product id success.""" product_id = 124 expected_data = { 'sales_date_time': '2025-09-24T00:00:00Z', 'user_timezone': 'UTC' } db.insert_scheduled_update_data() with db_session() as session: get_response = ( scheduled_update.get_unsupported_stores_timed_release_ws( product_id, session) ) assert get_response.status == http_status.OK assert get_response.message == expected_data @db.test_schema def test_get_unsupported_stores_timed_release_ws_not_found(): """Test to get timed release data by product id not found.""" product_id = 123 db.insert_scheduled_update_data() with db_session() as session: get_response = ( scheduled_update.get_unsupported_stores_timed_release_ws( product_id, session) ) assert get_response.status == http_status.NOT_FOUND @pytest.mark.parametrize( 'product_id, expected', [ (123, True), (124, False) ] ) @db.test_schema def test_check_if_unsupported_stores_schedule_oa_exists(product_id, expected): """Test check_if_unsupported_stores_schedule_oa_exists.""" db.insert_scheduled_update_data() with db_session() as session: result = ( scheduled_update.check_if_unsupported_stores_schedule_oa_exists( product_id, session ) ) assert result is expected @pytest.mark.parametrize( 'product_id, expect_error', [ # 1: Existing unsupported store update (124, False), # 2: New unsupported store insert (125, False) ] ) @db.test_schema def test_upsert_unsupported_stores_schedule_ws_success( product_id, expect_error, mocker, db_session_fixture, unsupported_stores_schedule_data_fixture ): """Parametrized test for upserting WS set unsupported stores schedule.""" db.insert_scheduled_update_data() with db_session() as session: upsert_response = ( scheduled_update.upsert_unsupported_stores_schedule_ws( product_id=product_id, data=unsupported_stores_schedule_data_fixture, identity_id='user-123', session=session ) ) assert upsert_response.status == http_status.OK assert upsert_response.message == { 'unsupported_releases': { 'product_id': product_id, 'schedule_datetime': '2028-08-08T10:00:00Z', 'schedule_time_offset': '00:30', 'process_at_datetime': '2028-08-08T09:30:00Z', 'delivery_store_ids': [1, 2, 5, 6, 9], 'scheduled_by': 'user-123', 'update': {'sale_start_date': '2028-08-08'}, 'source': 'workstation', 'user_timezone': None } } @db.test_schema def test_upsert_unsupported_stores_schedule_ws_db_failure( monkeypatch, db_session_fixture, unsupported_stores_schedule_data_fixture ): """Test upsert WS set unsupported store schedule db failure.""" db.insert_scheduled_update_data() session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') upsert_response = scheduled_update.upsert_unsupported_stores_schedule_ws( product_id=13, data=unsupported_stores_schedule_data_fixture, identity_id='user-123', session=session ) assert upsert_response.status == http_status.INTERNAL_ERROR @pytest.mark.parametrize( 'product_id, store_id, expected_status, expected_data', [ # 1: Success for OA set schedule ( 125, 4, http_status.OK, { 'timed': { 'sales_date_time': '2035-03-04T00:00:00Z' }, 'staggered': None } ), # 2: Success for workstation set schedule ( 126, 8, http_status.OK, { 'timed': { 'sales_date_time': '2035-09-26T18:00:00Z' }, 'staggered': None } ), # 3: Schedule NOT_FOUND (123, 5, http_status.NOT_FOUND, None), # 4: Current date past event schedule datetime, # one day earlier sales_date_time after adjustment ( 123, 1, http_status.OK, { 'timed': { 'sales_date_time': '2023-03-01T12:00:00Z' }, 'staggered': None } ), # 5: Current date past event schedule datetime, # same sales_date_time after adjustment ( 126, 7, http_status.OK, { 'timed': { 'sales_date_time': '2035-09-26T18:00:00Z' }, 'staggered': None } ) ] ) @db.test_schema def test_get_product_scheduled_update_by_store_id( product_id, store_id, expected_status, expected_data, mocker, db_session_fixture ): """Test for get_product_scheduled_update_by_store_id.""" db.insert_scheduled_update_data() with db_session() as session: get_schedule_response = ( scheduled_update.get_product_scheduled_update_by_store_id( product_id=product_id, store_id=store_id, session=session ) ) assert get_schedule_response.status == expected_status if expected_data: assert get_schedule_response.message == expected_data @db.test_schema def test_get_product_scheduled_update_by_store_id_db_failure( monkeypatch, db_session_fixture, unsupported_stores_schedule_data_fixture ): """Test get_product_scheduled_update_by_store_id db failure.""" db.insert_scheduled_update_data() session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') get_schedule_response = ( scheduled_update.get_product_scheduled_update_by_store_id( product_id=123, store_id=1, session=session ) ) assert get_schedule_response.status == http_status.INTERNAL_ERROR @pytest.mark.parametrize( 'product_id, expected_status', [ # Case 1: Delete scheduled update success (124, http_status.OK), # Case 2: Scheduled update not found (123, http_status.NOT_FOUND), # Case 3: DB error (124, http_status.INTERNAL_ERROR) ] ) @db.test_schema def test_delete_scheduled_update_ws( mocker, product_id, expected_status, db_session_fixture ): """Test delete scheduled update ws all use cases.""" db.insert_scheduled_update_data() if expected_status == http_status.INTERNAL_ERROR: session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') delete_response = scheduled_update.delete_scheduled_update_ws( product_id=product_id, session=session) else: with db_session() as session: delete_response = scheduled_update.delete_scheduled_update_ws( product_id=product_id, session=session) assert delete_response.status == expected_status @pytest.mark.parametrize( 'product_id, expected_status', [ # Case 1: Get scheduled update success (124, http_status.OK), # Case 2: Scheduled update not found (123, http_status.NOT_FOUND), # Case 3: DB error (126, http_status.INTERNAL_ERROR) ] ) @db.test_schema def test_get_scheduled_update_ws( mocker, product_id, expected_status, db_session_fixture ): """Test get scheduled update ws all use cases.""" db.insert_scheduled_update_data() if expected_status == http_status.INTERNAL_ERROR: session = db_session_fixture session.query.side_effect = SQLAlchemyError('DB query failure') get_response = scheduled_update.get_scheduled_update_ws( product_id=product_id, session=session) else: with db_session() as session: get_response = scheduled_update.get_scheduled_update_ws( product_id=product_id, session=session) assert get_response.status == expected_status @db.test_schema def test_add_unsupported_stores_schedule_ws_with_user_timezone(): """Test add unsupported stores schedule ws with user_timezone field.""" data = { 'delivery_store_ids': [187, 286], 'schedule_datetime': datetime(2027, 5, 3, 10, 10, 10), 'process_at_datetime': datetime(2027, 5, 3, 9, 40, 10), 'process_at_offset': '00:30', 'update': {'sale_start_date': date(2027, 5, 3)}, 'user_timezone': 'America/Chicago' } with db_session() as session: result = scheduled_update.add_unsupported_stores_schedule_ws( product_id=200, data=data, identity_id='user-123', session=session ) assert result.status == http_status.OK assert ( result.message['unsupported_releases']['user_timezone'] == 'America/Chicago' ) assert result.message['unsupported_releases']['product_id'] == 200 @db.test_schema def test_update_unsupported_stores_schedule_ws_with_user_timezone(): """Test update unsupported stores schedule ws with user_timezone.""" db.insert_scheduled_update_data() with db_session() as session: existing_schedule = session.query( scheduled_update.ScheduledProductUpdate ).filter_by( product_id=124, source='workstation' ).first() data = { 'delivery_store_ids': [100, 200], 'schedule_datetime': datetime(2028, 6, 4, 12, 0, 0), 'process_at_datetime': datetime(2028, 6, 4, 11, 30, 0), 'process_at_offset': '00:30', 'update': {'sale_start_date': date(2028, 6, 4)}, 'user_timezone': 'Europe/Paris' } result = scheduled_update.update_unsupported_stores_schedule_ws( existing_schedule=existing_schedule, data=data, identity_id='user-456', session=session ) assert result.status == http_status.OK assert ( result.message['unsupported_releases']['user_timezone'] == 'Europe/Paris' ) @db.test_schema def test_upsert_unsupported_stores_schedule_ws_with_user_timezone_new(): """Test upsert creates new schedule with user_timezone.""" data = { 'delivery_store_ids': [150], 'schedule_datetime': datetime(2027, 5, 3, 10, 10, 10), 'process_at_datetime': datetime(2027, 5, 3, 9, 40, 10), 'process_at_offset': '00:30', 'update': {'sale_start_date': date(2027, 5, 3)}, 'user_timezone': 'Australia/Sydney' } with db_session() as session: upsert_response = ( scheduled_update.upsert_unsupported_stores_schedule_ws( product_id=300, data=data, identity_id='user-789', session=session ) ) assert upsert_response.status == http_status.OK assert ( upsert_response.message['unsupported_releases']['user_timezone'] == 'Australia/Sydney' ) assert ( upsert_response.message['unsupported_releases']['product_id'] == 300 )