From 03f0f4d49015b4c2d7001ebf1dd6311873580af4 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Tue, 7 Jul 2026 15:32:13 +0000 Subject: [PATCH] =?UTF-8?q?Abandon=20a=20job=20through=20the=20relay=20can?= =?UTF-8?q?celjob=20route=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- infrastructure/abri/abri_client.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/infrastructure/abri/abri_client.py b/infrastructure/abri/abri_client.py index 3b85903d0..e6863386f 100644 --- a/infrastructure/abri/abri_client.py +++ b/infrastructure/abri/abri_client.py @@ -98,7 +98,19 @@ class AbriClient: return self._parse_appointment_amended(outcome) def abandon_job(self, request: AbandonJobRequest) -> AbandonJobResult: - raise NotImplementedError + outcome = self._exchange( + request_type="canceljob", + parameters=[ + ("job_no", request.job_no), + ("abandon_reason", request.reason.value), + ("date_abandoned", _format_appointment_date(request.date_abandoned)), + ], + ) + + if isinstance(outcome, AbriRequestRejected): + return outcome + + return self._parse_job_abandoned(outcome) def get_tenant_data(self, place_ref: PlaceRef) -> GetTenantDataResult: outcome = self._exchange( @@ -197,6 +209,22 @@ class AbriClient: appointment_time=appointment_time, ) + @staticmethod + def _parse_job_abandoned(root: ET.Element) -> JobAbandoned: + job_cancelled = root.find(".//JobCancelled") + + if job_cancelled is None: + raise AbriResponseParseError( + "JobCancelled element missing from relay response" + ) + + job_no = job_cancelled.get("job_no") + + if job_no is None: + raise AbriResponseParseError("JobCancelled element missing job_no") + + return JobAbandoned(job_no=job_no) + @staticmethod def _parse_tenancy_data(root: ET.Element) -> TenancyData: tenancies = root.findall("Tenancy")