Broker Assignment and Application Review
Summary
When a mortgage application is submitted, a BrokerAssignment record is created pointing to the first active Pro in the system. The assigned Pro can then list all their assignments, view full application detail, update the assignment status (which mirrors to the application status), and export a ZIP archive of the full dossier. Status transitions are kept in sync between BrokerAssignment and MortgageApplication via a Prisma transaction to guarantee consistency.
State Diagram
stateDiagram-v2 state "Dossier assigné" as Assigned state "Traitement en cours" as InProgress state "Dossier approuvé" as Approved state "Dossier refusé" as Refused [*] --> Assigned: BrokerAssignment created on application submit Assigned --> InProgress: Pro updates status to in_progress InProgress --> Approved: Pro approves → MortgageApplication.status = complete InProgress --> Refused: Pro refuses → MortgageApplication.status = rejected Assigned --> Approved: Direct approval without in_progress step Assigned --> Refused: Direct refusal Approved --> [*] Refused --> [*]
Steps
1. Assignment Creation (Actor: system)
Triggered automatically at the end of POST /mortgage/applications/:id/submit (see wizard-steps).
prisma.pro.findFirst({ where: { isActive: true } })— first active Pro in creation order.prisma.brokerAssignment.create({ data: { applicationId, proId, status: "assigned" } })— atomic with the application status update in a$transaction.notifyMortgageSubmission(buyerName, applicationId)— fire-and-forget Slack notification.
Triggers: Application successfully submitted
Outcome: BrokerAssignment with status: "assigned", Slack message posted
2. List Assigned Applications (Actor: pro)
GET /pro/applications — returns all BrokerAssignment records where proId = request.proId, ordered by most recently updated. Includes nested application summary with buyer info, property, and document analysis statuses.
Triggers: Pro opens their back-office dashboard Outcome: Array of assignments with lightweight application summaries
3. View Application Detail (Actor: pro)
GET /pro/applications/:id — finds the BrokerAssignment scoped to { applicationId: id, proId: request.proId }. Returns the full application with acheteur, property, all documents, and co-borrower data.
Cross-Pro access is prevented: a Pro can only retrieve applications assigned to them.
Triggers: Pro selects a specific application Outcome: Full application + assignment detail
4. Update Assignment Status (Actor: pro)
PUT /pro/applications/:id/status with body { status, notes? }.
Valid assignment statuses: assigned, in_progress, approved, refused.
Status mapping to application status (atomic Prisma transaction):
| Assignment status | Application status |
|---|---|
approved | complete |
refused | rejected |
| any other | sent |
Both BrokerAssignment and MortgageApplication are updated in the same $transaction — neither can succeed alone.
Triggers: Pro makes a decision or marks work in progress Outcome: Both assignment and application statuses updated atomically
5. Export Application as ZIP (Actor: pro)
GET /pro/applications/:id/export — generates a ZIP archive via generateMortgageExportZip() from lib/mortgage-export.ts.
Archive contents:
synthese.json— structured application summary (profile, financial, project, co-borrower, property, metadata)documents/{category}/{fileName}— all uploaded document files from disk
Response headers set to application/zip with Content-Disposition: attachment; filename="dossier-{id}.zip".
Triggers: Pro requests to download the complete dossier Outcome: ZIP buffer streamed as a file download
Error States
- No active Pro available at submission time → 503
NO_PRO_AVAILABLE(submit blocked) - Assignment not found or wrong Pro → 404
NOT_FOUND - Invalid status value → 400 (schema validation)
- Archive directory or files missing during export → 404 or partial ZIP
Related Processes
- wizard-steps — submission triggers assignment creation
- document-upload-analysis — uploaded documents are included in the ZIP export