Coverage for apps/borrower_portal/schemas.py: 100%
124 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-04 14:06 +0000
1"""Django Ninja schemas for the borrower portal (add-borrower-portal-api).
3Shapes follow the borrower portal's contracts (``borrower-pos/src/services/{auth,me,pos}/
4*.types.ts``): snake_case application fields, camelCase only where the portal already uses it.
5"""
7from __future__ import annotations
9from typing import Any, Literal
11from ninja import Schema
14# --- accounts ---------------------------------------------------------------------
15class NotifyOut(Schema):
16 email: bool
17 sms: bool
20class BorrowerUserOut(Schema):
21 id: int
22 name: str
23 email: str
24 phone: str
25 kind: Literal["borrower"]
26 notify: NotifyOut
29class BorrowerAuthResultOut(Schema):
30 token: str
31 user: BorrowerUserOut
34class RegisterInput(Schema):
35 name: str = ""
36 email: str = ""
37 password: str = ""
40class ResetInput(Schema):
41 token: str = ""
42 password: str = ""
45class OtpRequestInput(Schema):
46 email: str = ""
49class OtpRequestOut(Schema):
50 sent: bool
51 devOtp: str | None = None
54class OtpVerifyInput(Schema):
55 email: str = ""
56 code: str = ""
59class BorrowerProfilePatch(Schema):
60 name: str
61 email: str
62 phone: str = ""
63 notify: NotifyOut
66# --- application ------------------------------------------------------------------
67class StartApplicationInput(Schema):
68 purpose: str = ""
69 occupancy: str = ""
70 state_code: str = ""
73class SaveStepInput(Schema):
74 section: str
75 data: dict[str, Any] = {}
76 # For per-borrower sections, whose record to save; defaults to the signed-in borrower.
77 borrower_id: int | None = None
80class DeleteStepItemInput(Schema):
81 section: str
82 item_id: int | str
85class PosMyOut(Schema):
86 # The nested application is plain JSON built by pos_api._snapshot (PosApplication shape).
87 application: dict[str, Any] | None
88 steps: dict[str, bool]
89 percent_complete: int
92class PortalConfigOut(Schema):
93 languages: list[str]
94 default_language: str
95 programs: list[str]
96 sections_by_program: dict[str, list[str]]
97 features: dict[str, bool]
100class AddressSuggestionOut(Schema):
101 label: str
102 address_line: str
103 city: str
104 state_code: str
105 county: str
106 postal_code: str
109# --- invitations ------------------------------------------------------------------
110class PosInviteInput(Schema):
111 name: str = ""
112 email: str = ""
115class PosInviteOut(Schema):
116 user_id: int
117 # The temporary password goes only to the borrower by email (add-sendgrid-email).
118 email_sent: bool
119 # Development (DEBUG) only, for local testing without opening the email.
120 devTempPassword: str | None = None
123class BorrowerPosStatusOut(Schema):
124 borrower_id: int
125 name: str
126 email: str
127 invited: bool
128 started: bool
129 has_account: bool
130 # Status of the latest invite email (Sent / Delivered / Opened / Bounced / Failed …), or null.
131 invite_email_status: str | None = None
134# --- documents --------------------------------------------------------------------
135class UploadInviteInput(Schema):
136 email: str = ""
137 message: str = ""
140class UploadInviteOut(Schema):
141 id: int
142 email: str
143 message: str
144 status: str
145 created_at: str
148class UploadInviteCreatedOut(Schema):
149 invite: UploadInviteOut
150 uploadLink: str
153class UploadPageOut(Schema):
154 loanNumber: str
155 company: str
156 borrowerName: str
157 message: str
158 requested: list[dict[str, Any]]
159 uploadCount: int
160 catalog: list[dict[str, Any]]
163class DocumentUploadInput(Schema):
164 name: str = ""
165 classification: str = ""
166 need_id: int | None = None
169class UploadCountOut(Schema):
170 uploadCount: int
173class PortalNeedOut(Schema):
174 id: int
175 name: str
176 type: str
177 status: str
178 description: str
179 due_date: str | None
182class PortalDocumentOut(Schema):
183 id: int
184 name: str
185 classification: str
186 uploaded_via: str
187 created_at: str
190class PortalDisclosureOut(Schema):
191 id: int
192 package_type: str
193 status: str
194 sent_at: str | None
195 signed_at: str | None