Files
CBS-Mobile-App/src/modules/services/utils/chequeFate.ts
T

119 lines
3.8 KiB
TypeScript

/**
* 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<ChequeFate> => {
// 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.',
};
}
};