Files
cbsnexora/src/app/shares/share-receipt-option.ts
T
2026-09-23 15:51:10 +05:30

86 lines
3.2 KiB
TypeScript

/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/**
* One Share Collection receipt the counter can choose, in a single shape whatever it came from.
*
* {@code GET /shareadvancecollection/unattributed} answers with two differently-shaped lists — the
* member's own receipts under {@code own}, and every other receipt still going spare under
* {@code rows} — and normalising both to this on arrival is what lets a screen show one plain list
* of vouchers instead of two tables whose difference a counter has to understand before they can
* pick anything.
*
* Shared by the two screens that settle a share purchase (the first application's Apply Collection
* dialog and the Apply Additional Shares dialog) so a receipt reads identically on both.
*/
export interface ReceiptOption {
/** Stable identity for tracking and comparison; unique across both source lists. */
key: string;
/**
* The {@code m_share_advance_collection} row behind this receipt, or null while it is still only
* a voucher number. A null one is attached to the member on first pick.
*/
collectionId: number | null;
voucherNo: string;
glAccountNo: string;
glAccountName: string;
date: string;
amount: number;
description: string;
cashierName: string;
}
/**
* A receipt that already has an {@code m_share_advance_collection} row — ready to settle as-is.
*
* Also the shape {@code GET /shareadvancecollection/by-voucher} answers with, so a receipt found by
* number arrives here too, already attached.
*/
export function receiptFromOwn(row: any): ReceiptOption {
return {
key: `c${row.id}`,
collectionId: Number(row.id),
voucherNo: row.voucher_no || row.receipt_no || '',
glAccountNo: row.gl_code || '',
glAccountName: '',
date: String(row.collection_date || '').slice(0, 10),
amount: Number(row.amount || 0),
description: row.note || '',
cashierName: row.collected_by_name || ''
};
}
/** A receipt that is still only a voucher, attached to the member when it is picked. */
export function receiptFromUnattached(row: any): ReceiptOption {
return {
key: `v${row.id}`,
collectionId: null,
voucherNo: row.voucherNo || '',
glAccountNo: row.glAccountNo || '',
glAccountName: row.glAccountName || '',
date: String(row.txnDate || '').slice(0, 10),
amount: Number(row.amount || 0),
description: row.description || '',
cashierName: row.cashierName || ''
};
}
/**
* The GL account a receipt sits in, named where the name is known and coded where it is not.
*
* An attached receipt carries only its {@code gl_code}, so the name is looked up in whatever GL
* account list the screen already loaded for its voucher search rather than fetched again.
*/
export function receiptGlLabel(option: ReceiptOption, glAccounts: any[]): string {
const name = option.glAccountName || glAccounts.find((gl) => gl.gl_code === option.glAccountNo)?.name || '';
if (!option.glAccountNo) {
return name || '—';
}
return name ? `${option.glAccountNo} — ${name}` : option.glAccountNo;
}