From bd3c45d81c770943e4f51f31869111b3a2ad6550 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:56:49 +0000 Subject: [PATCH 01/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20fire?= =?UTF-8?q?s=20when=20confirmed=5Fsurvey=5Fdate=20is=20first=20set=20on=20?= =?UTF-8?q?an=20Abri=20Condition=20deal=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 6 ++++ etl/hubspot/tests/test_hubspot_deal_differ.py | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 6d49cf590..ee189bae0 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -170,6 +170,12 @@ class HubspotDealDiffer: return False + @staticmethod + def check_for_abri_survey_creation( + new_deal: Dict[str, str], old_deal: HubspotDealData + ) -> bool: + raise NotImplementedError + @staticmethod def check_for_magicplan_trigger( new_deal: Dict[str, str], old_deal: HubspotDealData diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index 949524243..7ba259cae 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -343,6 +343,36 @@ def test_magicplan_trigger__outcome_surveyed_uppercase__returns_true() -> None: assert result is True +# ================================== +# ABRI SURVEY CREATION TRIGGER TESTS +# ================================== + + +def test_abri_survey_creation__date_first_set_on_abri_deal__returns_true() -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Abri Condition", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="Abri Condition", + confirmed_survey_date="2026-07-15", + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + old_deal=old_deal, + ) + + # Assert + assert result is True + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From 51ac5e2f5ed1748af35d845da271ba4edb782ed0 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:57:26 +0000 Subject: [PATCH 02/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20fire?= =?UTF-8?q?s=20when=20confirmed=5Fsurvey=5Fdate=20is=20first=20set=20on=20?= =?UTF-8?q?an=20Abri=20Condition=20deal=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index ee189bae0..e757c7e59 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -174,7 +174,7 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: - raise NotImplementedError + return True @staticmethod def check_for_magicplan_trigger( From 697df8ade36aac9ccd7f33df5a113358a8357b71 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:58:09 +0000 Subject: [PATCH 03/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20deals=20that=20already=20have=20a=20confirmed=5Fsurvey=5F?= =?UTF-8?q?date=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/tests/test_hubspot_deal_differ.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index 7ba259cae..fcbe80e08 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -373,6 +373,31 @@ def test_abri_survey_creation__date_first_set_on_abri_deal__returns_true() -> No assert result is True +def test_abri_survey_creation__date_already_set__returns_false() -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Abri Condition", + confirmed_survey_date=datetime(2026, 7, 1, tzinfo=timezone.utc), + ) + new_deal = make_new_deal( + deal_id, + project_code="Abri Condition", + confirmed_survey_date="2026-07-15", + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + old_deal=old_deal, + ) + + # Assert + assert result is False + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From fc2ba887597af67c100b4042eb231ca6a61d752a Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:58:41 +0000 Subject: [PATCH 04/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20deals=20that=20already=20have=20a=20confirmed=5Fsurvey=5F?= =?UTF-8?q?date=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index e757c7e59..b4f130f63 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -174,7 +174,7 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: - return True + return old_deal.confirmed_survey_date is None @staticmethod def check_for_magicplan_trigger( From 882eb1eff95a5f962404d119544c037dc54e2cf1 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:59:05 +0000 Subject: [PATCH 05/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20deals=20outside=20the=20Abri=20Condition=20project=20?= =?UTF-8?q?=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/tests/test_hubspot_deal_differ.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index fcbe80e08..e9372bf6b 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -398,6 +398,31 @@ def test_abri_survey_creation__date_already_set__returns_false() -> None: assert result is False +def test_abri_survey_creation__non_abri_project_code__returns_false() -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Southern Retrofit", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="Southern Retrofit", + confirmed_survey_date="2026-07-15", + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + old_deal=old_deal, + ) + + # Assert + assert result is False + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From 97bf001fbfd82be9fdefc1d60a917a94b12b6dce Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 15:59:38 +0000 Subject: [PATCH 06/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20deals=20outside=20the=20Abri=20Condition=20project=20?= =?UTF-8?q?=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index b4f130f63..bacc60459 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -174,6 +174,8 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: + if new_deal.get("project_code") != "Abri Condition": + return False return old_deal.confirmed_survey_date is None @staticmethod From bd0c45aa5718f6015f1cb3db768ff035f2559c94 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:00:09 +0000 Subject: [PATCH 07/16] =?UTF-8?q?Abri=20Condition=20project=20code=20lives?= =?UTF-8?q?=20in=20a=20reusable=20class=20constant=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index bacc60459..b2a9024b2 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -12,6 +12,7 @@ class HubspotDealDiffer: ] RETROFIT_DESIGN_COMPLETE = "uploaded" LODGEMENT_COMPLETE: List[str] = ["lodgement complete", "measures lodged"] + ABRI_CONDITION_PROJECT_CODE = "Abri Condition" @staticmethod def check_for_db_update_trigger( @@ -174,7 +175,10 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: - if new_deal.get("project_code") != "Abri Condition": + if ( + new_deal.get("project_code") + != HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE + ): return False return old_deal.confirmed_survey_date is None From 5b9038ab6116f86b96498411277960929fae22e8 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:01:25 +0000 Subject: [PATCH 08/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20matc?= =?UTF-8?q?hes=20the=20Abri=20Condition=20project=20code=20case-insensitiv?= =?UTF-8?q?ely=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/tests/test_hubspot_deal_differ.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index e9372bf6b..7391706e9 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -423,6 +423,31 @@ def test_abri_survey_creation__non_abri_project_code__returns_false() -> None: assert result is False +def test_abri_survey_creation__project_code_cased_differently__returns_true() -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="ABRI CONDITION", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="ABRI CONDITION", + confirmed_survey_date="2026-07-15", + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + old_deal=old_deal, + ) + + # Assert + assert result is True + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From fb2b7e164c065fa5c6df5f372b4c780831da73b8 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:01:43 +0000 Subject: [PATCH 09/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20matc?= =?UTF-8?q?hes=20the=20Abri=20Condition=20project=20code=20case-insensitiv?= =?UTF-8?q?ely=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index b2a9024b2..29fd15c35 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -175,10 +175,8 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: - if ( - new_deal.get("project_code") - != HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE - ): + new_project_code = (new_deal.get("project_code") or "").lower() + if new_project_code != HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower(): return False return old_deal.confirmed_survey_date is None From c059771af5fe13d508aabc85cdbf2d57a668c648 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:02:08 +0000 Subject: [PATCH 10/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20syncs=20with=20no=20parseable=20confirmed=5Fsurvey=5Fdate?= =?UTF-8?q?=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/tests/test_hubspot_deal_differ.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index 7391706e9..a50634dea 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -448,6 +448,41 @@ def test_abri_survey_creation__project_code_cased_differently__returns_true() -> assert result is True +@pytest.mark.parametrize( + "new_overrides", + [ + {}, + {"confirmed_survey_date": ""}, + {"confirmed_survey_date": "not-a-date"}, + ], +) +def test_abri_survey_creation__no_parseable_new_date__returns_false( + new_overrides: Dict[str, str], +) -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Abri Condition", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="Abri Condition", + **new_overrides, + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + old_deal=old_deal, + ) + + # Assert + assert result is False + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From 7aabfdfa5b4f7fb7a335e67566d497bdfcade61a Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:02:36 +0000 Subject: [PATCH 11/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20igno?= =?UTF-8?q?res=20syncs=20with=20no=20parseable=20confirmed=5Fsurvey=5Fdate?= =?UTF-8?q?=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 29fd15c35..2e963eb54 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -178,7 +178,11 @@ class HubspotDealDiffer: new_project_code = (new_deal.get("project_code") or "").lower() if new_project_code != HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower(): return False - return old_deal.confirmed_survey_date is None + + if old_deal.confirmed_survey_date is not None: + return False + + return parse_hs_date(new_deal.get("confirmed_survey_date")) is not None @staticmethod def check_for_magicplan_trigger( From 592173e1e578aab04d887825bef78fc66b3696dd Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:03:34 +0000 Subject: [PATCH 12/16] =?UTF-8?q?Abri=20Condition=20project=20gate=20is=20?= =?UTF-8?q?a=20reusable=20helper=20for=20future=20Abri=20triggers=20?= =?UTF-8?q?=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 2e963eb54..6fbcf3432 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -175,8 +175,7 @@ class HubspotDealDiffer: def check_for_abri_survey_creation( new_deal: Dict[str, str], old_deal: HubspotDealData ) -> bool: - new_project_code = (new_deal.get("project_code") or "").lower() - if new_project_code != HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower(): + if not HubspotDealDiffer._is_abri_condition_deal(new_deal): return False if old_deal.confirmed_survey_date is not None: @@ -184,6 +183,11 @@ class HubspotDealDiffer: return parse_hs_date(new_deal.get("confirmed_survey_date")) is not None + @staticmethod + def _is_abri_condition_deal(new_deal: Dict[str, str]) -> bool: + new_project_code = (new_deal.get("project_code") or "").lower() + return new_project_code == HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower() + @staticmethod def check_for_magicplan_trigger( new_deal: Dict[str, str], old_deal: HubspotDealData From cc682e3e74b87bce5cd0cfe349acbaf5cddf3e38 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:27:05 +0000 Subject: [PATCH 13/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20reco?= =?UTF-8?q?gnises=20deals=20by=20their=20associated=20Abri=20project=20id?= =?UTF-8?q?=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 12 +++++-- etl/hubspot/tests/test_hubspot_deal_differ.py | 36 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 6fbcf3432..2017487a0 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -1,6 +1,7 @@ from typing import Dict, List, Optional from backend.app.db.models.hubspot_deal_data import HubspotDealData +from etl.hubspot.project_data import ProjectData from etl.hubspot.utils import parse_hs_bool, parse_hs_date @@ -12,6 +13,7 @@ class HubspotDealDiffer: ] RETROFIT_DESIGN_COMPLETE = "uploaded" LODGEMENT_COMPLETE: List[str] = ["lodgement complete", "measures lodged"] + ABRI_CONDITION_ASSOCIATED_PROJECT_ID = "123456" ABRI_CONDITION_PROJECT_CODE = "Abri Condition" @staticmethod @@ -173,9 +175,11 @@ class HubspotDealDiffer: @staticmethod def check_for_abri_survey_creation( - new_deal: Dict[str, str], old_deal: HubspotDealData + new_deal: Dict[str, str], + new_project: Optional[ProjectData], + old_deal: HubspotDealData, ) -> bool: - if not HubspotDealDiffer._is_abri_condition_deal(new_deal): + if not HubspotDealDiffer._is_abri_condition_deal(new_deal, new_project): return False if old_deal.confirmed_survey_date is not None: @@ -184,7 +188,9 @@ class HubspotDealDiffer: return parse_hs_date(new_deal.get("confirmed_survey_date")) is not None @staticmethod - def _is_abri_condition_deal(new_deal: Dict[str, str]) -> bool: + def _is_abri_condition_deal( + new_deal: Dict[str, str], new_project: Optional[ProjectData] + ) -> bool: new_project_code = (new_deal.get("project_code") or "").lower() return new_project_code == HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower() diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index a50634dea..ea0c3679f 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -6,6 +6,7 @@ import pytest from backend.app.db.models.hubspot_deal_data import HubspotDealData from etl.hubspot.hubspot_deal_differ import HubspotDealDiffer +from etl.hubspot.project_data import ProjectData BASE_TIME = datetime(2025, 12, 1, 12, 0, 0) @@ -366,6 +367,7 @@ def test_abri_survey_creation__date_first_set_on_abri_deal__returns_true() -> No # Act result = HubspotDealDiffer.check_for_abri_survey_creation( new_deal=new_deal, + new_project=None, old_deal=old_deal, ) @@ -391,6 +393,7 @@ def test_abri_survey_creation__date_already_set__returns_false() -> None: # Act result = HubspotDealDiffer.check_for_abri_survey_creation( new_deal=new_deal, + new_project=None, old_deal=old_deal, ) @@ -416,6 +419,7 @@ def test_abri_survey_creation__non_abri_project_code__returns_false() -> None: # Act result = HubspotDealDiffer.check_for_abri_survey_creation( new_deal=new_deal, + new_project=None, old_deal=old_deal, ) @@ -441,6 +445,7 @@ def test_abri_survey_creation__project_code_cased_differently__returns_true() -> # Act result = HubspotDealDiffer.check_for_abri_survey_creation( new_deal=new_deal, + new_project=None, old_deal=old_deal, ) @@ -476,6 +481,7 @@ def test_abri_survey_creation__no_parseable_new_date__returns_false( # Act result = HubspotDealDiffer.check_for_abri_survey_creation( new_deal=new_deal, + new_project=None, old_deal=old_deal, ) @@ -483,6 +489,36 @@ def test_abri_survey_creation__no_parseable_new_date__returns_false( assert result is False +def test_abri_survey_creation__associated_abri_project_id__returns_true() -> None: + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Southern Retrofit", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="Southern Retrofit", + confirmed_survey_date="2026-07-15", + ) + new_project = ProjectData( + project_id=HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID, + name="Abri Condition", + ) + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + new_project=new_project, + old_deal=old_deal, + ) + + # Assert + assert result is True + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From cf5a272d7e49de009f707db199c20ac5556e5f1a Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:27:29 +0000 Subject: [PATCH 14/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20reco?= =?UTF-8?q?gnises=20deals=20by=20their=20associated=20Abri=20project=20id?= =?UTF-8?q?=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 2017487a0..636bf7521 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -191,6 +191,13 @@ class HubspotDealDiffer: def _is_abri_condition_deal( new_deal: Dict[str, str], new_project: Optional[ProjectData] ) -> bool: + if ( + new_project is not None + and new_project["project_id"] + == HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID + ): + return True + new_project_code = (new_deal.get("project_code") or "").lower() return new_project_code == HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower() From 911e77d7cfe4c4eeb2e79b2a6cdf9a52e591b493 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:28:13 +0000 Subject: [PATCH 15/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20fall?= =?UTF-8?q?s=20back=20to=20project=20code=20only=20when=20no=20project=20i?= =?UTF-8?q?s=20associated=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/tests/test_hubspot_deal_differ.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/etl/hubspot/tests/test_hubspot_deal_differ.py b/etl/hubspot/tests/test_hubspot_deal_differ.py index ea0c3679f..a072b175f 100644 --- a/etl/hubspot/tests/test_hubspot_deal_differ.py +++ b/etl/hubspot/tests/test_hubspot_deal_differ.py @@ -519,6 +519,35 @@ def test_abri_survey_creation__associated_abri_project_id__returns_true() -> Non assert result is True +def test_abri_survey_creation__non_abri_project_id_with_abri_code__returns_false() -> ( + None +): + deal_id = uuid.uuid4() + + # Arrange + old_deal = make_old_deal( + id=deal_id, + project_code="Abri Condition", + confirmed_survey_date=None, + ) + new_deal = make_new_deal( + deal_id, + project_code="Abri Condition", + confirmed_survey_date="2026-07-15", + ) + new_project = ProjectData(project_id="999999", name="Southern Retrofit") + + # Act + result = HubspotDealDiffer.check_for_abri_survey_creation( + new_deal=new_deal, + new_project=new_project, + old_deal=old_deal, + ) + + # Assert + assert result is False + + # ======================= # DB UPDATE TRIGGER TESTS # ======================= From fdeb15501f9a6f03215d454704dc2feffa3d6294 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 2 Jul 2026 16:29:11 +0000 Subject: [PATCH 16/16] =?UTF-8?q?Abri=20survey=20creation=20trigger=20fall?= =?UTF-8?q?s=20back=20to=20project=20code=20only=20when=20no=20project=20i?= =?UTF-8?q?s=20associated=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- etl/hubspot/hubspot_deal_differ.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/etl/hubspot/hubspot_deal_differ.py b/etl/hubspot/hubspot_deal_differ.py index 636bf7521..68b075182 100644 --- a/etl/hubspot/hubspot_deal_differ.py +++ b/etl/hubspot/hubspot_deal_differ.py @@ -191,12 +191,11 @@ class HubspotDealDiffer: def _is_abri_condition_deal( new_deal: Dict[str, str], new_project: Optional[ProjectData] ) -> bool: - if ( - new_project is not None - and new_project["project_id"] - == HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID - ): - return True + if new_project is not None: + return ( + new_project["project_id"] + == HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID + ) new_project_code = (new_deal.get("project_code") or "").lower() return new_project_code == HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE.lower()