@finsys/core 3.2.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +176 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +130 -2
- package/dist/index.d.ts +130 -2
- package/dist/index.js +168 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -57,12 +57,16 @@ __export(index_exports, {
|
|
|
57
57
|
applyAggregation: () => applyAggregation,
|
|
58
58
|
applyDynamicTitles: () => applyDynamicTitles,
|
|
59
59
|
assertAdapterCategory: () => assertAdapterCategory,
|
|
60
|
+
buildDocumentRows: () => buildDocumentRows,
|
|
60
61
|
buildFileFieldTables: () => buildFileFieldTables,
|
|
61
62
|
categoryFieldsOf: () => categoryFieldsOf,
|
|
62
63
|
categoryForField: () => categoryForField,
|
|
63
64
|
categorySchemaOf: () => categorySchemaOf,
|
|
64
65
|
evaluateExpression: () => evaluateExpression,
|
|
65
66
|
extractTimePeriods: () => extractTimePeriods,
|
|
67
|
+
formatDocumentSize: () => formatDocumentSize,
|
|
68
|
+
formatDocumentType: () => formatDocumentType,
|
|
69
|
+
formatDocumentUploaded: () => formatDocumentUploaded,
|
|
66
70
|
generateRHFSchema: () => generateRHFSchema,
|
|
67
71
|
generateSurveyJson: () => generateSurveyJson,
|
|
68
72
|
getBaseCategories: () => getBaseCategories,
|
|
@@ -72,9 +76,12 @@ __export(index_exports, {
|
|
|
72
76
|
getCategoryName: () => getCategoryName,
|
|
73
77
|
getDisplayName: () => getDisplayName,
|
|
74
78
|
getDisplayNames: () => getDisplayNames,
|
|
79
|
+
getDocDisplayNames: () => getDocDisplayNames,
|
|
80
|
+
getExtractableDocTypes: () => getExtractableDocTypes,
|
|
75
81
|
getGroupDisplayNames: () => getGroupDisplayNames,
|
|
76
82
|
getPastMonthLabel: () => getPastMonthLabel,
|
|
77
83
|
getPastYearLabel: () => getPastYearLabel,
|
|
84
|
+
getReuploadableDocTypes: () => getReuploadableDocTypes,
|
|
78
85
|
getStepDefaultValues: () => getStepDefaultValues,
|
|
79
86
|
getStepSchema: () => getStepSchema,
|
|
80
87
|
groupColumnsByTimePeriod: () => groupColumnsByTimePeriod,
|
|
@@ -85,6 +92,7 @@ __export(index_exports, {
|
|
|
85
92
|
isFailureIhsStatus: () => isFailureIhsStatus,
|
|
86
93
|
isTerminalIhsStatus: () => isTerminalIhsStatus,
|
|
87
94
|
isValidIhsStatus: () => isValidIhsStatus,
|
|
95
|
+
parseFileField: () => parseFileField,
|
|
88
96
|
processIhsDetails: () => processIhsDetails,
|
|
89
97
|
resolveExtractionStatus: () => resolveExtractionStatus,
|
|
90
98
|
resolvePageFields: () => resolvePageFields,
|
|
@@ -9461,7 +9469,7 @@ function formatValue(value, numeric) {
|
|
|
9461
9469
|
}
|
|
9462
9470
|
return String(value);
|
|
9463
9471
|
}
|
|
9464
|
-
function buildTableForGroup(groupName, fields, ihsData) {
|
|
9472
|
+
function buildTableForGroup(groupName, fields, ihsData, fieldProvenance) {
|
|
9465
9473
|
const allColumns = [];
|
|
9466
9474
|
for (const field of fields) {
|
|
9467
9475
|
if (field.ihs_column_names) {
|
|
@@ -9480,11 +9488,20 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9480
9488
|
const numeric = isNumericField(baseName);
|
|
9481
9489
|
const data = {};
|
|
9482
9490
|
const formattedData = {};
|
|
9491
|
+
const confidence = {};
|
|
9492
|
+
const provenance = {};
|
|
9483
9493
|
for (const period of periods) {
|
|
9484
9494
|
const colName = periodMap[period];
|
|
9485
9495
|
const value = colName ? ihsData[colName] ?? null : null;
|
|
9486
9496
|
data[period] = value;
|
|
9487
9497
|
formattedData[period] = formatValue(value, numeric);
|
|
9498
|
+
const prov = colName ? fieldProvenance?.[colName] : void 0;
|
|
9499
|
+
if (prov) {
|
|
9500
|
+
provenance[period] = prov;
|
|
9501
|
+
if (prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence)) {
|
|
9502
|
+
confidence[period] = prov.confidence;
|
|
9503
|
+
}
|
|
9504
|
+
}
|
|
9488
9505
|
}
|
|
9489
9506
|
items.push({
|
|
9490
9507
|
displayName: getDisplayName(baseName),
|
|
@@ -9492,7 +9509,9 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9492
9509
|
data,
|
|
9493
9510
|
formattedData,
|
|
9494
9511
|
type: tableType,
|
|
9495
|
-
isNumeric: numeric
|
|
9512
|
+
isNumeric: numeric,
|
|
9513
|
+
...Object.keys(confidence).length ? { confidence } : {},
|
|
9514
|
+
...Object.keys(provenance).length ? { provenance } : {}
|
|
9496
9515
|
});
|
|
9497
9516
|
}
|
|
9498
9517
|
const hasData = items.some(
|
|
@@ -9504,13 +9523,16 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9504
9523
|
for (const colName of allColumns) {
|
|
9505
9524
|
const value = ihsData[colName] ?? null;
|
|
9506
9525
|
const numeric = isNumericField(colName);
|
|
9526
|
+
const prov = fieldProvenance?.[colName];
|
|
9507
9527
|
items.push({
|
|
9508
9528
|
displayName: getDisplayName(colName),
|
|
9509
9529
|
timePeriods: [],
|
|
9510
9530
|
data: { value },
|
|
9511
9531
|
formattedData: { value: formatValue(value, numeric) },
|
|
9512
9532
|
type: tableType,
|
|
9513
|
-
isNumeric: numeric
|
|
9533
|
+
isNumeric: numeric,
|
|
9534
|
+
...prov && prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence) ? { confidence: { value: prov.confidence } } : {},
|
|
9535
|
+
...prov ? { provenance: { value: prov } } : {}
|
|
9514
9536
|
});
|
|
9515
9537
|
}
|
|
9516
9538
|
const hasData = items.some((item) => {
|
|
@@ -9520,19 +9542,160 @@ function buildTableForGroup(groupName, fields, ihsData) {
|
|
|
9520
9542
|
return { name: groupName, displayName: groupDisplayName, type: tableType, items, hasData };
|
|
9521
9543
|
}
|
|
9522
9544
|
}
|
|
9523
|
-
function buildFileFieldTables(ihsData) {
|
|
9545
|
+
function buildFileFieldTables(ihsData, fieldProvenance) {
|
|
9524
9546
|
const specs = getBaseFieldSpecs();
|
|
9525
9547
|
const fileFields = specs.filter((f) => f.type === "file" && f.ihs_column_names?.length);
|
|
9526
9548
|
const grouped = groupFieldsByPattern(fileFields);
|
|
9527
9549
|
const tables = {};
|
|
9528
9550
|
for (const [groupName, fields] of Object.entries(grouped)) {
|
|
9529
|
-
const table = buildTableForGroup(groupName, fields, ihsData);
|
|
9551
|
+
const table = buildTableForGroup(groupName, fields, ihsData, fieldProvenance);
|
|
9530
9552
|
if (table && table.hasData) {
|
|
9531
9553
|
tables[groupName] = table;
|
|
9532
9554
|
}
|
|
9533
9555
|
}
|
|
9534
9556
|
return tables;
|
|
9535
9557
|
}
|
|
9558
|
+
var DOC_DISPLAY_NAMES = {
|
|
9559
|
+
bankStatements: "Bank Statements",
|
|
9560
|
+
financialStatements: "Financial Statements",
|
|
9561
|
+
form9: "Form 9",
|
|
9562
|
+
epfStatements: "EPF Statements",
|
|
9563
|
+
payslips: "Payslips",
|
|
9564
|
+
ssm: "SSM Company Profile",
|
|
9565
|
+
ic: "Identity Card",
|
|
9566
|
+
ssm_registration_documents: "Form 9",
|
|
9567
|
+
ic_documents: "Identity Documents (Supplementary)",
|
|
9568
|
+
consentForm: "Consent Form",
|
|
9569
|
+
supplementaryDoc: "Supplementary Documents",
|
|
9570
|
+
coreIncomeDoc: "Core Income Document",
|
|
9571
|
+
incomeSupportingDoc: "Income Supporting Document",
|
|
9572
|
+
incomeEPF_iakaun: "EPF i-Akaun",
|
|
9573
|
+
photocopyRegistrationCard: "Registration Card",
|
|
9574
|
+
bankStatementOrSavingPassbook: "Bank Passbook",
|
|
9575
|
+
tnbBills: "TNB Bills"
|
|
9576
|
+
};
|
|
9577
|
+
var EXTRACTABLE_DOC_TYPES = /* @__PURE__ */ new Set([
|
|
9578
|
+
"bankStatements",
|
|
9579
|
+
"financialStatements",
|
|
9580
|
+
"form9",
|
|
9581
|
+
"epfStatements",
|
|
9582
|
+
"payslips",
|
|
9583
|
+
"ssm",
|
|
9584
|
+
"ic",
|
|
9585
|
+
"ssm_registration_documents",
|
|
9586
|
+
"ic_documents"
|
|
9587
|
+
]);
|
|
9588
|
+
var REUPLOADABLE_DOC_TYPES = /* @__PURE__ */ new Set(["bankStatements", "financialStatements"]);
|
|
9589
|
+
function getDocDisplayNames() {
|
|
9590
|
+
return DOC_DISPLAY_NAMES;
|
|
9591
|
+
}
|
|
9592
|
+
function getExtractableDocTypes() {
|
|
9593
|
+
return EXTRACTABLE_DOC_TYPES;
|
|
9594
|
+
}
|
|
9595
|
+
function getReuploadableDocTypes() {
|
|
9596
|
+
return REUPLOADABLE_DOC_TYPES;
|
|
9597
|
+
}
|
|
9598
|
+
function isProbablyId(str) {
|
|
9599
|
+
if (!str) return false;
|
|
9600
|
+
const clean = str.split(".")[0];
|
|
9601
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(clean)) return true;
|
|
9602
|
+
if (/^[0-9a-f]{32,128}$/i.test(clean)) return true;
|
|
9603
|
+
return false;
|
|
9604
|
+
}
|
|
9605
|
+
function parseFileField(value) {
|
|
9606
|
+
if (!value) return [];
|
|
9607
|
+
if (Array.isArray(value)) return value;
|
|
9608
|
+
if (typeof value === "string") {
|
|
9609
|
+
try {
|
|
9610
|
+
const parsed = JSON.parse(value);
|
|
9611
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
9612
|
+
} catch {
|
|
9613
|
+
if (value.startsWith("http")) {
|
|
9614
|
+
return [{ path: value, documentId: value.split("/").pop() || void 0 }];
|
|
9615
|
+
}
|
|
9616
|
+
return [];
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
return [];
|
|
9620
|
+
}
|
|
9621
|
+
function toBytes(value) {
|
|
9622
|
+
if (typeof value === "number") return Number.isNaN(value) ? null : value;
|
|
9623
|
+
if (typeof value === "string") {
|
|
9624
|
+
const n = parseInt(value, 10);
|
|
9625
|
+
return Number.isNaN(n) ? null : n;
|
|
9626
|
+
}
|
|
9627
|
+
return null;
|
|
9628
|
+
}
|
|
9629
|
+
function buildDocumentRows(ihsData) {
|
|
9630
|
+
const metaMap = ihsData.documentMetadata ?? {};
|
|
9631
|
+
const rows = [];
|
|
9632
|
+
for (const docType of Object.keys(DOC_DISPLAY_NAMES)) {
|
|
9633
|
+
const files = parseFileField(ihsData[docType]);
|
|
9634
|
+
if (files.length === 0) continue;
|
|
9635
|
+
const label = DOC_DISPLAY_NAMES[docType];
|
|
9636
|
+
const extractable = EXTRACTABLE_DOC_TYPES.has(docType);
|
|
9637
|
+
const reUploadable = extractable && REUPLOADABLE_DOC_TYPES.has(docType);
|
|
9638
|
+
files.forEach((file, index) => {
|
|
9639
|
+
const path = file.path ?? null;
|
|
9640
|
+
const meta = path ? metaMap[path] : void 0;
|
|
9641
|
+
const documentId = file.documentId || (path ? path.split("/").pop() || null : null);
|
|
9642
|
+
const timePeriod = file.month ? `T${file.month}` : file.year ? `T${file.year}` : "ALL";
|
|
9643
|
+
const rawName = file.fileName ?? meta?.fileName ?? void 0;
|
|
9644
|
+
const fileName = rawName && !isProbablyId(rawName) ? rawName : null;
|
|
9645
|
+
const rawExt = (rawName ?? "").split(".").pop();
|
|
9646
|
+
const ext = rawExt && rawExt.length <= 5 && !isProbablyId(rawExt) ? rawExt.toUpperCase() : null;
|
|
9647
|
+
const mime = file.fileType ?? meta?.fileType;
|
|
9648
|
+
const fileType = ext || (mime?.split("/").pop()?.toUpperCase() ?? null);
|
|
9649
|
+
const fileSize = toBytes(file.fileSize) ?? meta?.fileSize ?? null;
|
|
9650
|
+
const uploadedAt = file.createdAt ?? meta?.createdAt ?? null;
|
|
9651
|
+
const periodLabel = file.month && file.year ? new Date(file.year, file.month - 1).toLocaleDateString("en-MY", {
|
|
9652
|
+
year: "numeric",
|
|
9653
|
+
month: "short"
|
|
9654
|
+
}) : file.year ? `Year ${file.year}` : null;
|
|
9655
|
+
const displayName = fileName || (periodLabel ? `${label} \u2014 ${periodLabel}` : files.length > 1 ? `${label} ${index + 1}` : label);
|
|
9656
|
+
rows.push({
|
|
9657
|
+
docType,
|
|
9658
|
+
label,
|
|
9659
|
+
index,
|
|
9660
|
+
displayName,
|
|
9661
|
+
documentId,
|
|
9662
|
+
path,
|
|
9663
|
+
timePeriod,
|
|
9664
|
+
periodLabel,
|
|
9665
|
+
fileName,
|
|
9666
|
+
fileType,
|
|
9667
|
+
fileSize,
|
|
9668
|
+
uploadedAt,
|
|
9669
|
+
capabilities: {
|
|
9670
|
+
download: !!documentId,
|
|
9671
|
+
viewJson: extractable,
|
|
9672
|
+
reExtract: extractable,
|
|
9673
|
+
reUpload: reUploadable
|
|
9674
|
+
}
|
|
9675
|
+
});
|
|
9676
|
+
});
|
|
9677
|
+
}
|
|
9678
|
+
return rows;
|
|
9679
|
+
}
|
|
9680
|
+
var EM_DASH = "\u2014";
|
|
9681
|
+
function formatDocumentType(row) {
|
|
9682
|
+
return row.fileType ?? EM_DASH;
|
|
9683
|
+
}
|
|
9684
|
+
function formatDocumentSize(bytes) {
|
|
9685
|
+
if (!bytes || Number.isNaN(bytes)) return EM_DASH;
|
|
9686
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
9687
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
9688
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
9689
|
+
}
|
|
9690
|
+
function formatDocumentUploaded(row) {
|
|
9691
|
+
if (row.uploadedAt) {
|
|
9692
|
+
const d = new Date(row.uploadedAt);
|
|
9693
|
+
if (!Number.isNaN(d.getTime())) {
|
|
9694
|
+
return d.toLocaleDateString("en-MY", { year: "numeric", month: "short", day: "numeric" });
|
|
9695
|
+
}
|
|
9696
|
+
}
|
|
9697
|
+
return row.periodLabel ?? EM_DASH;
|
|
9698
|
+
}
|
|
9536
9699
|
function isFileOrFinancialColumn(fieldName, fileColumnSet) {
|
|
9537
9700
|
return fileColumnSet.has(fieldName) || fieldName.startsWith("financials") || fieldName.startsWith("bank_statement");
|
|
9538
9701
|
}
|
|
@@ -10456,12 +10619,16 @@ function assertAdapterCategory(id) {
|
|
|
10456
10619
|
applyAggregation,
|
|
10457
10620
|
applyDynamicTitles,
|
|
10458
10621
|
assertAdapterCategory,
|
|
10622
|
+
buildDocumentRows,
|
|
10459
10623
|
buildFileFieldTables,
|
|
10460
10624
|
categoryFieldsOf,
|
|
10461
10625
|
categoryForField,
|
|
10462
10626
|
categorySchemaOf,
|
|
10463
10627
|
evaluateExpression,
|
|
10464
10628
|
extractTimePeriods,
|
|
10629
|
+
formatDocumentSize,
|
|
10630
|
+
formatDocumentType,
|
|
10631
|
+
formatDocumentUploaded,
|
|
10465
10632
|
generateRHFSchema,
|
|
10466
10633
|
generateSurveyJson,
|
|
10467
10634
|
getBaseCategories,
|
|
@@ -10471,9 +10638,12 @@ function assertAdapterCategory(id) {
|
|
|
10471
10638
|
getCategoryName,
|
|
10472
10639
|
getDisplayName,
|
|
10473
10640
|
getDisplayNames,
|
|
10641
|
+
getDocDisplayNames,
|
|
10642
|
+
getExtractableDocTypes,
|
|
10474
10643
|
getGroupDisplayNames,
|
|
10475
10644
|
getPastMonthLabel,
|
|
10476
10645
|
getPastYearLabel,
|
|
10646
|
+
getReuploadableDocTypes,
|
|
10477
10647
|
getStepDefaultValues,
|
|
10478
10648
|
getStepSchema,
|
|
10479
10649
|
groupColumnsByTimePeriod,
|
|
@@ -10484,6 +10654,7 @@ function assertAdapterCategory(id) {
|
|
|
10484
10654
|
isFailureIhsStatus,
|
|
10485
10655
|
isTerminalIhsStatus,
|
|
10486
10656
|
isValidIhsStatus,
|
|
10657
|
+
parseFileField,
|
|
10487
10658
|
processIhsDetails,
|
|
10488
10659
|
resolveExtractionStatus,
|
|
10489
10660
|
resolvePageFields,
|