"""Contract Advance functional tests.""" from abacus_common_logic.utils.dates import safe_format_date from abacus_contract.constants import constants from abacus_contract.constants import error from tests.utils.factories import ContractAdvanceFactory from tests.utils.factories import ContractFactory from tests.utils.factories import ReferencePaymentTypeFactory def test_create_contract_advance(fixture_client): """Test create a contract_advance.""" contract_advance = ContractAdvanceFactory.create() post_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'advance_status': contract_advance.advance_status, 'note': contract_advance.note, 'reference_payment_type_id': None, } res = fixture_client.post('contract/1/advance', json=post_data) assert res.status_code == 201 assert res.json == { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': safe_format_date(contract_advance.milestone_date), 'advance_status': contract_advance.advance_status, 'note': contract_advance.note, 'created_at': safe_format_date(contract_advance.created_at), 'contract_id': contract_advance.contract_id, 'contract_advance_id': 2, 'reference_payment_type_id': None, 'vat_amount': None, 'withholding_tax_amount': None, 'amount_after_withholding_and_vat': None, 'us_source_income_rate': None, 'created_by': contract_advance.created_by } def test_create_contract_advance_payment_enabled(fixture_client): """Test create a contract_advance (payment enabled).""" contract_advance = ContractAdvanceFactory.create() post_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'advance_status': contract_advance.advance_status, 'note': contract_advance.note, 'reference_payment_type_id': None, 'vat_amount': str(contract_advance.vat_amount), 'withholding_tax_amount': str(contract_advance.withholding_tax_amount), 'us_source_income_rate': str(contract_advance.us_source_income_rate), } res = fixture_client.post('contract/1/advance', json=post_data) assert res.status_code == 201 assert res.json == { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': safe_format_date(contract_advance.milestone_date), 'advance_status': contract_advance.advance_status, 'note': contract_advance.note, 'created_at': safe_format_date(contract_advance.created_at), 'contract_id': contract_advance.contract_id, 'contract_advance_id': 2, 'reference_payment_type_id': None, 'vat_amount': str(contract_advance.vat_amount), 'withholding_tax_amount': str(contract_advance.withholding_tax_amount), 'amount_after_withholding_and_vat': str( contract_advance.amount_after_withholding_and_vat ), 'us_source_income_rate': str( contract_advance.us_source_income_rate ), 'created_by': contract_advance.created_by } def test_create_contract_advance_payment_enabled_failure_validation( fixture_client ): """Test validation failure on create a contract_advance (payment enabled).""" contract_advance = ContractAdvanceFactory.create( advance_status=constants.ADVANCE_STATUSES.QUALIFIED ) post_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'advance_status': contract_advance.advance_status, 'note': contract_advance.note, 'reference_payment_type_id': None, } res = fixture_client.post('contract/1/advance', json=post_data) assert res.status_code == 400 assert res.json == { 'code': 'error', 'message': 'Both vat_amount and withholding_tax_amount are required.' } def test_create_contract_advance_default_values(fixture_client): """Test create a contract_advance.""" contract_advance = ContractAdvanceFactory.create() post_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'note': contract_advance.note } res = fixture_client.post('contract/1/advance', json=post_data) assert res.status_code == 201 assert res.json == { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': contract_advance.advance_description, 'milestone': contract_advance.milestone, 'milestone_date': safe_format_date(contract_advance.milestone_date), 'advance_status': constants.ADVANCE_STATUSES.NOT_QUALIFIED, 'note': contract_advance.note, 'created_at': safe_format_date(contract_advance.created_at), 'contract_id': contract_advance.contract_id, 'contract_advance_id': 2, 'reference_payment_type_id': None, 'vat_amount': None, 'withholding_tax_amount': None, 'amount_after_withholding_and_vat': None, 'us_source_income_rate': None, 'created_by': contract_advance.created_by } def test_get_pending_contract_advances(fixture_client): """Test to get a list of pending contract advances.""" contract = ContractFactory.create() pending_contract_advance = ContractAdvanceFactory.create(contract=contract) ContractAdvanceFactory.create( contract=contract, advance_status=constants.ADVANCE_STATUSES.PAID ) contract_id = contract.contract_id status = 'pending' res = fixture_client.get( f'/contract/{contract_id}/advances/{status}/?limit=10&offset=0' ) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'] == [{ 'contract_advance_id': 1, 'milestone_description': 'Milestone Description', 'currency_code': 'USD', 'milestone_date': safe_format_date(pending_contract_advance.milestone_date), 'note': None, 'advance_status': 'not_qualified', 'milestone': 'recoupment', 'advance_description': 'Advance Description', 'reference_payment_type_id': None, 'contract_id': 1, 'created_at': safe_format_date(pending_contract_advance.created_at), 'amount': '100.00', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'created_by': pending_contract_advance.created_by }] def test_get_qualified_contract_advances_by_reference_payment_type(fixture_client): """Test to get a list of pending contract advances.""" reference_payment_type = ReferencePaymentTypeFactory.create() contract = ContractFactory.create() ContractAdvanceFactory.create(contract=contract) contract_advance = ContractAdvanceFactory.create( contract=contract, advance_status=constants.ADVANCE_STATUSES.QUALIFIED, reference_payment_type=reference_payment_type ) contract_id = contract.contract_id reference_payment_type_id = reference_payment_type.reference_payment_type_id status = 'qualified' res = fixture_client.get( f'/contract/{contract_id}/advances/{status}/' f'?limit=10&offset=0' f'&reference_payment_type_id={reference_payment_type_id}' ) assert res.status_code == 200 assert res.json['total_count'] == 1 assert res.json['items'] == [{ 'contract_advance_id': contract_advance.contract_advance_id, 'milestone_description': 'Milestone Description', 'currency_code': 'USD', 'milestone_date': safe_format_date(contract_advance.milestone_date), 'note': None, 'advance_status': 'qualified', 'milestone': 'recoupment', 'advance_description': 'Advance Description', 'reference_payment_type_id': reference_payment_type_id, 'contract_id': 1, 'created_at': safe_format_date(contract_advance.created_at), 'amount': '100.00', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'created_by': contract_advance.created_by }] def test_get_all_contract_advances(fixture_client): """Test to get a list of all contract advances.""" contract = ContractFactory.create() pending_contract_advance = ContractAdvanceFactory.create(contract=contract) paid_contract_advance = ContractAdvanceFactory.create( contract=contract, advance_description='Advance Description', amount=190.90, currency_code='AUD', milestone_description='Milestone Description', milestone_date='2022-09-30', advance_status=constants.ADVANCE_STATUSES.PAID ) contract_id = contract.contract_id res = fixture_client.get( f'/contract/{contract_id}/advances/?limit=10&offset=0' ) assert res.status_code == 200 assert res.json['total_count'] == 2 assert res.json['items'] == [{ 'contract_advance_id': 1, 'milestone_description': 'Milestone Description', 'currency_code': 'USD', 'milestone_date': safe_format_date(pending_contract_advance.milestone_date), 'note': None, 'advance_status': 'not_qualified', 'milestone': 'recoupment', 'advance_description': 'Advance Description', 'reference_payment_type_id': None, 'contract_id': 1, 'created_at': safe_format_date(pending_contract_advance.created_at), 'amount': '100.00', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'created_by': pending_contract_advance.created_by }, { 'contract_advance_id': 2, 'milestone_description': 'Milestone Description', 'currency_code': 'AUD', 'milestone_date': safe_format_date(paid_contract_advance.milestone_date), 'note': None, 'advance_status': 'paid', 'milestone': 'recoupment', 'advance_description': 'Advance Description', 'reference_payment_type_id': None, 'contract_id': 1, 'created_at': safe_format_date(paid_contract_advance.created_at), 'amount': '190.90', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'created_by': paid_contract_advance.created_by }] def test_get_contract_advances_invalid_status(fixture_client): """Test to get a list of contract advances for an invalid status.""" contract = ContractFactory.create() status = 'test' res = fixture_client.get( f'/contract/{contract.contract_id}/advances/{status}/' ) assert res.status_code == 400 assert res.json['message'] == error.ERROR_INVALID_CONTRACT_ADVANCE_STATUS.format( status=', '.join(['pending', 'paid', 'qualified', 'in_review']) ) def test_get_paid_contract_advances(fixture_client, create_mock_paid_advances): """Test to get a list of paid contract advances.""" contract_id = 1 status = 'paid' res = fixture_client.get( f'/contract/{contract_id}/advances/{status}/?limit=10&offset=0' ) items = res.json['items'] assert res.status_code == 200 assert res.json['total_count'] == 2 assert sorted(items, key=lambda x: x['contract_advance_id']) == [ { 'contract_advance_id': 1, 'contract_id': 1, 'statement_period_id': 1, 'amount': '100.00', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'currency_code': 'USD', 'advance_amount_payee_currency': '100.00', 'advance_payee_currency_code': 'USD', 'milestone': 'recoupment', 'advance_status': 'paid', 'advance_description': 'Advance Description', 'milestone_description': 'Milestone Description', 'note': None, 'reference_payment_type_id': None, 'milestone_date': '2022-09-16', 'created_at': items[0]['created_at'], 'date_paid': '2022-09-13', 'created_by': 'default_user_id', }, { 'contract_advance_id': 3, 'contract_id': 1, 'statement_period_id': 1, 'amount': '100.00', 'vat_amount': '20.00', 'withholding_tax_amount': '-10.00', 'amount_after_withholding_and_vat': '110.00', 'us_source_income_rate': '99.000001', 'currency_code': 'USD', 'advance_amount_payee_currency': '101.00', 'advance_payee_currency_code': 'USD', 'milestone': 'recoupment', 'advance_status': 'pending_payment', 'advance_description': 'Advance Description', 'milestone_description': 'Milestone Description', 'note': None, 'reference_payment_type_id': None, 'milestone_date': '2022-09-16', 'created_at': items[0]['created_at'], 'date_paid': '2022-09-13', 'created_by': 'default_user_id', } ] def test_update_contract_advance_payment_enabled(fixture_client): """Test to update a contract_advance record.""" contract_advance = ContractAdvanceFactory() put_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': 'Changed description', 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'advance_status': constants.ADVANCE_STATUSES.QUALIFIED, 'note': contract_advance.note, 'vat_amount': '22.00', 'withholding_tax_amount': '-11.00', 'us_source_income_rate': '99.000001', } res = fixture_client.put( f'/contract-advance/{contract_advance.contract_advance_id}', json=put_data ) assert res.status_code == 200 assert res.json == { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': 'Changed description', 'milestone': contract_advance.milestone, 'milestone_date': safe_format_date(contract_advance.milestone_date), 'advance_status': constants.ADVANCE_STATUSES.QUALIFIED, 'note': contract_advance.note, 'reference_payment_type_id': None, 'created_at': safe_format_date(contract_advance.created_at), 'contract_id': contract_advance.contract_id, 'contract_advance_id': contract_advance.contract_advance_id, 'vat_amount': '22.00', 'withholding_tax_amount': '-11.00', 'amount_after_withholding_and_vat': '111.00', 'us_source_income_rate': '99.000001', 'created_by': contract_advance.created_by } def test_update_contract_advance_payment_enabled_failure_validation( fixture_client ): """Test validation failure on update a contract_advance record.""" contract_advance = ContractAdvanceFactory( vat_amount=None, withholding_tax_amount=None ) put_data = { 'milestone_description': contract_advance.milestone_description, 'amount': str(contract_advance.amount), 'currency_code': contract_advance.currency_code, 'advance_description': 'Changed description', 'milestone': contract_advance.milestone, 'milestone_date': '2022-09-16', 'advance_status': constants.ADVANCE_STATUSES.QUALIFIED, 'note': contract_advance.note } res = fixture_client.put( f'/contract-advance/{contract_advance.contract_advance_id}', json=put_data ) assert res.status_code == 400 assert res.json == { 'code': 'error', 'message': 'Both vat_amount and withholding_tax_amount are required.' } def test_delete_pending_contract_advance(fixture_client): """Test to delete pending contract advance.""" contract = ContractFactory.create() pending_contract_advance = ContractAdvanceFactory.create(contract=contract) contract_advance_id = pending_contract_advance.contract_advance_id res = fixture_client.delete(f'/contract-advance/{contract_advance_id}') assert res.status_code == 204 assert pending_contract_advance.deleted_at assert pending_contract_advance.deleted_by assert pending_contract_advance.advance_status == constants.ADVANCE_STATUSES.DELETED def test_delete_paid_contract_advance(fixture_client): """Test to delete paid contract advance.""" contract = ContractFactory.create() paid_contract_advance = ContractAdvanceFactory.create( contract=contract, advance_status=constants.ADVANCE_STATUSES.PAID ) contract_advance_id = paid_contract_advance.contract_advance_id res = fixture_client.delete(f'/contract-advance/{contract_advance_id}') assert res.status_code == 400 assert res.json['message'] == error.ERROR_CONTRACT_ADVANCE_PAID_DELETE def test_get_contract_advance_by_id(fixture_client): """Test to get a contract advance by specified ID.""" contract = ContractFactory.create() contract_advance = ContractAdvanceFactory.create(contract=contract) res = fixture_client.get( f'/contract-advance/{contract_advance.contract_advance_id}' ) assert res.status_code == 200 assert res.json == { 'contract_advance_id': contract_advance.contract_advance_id, 'milestone_description': contract_advance.milestone_description, 'currency_code': contract_advance.currency_code, 'milestone_date': safe_format_date(contract_advance.milestone_date), 'note': contract_advance.note, 'advance_status': contract_advance.advance_status, 'milestone': contract_advance.milestone, 'advance_description': contract_advance.advance_description, 'contract_id': contract_advance.contract_id, 'created_at': safe_format_date(contract_advance.created_at), 'amount': str(contract_advance.amount), 'reference_payment_type_id': None, 'vat_amount': str(contract_advance.vat_amount), 'withholding_tax_amount': str(contract_advance.withholding_tax_amount), 'amount_after_withholding_and_vat': str( contract_advance.amount_after_withholding_and_vat ), 'us_source_income_rate': str( contract_advance.us_source_income_rate ), 'created_by': contract_advance.created_by }