diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 39a1956bb..c4395685b 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -21,8 +21,14 @@ class HubspotDealDiffer: "tenant refusal", "not viable", ] - ABRI_CONDITION_ASSOCIATED_PROJECT_ID = "123456" - ABRI_CONDITION_PROJECT_CODE = "Abri Condition" + # Verified against the portal (2026-07-07): Abri stock-condition deals + # carry no project association, so the project_code match is the branch + # that fires in production; the id below is the project object id + # embedded at the end of that code, kept for when associations appear. + ABRI_CONDITION_ASSOCIATED_PROJECT_ID = "1247536318670" + ABRI_CONDITION_PROJECT_CODE = ( + "[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]" + ) @staticmethod def check_for_db_update_trigger( diff --git a/etl/hubspot/tests/test_abri_flow_triggers.py b/etl/hubspot/tests/test_abri_flow_triggers.py index 63dbee4f9..9c7291562 100644 --- a/etl/hubspot/tests/test_abri_flow_triggers.py +++ b/etl/hubspot/tests/test_abri_flow_triggers.py @@ -7,6 +7,10 @@ from etl.hubspot.abri_flow_triggers import build_abri_trigger_message BASE_TIME = datetime(2025, 12, 1, 12, 0, 0) +ABRI_PROJECT_CODE = ( + "[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]" +) + DEAL_ID = "9876543210" LISTING = {"listing_id": "55", "owner_property_id": "1007165", "national_uprn": "1"} @@ -26,7 +30,7 @@ def make_new_deal(**overrides: str) -> Dict[str, str]: return { "hs_object_id": DEAL_ID, "dealname": "49 Admers Crescent", - "project_code": "Abri Condition", + "project_code": ABRI_PROJECT_CODE, **overrides, } @@ -39,7 +43,7 @@ def make_new_deal(**overrides: str) -> Dict[str, str]: def test_a_first_confirmed_survey_date_builds_a_log_job_message() -> None: # Arrange old_deal = make_old_deal( - project_code="Abri Condition", confirmed_survey_date=None + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None ) new_deal = make_new_deal( confirmed_survey_date="2026-06-24", confirmed_survey_time="14:30" @@ -68,7 +72,7 @@ def test_a_first_confirmed_survey_date_builds_a_log_job_message() -> None: def test_a_changed_confirmed_survey_date_builds_an_amend_job_message() -> None: # Arrange old_deal = make_old_deal( - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 6, 18, tzinfo=timezone.utc), ) new_deal = make_new_deal( @@ -93,7 +97,7 @@ def test_a_changed_confirmed_survey_date_builds_an_amend_job_message() -> None: def test_a_first_expected_commencement_date_builds_a_tenant_sync_message() -> None: # Arrange old_deal = make_old_deal( - project_code="Abri Condition", expected_commencement_date=None + project_code=ABRI_PROJECT_CODE, expected_commencement_date=None ) new_deal = make_new_deal(expected_commencement_date="2026-07-01") @@ -120,7 +124,7 @@ def test_a_first_expected_commencement_date_builds_a_tenant_sync_message() -> No def test_several_flows_firing_in_one_scrape_share_one_message() -> None: # Arrange: date changed and commencement date first set together. old_deal = make_old_deal( - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 6, 18, tzinfo=timezone.utc), expected_commencement_date=None, ) @@ -151,7 +155,7 @@ def test_several_flows_firing_in_one_scrape_share_one_message() -> None: def test_no_message_when_no_abri_trigger_fires() -> None: # Arrange: something changed, but nothing Abri cares about. - old_deal = make_old_deal(project_code="Abri Condition", outcome=None) + old_deal = make_old_deal(project_code=ABRI_PROJECT_CODE, outcome=None) new_deal = make_new_deal(outcome="left voicemail") # Act @@ -191,7 +195,7 @@ def test_abandonment_alone_stays_unwired_and_builds_no_message() -> None: # Arrange: the abandonment predicate would fire, but CancelJob does not # exist yet, so no flow may be dispatched for it. old_deal = make_old_deal( - project_code="Abri Condition", number_of_attempts="2", outcome=None + project_code=ABRI_PROJECT_CODE, number_of_attempts="2", outcome=None ) new_deal = make_new_deal(number_of_attempts="3", outcome="no answer") @@ -217,7 +221,7 @@ def test_a_missing_listing_still_builds_the_message_without_a_place_ref() -> Non # Arrange: validation in the abri lambda is the visibility surface for # a fired flow that lacks its place_ref; the scraper still sends. old_deal = make_old_deal( - project_code="Abri Condition", confirmed_survey_date=None + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None ) new_deal = make_new_deal(confirmed_survey_date="2026-06-24") diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index 12cb39425..71d5892ea 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -11,6 +11,10 @@ from etl.hubspot.project_data import ProjectData BASE_TIME = datetime(2025, 12, 1, 12, 0, 0) +ABRI_PROJECT_CODE = ( + "[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]" +) + def make_old_deal(**overrides: Any) -> HubspotDealData: return HubspotDealData( @@ -355,12 +359,12 @@ def test_abri_job_logging__date_first_set_on_abri_deal__returns_true() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", ) @@ -381,12 +385,12 @@ def test_abri_job_logging__date_already_set__returns_false() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 7, 1, tzinfo=timezone.utc), ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", ) @@ -433,12 +437,12 @@ def test_abri_job_logging__project_code_cased_differently__returns_true() -> Non # Arrange old_deal = make_old_deal( id=deal_id, - project_code="ABRI CONDITION", + project_code=ABRI_PROJECT_CODE.upper(), confirmed_survey_date=None, ) new_deal = make_new_deal( deal_id, - project_code="ABRI CONDITION", + project_code=ABRI_PROJECT_CODE.upper(), confirmed_survey_date="2026-07-15", ) @@ -498,12 +502,12 @@ def test_abri_job_logging__no_parseable_new_date__returns_false( # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, **new_overrides, ) @@ -556,12 +560,12 @@ def test_abri_job_logging__non_abri_project_id_with_abri_code__returns_false() - # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", ) new_project = ProjectData(project_id="999999", name="Southern Retrofit") @@ -588,12 +592,12 @@ def test_abri_job_amendment__date_changed_on_abri_deal__returns_true() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 7, 1, tzinfo=timezone.utc), ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", ) @@ -640,13 +644,13 @@ def test_abri_job_amendment__date_and_time_unchanged__returns_false() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 7, 15, tzinfo=timezone.utc), confirmed_survey_time="09:30", ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", confirmed_survey_time="09:30", ) @@ -668,13 +672,13 @@ def test_abri_job_amendment__time_changed_on_abri_deal__returns_true() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=datetime(2026, 7, 15, tzinfo=timezone.utc), confirmed_survey_time="09:30", ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", confirmed_survey_time="14:00", ) @@ -696,12 +700,12 @@ def test_abri_job_amendment__date_first_set_on_abri_deal__returns_false() -> Non # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-07-15", ) @@ -729,12 +733,12 @@ def test_abri_tenant_data_fetch__commencement_date_first_set_on_abri_deal__retur # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date="2026-08-01", ) @@ -781,12 +785,12 @@ def test_abri_tenant_data_fetch__commencement_date_already_set__returns_false() # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date=datetime(2026, 7, 1, tzinfo=timezone.utc), ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date="2026-08-01", ) @@ -817,12 +821,12 @@ def test_abri_tenant_data_fetch__no_parseable_new_commencement_date__returns_fal # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, **new_overrides, ) @@ -875,12 +879,12 @@ def test_abri_tenant_data_fetch__non_abri_project_id_with_abri_code__returns_fal # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, expected_commencement_date="2026-08-01", ) new_project = ProjectData(project_id="999999", name="Southern Retrofit") @@ -909,12 +913,12 @@ def test_abri_deal_abandonment__third_attempt_with_negative_outcome__returns_tru # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, outcome=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, number_of_attempts="3", outcome="No Answer", ) @@ -974,12 +978,12 @@ def test_abri_deal_abandonment__fewer_than_three_parseable_attempts__returns_fal # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, outcome=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, outcome="No Answer", **new_overrides, ) @@ -1011,12 +1015,12 @@ def test_abri_deal_abandonment__outcome_not_negative__returns_false( # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, outcome=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, number_of_attempts="3", **new_overrides, ) @@ -1051,12 +1055,12 @@ def test_abri_deal_abandonment__each_negative_outcome__returns_true( # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, outcome=None, ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, number_of_attempts="3", outcome=outcome, ) @@ -1078,13 +1082,13 @@ def test_abri_deal_abandonment__deal_already_abandoned__returns_false() -> None: # Arrange old_deal = make_old_deal( id=deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, number_of_attempts="3", outcome="No Answer", ) new_deal = make_new_deal( deal_id, - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, number_of_attempts="4", outcome="No Answer", ) diff --git a/etl/hubspot/tests/test_scraper_handler.py b/etl/hubspot/tests/test_scraper_handler.py index 33452bccf..9963aa0e1 100644 --- a/etl/hubspot/tests/test_scraper_handler.py +++ b/etl/hubspot/tests/test_scraper_handler.py @@ -13,6 +13,9 @@ PASHUB_LINK = "https://pashub.example.com/deal/999" MAGICPLAN_QUEUE_URL = "https://sqs.eu-west-2.amazonaws.com/123/magic-plan-dev" PASHUB_QUEUE_URL = "https://sqs.test/pashub" ABRI_QUEUE_URL = "https://sqs.test/abri" +ABRI_PROJECT_CODE = ( + "[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]" +) PROJECT = {"project_id": "proj-1", "name": "Project One"} @@ -239,10 +242,10 @@ def test_existing_deal_pashub_link_unchanged__no_pashub_sqs() -> None: def test_existing_abri_deal_first_survey_date__sends_abri_sqs() -> None: # Arrange db_deal = make_db_deal( - project_code="Abri Condition", confirmed_survey_date=None + project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None ) hubspot_deal = make_hubspot_deal( - project_code="Abri Condition", + project_code=ABRI_PROJECT_CODE, confirmed_survey_date="2026-06-24", confirmed_survey_time="14:30", )