Real Abri portal deals fire the job-logging trigger 🟩

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Roth 2026-07-07 11:46:33 +00:00
parent eaedd9a63d
commit 481c01098d
4 changed files with 65 additions and 48 deletions

View file

@ -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(

View file

@ -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")

View file

@ -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",
)

View file

@ -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",
)