"""Tests for the create-time reference_sap_profit_center_id resolver. Covers the SINGLE_SUPPLY_CHAIN_COMPANY_CODES dual-path behavior table from ACC-10447. """ from unittest.mock import patch import pytest from marshmallow import ValidationError from abacus_contract.constants import error from abacus_contract.logic import contract as logic from abacus_contract.logic.contract import _resolve_reference_sap_profit_center_id from abacus_contract.models.contract import Contract from abacus_contract.tests.utils.factories import ( ReferenceSapProfitCenterFactory, ReferenceSigningEntityFactory, SigningEntitySapProfitCenterFactory, ) FF_PATH = 'abacus_contract.logic.contract.is_single_supply_chain_company_codes_enabled' @patch(FF_PATH, return_value=False) def test_ff_off_pc_provided_pair_in_junction_returns_pc(_): """FF OFF + PC provided + (SE, PC) in junction → returns the provided PC id.""" se = ReferenceSigningEntityFactory.create() other_pc = ReferenceSapProfitCenterFactory.create() SigningEntitySapProfitCenterFactory.create( reference_signing_entity=se, reference_sap_profit_center=other_pc ) result = _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, other_pc.reference_sap_profit_center_id ) assert result == other_pc.reference_sap_profit_center_id @patch(FF_PATH, return_value=False) def test_ff_off_pc_provided_pair_not_in_junction_raises(_): """FF OFF + PC provided + (SE, PC) NOT in junction → ValidationError.""" se = ReferenceSigningEntityFactory.create() unrelated_pc = ReferenceSapProfitCenterFactory.create() with pytest.raises(ValidationError) as exc_info: _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, unrelated_pc.reference_sap_profit_center_id ) assert str(se.reference_signing_entity_id) in str(exc_info.value) assert str(unrelated_pc.reference_sap_profit_center_id) in str(exc_info.value) @patch(FF_PATH, return_value=False) def test_ff_off_pc_omitted_defaults_to_se_legacy_pc(_): """FF OFF + PC omitted → defaults to the SE's legacy reference_sap_profit_center_id.""" se = ReferenceSigningEntityFactory.create() result = _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, None ) assert result == se.reference_sap_profit_center_id @patch(FF_PATH, return_value=True) def test_ff_on_pc_provided_pair_in_junction_returns_pc(_): """FF ON + PC provided + (SE, PC) in junction → returns the provided PC id.""" se = ReferenceSigningEntityFactory.create() other_pc = ReferenceSapProfitCenterFactory.create() SigningEntitySapProfitCenterFactory.create( reference_signing_entity=se, reference_sap_profit_center=other_pc ) result = _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, other_pc.reference_sap_profit_center_id ) assert result == other_pc.reference_sap_profit_center_id @patch(FF_PATH, return_value=True) def test_ff_on_pc_provided_pair_not_in_junction_raises(_): """FF ON + PC provided + (SE, PC) NOT in junction → ValidationError.""" se = ReferenceSigningEntityFactory.create() unrelated_pc = ReferenceSapProfitCenterFactory.create() with pytest.raises(ValidationError): _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, unrelated_pc.reference_sap_profit_center_id ) @patch(FF_PATH, return_value=True) def test_ff_on_pc_omitted_raises(_): """FF ON + PC omitted → ValidationError (explicit selection required).""" se = ReferenceSigningEntityFactory.create() with pytest.raises(ValidationError) as exc_info: _resolve_reference_sap_profit_center_id(se.reference_signing_entity_id, None) assert error.ERROR_REFERENCE_SAP_PROFIT_CENTER_REQUIRED in str(exc_info.value) @patch(FF_PATH, return_value=False) def test_soft_deleted_junction_row_does_not_satisfy_validation(_): """A soft-deleted (SE, PC) row in the junction must not be treated as authorized.""" se = ReferenceSigningEntityFactory.create(with_junction_row=False) pc = ReferenceSapProfitCenterFactory.create() junction = SigningEntitySapProfitCenterFactory.create( reference_signing_entity=se, reference_sap_profit_center=pc ) junction.deleted_at = junction.last_modified junction.deleted_by = 'test' with pytest.raises(ValidationError): _resolve_reference_sap_profit_center_id( se.reference_signing_entity_id, pc.reference_sap_profit_center_id ) @patch(FF_PATH, return_value=False) def test_ff_off_pc_omitted_se_has_no_junction_row_raises(_): """FF OFF + PC omitted + SE's legacy PC is not in junction → ValidationError. Every contract's (SE, PC) pair must be authorized in the junction, even when defaulting from the legacy SE.PC column. """ se = ReferenceSigningEntityFactory.create(with_junction_row=False) with pytest.raises(ValidationError): _resolve_reference_sap_profit_center_id(se.reference_signing_entity_id, None) # --- End-to-end create_contract tests (no models mock) --- @patch('abacus_contract.logic.contract.emit_contract_event') @patch(FF_PATH, return_value=False) def test_create_contract_ff_off_pc_omitted_persists_se_legacy_pc(_, __): """End-to-end: FF OFF + PC omitted → persisted contract uses SE's legacy PC.""" se = ReferenceSigningEntityFactory.create() result = logic.create_contract( contract_name='ACC-10447 E2E omitted', contract_type='distribution', reference_signing_entity_id=se.reference_signing_entity_id, ) assert result.status == 201 persisted = Contract.query.filter_by(contract_name='ACC-10447 E2E omitted').one() assert persisted.reference_sap_profit_center_id == se.reference_sap_profit_center_id @patch('abacus_contract.logic.contract.emit_contract_event') @patch(FF_PATH, return_value=False) def test_create_contract_ff_off_pc_provided_persists_provided_pc(_, __): """End-to-end: FF OFF + PC provided → persisted contract uses the provided PC.""" se = ReferenceSigningEntityFactory.create() other_pc = ReferenceSapProfitCenterFactory.create() SigningEntitySapProfitCenterFactory.create( reference_signing_entity=se, reference_sap_profit_center=other_pc ) result = logic.create_contract( contract_name='ACC-10447 E2E provided', contract_type='distribution', reference_signing_entity_id=se.reference_signing_entity_id, reference_sap_profit_center_id=other_pc.reference_sap_profit_center_id, ) assert result.status == 201 persisted = Contract.query.filter_by(contract_name='ACC-10447 E2E provided').one() assert ( persisted.reference_sap_profit_center_id == other_pc.reference_sap_profit_center_id )