mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Merge pull request #1519 from Hestia-Homes/feature/abri-api-integration
Add logging to logic for deciding whether abri API should be triggered
This commit is contained in:
commit
2c83c977e6
1 changed files with 133 additions and 20 deletions
|
|
@ -5,6 +5,9 @@ from backend.app.db.models.hubspot_deal_data import HubspotDealData
|
|||
from domain.abri.models import UNSUCCESSFUL_OUTCOMES
|
||||
from etl.hubspot.project_data import ProjectData
|
||||
from etl.hubspot.utils import parse_hs_bool, parse_hs_date, parse_hs_int
|
||||
from utilities.logger import setup_logger
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
class HubspotDealDiffer:
|
||||
|
|
@ -200,31 +203,59 @@ class HubspotDealDiffer:
|
|||
new_listing: Optional[Dict[str, str]],
|
||||
old_deal: HubspotDealData,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
logger.info(
|
||||
"Evaluating Abri triggers for HubSpot deal %s "
|
||||
"(project_code=%r, associated_project_id=%s)",
|
||||
hubspot_deal_id,
|
||||
new_deal.get("project_code"),
|
||||
new_project["project_id"] if new_project is not None else None,
|
||||
)
|
||||
amend_job = HubspotDealDiffer.check_for_abri_job_amendment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
)
|
||||
log_job = HubspotDealDiffer.check_for_abri_job_logging(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
)
|
||||
sync_tenant_data = HubspotDealDiffer.check_for_abri_tenant_data_fetch(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
)
|
||||
abandon_job = HubspotDealDiffer.check_for_abri_deal_abandonment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
)
|
||||
logger.info(
|
||||
"Abri trigger results for HubSpot deal %s: "
|
||||
"amend_job=%s log_job=%s sync_tenant_data=%s abandon_job=%s",
|
||||
hubspot_deal_id,
|
||||
amend_job,
|
||||
log_job,
|
||||
sync_tenant_data,
|
||||
abandon_job,
|
||||
)
|
||||
|
||||
flows: List[str] = []
|
||||
if HubspotDealDiffer.check_for_abri_job_amendment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
if amend_job:
|
||||
flows.append("amend_job")
|
||||
if HubspotDealDiffer.check_for_abri_job_logging(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
if log_job:
|
||||
flows.append("log_job")
|
||||
if HubspotDealDiffer.check_for_abri_tenant_data_fetch(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
if sync_tenant_data:
|
||||
flows.append("sync_tenant_data")
|
||||
if HubspotDealDiffer.check_for_abri_deal_abandonment(
|
||||
new_deal=new_deal, new_project=new_project, old_deal=old_deal
|
||||
):
|
||||
if abandon_job:
|
||||
flows.append("abandon_job")
|
||||
|
||||
if not flows:
|
||||
logger.info(
|
||||
"No Abri flows triggered for HubSpot deal %s", hubspot_deal_id
|
||||
)
|
||||
return None
|
||||
|
||||
logger.info(
|
||||
"Abri flows triggered for HubSpot deal %s: %s", hubspot_deal_id, flows
|
||||
)
|
||||
|
||||
confirmed_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
last_submission_date = parse_hs_date(new_deal.get("last_submission_date"))
|
||||
listing = new_listing or {}
|
||||
return {
|
||||
message: Dict[str, Any] = {
|
||||
"hubspot_deal_id": hubspot_deal_id,
|
||||
"flows": flows,
|
||||
"place_ref": listing.get("owner_property_id"),
|
||||
|
|
@ -246,6 +277,12 @@ class HubspotDealDiffer:
|
|||
# the other flows, which ignore it.
|
||||
"outcome": new_deal.get("outcome"),
|
||||
}
|
||||
logger.info(
|
||||
"Constructed Abri message for HubSpot deal %s: %s",
|
||||
hubspot_deal_id,
|
||||
message,
|
||||
)
|
||||
return message
|
||||
|
||||
@staticmethod
|
||||
def check_for_abri_job_logging(
|
||||
|
|
@ -256,10 +293,19 @@ class HubspotDealDiffer:
|
|||
if not HubspotDealDiffer._is_abri_condition_deal(new_deal, new_project):
|
||||
return False
|
||||
|
||||
new_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
logger.info(
|
||||
"Abri job-logging check: old_confirmed_survey_date=%s "
|
||||
"new_confirmed_survey_date=%s",
|
||||
old_deal.confirmed_survey_date,
|
||||
new_survey_date,
|
||||
)
|
||||
|
||||
# Only a first-time survey date (previously empty) logs a new job.
|
||||
if old_deal.confirmed_survey_date is not None:
|
||||
return False
|
||||
|
||||
return parse_hs_date(new_deal.get("confirmed_survey_date")) is not None
|
||||
return new_survey_date is not None
|
||||
|
||||
@staticmethod
|
||||
def check_for_abri_job_amendment(
|
||||
|
|
@ -270,6 +316,18 @@ class HubspotDealDiffer:
|
|||
if not HubspotDealDiffer._is_abri_condition_deal(new_deal, new_project):
|
||||
return False
|
||||
|
||||
new_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
new_survey_time = new_deal.get("confirmed_survey_time")
|
||||
logger.info(
|
||||
"Abri job-amendment check: "
|
||||
"old_confirmed_survey_date=%s new_confirmed_survey_date=%s "
|
||||
"old_confirmed_survey_time=%s new_confirmed_survey_time=%s",
|
||||
old_deal.confirmed_survey_date,
|
||||
new_survey_date,
|
||||
old_deal.confirmed_survey_time,
|
||||
new_survey_time,
|
||||
)
|
||||
|
||||
# A first-time survey date logs a new job, not an amendment.
|
||||
if old_deal.confirmed_survey_date is None:
|
||||
return False
|
||||
|
|
@ -278,11 +336,10 @@ class HubspotDealDiffer:
|
|||
# check, but the amendoptiappt route cannot express a cancellation.
|
||||
# Cancellation semantics (the "delete" action / canceljob route) need
|
||||
# a deliberate decision before this trigger is wired to a consumer.
|
||||
new_survey_date = parse_hs_date(new_deal.get("confirmed_survey_date"))
|
||||
if old_deal.confirmed_survey_date != new_survey_date:
|
||||
return True
|
||||
|
||||
return old_deal.confirmed_survey_time != new_deal.get("confirmed_survey_time")
|
||||
return old_deal.confirmed_survey_time != new_survey_time
|
||||
|
||||
@staticmethod
|
||||
def check_for_abri_tenant_data_fetch(
|
||||
|
|
@ -293,10 +350,21 @@ class HubspotDealDiffer:
|
|||
if not HubspotDealDiffer._is_abri_condition_deal(new_deal, new_project):
|
||||
return False
|
||||
|
||||
new_commencement_date = parse_hs_date(
|
||||
new_deal.get("expected_commencement_date")
|
||||
)
|
||||
logger.info(
|
||||
"Abri tenant-data-fetch check: old_commencement_date=%s "
|
||||
"new_commencement_date=%s",
|
||||
old_deal.expected_commencement_date,
|
||||
new_commencement_date,
|
||||
)
|
||||
|
||||
# Only a first-time commencement date (previously empty) fires the fetch.
|
||||
if old_deal.expected_commencement_date is not None:
|
||||
return False
|
||||
|
||||
return parse_hs_date(new_deal.get("expected_commencement_date")) is not None
|
||||
return new_commencement_date is not None
|
||||
|
||||
@staticmethod
|
||||
def check_for_abri_deal_abandonment(
|
||||
|
|
@ -307,6 +375,19 @@ class HubspotDealDiffer:
|
|||
if not HubspotDealDiffer._is_abri_condition_deal(new_deal, new_project):
|
||||
return False
|
||||
|
||||
logger.info(
|
||||
"Abri deal-abandonment check: "
|
||||
"old_number_of_attempts=%s old_outcome=%r "
|
||||
"new_number_of_attempts=%s new_outcome=%r "
|
||||
"attempts_threshold=%s",
|
||||
old_deal.number_of_attempts,
|
||||
old_deal.outcome,
|
||||
new_deal.get("number_of_attempts"),
|
||||
new_deal.get("outcome"),
|
||||
HubspotDealDiffer.ABANDONMENT_ATTEMPTS_THRESHOLD,
|
||||
)
|
||||
|
||||
# Already abandoned before this change — nothing new to fire.
|
||||
if HubspotDealDiffer._is_abandoned(
|
||||
old_deal.number_of_attempts, old_deal.outcome
|
||||
):
|
||||
|
|
@ -333,19 +414,43 @@ class HubspotDealDiffer:
|
|||
attempts is None
|
||||
or attempts < HubspotDealDiffer.ABANDONMENT_ATTEMPTS_THRESHOLD
|
||||
):
|
||||
logger.info(
|
||||
"Abri _is_abandoned=False (attempts gate): "
|
||||
"raw_attempts=%r parsed_attempts=%s threshold=%s",
|
||||
number_of_attempts,
|
||||
attempts,
|
||||
HubspotDealDiffer.ABANDONMENT_ATTEMPTS_THRESHOLD,
|
||||
)
|
||||
return False
|
||||
|
||||
return (outcome or "").lower() in UNSUCCESSFUL_OUTCOMES
|
||||
outcome_is_unsuccessful = (outcome or "").lower() in UNSUCCESSFUL_OUTCOMES
|
||||
logger.info(
|
||||
"Abri _is_abandoned=%s (outcome gate): "
|
||||
"parsed_attempts=%s outcome=%r outcome_is_unsuccessful=%s",
|
||||
outcome_is_unsuccessful,
|
||||
attempts,
|
||||
outcome,
|
||||
outcome_is_unsuccessful,
|
||||
)
|
||||
return outcome_is_unsuccessful
|
||||
|
||||
@staticmethod
|
||||
def _is_abri_condition_deal(
|
||||
new_deal: Dict[str, str], new_project: Optional[ProjectData]
|
||||
) -> bool:
|
||||
if new_project is not None:
|
||||
return (
|
||||
is_match = (
|
||||
new_project["project_id"]
|
||||
== HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID
|
||||
)
|
||||
logger.info(
|
||||
"Abri condition-deal check via associated project: "
|
||||
"project_id=%s expected=%s match=%s",
|
||||
new_project["project_id"],
|
||||
HubspotDealDiffer.ABRI_CONDITION_ASSOCIATED_PROJECT_ID,
|
||||
is_match,
|
||||
)
|
||||
return is_match
|
||||
|
||||
# TEST_ABRI_PROJECT_CODE_OVERRIDE lets a non-production deploy fire on a
|
||||
# sandbox deal's own project code; unset (the production default) falls
|
||||
|
|
@ -355,7 +460,15 @@ class HubspotDealDiffer:
|
|||
or HubspotDealDiffer.ABRI_CONDITION_PROJECT_CODE
|
||||
)
|
||||
new_project_code = (new_deal.get("project_code") or "").lower()
|
||||
return new_project_code == expected_code.lower()
|
||||
is_match = new_project_code == expected_code.lower()
|
||||
logger.info(
|
||||
"Abri condition-deal check via project_code: "
|
||||
"new_project_code=%r expected=%r match=%s",
|
||||
new_project_code,
|
||||
expected_code.lower(),
|
||||
is_match,
|
||||
)
|
||||
return is_match
|
||||
|
||||
@staticmethod
|
||||
def _has_valid_pashub_link(new_pashub_link: str) -> bool:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue