mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
move trigger check to HubspotDealDiffer
This commit is contained in:
parent
d9b441962f
commit
3934e2d359
5 changed files with 68 additions and 93 deletions
|
|
@ -1,59 +0,0 @@
|
|||
"""Builds the one-per-scrape SQS message for the Abri OpenHousing lambda.
|
||||
|
||||
The scraper decides which flows fire (the differ predicates live in one
|
||||
tested place); the lambda is a dumb dispatcher. When any predicate fires,
|
||||
one message carries every fired flow plus the deal fields they need, so
|
||||
flows for the same deal cannot interleave across concurrent lambda
|
||||
invocations.
|
||||
|
||||
Abandonment (no-access) detection stays unwired until the CancelJob flow
|
||||
exists — check_for_abri_deal_abandonment is deliberately not called here.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
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
|
||||
from etl.hubspot.utils import parse_hs_date
|
||||
|
||||
|
||||
def abri_trigger_message_for_scrape(
|
||||
hubspot_deal_id: str,
|
||||
new_deal: Dict[str, str],
|
||||
new_project: Optional[ProjectData],
|
||||
new_listing: Optional[Dict[str, str]],
|
||||
old_deal: HubspotDealData,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""The Abri trigger message for this scrape, or None if no flow fired."""
|
||||
flows: List[str] = []
|
||||
if HubspotDealDiffer.check_for_abri_job_amendment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("amend_job")
|
||||
if HubspotDealDiffer.check_for_abri_job_logging(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("log_job")
|
||||
if HubspotDealDiffer.check_for_abri_tenant_data_fetch(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("sync_tenant_data")
|
||||
|
||||
if not flows:
|
||||
return None
|
||||
|
||||
confirmed_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
listing = new_listing or {}
|
||||
return {
|
||||
"hubspot_deal_id": hubspot_deal_id,
|
||||
"flows": flows,
|
||||
"place_ref": listing.get("owner_property_id"),
|
||||
"deal_name": new_deal.get("dealname"),
|
||||
"confirmed_survey_date": (
|
||||
confirmed_survey_date.date().isoformat()
|
||||
if confirmed_survey_date is not None
|
||||
else None
|
||||
),
|
||||
"confirmed_survey_time": new_deal.get("confirmed_survey_time"),
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Dict, List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from backend.app.db.models.hubspot_deal_data import HubspotDealData
|
||||
from etl.hubspot.project_data import ProjectData
|
||||
|
|
@ -189,6 +189,46 @@ class HubspotDealDiffer:
|
|||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def check_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id: str,
|
||||
new_deal: Dict[str, str],
|
||||
new_project: Optional[ProjectData],
|
||||
new_listing: Optional[Dict[str, str]],
|
||||
old_deal: HubspotDealData,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
flows: List[str] = []
|
||||
if HubspotDealDiffer.check_for_abri_job_amendment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("amend_job")
|
||||
if HubspotDealDiffer.check_for_abri_job_logging(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("log_job")
|
||||
if HubspotDealDiffer.check_for_abri_tenant_data_fetch(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
flows.append("sync_tenant_data")
|
||||
|
||||
if not flows:
|
||||
return None
|
||||
|
||||
confirmed_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
listing = new_listing or {}
|
||||
return {
|
||||
"hubspot_deal_id": hubspot_deal_id,
|
||||
"flows": flows,
|
||||
"place_ref": listing.get("owner_property_id"),
|
||||
"deal_name": new_deal.get("dealname"),
|
||||
"confirmed_survey_date": (
|
||||
confirmed_survey_date.date().isoformat()
|
||||
if confirmed_survey_date is not None
|
||||
else None
|
||||
),
|
||||
"confirmed_survey_time": new_deal.get("confirmed_survey_time"),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def check_for_abri_job_logging(
|
||||
new_deal: Dict[str, str],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from backend.app.config import get_settings
|
|||
from etl.hubspot.hubspotClient import HubspotClient
|
||||
from etl.hubspot.hubspotDataTodB import CompanyData, HubspotDataToDb
|
||||
from etl.hubspot.project_data import ProjectData
|
||||
from etl.hubspot.abri_flow_triggers import abri_trigger_message_for_scrape
|
||||
from etl.hubspot.abri_flow_triggers import check_for_abri_triggers_and_construct_message
|
||||
from etl.hubspot.hubspot_deal_differ import HubspotDealDiffer
|
||||
from etl.hubspot.hubspot_trigger_orchestrator_trigger_request import (
|
||||
HubspotTriggerOrchestratorTriggerRequest,
|
||||
|
|
@ -128,14 +128,14 @@ def handler(body: dict[str, Any], context: Any) -> None:
|
|||
sqs_client, hubspot_deal, listing, hubspot_deal_id
|
||||
)
|
||||
|
||||
# None means no Abri flow fired this scrape; a dict is the message
|
||||
# naming the flows that did.
|
||||
abri_message = abri_trigger_message_for_scrape(
|
||||
hubspot_deal_id=hubspot_deal_id,
|
||||
new_deal=hubspot_deal,
|
||||
new_project=project,
|
||||
new_listing=listing,
|
||||
old_deal=db_deal,
|
||||
abri_message: Optional[Dict[str, Any]] = (
|
||||
HubspotDealDiffer.check_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=hubspot_deal_id,
|
||||
new_deal=hubspot_deal,
|
||||
new_project=project,
|
||||
new_listing=listing,
|
||||
old_deal=db_deal,
|
||||
)
|
||||
)
|
||||
if abri_message is not None:
|
||||
logger.info(
|
||||
|
|
|
|||
|
|
@ -3,13 +3,11 @@ from typing import Any, Dict
|
|||
import uuid
|
||||
|
||||
from backend.app.db.models.hubspot_deal_data import HubspotDealData
|
||||
from etl.hubspot.abri_flow_triggers import abri_trigger_message_for_scrape
|
||||
from etl.hubspot.abri_flow_triggers import check_for_abri_triggers_and_construct_message
|
||||
|
||||
BASE_TIME = datetime(2025, 12, 1, 12, 0, 0)
|
||||
|
||||
ABRI_PROJECT_CODE = (
|
||||
"[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]"
|
||||
)
|
||||
ABRI_PROJECT_CODE = "[Abri Stock Condition - Privately Funded - 062026 - 1247536318670]"
|
||||
|
||||
DEAL_ID = "9876543210"
|
||||
|
||||
|
|
@ -42,15 +40,13 @@ 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_PROJECT_CODE, confirmed_survey_date=None
|
||||
)
|
||||
old_deal = make_old_deal(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"
|
||||
)
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -80,7 +76,7 @@ def test_a_changed_confirmed_survey_date_builds_an_amend_job_message() -> None:
|
|||
)
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -102,7 +98,7 @@ def test_a_first_expected_commencement_date_builds_a_tenant_sync_message() -> No
|
|||
new_deal = make_new_deal(expected_commencement_date="2026-07-01")
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -135,7 +131,7 @@ def test_several_flows_firing_in_one_scrape_share_one_message() -> None:
|
|||
)
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -159,7 +155,7 @@ def test_no_message_when_no_abri_trigger_fires() -> None:
|
|||
new_deal = make_new_deal(outcome="left voicemail")
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -174,12 +170,10 @@ def test_no_message_when_no_abri_trigger_fires() -> None:
|
|||
def test_no_message_for_a_non_abri_deal() -> None:
|
||||
# Arrange: a survey date first set, but on another project's deal.
|
||||
old_deal = make_old_deal(project_code="Other", confirmed_survey_date=None)
|
||||
new_deal = make_new_deal(
|
||||
project_code="Other", confirmed_survey_date="2026-06-24"
|
||||
)
|
||||
new_deal = make_new_deal(project_code="Other", confirmed_survey_date="2026-06-24")
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -200,7 +194,7 @@ def test_abandonment_alone_stays_unwired_and_builds_no_message() -> None:
|
|||
new_deal = make_new_deal(number_of_attempts="3", outcome="no answer")
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
@ -220,13 +214,11 @@ def test_abandonment_alone_stays_unwired_and_builds_no_message() -> None:
|
|||
def test_a_missing_listing_still_builds_the_message_without_a_place_ref() -> None:
|
||||
# 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_PROJECT_CODE, confirmed_survey_date=None
|
||||
)
|
||||
old_deal = make_old_deal(project_code=ABRI_PROJECT_CODE, confirmed_survey_date=None)
|
||||
new_deal = make_new_deal(confirmed_survey_date="2026-06-24")
|
||||
|
||||
# Act
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=new_deal,
|
||||
new_project=None,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ canned LogJob success carrying a fake job_no. Concretely, the script
|
|||
1. fetches the deal, listing and project from the real HubSpot portal
|
||||
(exactly what the scraper lambda sees),
|
||||
2. reads the deal's row from the real (dev) deal database,
|
||||
3. runs the real differ predicates via abri_trigger_message_for_scrape,
|
||||
3. runs the real differ predicates via abri_message_if_triggered,
|
||||
4. validates the real message contract (AbriTriggerRequest),
|
||||
5. runs the real dispatch through the real AbriOrchestrator, so the fake
|
||||
job_no is written to the deal's client_booking_reference property in
|
||||
|
|
@ -129,7 +129,9 @@ def main() -> None:
|
|||
from applications.abri.abri_trigger_request import AbriTriggerRequest
|
||||
from applications.abri.dispatch import dispatch_abri_flows
|
||||
from backend.app.db.models.hubspot_deal_data import HubspotDealData
|
||||
from etl.hubspot.abri_flow_triggers import abri_trigger_message_for_scrape
|
||||
from etl.hubspot.abri_flow_triggers import (
|
||||
check_for_abri_triggers_and_construct_message,
|
||||
)
|
||||
from etl.hubspot.hubspotClient import HubspotClient
|
||||
from infrastructure.abri.abri_client import AbriClient
|
||||
from infrastructure.abri.config import AbriConfig
|
||||
|
|
@ -196,7 +198,7 @@ def main() -> None:
|
|||
f"job_no={deal_row.client_booking_reference}"
|
||||
)
|
||||
|
||||
message = abri_trigger_message_for_scrape(
|
||||
message = check_for_abri_triggers_and_construct_message(
|
||||
hubspot_deal_id=DEAL_ID,
|
||||
new_deal=hubspot_deal,
|
||||
new_project=project,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue