Files
2026-09-28 23:15:47 +05:30

74 lines
2.1 KiB
TypeScript

export const BILL_NOT_FOUND =
"Bill not found yet. If you just received the SMS, wait a moment and refresh.";
export type BillLine = {
description: string;
qty: number | string | null;
unitPrice: number;
lineTotal: number;
};
export type BillView = {
shopName: string;
address: string;
phone: string;
number: string;
createdAt: string;
customerName: string;
customerPhone: string;
vehicleReg: string;
vehicleModel: string;
lines: BillLine[];
total: number;
paymentMethod: string;
};
function isRecord(value: unknown): value is Record<string, unknown> {
return !!value && typeof value === "object" && !Array.isArray(value);
}
function asString(value: unknown): string {
return typeof value === "string" ? value : "";
}
function asNumber(value: unknown): number {
return typeof value === "number" && Number.isFinite(value) ? value : 0;
}
export function parseBill(raw: string): BillView | null {
let data: unknown;
try {
data = JSON.parse(raw);
} catch {
return null;
}
if (!isRecord(data)) return null;
const lines = Array.isArray(data.lines) ? data.lines.filter(isRecord) : [];
return {
shopName: asString(data.shopName),
address: asString(data.address),
phone: asString(data.phone),
number: asString(data.number),
createdAt: asString(data.createdAt),
customerName: asString(data.customerName),
customerPhone: asString(data.customerPhone),
vehicleReg: asString(data.vehicleReg),
vehicleModel: asString(data.vehicleModel),
lines: lines.map((line) => ({
description: asString(line.description),
qty: typeof line.qty === "number" || typeof line.qty === "string" ? line.qty : null,
unitPrice: asNumber(line.unitPrice),
lineTotal: asNumber(line.lineTotal),
})),
total: asNumber(data.total),
paymentMethod: asString(data.paymentMethod),
};
}
export function formatBillDate(iso: string): string {
if (!iso) return "";
const date = new Date(iso);
if (Number.isNaN(date.getTime())) return "";
return date.toLocaleString("en-LK", { timeZone: "Asia/Colombo" });
}