feat(investment,reconciliation): add Export to Excel across Investment, fix export popup
Adds a shared Export to Excel utility (investment-export.ts) and wires it into every listing/report screen in the Investment module — Dashboard (break-up + allocation), Reports (all ~20 report shapes), Interest (per active tab), the FD/Bond/Share Holdings registers, and Masters (per active master tab). Entry/transaction forms intentionally have no export button. No sign-off is included here, matching the request to keep that feature reconciliation-only. Also fixes the Reconciliation export flow: the Prepared/Checked/Approved sign-off is now an optional one-off popup shown when "Export to Excel" is clicked (fields are blank by default and downloading works whether or not they're filled), replacing the earlier always-visible sign-off card. Also fixes three reconciliation reports (Sundry Dr/Cr, NEFT/RTGS, UDIR) whose labels contain "/" — an Excel-forbidden worksheet-name character — which was silently aborting their export.
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
LienReason,
|
||||
InstrumentType
|
||||
} from '../investment-data';
|
||||
import { exportWorkbook, ExportSheetSpec } from '../investment-export';
|
||||
|
||||
type MasterTab =
|
||||
| 'party'
|
||||
@@ -85,6 +86,20 @@ export class InvestmentMastersComponent {
|
||||
'SHARE'
|
||||
];
|
||||
|
||||
private readonly masterLabels: Record<MasterTab, string> = {
|
||||
party: 'Bank / Party Master',
|
||||
script: 'Script Master',
|
||||
subtype: 'SubType Master',
|
||||
broker: 'Broker Master',
|
||||
control: 'Control Parameter',
|
||||
dailyscript: 'Daily Script Master',
|
||||
lien: 'LIEN Reason Master',
|
||||
mfproduct: 'Mutual Fund Product Master',
|
||||
sglbank: 'SGL Bank Master',
|
||||
marketdetail: 'Script Market Detail'
|
||||
};
|
||||
|
||||
generating = false;
|
||||
toastMsg = '';
|
||||
toastVisible = false;
|
||||
private toastTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
@@ -251,6 +266,244 @@ export class InvestmentMastersComponent {
|
||||
this.toast('Daily script rate added.');
|
||||
}
|
||||
|
||||
// -------------------- Export to Excel --------------------
|
||||
private exportSheets(): ExportSheetSpec[] {
|
||||
const title = this.masterLabels[this.activeTab];
|
||||
const one = (headers: string[], widths: number[], rows: (string | number | null)[][]): ExportSheetSpec[] => [
|
||||
{ sheetName: title, title, headers, widths, rows }];
|
||||
|
||||
switch (this.activeTab) {
|
||||
case 'party':
|
||||
return one(
|
||||
[
|
||||
'Party Code',
|
||||
'Party Name',
|
||||
'Type',
|
||||
'PAN No'
|
||||
],
|
||||
[
|
||||
12,
|
||||
30,
|
||||
16,
|
||||
14
|
||||
],
|
||||
this.parties.map((p) => [
|
||||
p.partyCode,
|
||||
p.partyName,
|
||||
p.partyType,
|
||||
p.panNo
|
||||
])
|
||||
);
|
||||
case 'script':
|
||||
return one(
|
||||
[
|
||||
'Script Code',
|
||||
'Script Name',
|
||||
'Instrument',
|
||||
'ISIN',
|
||||
'Face Value/Unit'
|
||||
],
|
||||
[
|
||||
16,
|
||||
30,
|
||||
16,
|
||||
16,
|
||||
16
|
||||
],
|
||||
this.scripts.map((s) => [
|
||||
s.scriptCode,
|
||||
s.scriptName,
|
||||
s.instrumentType,
|
||||
s.isin,
|
||||
s.faceValuePerUnit
|
||||
])
|
||||
);
|
||||
case 'subtype':
|
||||
return one(
|
||||
[
|
||||
'Code',
|
||||
'Sub Type',
|
||||
'Instrument'
|
||||
],
|
||||
[
|
||||
10,
|
||||
24,
|
||||
16
|
||||
],
|
||||
this.subTypes.map((s) => [
|
||||
s.subTypeCode,
|
||||
s.subTypeName,
|
||||
s.instrumentType
|
||||
])
|
||||
);
|
||||
case 'broker':
|
||||
return one(
|
||||
[
|
||||
'Broker Code',
|
||||
'Broker Name',
|
||||
'Contact',
|
||||
'Empanelled On',
|
||||
'Status'
|
||||
],
|
||||
[
|
||||
14,
|
||||
30,
|
||||
16,
|
||||
16,
|
||||
12
|
||||
],
|
||||
this.brokers.map((b) => [
|
||||
b.brokerCode,
|
||||
b.brokerName,
|
||||
b.contactNo,
|
||||
b.empanelledOn,
|
||||
b.status
|
||||
])
|
||||
);
|
||||
case 'control':
|
||||
return one(
|
||||
[
|
||||
'Parameter',
|
||||
'Value',
|
||||
'Description'
|
||||
],
|
||||
[
|
||||
26,
|
||||
14,
|
||||
40
|
||||
],
|
||||
this.controlParams.map((c) => [
|
||||
c.paramName,
|
||||
c.paramValue,
|
||||
c.description
|
||||
])
|
||||
);
|
||||
case 'dailyscript':
|
||||
return one(
|
||||
[
|
||||
'Rate Date',
|
||||
'Script Code',
|
||||
'Script Name',
|
||||
'Open',
|
||||
'High',
|
||||
'Low',
|
||||
'Close'
|
||||
],
|
||||
[
|
||||
14,
|
||||
16,
|
||||
26,
|
||||
12,
|
||||
12,
|
||||
12,
|
||||
12
|
||||
],
|
||||
this.dailyScriptRates.map((r) => [
|
||||
r.rateDate,
|
||||
r.scriptCode,
|
||||
r.scriptName,
|
||||
r.openRate,
|
||||
r.highRate,
|
||||
r.lowRate,
|
||||
r.closeRate
|
||||
])
|
||||
);
|
||||
case 'lien':
|
||||
return one(
|
||||
[
|
||||
'Reason Code',
|
||||
'Description'
|
||||
],
|
||||
[
|
||||
14,
|
||||
40
|
||||
],
|
||||
this.lienReasons.map((l) => [
|
||||
l.reasonCode,
|
||||
l.reasonDescription
|
||||
])
|
||||
);
|
||||
case 'mfproduct':
|
||||
return one(
|
||||
[
|
||||
'Product Code',
|
||||
'Product Name',
|
||||
'AMC',
|
||||
'Category',
|
||||
'Risk'
|
||||
],
|
||||
[
|
||||
14,
|
||||
30,
|
||||
24,
|
||||
20,
|
||||
12
|
||||
],
|
||||
this.mfProducts.map((m) => [
|
||||
m.productCode,
|
||||
m.productName,
|
||||
m.amcName,
|
||||
m.category,
|
||||
m.riskLevel
|
||||
])
|
||||
);
|
||||
case 'sglbank':
|
||||
return one(
|
||||
[
|
||||
'SGL Code',
|
||||
'Bank Name',
|
||||
'Branch'
|
||||
],
|
||||
[
|
||||
14,
|
||||
30,
|
||||
24
|
||||
],
|
||||
this.sglBanks.map((s) => [
|
||||
s.sglCode,
|
||||
s.bankName,
|
||||
s.branch
|
||||
])
|
||||
);
|
||||
case 'marketdetail':
|
||||
return one(
|
||||
[
|
||||
'Script Code',
|
||||
'Market Price',
|
||||
'As On',
|
||||
'YTM %'
|
||||
],
|
||||
[
|
||||
16,
|
||||
16,
|
||||
14,
|
||||
12
|
||||
],
|
||||
this.marketDetails.map((m) => [
|
||||
m.scriptCode,
|
||||
m.marketPrice,
|
||||
m.asOnDate,
|
||||
m.ytm
|
||||
])
|
||||
);
|
||||
default:
|
||||
return one([], [], []);
|
||||
}
|
||||
}
|
||||
|
||||
async exportExcel(): Promise<void> {
|
||||
this.generating = true;
|
||||
try {
|
||||
await exportWorkbook(this.exportSheets(), `Investment-${this.masterLabels[this.activeTab]}`);
|
||||
this.toast(`${this.masterLabels[this.activeTab]} exported.`);
|
||||
} catch (err) {
|
||||
console.error('Investment Masters export failed', err);
|
||||
this.toast('Could not generate the workbook — please retry.');
|
||||
} finally {
|
||||
this.generating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private toast(msg: string): void {
|
||||
this.toastMsg = msg;
|
||||
this.toastVisible = true;
|
||||
|
||||
Reference in New Issue
Block a user