from datetime import datetime, timezone from typing import Any, Dict import uuid import pytest from backend.app.db.models.hubspot_deal_data import HubspotDealData from etl.hubspot.hubspot_deal_differ import HubspotDealDiffer BASE_TIME = datetime(2025, 12, 1, 12, 0, 0) def make_old_deal(**overrides: Any) -> HubspotDealData: return HubspotDealData( id=overrides.get("id", uuid.uuid4()), deal_id="1", created_at=BASE_TIME, updated_at=BASE_TIME, **{k: v for k, v in overrides.items() if k != "id"}, ) def make_new_deal(deal_id: uuid.UUID, **overrides: Any) -> Dict[str, str]: return { "id": str(deal_id), "deal_id": "1", "created_at": BASE_TIME.isoformat(), "updated_at": datetime(2025, 12, 1, 12, 30, 0).isoformat(), **overrides, } # ==================== # PASHUB TRIGGER TESTS # ==================== @pytest.mark.parametrize( "new_overrides,expected", [ ({"outcome_notes": "test note"}, False), ], ) def test_pashub_trigger__outcome_note_added__returns_false( new_overrides: Dict[str, str], expected: bool, ) -> None: deal_id = uuid.uuid4() old_deal = make_old_deal(id=deal_id) new_deal = make_new_deal(deal_id, **new_overrides) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) == expected ) @pytest.mark.parametrize( "old_overrides,new_overrides,expected", [ ( {"pashub_link": "www.google.co.uk"}, {"pashub_link": "www.bbc.co.uk"}, True, ), ], ) def test_pashub_trigger__pashub_link_changed__returns_true( old_overrides: Dict[str, str], new_overrides: Dict[str, str], expected: bool, ) -> None: deal_id = uuid.uuid4() old_deal = make_old_deal(id=deal_id, **old_overrides) new_deal = make_new_deal(deal_id, **new_overrides) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) == expected ) @pytest.mark.parametrize( "coordination_status,expected", [ ("(v1) ioe/mtp complete", True), ("(v2) ioe/mtp complete", True), ], ) def test_pashub_trigger__coordination_completed_and_pashub_link_set__returns_true( coordination_status: str, expected: bool, ) -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, pashub_link="www.google.co.uk", coordination_status="random", ) new_deal = make_new_deal( deal_id, pashub_link="www.google.co.uk", **{"coordination_status__stage_1_": coordination_status}, ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) == expected ) def test_pashub_trigger__coordination_completed_and_pashub_link_not_set__returns_false() -> ( None ): deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, coordination_status="random", ) new_deal = make_new_deal( deal_id, coordination_status="v2 ioe/mtp complete", ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) is False ) def test_pashub_trigger__design_completed_and_pashub_link_set__returns_true() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, pashub_link="www.google.co.uk", ) new_deal = make_new_deal( deal_id, pashub_link="www.google.co.uk", retrofit_design_status="uploaded", ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) is True ) def test_pashub_trigger__design_completed_and_pashub_link_not_set__returns_false() -> ( None ): deal_id = uuid.uuid4() old_deal = make_old_deal(id=deal_id) new_deal = make_new_deal( deal_id, retrofit_design_status="uploaded", ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) is False ) @pytest.mark.parametrize( "lodgement_status,expected", [ ("lodgement complete", True), ("measures lodged", True), ], ) def test_pashub_trigger__lodgement_completed_and_pashub_link_set__returns_true( lodgement_status: str, expected: bool, ) -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, pashub_link="www.google.co.uk", ) new_deal = make_new_deal( deal_id, pashub_link="www.google.co.uk", lodgement_status=lodgement_status, ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) == expected ) def test_pashub_trigger__lodgement_completed_and_pashub_link_not_set__returns_false() -> ( None ): deal_id = uuid.uuid4() old_deal = make_old_deal(id=deal_id) new_deal = make_new_deal( deal_id, design_status="lodgement complete", ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) is False ) def test_pashub_trigger__coordination_design_lodgement_not_completed_and_pashub_link_set__returns_false() -> ( None ): deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, pashub_link="www.google.co.uk", ) new_deal = make_new_deal( deal_id, pashub_link="www.google.co.uk", coordination_status="not uploaded", design_status="not uploaded", lodgement_status="not uploaded", ) assert ( HubspotDealDiffer.check_for_pashub_trigger( new_deal=new_deal, old_deal=old_deal, ) is False ) # ========================== # MAGICPLAN TRIGGER TESTS # ========================== def test_magicplan_trigger__outcome_transitions_to_surveyed__returns_true() -> None: deal_id = uuid.uuid4() # Arrange old_deal = make_old_deal(id=deal_id, outcome="assessed") new_deal = make_new_deal(deal_id, outcome="surveyed") # Act result = HubspotDealDiffer.check_for_magicplan_trigger( new_deal=new_deal, old_deal=old_deal, ) # Assert assert result is True def test_magicplan_trigger__outcome_already_surveyed__returns_false() -> None: deal_id = uuid.uuid4() # Arrange old_deal = make_old_deal(id=deal_id, outcome="surveyed") new_deal = make_new_deal(deal_id, outcome="surveyed") # Act result = HubspotDealDiffer.check_for_magicplan_trigger( new_deal=new_deal, old_deal=old_deal, ) # Assert assert result is False def test_magicplan_trigger__outcome_transitions_to_non_surveyed__returns_false() -> None: deal_id = uuid.uuid4() # Arrange old_deal = make_old_deal(id=deal_id, outcome="assessed") new_deal = make_new_deal(deal_id, outcome="assessed") # Act result = HubspotDealDiffer.check_for_magicplan_trigger( new_deal=new_deal, old_deal=old_deal, ) # Assert assert result is False def test_magicplan_trigger__outcome_surveyed_uppercase__returns_true() -> None: deal_id = uuid.uuid4() # Arrange old_deal = make_old_deal(id=deal_id, outcome="assessed") new_deal = make_new_deal(deal_id, outcome="SURVEYED") # Act result = HubspotDealDiffer.check_for_magicplan_trigger( new_deal=new_deal, old_deal=old_deal, ) # Assert assert result is True # ======================= # DB UPDATE TRIGGER TESTS # ======================= def test_db_update_trigger__no_changes__returns_false() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, dealname="Test Deal", dealstage="stage_1", outcome="won", ) new_deal = make_new_deal( deal_id, hs_object_id="1", dealname="Test Deal", dealstage="stage_1", outcome="won", ) result = HubspotDealDiffer.check_for_db_update_trigger( new_deal=new_deal, new_company=None, new_listing=None, old_deal=old_deal, ) assert result is False def test_db_update_trigger__dealname_changed__returns_true() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, dealname="Old Name", ) new_deal = make_new_deal( deal_id, hs_object_id="1", dealname="New Name", ) result = HubspotDealDiffer.check_for_db_update_trigger( new_deal=new_deal, new_company=None, new_listing=None, old_deal=old_deal, ) assert result is True def test_db_update_trigger__company_changed__returns_true() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, company_id="old_company", ) new_deal = make_new_deal( deal_id, hs_object_id="1", ) new_company = "new_company" result = HubspotDealDiffer.check_for_db_update_trigger( new_deal=new_deal, new_company=new_company, new_listing=None, old_deal=old_deal, ) assert result is True def test_db_update_trigger__missing_hubspot_timezone__returns_false() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, design_completion_date=datetime(2025, 11, 3, 0, 0, tzinfo=timezone.utc), ) new_deal = make_new_deal( deal_id, hs_object_id="1", design_completion_date=datetime(2025, 11, 3, 0, 0).isoformat(), ) result = HubspotDealDiffer.check_for_db_update_trigger( new_deal=new_deal, new_company=None, new_listing=None, old_deal=old_deal, ) assert result is False def test_db_update_trigger__listing_changed__returns_true() -> None: deal_id = uuid.uuid4() old_deal = make_old_deal( id=deal_id, listing_id="abc", ) new_deal = make_new_deal( deal_id, hs_object_id="1", ) new_listing = {"listing_id": "xyz"} result = HubspotDealDiffer.check_for_db_update_trigger( new_deal=new_deal, new_company=None, new_listing=new_listing, old_deal=old_deal, ) assert result is True