Model/domain/abri/models.py
2026-07-07 16:30:36 +00:00

106 lines
2.3 KiB
Python

from dataclasses import dataclass
from datetime import date
from enum import Enum
from typing import Literal, NewType, Optional, Tuple, Union
PlaceRef = NewType("PlaceRef", str)
SlotCode = Literal["AM", "PM", "AD"]
class AbandonReason(str, Enum):
"""OpenHousing's coded reason a job was abandoned.
Only CARDED is used for now; the full HubSpot-outcome-to-code table is a
documented follow-up - enum based on Abri codes needs creating and mapping from hubspot
"""
CARDED = "CARDED"
@dataclass(frozen=True)
class LogJobRequest:
client_ref: str
place_ref: PlaceRef
appointment_date: date
appointment_time: SlotCode
short_description: str
long_description: str
@dataclass(frozen=True)
class JobLogged:
job_no: str
logged_info: str
@dataclass(frozen=True)
class AbriRequestRejected:
code: str
message: str
LogJobResult = Union[JobLogged, AbriRequestRejected]
@dataclass(frozen=True)
class AmendJobRequest:
job_no: str
appointment_date: date
appointment_time: SlotCode
resource: Optional[str] = None
@dataclass(frozen=True)
class AppointmentAmended:
job_no: str
appointment_date: str
appointment_time: str
AmendJobResult = Union[AppointmentAmended, AbriRequestRejected]
@dataclass(frozen=True)
class Tenant:
"""A tenancy signatory, minimised to the fields the HubSpot sync needs.
Person title, per-person references, the main-contact flag and tenancy
dates are deliberately dropped at parse time (data minimisation); mobile
and telephone are the single best number of each kind, pre-selected by
priority, and secondary_number is the best of the numbers they left
unused.
"""
forenames: str
surname: str
mobile: Optional[str]
telephone: Optional[str]
secondary_number: Optional[str]
vulnerabilities: Tuple[str, ...]
@dataclass(frozen=True)
class TenancyData:
"""Tenancy signatories for a place; the reference is PII-safe."""
tenancy_reference: str
tenants: Tuple[Tenant, ...]
GetTenantDataResult = Union[TenancyData, AbriRequestRejected]
@dataclass(frozen=True)
class AbandonJobRequest:
job_no: str
reason: AbandonReason
date_abandoned: date
@dataclass(frozen=True)
class JobAbandoned:
job_no: str
AbandonJobResult = Union[JobAbandoned, AbriRequestRejected]