"""Tests for contract serialization.""" import datetime from decimal import Decimal from abacus_common_logic.utils.dates import safe_format_date, safe_format_datetime import pytest from abacus_contract.constants.constants import \ CONTRACT_LIFECYCLE_SCHEDULE_RENEWAL_TYPES from abacus_contract.constants.error import \ ERROR_CONTRACT_LIFECYCLE_SCHEDULES_LIST_EMPTY from abacus_contract.schemas.contract import ContractAndLifecyclePostSchema from abacus_contract.schemas.contract import ContractDetailSchema from abacus_contract.schemas.contract import ContractPostSchema from abacus_contract.schemas.contract import ContractPutSchema from abacus_contract.schemas.contract import ContractSapFormattedSchema from abacus_contract.schemas.contract import ContractTerminationSchema from abacus_contract.schemas.contract import ContractVatInfoSchema from tests.utils.factories import AccountContractFactory from tests.utils.factories import ContractFactory from tests.utils.factories import ReferenceSapProfitCenterFactory from tests.utils.factories import ReferenceSigningEntityFactory def test_contract_detail_schema(create_mock_account): """Test contract detail serialization.""" contract = ContractFactory.create(term_end=None) AccountContractFactory.create( contract=contract ) result = ContractDetailSchema().dump(contract) assert result == { 'account_id': 1, 'contract_id': contract.contract_id, 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'execution_date': None, 'initial_start_date': '2018-07-28', 'is_excluded_from_accounting_run': False, 'oa_contract_id': None, 'term_end': safe_format_date(contract.term_end), 'term_start': safe_format_date(contract.term_start), 'reference_signing_entity_id': 1, 'sap_created_at': None, 'summary_note': contract.summary_note, 'general_note': contract.general_note } def test_contract_post_schema(): """Test contract post serialization.""" contract = ContractFactory.create(term_end=None, initial_start_date=None) oa_contract_id = 1 contract.oa_contract_id = oa_contract_id result = ContractPostSchema().dump(contract) assert result == { 'contract_id': contract.contract_id, 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'execution_date': None, 'oa_contract_id': oa_contract_id, 'term_end': safe_format_date(contract.term_end), 'term_start': safe_format_date(contract.term_start), 'reference_signing_entity_id': 1, 'summary_note': contract.summary_note, 'general_note': contract.general_note, 'is_excluded_from_accounting_run': False } def test_contract_post_schema_no_term_dates(): """Test contract post serialization.""" contract = ContractFactory.create( term_start=None, term_end=None, initial_start_date=None ) oa_contract_id = 1 contract.oa_contract_id = oa_contract_id result = ContractPostSchema().dump(contract) assert result == { 'contract_id': contract.contract_id, 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'execution_date': None, 'oa_contract_id': oa_contract_id, 'term_end': None, 'term_start': None, 'reference_signing_entity_id': 1, 'summary_note': contract.summary_note, 'general_note': contract.general_note, 'is_excluded_from_accounting_run': False } def test_contract_put_schema(): """Test contract put serialization.""" contract = ContractFactory.create( term_end=None, is_excluded_from_accounting_run=True ) result = ContractPutSchema().dump(contract) assert result == { 'contract_name': contract.contract_name, 'is_excluded_from_accounting_run': True, 'reference_signing_entity_id': 1, 'sap_created_at': None, 'term_end': safe_format_date(contract.term_end), 'term_start': safe_format_date(contract.term_start), 'summary_note': contract.summary_note, 'general_note': contract.general_note, 'execution_date': None, 'initial_start_date': safe_format_date(contract.initial_start_date) } def test_contract_put_schema_with_execution_date(): """Test contract put schema with execution_date.""" mock_put_request = { 'contract_name': 'Test Contract Name', 'is_excluded_from_accounting_run': False, 'execution_date': datetime.date(2024, 8, 27) } result = ContractPutSchema().dump(mock_put_request) assert result == { 'contract_name': mock_put_request['contract_name'], 'is_excluded_from_accounting_run': mock_put_request['is_excluded_from_accounting_run'], 'execution_date': str(mock_put_request['execution_date']) } def test_contract_put_schema_with_initial_start_date(): """Test contract put schema with initial_start_date.""" mock_put_request = { 'contract_name': 'Test Contract Name', 'is_excluded_from_accounting_run': False, 'initial_start_date': datetime.date(2024, 8, 27) } result = ContractPutSchema().dump(mock_put_request) assert result == { 'contract_name': mock_put_request['contract_name'], 'is_excluded_from_accounting_run': mock_put_request['is_excluded_from_accounting_run'], 'initial_start_date': str(mock_put_request['initial_start_date']) } def test_contract_put_termination_schema(): """Test contract put termination.""" termination_data = { 'termination_effective': '2024-08-27', 'termination_notice_received': None } result = ContractTerminationSchema().load(termination_data) assert result == { 'termination_effective': datetime.date(2024, 8, 27), 'termination_notice_received': None } def test_contract_post_schema_with_account_success(): """Test contract post succeeds with account_id.""" contract = ContractFactory.create(summary_note=None, general_note=None) contract_params = { 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'term_end': safe_format_date(contract.term_end), 'term_start': safe_format_date(contract.term_start), 'account_id': 1, 'reference_signing_entity_id': contract.reference_signing_entity_id, } res = ContractPostSchema().load(contract_params) assert res == { 'account_id': contract_params.get('account_id'), 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'reference_signing_entity_id': contract.reference_signing_entity_id, 'term_end': contract.term_end, 'term_start': contract.term_start, } def test_contract_vat_info_list_schema(): """Test contract vat info list serialization.""" vat_info_data = [{ 'account_id': 123, 'contract_id': 123, 'country_of_tax_residence': 'GBR', 'account_is_sba_signed': True, 'client_tax_rate': Decimal('20.00'), 'supplier_tax_rate': None }] result = ContractVatInfoSchema(many=True).dump(vat_info_data) assert result == [{ 'account_id': 123, 'contract_id': 123, 'country_of_tax_residence': 'GBR', 'account_is_sba_signed': True, 'client_tax_rate': '20.00', 'supplier_tax_rate': None }] def test_contract_sap_formatted_schema(create_mock_account): """Test contract schema for SAP api.""" referenceSigningEntity = ReferenceSigningEntityFactory.create(company_code='4444') sapProfileCenter = ReferenceSapProfitCenterFactory.create( company_code=referenceSigningEntity.company_code ) contract = ContractFactory.create( term_start='2025-01-01', term_end='2025-01-01', reference_signing_entity=referenceSigningEntity, ) account_contract = AccountContractFactory.create(contract=contract) mock_sap_schema = { 'account_id': account_contract.account_id, 'contract_id': contract.contract_id, 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'term_end': contract.term_end, 'term_start': contract.term_start, 'Bukrs': sapProfileCenter.company_code, 'Prctr': sapProfileCenter.profit_center, } result = ContractSapFormattedSchema().dump(mock_sap_schema) assert result == { 'AccountId': str(contract.account_id), 'ContractId': str(contract.contract_id), 'ContractName': contract.contract_name, 'ContractType': contract.contract_type, 'DateTo': safe_format_datetime(contract.term_end), 'DateFrm': safe_format_datetime(contract.term_start), 'Bukrs': sapProfileCenter.company_code, 'Prctr': sapProfileCenter.profit_center, 'BusUnit': None, 'Zzfield1': None, 'Zzfield2': None, 'Zzfield3': None, } def test_contract_name_sap_formatted_schema(create_mock_account): """Test contract schema for SAP api with long contract_name.""" referenceSigningEntity = ReferenceSigningEntityFactory.create(company_code='4444') sapProfileCenter = ReferenceSapProfitCenterFactory.create( company_code=referenceSigningEntity.company_code ) contract = ContractFactory.create( term_start='2025-01-01', term_end='2025-01-01', reference_signing_entity=referenceSigningEntity, ) account_contract = AccountContractFactory.create(contract=contract) contract.contract_name = 'AGR503463 - Joel Madden, Benji Madden, Billy Martin, Dean Butterworth and Paul Thomas professionally known as “Good Charlotte” - AWAL Recordings Agreement (Christmas EP)' # noqa: E501 mock_sap_schema = { 'account_id': account_contract.account_id, 'contract_id': contract.contract_id, 'contract_name': contract.contract_name, 'contract_type': contract.contract_type, 'term_end': contract.term_end, 'term_start': contract.term_start, 'Bukrs': sapProfileCenter.company_code, 'Prctr': sapProfileCenter.profit_center, } result = ContractSapFormattedSchema().dump(mock_sap_schema) assert result == { 'AccountId': str(contract.account_id), 'ContractId': str(contract.contract_id), 'ContractName': contract.contract_name[:120], 'ContractType': contract.contract_type, 'DateTo': safe_format_datetime(contract.term_end), 'DateFrm': safe_format_datetime(contract.term_start), 'Bukrs': sapProfileCenter.company_code, 'Prctr': sapProfileCenter.profit_center, 'BusUnit': None, 'Zzfield1': None, 'Zzfield2': None, 'Zzfield3': None, } def test_contract_and_lifecycle_post_request_schema( mock_contract_and_lifecycle_post_payload ): """Test contract, contract_lifecycle and contract_lifecycle_schedule POST schema.""" continuously_active_renewal_type = \ CONTRACT_LIFECYCLE_SCHEDULE_RENEWAL_TYPES.CONTINUOUSLY_ACTIVE reference_signing_entity_id = \ mock_contract_and_lifecycle_post_payload['contract']['reference_signing_entity_id'] # noqa: E501 mock_contract_and_lifecycle_post_payload['contract_lifecycle'] = { 'lifecycle_term_start': datetime.date(2024, 7, 30) } res = ContractAndLifecyclePostSchema().dump( mock_contract_and_lifecycle_post_payload ) assert res == { 'contract': { 'account_id': 1, 'contract_type': 'distribution', 'execution_date': None, 'reference_signing_entity_id': reference_signing_entity_id, 'summary_note': 'This is for the test', 'general_note': 'This is for the test (general_note)', 'contract_name': 'Test Contract', 'oa_contract_id': 1 }, 'contract_lifecycle_schedules': [{ 'renewal_type': continuously_active_renewal_type, 'schedule_end': None, 'termination_notice_detail_interval': 1, 'termination_notice_detail_type': 'month', 'renewal_offset_detail_interval': None, 'renewal_offset_detail_type': None, 'collection_period_detail_interval': None, 'collection_period_detail_type': None, }], 'contract_lifecycle': { 'lifecycle_term_start': '2024-07-30' } } def test_contract_and_lifecycle_post_request_schema_error( mock_contract_and_lifecycle_post_payload ): """Test contract_lifecycle_schedule post schema. throws an error when an empty list passed to the contract_lifecycle_schedules field. """ mock_contract_and_lifecycle_post_payload['contract_lifecycle_schedules'] = [] with pytest.raises(Exception) as excinfo: ContractAndLifecyclePostSchema().load( mock_contract_and_lifecycle_post_payload ) assert excinfo.value.messages == {'_schema': [ ERROR_CONTRACT_LIFECYCLE_SCHEDULES_LIST_EMPTY ]}