Mortgage Application Wizard Steps
Summary
After a MortgageApplication is created in draft status, the applicant (or their Pro agent) fills in the application through a 5-step wizard. Each step is saved individually via PUT /mortgage/applications/:id/step/:step. Steps 1, 2, and 4 persist JSON data to dedicated columns on the application. Steps 3 and 5 advance the currentStep counter only. Step 1 also handles an optional co-borrower (upsert or delete). After all steps and at least one document, POST /mortgage/applications/:id/submit transitions the application to pending_review and creates a BrokerAssignment.
State Diagram
stateDiagram-v2 state "Brouillon" as Draft state "Étape 1 — Profil sauvegardé" as Step1Saved state "Étape 2 — Finances sauvegardées" as Step2Saved state "Étape 3 — Avancée" as Step3Advanced state "Étape 4 — Projet sauvegardé" as Step4Saved state "Étape 5 — Avancée" as Step5Advanced state "En attente de revue" as PendingReview [*] --> Draft Draft --> Step1Saved: applicant saves step 1 (profileData + optional coBorrower) Step1Saved --> Step2Saved: applicant saves step 2 (financialData) Step2Saved --> Step3Advanced: applicant completes step 3 Step3Advanced --> Step4Saved: applicant saves step 4 (projectData) Step4Saved --> Step5Advanced: applicant completes step 5 Step5Advanced --> PendingReview: applicant submits (all sections + at least 1 doc) Draft --> PendingReview: applicant submits (all sections already complete) PendingReview --> [*]
Steps
1. Save Step 1 — Profile Data (Actor: acheteur or pro)
PUT /mortgage/applications/:id/step/1 with body { data: {...}, coBorrower?: {...} }.
- Writes
profileDataJSON to the application. - If
callerRole === "pro": also updates the placeholderAcheteurrecord with real name/email/phone fromdata. - If
coBorroweris a non-empty object: upserts aCoBorrowerrecord linked to the application. - If
coBorroweris an explicit empty object{}: deletes any existingCoBorrower. currentStepadvances toMath.max(currentStep, 1)— never goes backward.completionRateis recalculated: each of profileData, financialData, projectData, and docs present contributes 25%.
Triggers: User completes the personal profile form
Outcome: profileData persisted, optional co-borrower record upserted or deleted, completionRate updated
2. Save Step 2 — Financial Data (Actor: acheteur or pro)
PUT /mortgage/applications/:id/step/2 with body { data: {...} }.
- Writes
financialDataJSON column. - Advances
currentStepto at least 2. - Recalculates
completionRate.
Triggers: User completes the financial situation form
Outcome: financialData persisted
3. Save Step 3 — Advance Only (Actor: acheteur or pro)
PUT /mortgage/applications/:id/step/3 with body { data: {...} }.
- No dedicated JSON column —
datais accepted but not stored. - Advances
currentStepto at least 3. - Recalculates
completionRatebased on previously saved data.
Triggers: User completes step 3 UI (e.g. document review or declaration page)
Outcome: currentStep advanced
4. Save Step 4 — Project Data (Actor: acheteur or pro)
PUT /mortgage/applications/:id/step/4 with body { data: {...} }.
- Writes
projectDataJSON column. - Advances
currentStepto at least 4. - Recalculates
completionRate.
Triggers: User completes the property project form
Outcome: projectData persisted
5. Save Step 5 — Advance Only (Actor: acheteur or pro)
PUT /mortgage/applications/:id/step/5 with body { data: {...} }.
- No dedicated JSON column.
- Advances
currentStepto at least 5. - Recalculates
completionRate.
Triggers: User completes final review step
Outcome: currentStep advanced to 5
6. Submit Application (Actor: acheteur or pro)
POST /mortgage/applications/:id/submit.
Pre-conditions validated before submission:
profileData,financialData,projectDatamust all be non-null.- At least one
MortgageDocumentmust be linked to the application. - At least one active
Promust exist in the system to receive the assignment.
On success (Prisma transaction, atomic):
MortgageApplication.status→pending_reviewMortgageApplication.completionRate→ 100MortgageApplication.sentAt→ nowBrokerAssignmentcreated withstatus: "assigned"linked to the first active Pro.
Fire-and-forget Slack notification via notifyMortgageSubmission.
Triggers: User clicks “Submit” after completing all steps and uploading documents
Outcome: Application transitions to pending_review, broker is assigned, Slack notified
Error States
- Ownership violation (wrong
acheteurIdorproId) → 404, application not found - Invalid step number → no dedicated column but
currentStepstill advances - Submit with missing sections → 422,
INCOMPLETE_APPLICATION - Submit with no documents → 422,
NO_DOCUMENTS - Submit with no active Pro → 503,
NO_PRO_AVAILABLE
Related Processes
- application-creation — prerequisite, creates the draft
- document-upload-analysis — documents must be uploaded before submit
- broker-assignment-review — broker reviews once status is pending_review