/** * Cheque status lookup. * * There is no CBS endpoint for this yet — `endpoints.ts` has cheque book * requests and stop payments but nothing that answers "what happened to leaf * 123456". Until there is, the answer is resolved locally, in the same way the * dashboard, cards and loans resolve from fixtures today. * * The result is derived from the cheque number rather than drawn at random, so * the same number always gives the same answer. A demo that changes its mind * between two taps of the same button reads as a bug, and it makes the screen * impossible to write a test against. * * To go live, replace the body of `lookupChequeFate` with the API call. The * `ChequeFate` shape is what the screen renders, so it is the contract to map * the response onto. */ export type ChequeFateStatus = 'paid' | 'in_clearing' | 'returned' | 'stopped' | 'not_found'; export type ChequeFate = { chequeNumber: string; status: ChequeFateStatus; /** Short human label for the status, shown as the result headline. */ label: string; amount?: number; presentedOn?: string; clearedOn?: string; payee?: string; /** Why a cheque was returned or stopped. Absent for a clean outcome. */ reason?: string; /** The caveat under the result — what the customer should do next. */ note: string; }; const formatDay = (daysAgo: number) => { const date = new Date(); date.setDate(date.getDate() - daysAgo); return new Intl.DateTimeFormat('en-IN', { day: '2-digit', month: 'short', year: 'numeric', }).format(date); }; export type ChequeFateQuery = { accountNumber: string; chequeNumber: string; }; export const lookupChequeFate = async ({ accountNumber, chequeNumber, }: ChequeFateQuery): Promise => { // Stands in for the round trip, so the button's loading state is visible and // the screen is exercised the way it will behave against the real API. await new Promise((resolve) => setTimeout(resolve, 600)); const digits = Number.parseInt(chequeNumber, 10); // Mixing the account in means the same leaf number on two accounts gives two // answers, which is the behaviour the real ledger has. const seed = (Number.isNaN(digits) ? 0 : digits) + Number(accountNumber.slice(-2) || 0); const amount = 1500 + (seed % 220) * 125; switch (seed % 5) { case 0: return { chequeNumber, status: 'paid', label: 'Paid', amount, presentedOn: formatDay(6), clearedOn: formatDay(4), payee: 'Meghana Rao', note: 'Funds have left your account. The clearing house record is final.', }; case 1: return { chequeNumber, status: 'in_clearing', label: 'In clearing', amount, presentedOn: formatDay(1), payee: 'Sunrise Traders', note: 'Presented and awaiting settlement. Cheques normally clear within two working days.', }; case 2: return { chequeNumber, status: 'returned', label: 'Returned unpaid', amount, presentedOn: formatDay(3), payee: 'Vasan Electricals', reason: 'Insufficient funds', note: 'A return charge may apply. Contact your branch before re-presenting the cheque.', }; case 3: return { chequeNumber, status: 'stopped', label: 'Stop payment in force', amount, presentedOn: formatDay(2), reason: 'Stop payment requested by you', note: 'This cheque will not be paid while the stop instruction stands.', }; default: return { chequeNumber, status: 'not_found', label: 'No record found', note: 'This cheque has not been presented on the selected account. Check the number and the account, then try again.', }; } };