# Loan Offer flow

Apply `prisma/loan_offers.sql` once after the gold rate settings migration and generate the Prisma client. The migration adds `loan_offers`, `loan_offer_charges`, `applications.current_offer_id`, and the `CREDIT_APPROVAL` application status.

The Loan Offer queue uses `GET /api/crm/applications?status=LOAN_OFFER`. `GET /api/crm/applications/offer/:id` returns customer and evaluation summaries, the current offer, and prior versions. `PUT /api/crm/applications/offer/:id` saves terms. Send `expectedOfferId` as the current offer ID (or `null` for the first offer) to reject stale edits. An undecided offer is updated in place; an accepted or declined offer generates a new version with `AWAITING_DECISION`.

`POST /api/crm/loan-offers/decision/:offerId` accepts `decision` (`ACCEPTED` or `DECLINED`), `acceptanceMethod` (`IN_PERSON`, `DIGITAL`, `OTHER`) for acceptance, and `decisionRemark` for the optional acceptance note or required decline reason. It only changes the current undecided offer. Terms, fees, and net payout are calculated by the backend using the finalised evaluation's eligible amount. Processing fees are deducted upfront; additional charges are deducted only when `deductedUpfront` is true.

`PATCH /api/crm/applications/status/:id` moves a Loan Offer application to `CREDIT_APPROVAL` only when its current offer is accepted and KYC and evaluation remain valid. It can also reject the application with a required reason. Both status changes write history in the same transaction. Recording an offer decision does not move the application.

The Loan Offer detail page can download or open a printable PDF of the current saved offer. It refreshes the backend record before generating the document and disables PDF actions while terms are unsaved. The PDF shows the saved version, amounts, charges, payout, customer acknowledgment, and spaces for customer and staff signatures. Printing does not record the customer's decision; staff records acceptance or decline separately.
