From c542a57ae5e8c5f14c5ac517b4fc189d4f61ac8b Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Fri, 3 Jul 2026 16:17:41 +0000 Subject: [PATCH] =?UTF-8?q?Abri=20amend=5Fjob=20amends=20an=20OpenHousing?= =?UTF-8?q?=20appointment=20and=20returns=20the=20echoed=20booking=20?= =?UTF-8?q?=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- infrastructure/abri/abri_client.py | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/infrastructure/abri/abri_client.py b/infrastructure/abri/abri_client.py index 4342ba946..f9b1ddc1f 100644 --- a/infrastructure/abri/abri_client.py +++ b/infrastructure/abri/abri_client.py @@ -7,6 +7,7 @@ from domain.abri.models import ( AbriRequestRejected, AmendJobRequest, AmendJobResult, + AppointmentAmended, JobLogged, LogJobRequest, LogJobResult, @@ -48,7 +49,20 @@ class AbriClient: return self._parse_job_logged(outcome) def amend_job(self, request: AmendJobRequest) -> AmendJobResult: - raise NotImplementedError + outcome = self._exchange( + request_type="amendoptiappt", + parameters=[ + ("job_no", request.job_no), + ("action", "amend"), + ("appointment_date", request.appointment_date.strftime("%d/%m/%Y")), + ("appointment_time", request.appointment_time), + ], + ) + + if isinstance(outcome, AbriRequestRejected): + return outcome + + return self._parse_appointment_amended(outcome) def _exchange( self, request_type: str, parameters: List[Tuple[str, str]] @@ -106,6 +120,31 @@ class AbriClient: return JobLogged(job_no=job_no, logged_info=logged_info) + @staticmethod + def _parse_appointment_amended(root: ET.Element) -> AppointmentAmended: + amended = root.find("AmendOptiAppt") + + if amended is None: + raise AbriResponseParseError( + "AmendOptiAppt element missing from relay response" + ) + + job_no = amended.get("job_no") + appointment_date = amended.get("appointment_date") + appointment_time = amended.get("appointment_time") + + if job_no is None or appointment_date is None or appointment_time is None: + raise AbriResponseParseError( + "AmendOptiAppt element missing job_no, appointment_date " + "or appointment_time" + ) + + return AppointmentAmended( + job_no=job_no, + appointment_date=appointment_date, + appointment_time=appointment_time, + ) + @staticmethod def _parse_rejection(root: ET.Element) -> AbriRequestRejected: success = root.findtext("success")