diff --git a/CONTEXT.md b/CONTEXT.md index 859c56b08..46c920f8b 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -473,7 +473,7 @@ The auth credential required by the New EPC API; stored in the `EPC_AUTH_TOKEN` _Avoid_: API key, auth token, secret **Void Property**: -A place Abri reports as having no live tenancy, signalled by `getSCSTenantData` returning a `RelayError` whose message is exactly `No_tenancy_found`. A normal outcome of the tenant-data sync, not a failure: there are no signatories to create as deal contacts, so the flow completes instead of dead-lettering the message, prefixing the deal's **Extra booking information** (`notes_for_surveyor`) with the `Void ||` marker. HubSpot has no append, so that property is read live and rewritten whole — never rewritten from the scraped snapshot, which lags by a scrape cycle and would discard a coordinator's unscraped edit. The marker doubles as the idempotency guard: a note already carrying it is left untouched, so redelivery never stacks markers. Distinct from a tenancy carrying no tenants (a tenancy exists; nobody is recorded against it), and from the same words arriving as a dumped 4GL query (`No Tenancy Found for Query FOR EACH ...`), which stays a rejection — Abri does not send that form to mean "known empty". +A place Abri reports as having no live tenancy, signalled by `getSCSTenantData` returning a `RelayError` whose message is exactly `No_tenancy_found`. A normal outcome of the tenant-data sync, not a failure: there are no signatories to create as deal contacts, so the flow completes instead of dead-lettering the message, prefixing the deal's **Extra booking information** (`notes_for_surveyor`) with the `Void. ` marker. HubSpot has no append, so that property is read live and rewritten whole — never rewritten from the scraped snapshot, which lags by a scrape cycle and would discard a coordinator's unscraped edit. The marker doubles as the idempotency guard: a note already carrying it is left untouched, so redelivery never stacks markers. Distinct from a tenancy carrying no tenants (a tenancy exists; nobody is recorded against it), and from the same words arriving as a dumped 4GL query (`No Tenancy Found for Query FOR EACH ...`), which stays a rejection — Abri does not send that form to mean "known empty". _Avoid_: empty property, no tenancy (names the message, not the state), untenanted ## Team diff --git a/docs/abri-hubspot-ops-guide.md b/docs/abri-hubspot-ops-guide.md index 62a87011e..0a07c379a 100644 --- a/docs/abri-hubspot-ops-guide.md +++ b/docs/abri-hubspot-ops-guide.md @@ -43,12 +43,12 @@ system. **Empty properties.** If Abri has no live tenancy for the property, no tenant contacts appear on the deal — there is nobody to add — and **Extra booking information** is -prefixed with `Void ||` so the surveyor sees it first. Anything already in that field is +prefixed with `Void. ` so the surveyor sees it first. Anything already in that field is kept, after the prefix. This is expected, not a fault, and nothing needs re-triggering. Note that Abri sends the same signal for a property reference it does not recognise, so if you were expecting tenants, check the property is right before assuming it's empty. -Delete the `Void ||` prefix if you establish the property is not empty after all — the +Delete the `Void. ` prefix if you establish the property is not empty after all — the system only adds it once, so it will not come back on its own. ## The fields, and why they matter diff --git a/orchestration/abri_orchestrator.py b/orchestration/abri_orchestrator.py index c9fda15f5..ef6d167e0 100644 --- a/orchestration/abri_orchestrator.py +++ b/orchestration/abri_orchestrator.py @@ -32,7 +32,7 @@ NOTES_FOR_SURVEYOR_DEAL_PROPERTY = "notes_for_surveyor" # Prepended to that property when Abri reports the place as having no live # tenancy, so a surveyor sees it first. Doubles as the idempotency marker: a # note already carrying it is left alone, so redelivery never stacks markers. -VOID_MARKER = "Void ||" +VOID_MARKER = "Void. " def _vulnerability_description(tenant: Tenant) -> Optional[str]: @@ -338,9 +338,7 @@ class AbriOrchestrator: AmendJobRequest( job_no=job_no, appointment_date=change.confirmed_survey_date, - appointment_time=slot_for_confirmed_time( - change.confirmed_survey_time - ), + appointment_time=slot_for_confirmed_time(change.confirmed_survey_time), resource=change.third_party_surveyor_identifier, ) ) @@ -373,9 +371,7 @@ class AbriOrchestrator: client_ref=client_ref_for_deal(booking.deal_id), place_ref=booking.place_ref, appointment_date=booking.confirmed_survey_date, - appointment_time=slot_for_confirmed_time( - booking.confirmed_survey_time - ), + appointment_time=slot_for_confirmed_time(booking.confirmed_survey_time), short_description=descriptions.short_description, long_description=descriptions.long_description, resource=booking.third_party_surveyor_identifier, diff --git a/tests/orchestration/test_abri_orchestrator_tenant_data_sync.py b/tests/orchestration/test_abri_orchestrator_tenant_data_sync.py index f0b8c8aed..76b09387a 100644 --- a/tests/orchestration/test_abri_orchestrator_tenant_data_sync.py +++ b/tests/orchestration/test_abri_orchestrator_tenant_data_sync.py @@ -75,9 +75,7 @@ class FakeDealDatabase: @pytest.fixture() -def orchestrator( - mock_session: MagicMock, sdk_client: MagicMock -) -> AbriOrchestrator: +def orchestrator(mock_session: MagicMock, sdk_client: MagicMock) -> AbriOrchestrator: with patch( "infrastructure.abri.abri_client.requests.Session", return_value=mock_session, @@ -587,7 +585,7 @@ def test_a_void_property_is_flagged_at_the_front_of_the_deals_booking_informatio sdk_client.crm.deals.basic_api.update.assert_called_once_with( DEAL_ID, simple_public_object_input=DealPropertyInput( - properties={"notes_for_surveyor": "Void || Key safe code 1234"} + properties={"notes_for_surveyor": "Void. Key safe code 1234"} ), ) @@ -612,7 +610,7 @@ def test_a_void_property_with_no_existing_booking_information_is_flagged_alone( sdk_client.crm.deals.basic_api.update.assert_called_once_with( DEAL_ID, simple_public_object_input=DealPropertyInput( - properties={"notes_for_surveyor": "Void ||"} + properties={"notes_for_surveyor": "Void. "} ), ) @@ -627,7 +625,7 @@ def test_a_deal_already_flagged_void_is_left_alone_so_redelivery_never_stacks_fl "abri_relay_getscstenantdata_notenancyfound_response.xml" ) sdk_client.crm.deals.basic_api.get_by_id.return_value.properties = { - "notes_for_surveyor": "Void || Key safe code 1234" + "notes_for_surveyor": "Void. Key safe code 1234" } # Act