@finsys/core 3.5.0 → 4.1.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 CHANGED
@@ -37,7 +37,6 @@ __export(index_exports, {
37
37
  BasicFormField: () => BasicFormField,
38
38
  DEFAULT_VALIDATOR_DEFINITIONS: () => DEFAULT_VALIDATOR_DEFINITIONS,
39
39
  DocExtractionStatus: () => DocExtractionStatus,
40
- ExtractionFileType: () => ExtractionFileType,
41
40
  ExtractionJobStatus: () => ExtractionJobStatus,
42
41
  FIELD_TYPE_DEFINITIONS: () => FIELD_TYPE_DEFINITIONS,
43
42
  FieldType: () => FieldType,
@@ -48,6 +47,7 @@ __export(index_exports, {
48
47
  FormFieldValidator: () => FormFieldValidator,
49
48
  FormSpec: () => FormSpec,
50
49
  IHS_FAILURE_STATUSES: () => IHS_FAILURE_STATUSES,
50
+ IHS_FIELD_ORIGINS: () => IHS_FIELD_ORIGINS,
51
51
  IHS_TERMINAL_STATUSES: () => IHS_TERMINAL_STATUSES,
52
52
  IHS_VALID_STATUSES: () => IHS_VALID_STATUSES,
53
53
  IhsStatus: () => IhsStatus,
@@ -57,8 +57,10 @@ __export(index_exports, {
57
57
  applyAggregation: () => applyAggregation,
58
58
  applyDynamicTitles: () => applyDynamicTitles,
59
59
  assertAdapterCategory: () => assertAdapterCategory,
60
+ assertDocumentType: () => assertDocumentType,
60
61
  buildDocumentRows: () => buildDocumentRows,
61
62
  buildFileFieldTables: () => buildFileFieldTables,
63
+ buildFileFieldTablesFromInstances: () => buildFileFieldTablesFromInstances,
62
64
  categoryFieldsOf: () => categoryFieldsOf,
63
65
  categoryForField: () => categoryForField,
64
66
  categorySchemaOf: () => categorySchemaOf,
@@ -77,6 +79,7 @@ __export(index_exports, {
77
79
  getDisplayName: () => getDisplayName,
78
80
  getDisplayNames: () => getDisplayNames,
79
81
  getDocDisplayNames: () => getDocDisplayNames,
82
+ getDocumentTypeGroups: () => getDocumentTypeGroups,
80
83
  getExtractableDocTypes: () => getExtractableDocTypes,
81
84
  getGroupDisplayNames: () => getGroupDisplayNames,
82
85
  getPastMonthLabel: () => getPastMonthLabel,
@@ -84,13 +87,16 @@ __export(index_exports, {
84
87
  getReuploadableDocTypes: () => getReuploadableDocTypes,
85
88
  getStepDefaultValues: () => getStepDefaultValues,
86
89
  getStepSchema: () => getStepSchema,
90
+ groupColumnsByInstance: () => groupColumnsByInstance,
87
91
  groupColumnsByTimePeriod: () => groupColumnsByTimePeriod,
88
92
  groupDetailsByCategory: () => groupDetailsByCategory,
89
93
  groupFieldsByCategory: () => groupFieldsByCategory,
90
94
  groupFieldsByPattern: () => groupFieldsByPattern,
91
95
  isAdapterCategory: () => isAdapterCategory,
96
+ isDocumentType: () => isDocumentType,
92
97
  isFailureIhsStatus: () => isFailureIhsStatus,
93
98
  isTerminalIhsStatus: () => isTerminalIhsStatus,
99
+ isValidIhsFieldOrigin: () => isValidIhsFieldOrigin,
94
100
  isValidIhsStatus: () => isValidIhsStatus,
95
101
  parseFileField: () => parseFileField,
96
102
  processIhsDetails: () => processIhsDetails,
@@ -8002,7 +8008,13 @@ var form_field_base_specs_default = {
8002
8008
  "openingBalanceT1",
8003
8009
  "bankBalanceT1"
8004
8010
  ],
8005
- category: "13"
8011
+ category: "13",
8012
+ document_type: "bankStatements",
8013
+ document_group: "bank_statements",
8014
+ document_group_label: "Bank Statements",
8015
+ wire_format: "path_array",
8016
+ document_slot: 1,
8017
+ time_period_unit: "month"
8006
8018
  },
8007
8019
  {
8008
8020
  name: "bank_statement_t2",
@@ -8018,7 +8030,13 @@ var form_field_base_specs_default = {
8018
8030
  "openingBalanceT2",
8019
8031
  "bankBalanceT2"
8020
8032
  ],
8021
- category: "13"
8033
+ category: "13",
8034
+ document_type: "bankStatements",
8035
+ document_group: "bank_statements",
8036
+ document_group_label: "Bank Statements",
8037
+ wire_format: "path_array",
8038
+ document_slot: 2,
8039
+ time_period_unit: "month"
8022
8040
  },
8023
8041
  {
8024
8042
  name: "bank_statement_t3",
@@ -8034,7 +8052,13 @@ var form_field_base_specs_default = {
8034
8052
  "openingBalanceT3",
8035
8053
  "bankBalanceT3"
8036
8054
  ],
8037
- category: "13"
8055
+ category: "13",
8056
+ document_type: "bankStatements",
8057
+ document_group: "bank_statements",
8058
+ document_group_label: "Bank Statements",
8059
+ wire_format: "path_array",
8060
+ document_slot: 3,
8061
+ time_period_unit: "month"
8038
8062
  },
8039
8063
  {
8040
8064
  name: "bank_statement_t4",
@@ -8050,7 +8074,13 @@ var form_field_base_specs_default = {
8050
8074
  "openingBalanceT4",
8051
8075
  "bankBalanceT4"
8052
8076
  ],
8053
- category: "13"
8077
+ category: "13",
8078
+ document_type: "bankStatements",
8079
+ document_group: "bank_statements",
8080
+ document_group_label: "Bank Statements",
8081
+ wire_format: "path_array",
8082
+ document_slot: 4,
8083
+ time_period_unit: "month"
8054
8084
  },
8055
8085
  {
8056
8086
  name: "bank_statement_t5",
@@ -8066,7 +8096,13 @@ var form_field_base_specs_default = {
8066
8096
  "openingBalanceT5",
8067
8097
  "bankBalanceT5"
8068
8098
  ],
8069
- category: "13"
8099
+ category: "13",
8100
+ document_type: "bankStatements",
8101
+ document_group: "bank_statements",
8102
+ document_group_label: "Bank Statements",
8103
+ wire_format: "path_array",
8104
+ document_slot: 5,
8105
+ time_period_unit: "month"
8070
8106
  },
8071
8107
  {
8072
8108
  name: "bank_statement_t6",
@@ -8082,7 +8118,13 @@ var form_field_base_specs_default = {
8082
8118
  "openingBalanceT6",
8083
8119
  "bankBalanceT6"
8084
8120
  ],
8085
- category: "13"
8121
+ category: "13",
8122
+ document_type: "bankStatements",
8123
+ document_group: "bank_statements",
8124
+ document_group_label: "Bank Statements",
8125
+ wire_format: "path_array",
8126
+ document_slot: 6,
8127
+ time_period_unit: "month"
8086
8128
  },
8087
8129
  {
8088
8130
  name: "financials",
@@ -8103,7 +8145,13 @@ var form_field_base_specs_default = {
8103
8145
  "netOperatingCashFlow",
8104
8146
  "ebitda"
8105
8147
  ],
8106
- category: "13"
8148
+ category: "13",
8149
+ document_type: "financialStatements",
8150
+ document_group: "financials",
8151
+ document_group_label: "Audited Financial Statements",
8152
+ wire_format: "path_array",
8153
+ document_slot: 1,
8154
+ time_period_unit: "year"
8107
8155
  },
8108
8156
  {
8109
8157
  name: "financials_fincap_t1",
@@ -8347,7 +8395,13 @@ var form_field_base_specs_default = {
8347
8395
  "depreciationOfInvestmentSecuritiesT2",
8348
8396
  "endOfYearCashT2"
8349
8397
  ],
8350
- category: "13"
8398
+ category: "13",
8399
+ document_type: "financialStatements",
8400
+ document_group: "financials",
8401
+ document_group_label: "Audited Financial Statements",
8402
+ wire_format: "path_array",
8403
+ document_slot: 1,
8404
+ time_period_unit: "year"
8351
8405
  },
8352
8406
  {
8353
8407
  name: "financials_fincap_t2",
@@ -8473,7 +8527,13 @@ var form_field_base_specs_default = {
8473
8527
  "depreciationOfInvestmentSecuritiesT3",
8474
8528
  "endOfYearCashT3"
8475
8529
  ],
8476
- category: "13"
8530
+ category: "13",
8531
+ document_type: "financialStatements",
8532
+ document_group: "financials",
8533
+ document_group_label: "Audited Financial Statements",
8534
+ wire_format: "path_array",
8535
+ document_slot: 2,
8536
+ time_period_unit: "year"
8477
8537
  },
8478
8538
  {
8479
8539
  name: "form9",
@@ -8484,7 +8544,11 @@ var form_field_base_specs_default = {
8484
8544
  "companyName",
8485
8545
  "companyRegNo"
8486
8546
  ],
8487
- category: "13"
8547
+ category: "13",
8548
+ document_type: "form9",
8549
+ document_group: "form9",
8550
+ document_group_label: "Form 9 / Section 17 / Form D",
8551
+ wire_format: "url_string"
8488
8552
  },
8489
8553
  {
8490
8554
  name: "ssm",
@@ -8508,7 +8572,11 @@ var form_field_base_specs_default = {
8508
8572
  "businessOrigin",
8509
8573
  "registeredAddress"
8510
8574
  ],
8511
- category: "13"
8575
+ category: "13",
8576
+ document_type: "ssm",
8577
+ document_group: "ssm_documents",
8578
+ document_group_label: "SSM Company Information",
8579
+ wire_format: "url_string"
8512
8580
  },
8513
8581
  {
8514
8582
  name: "ic",
@@ -8525,7 +8593,11 @@ var form_field_base_specs_default = {
8525
8593
  "icNationality",
8526
8594
  "icRace"
8527
8595
  ],
8528
- category: "13"
8596
+ category: "13",
8597
+ document_type: "ic",
8598
+ document_group: "ic_documents",
8599
+ document_group_label: "Identification Card",
8600
+ wire_format: "url_string"
8529
8601
  },
8530
8602
  {
8531
8603
  name: "epf_statement_t1",
@@ -8542,7 +8614,13 @@ var form_field_base_specs_default = {
8542
8614
  "epfTotalContributionT1",
8543
8615
  "epfTotalCurrentContributionT1"
8544
8616
  ],
8545
- category: "13"
8617
+ category: "13",
8618
+ document_type: "epfStatements",
8619
+ document_group: "epf_statements",
8620
+ document_group_label: "EPF Statements",
8621
+ wire_format: "path_array",
8622
+ document_slot: 1,
8623
+ time_period_unit: "year"
8546
8624
  },
8547
8625
  {
8548
8626
  name: "epf_statement_t2",
@@ -8559,7 +8637,13 @@ var form_field_base_specs_default = {
8559
8637
  "epfTotalContributionT2",
8560
8638
  "epfTotalCurrentContributionT2"
8561
8639
  ],
8562
- category: "13"
8640
+ category: "13",
8641
+ document_type: "epfStatements",
8642
+ document_group: "epf_statements",
8643
+ document_group_label: "EPF Statements",
8644
+ wire_format: "path_array",
8645
+ document_slot: 2,
8646
+ time_period_unit: "year"
8563
8647
  },
8564
8648
  {
8565
8649
  name: "payslip_statement_t1",
@@ -8582,7 +8666,13 @@ var form_field_base_specs_default = {
8582
8666
  "payslipEmployeeTaxT1",
8583
8667
  "payslipOtherDeductionT1"
8584
8668
  ],
8585
- category: "13"
8669
+ category: "13",
8670
+ document_type: "payslips",
8671
+ document_group: "payslip_statements",
8672
+ document_group_label: "Payslip Statements",
8673
+ wire_format: "path_array",
8674
+ document_slot: 1,
8675
+ time_period_unit: "month"
8586
8676
  },
8587
8677
  {
8588
8678
  name: "payslip_statement_t2",
@@ -8605,7 +8695,13 @@ var form_field_base_specs_default = {
8605
8695
  "payslipEmployeeTaxT2",
8606
8696
  "payslipOtherDeductionT2"
8607
8697
  ],
8608
- category: "13"
8698
+ category: "13",
8699
+ document_type: "payslips",
8700
+ document_group: "payslip_statements",
8701
+ document_group_label: "Payslip Statements",
8702
+ wire_format: "path_array",
8703
+ document_slot: 2,
8704
+ time_period_unit: "month"
8609
8705
  },
8610
8706
  {
8611
8707
  name: "payslip_statement_t3",
@@ -8628,7 +8724,13 @@ var form_field_base_specs_default = {
8628
8724
  "payslipEmployeeTaxT3",
8629
8725
  "payslipOtherDeductionT3"
8630
8726
  ],
8631
- category: "13"
8727
+ category: "13",
8728
+ document_type: "payslips",
8729
+ document_group: "payslip_statements",
8730
+ document_group_label: "Payslip Statements",
8731
+ wire_format: "path_array",
8732
+ document_slot: 3,
8733
+ time_period_unit: "month"
8632
8734
  },
8633
8735
  {
8634
8736
  name: "payslip_statement_t4",
@@ -8651,7 +8753,13 @@ var form_field_base_specs_default = {
8651
8753
  "payslipEmployeeTaxT4",
8652
8754
  "payslipOtherDeductionT4"
8653
8755
  ],
8654
- category: "13"
8756
+ category: "13",
8757
+ document_type: "payslips",
8758
+ document_group: "payslip_statements",
8759
+ document_group_label: "Payslip Statements",
8760
+ wire_format: "path_array",
8761
+ document_slot: 4,
8762
+ time_period_unit: "month"
8655
8763
  },
8656
8764
  {
8657
8765
  name: "payslip_statement_t5",
@@ -8674,7 +8782,13 @@ var form_field_base_specs_default = {
8674
8782
  "payslipEmployeeTaxT5",
8675
8783
  "payslipOtherDeductionT5"
8676
8784
  ],
8677
- category: "13"
8785
+ category: "13",
8786
+ document_type: "payslips",
8787
+ document_group: "payslip_statements",
8788
+ document_group_label: "Payslip Statements",
8789
+ wire_format: "path_array",
8790
+ document_slot: 5,
8791
+ time_period_unit: "month"
8678
8792
  },
8679
8793
  {
8680
8794
  name: "payslip_statement_t6",
@@ -8697,7 +8811,13 @@ var form_field_base_specs_default = {
8697
8811
  "payslipEmployeeTaxT6",
8698
8812
  "payslipOtherDeductionT6"
8699
8813
  ],
8700
- category: "13"
8814
+ category: "13",
8815
+ document_type: "payslips",
8816
+ document_group: "payslip_statements",
8817
+ document_group_label: "Payslip Statements",
8818
+ wire_format: "path_array",
8819
+ document_slot: 6,
8820
+ time_period_unit: "month"
8701
8821
  }
8702
8822
  ]
8703
8823
  };
@@ -9190,6 +9310,59 @@ var FileFieldTableType = /* @__PURE__ */ ((FileFieldTableType2) => {
9190
9310
  FileFieldTableType2["KEY_VALUE"] = "keyValue";
9191
9311
  return FileFieldTableType2;
9192
9312
  })(FileFieldTableType || {});
9313
+ var IHS_FIELD_ORIGINS = ["extracted", "derived", "manual"];
9314
+ function isValidIhsFieldOrigin(origin) {
9315
+ return typeof origin === "string" && IHS_FIELD_ORIGINS.includes(origin);
9316
+ }
9317
+
9318
+ // src/document-types.ts
9319
+ var cached = null;
9320
+ function buildDocumentTypeGroups() {
9321
+ const fileFields = getBaseFieldSpecs().filter(
9322
+ (f) => f.type === "file" && !!f.name
9323
+ );
9324
+ const order = [];
9325
+ const byDocumentType = /* @__PURE__ */ new Map();
9326
+ for (const f of fileFields) {
9327
+ const documentType = f.document_type ?? f.name;
9328
+ const documentGroup = f.document_group ?? documentType;
9329
+ const label = f.document_group_label ?? f.displayName ?? documentType;
9330
+ if (!byDocumentType.has(documentType)) {
9331
+ order.push(documentType);
9332
+ byDocumentType.set(documentType, {
9333
+ documentGroup,
9334
+ label,
9335
+ wireFormat: f.wire_format,
9336
+ fields: []
9337
+ });
9338
+ }
9339
+ byDocumentType.get(documentType).fields.push(f);
9340
+ }
9341
+ return order.map((documentType) => {
9342
+ const entry = byDocumentType.get(documentType);
9343
+ return {
9344
+ documentType,
9345
+ documentGroup: entry.documentGroup,
9346
+ label: entry.label,
9347
+ wireFormat: entry.wireFormat,
9348
+ fields: entry.fields
9349
+ };
9350
+ });
9351
+ }
9352
+ function getDocumentTypeGroups() {
9353
+ if (!cached) cached = buildDocumentTypeGroups();
9354
+ return cached;
9355
+ }
9356
+ function isDocumentType(id) {
9357
+ return getDocumentTypeGroups().some((g) => g.documentType === id);
9358
+ }
9359
+ function assertDocumentType(id) {
9360
+ if (!isDocumentType(id)) {
9361
+ const known = getDocumentTypeGroups().map((g) => g.documentType);
9362
+ throw new Error(`Unknown document type: "${id}". Available: ${known.join(", ")}`);
9363
+ }
9364
+ return id;
9365
+ }
9193
9366
 
9194
9367
  // src/data/form-field-display-names.json
9195
9368
  var form_field_display_names_default = {
@@ -9399,42 +9572,26 @@ function groupColumnsByTimePeriod(columnNames) {
9399
9572
  }
9400
9573
  return groups;
9401
9574
  }
9402
- var FIELD_GROUP_PREFIXES = [
9403
- ["bank_statement", "bank_statements"],
9404
- ["financials", "financials"],
9405
- ["epf_statement", "epf_statements"],
9406
- ["payslip_statement", "payslip_statements"],
9407
- ["ssm", "ssm_documents"],
9408
- ["form9", "form9"],
9409
- ["ic", "ic_documents"]
9410
- ];
9411
9575
  function groupFieldsByPattern(fields) {
9412
9576
  const groups = {};
9413
9577
  for (const field of fields) {
9414
9578
  if (!field.name) continue;
9415
- let groupName = field.name;
9416
- for (const [prefix, group] of FIELD_GROUP_PREFIXES) {
9417
- if (field.name.startsWith(prefix)) {
9418
- groupName = group;
9419
- break;
9420
- }
9421
- }
9579
+ const groupName = field.document_group ?? field.name;
9422
9580
  if (!groups[groupName]) groups[groupName] = [];
9423
9581
  groups[groupName].push(field);
9424
9582
  }
9425
9583
  return groups;
9426
9584
  }
9427
- var GROUP_DISPLAY_NAMES = {
9428
- bank_statements: "Bank Statements",
9429
- financials: "Audited Financial Statements",
9430
- epf_statements: "EPF Statements",
9431
- payslip_statements: "Payslip Statements",
9432
- form9: "Form 9 / Section 17 / Form D",
9433
- ssm_documents: "SSM Company Information",
9434
- ic_documents: "Identification Card"
9435
- };
9585
+ var cachedGroupDisplayNames = null;
9436
9586
  function getGroupDisplayNames() {
9437
- return GROUP_DISPLAY_NAMES;
9587
+ if (!cachedGroupDisplayNames) {
9588
+ const names = {};
9589
+ for (const group of getDocumentTypeGroups()) {
9590
+ names[group.documentGroup] = group.label;
9591
+ }
9592
+ cachedGroupDisplayNames = names;
9593
+ }
9594
+ return cachedGroupDisplayNames;
9438
9595
  }
9439
9596
  function isNumericField(fieldName) {
9440
9597
  const patterns = [
@@ -9479,7 +9636,7 @@ function buildTableForGroup(groupName, fields, ihsData, fieldProvenance) {
9479
9636
  const periods = extractTimePeriods(allColumns);
9480
9637
  const isTimeSeries = periods.length > 0;
9481
9638
  const tableType = isTimeSeries ? "timeSeries" /* TIME_SERIES */ : "keyValue" /* KEY_VALUE */;
9482
- const groupDisplayName = GROUP_DISPLAY_NAMES[groupName] || fields[0]?.displayName || getDisplayName(groupName);
9639
+ const groupDisplayName = getGroupDisplayNames()[groupName] || fields[0]?.displayName || getDisplayName(groupName);
9483
9640
  if (isTimeSeries) {
9484
9641
  const columnGroups = groupColumnsByTimePeriod(allColumns);
9485
9642
  const items = [];
@@ -9554,6 +9711,124 @@ function buildFileFieldTables(ihsData, fieldProvenance) {
9554
9711
  }
9555
9712
  return tables;
9556
9713
  }
9714
+ function instanceColumnLabel(row) {
9715
+ const period = row.timePeriod || row.instanceKey;
9716
+ return row.sourceLabel ? `${period} \xB7 ${row.sourceLabel}` : period;
9717
+ }
9718
+ function instanceColumnLabels(rows) {
9719
+ const seenCounts = /* @__PURE__ */ new Map();
9720
+ return rows.map((row) => {
9721
+ const raw = instanceColumnLabel(row);
9722
+ const occurrence = (seenCounts.get(raw) ?? 0) + 1;
9723
+ seenCounts.set(raw, occurrence);
9724
+ return occurrence === 1 ? raw : `${raw} (${occurrence})`;
9725
+ });
9726
+ }
9727
+ function groupColumnsByInstance(baseColumnNames, instanceRows) {
9728
+ const groups = {};
9729
+ for (const baseName of baseColumnNames) {
9730
+ groups[baseName] = {};
9731
+ }
9732
+ if (!instanceRows?.length) return groups;
9733
+ const labels = instanceColumnLabels(instanceRows);
9734
+ instanceRows.forEach((row, i) => {
9735
+ const label = labels[i];
9736
+ for (const baseName of baseColumnNames) {
9737
+ if (Object.prototype.hasOwnProperty.call(row, baseName)) {
9738
+ groups[baseName][label] = row[baseName];
9739
+ }
9740
+ }
9741
+ });
9742
+ return groups;
9743
+ }
9744
+ function buildInstanceTable(groupName, baseNames, groupDisplayName, instanceRows, fieldProvenance) {
9745
+ const columnGroups = groupColumnsByInstance(baseNames, instanceRows);
9746
+ const instanceLabels = instanceColumnLabels(instanceRows);
9747
+ const items = [];
9748
+ for (const [baseName, labelMap] of Object.entries(columnGroups)) {
9749
+ const hasAny = Object.values(labelMap).some((v) => v !== null && v !== void 0 && v !== "");
9750
+ if (!hasAny) continue;
9751
+ const numeric = isNumericField(baseName);
9752
+ const data = {};
9753
+ const formattedData = {};
9754
+ const confidence = {};
9755
+ const provenance = {};
9756
+ for (const [i, row] of instanceRows.entries()) {
9757
+ const label = instanceLabels[i];
9758
+ const value = labelMap[label] ?? null;
9759
+ data[label] = value;
9760
+ formattedData[label] = formatValue(value, numeric);
9761
+ const legacyKey = row.timePeriod ? `${baseName}${row.timePeriod}` : void 0;
9762
+ const prov = legacyKey ? fieldProvenance?.[legacyKey] : void 0;
9763
+ if (prov) {
9764
+ provenance[label] = prov;
9765
+ if (prov.origin === "extracted" && typeof prov.confidence === "number" && !Number.isNaN(prov.confidence)) {
9766
+ confidence[label] = prov.confidence;
9767
+ }
9768
+ }
9769
+ }
9770
+ items.push({
9771
+ displayName: getDisplayName(baseName),
9772
+ timePeriods: instanceLabels,
9773
+ data,
9774
+ formattedData,
9775
+ type: "timeSeries" /* TIME_SERIES */,
9776
+ isNumeric: numeric,
9777
+ ...Object.keys(confidence).length ? { confidence } : {},
9778
+ ...Object.keys(provenance).length ? { provenance } : {}
9779
+ });
9780
+ }
9781
+ const hasData = items.some(
9782
+ (item) => Object.values(item.data).some((v) => v !== null && v !== void 0 && v !== "")
9783
+ );
9784
+ if (!items.length || !hasData) return null;
9785
+ return {
9786
+ name: groupName,
9787
+ displayName: groupDisplayName,
9788
+ type: "timeSeries" /* TIME_SERIES */,
9789
+ items,
9790
+ hasData
9791
+ };
9792
+ }
9793
+ function buildFileFieldTablesFromInstances(instancesByCategory = {}, fieldProvenance, categoryOverrides) {
9794
+ const specs = getBaseFieldSpecs();
9795
+ const fileFields = specs.filter((f) => f.type === "file" && f.ihs_column_names?.length);
9796
+ const grouped = groupFieldsByPattern(fileFields);
9797
+ const tables = {};
9798
+ for (const [groupName, fields] of Object.entries(grouped)) {
9799
+ const instanceRows = instancesByCategory[groupName];
9800
+ if (!instanceRows?.length) continue;
9801
+ const baseNames = /* @__PURE__ */ new Set();
9802
+ for (const field of fields) {
9803
+ for (const col of field.ihs_column_names ?? []) {
9804
+ baseNames.add(col.replace(TIME_PERIOD_REGEX, ""));
9805
+ }
9806
+ }
9807
+ const groupDisplayName = getGroupDisplayNames()[groupName] || fields[0]?.displayName || getDisplayName(groupName);
9808
+ const table = buildInstanceTable(
9809
+ groupName,
9810
+ [...baseNames],
9811
+ groupDisplayName,
9812
+ instanceRows,
9813
+ fieldProvenance
9814
+ );
9815
+ if (table) tables[groupName] = table;
9816
+ }
9817
+ for (const [groupName, spec] of Object.entries(categoryOverrides ?? {})) {
9818
+ if (Object.prototype.hasOwnProperty.call(tables, groupName)) continue;
9819
+ const instanceRows = instancesByCategory[groupName];
9820
+ if (!instanceRows?.length) continue;
9821
+ const table = buildInstanceTable(
9822
+ groupName,
9823
+ spec.baseColumnNames,
9824
+ spec.displayName,
9825
+ instanceRows,
9826
+ fieldProvenance
9827
+ );
9828
+ if (table) tables[groupName] = table;
9829
+ }
9830
+ return tables;
9831
+ }
9557
9832
  var DOC_DISPLAY_NAMES = {
9558
9833
  bankStatements: "Bank Statements",
9559
9834
  financialStatements: "Financial Statements",
@@ -9800,22 +10075,13 @@ var ExtractionJobStatus = /* @__PURE__ */ ((ExtractionJobStatus2) => {
9800
10075
  ExtractionJobStatus2["Failed"] = "failed";
9801
10076
  return ExtractionJobStatus2;
9802
10077
  })(ExtractionJobStatus || {});
9803
- var ExtractionFileType = /* @__PURE__ */ ((ExtractionFileType2) => {
9804
- ExtractionFileType2["FinancialStatement"] = "financialStatements";
9805
- ExtractionFileType2["BankStatement"] = "bankStatements";
9806
- ExtractionFileType2["Epf"] = "epfStatements";
9807
- ExtractionFileType2["Payslip"] = "payslips";
9808
- ExtractionFileType2["Ssm"] = "ssm";
9809
- ExtractionFileType2["Form9"] = "form9";
9810
- ExtractionFileType2["Ic"] = "ic";
9811
- return ExtractionFileType2;
9812
- })(ExtractionFileType || {});
9813
10078
 
9814
10079
  // src/ihs-status.ts
9815
10080
  var IhsStatus = /* @__PURE__ */ ((IhsStatus2) => {
9816
10081
  IhsStatus2["CreatingApplication"] = "CREATING_APPLICATION";
9817
10082
  IhsStatus2["ApplicationFinalized"] = "APPLICATION_FINALIZED";
9818
10083
  IhsStatus2["LenderEvaluation"] = "LENDER_EVALUATION";
10084
+ IhsStatus2["EditingApplication"] = "EDITING_APPLICATION";
9819
10085
  IhsStatus2["Approved"] = "APPROVED";
9820
10086
  IhsStatus2["LouDelivered"] = "LOU_DELIVERED";
9821
10087
  IhsStatus2["AwaitingDisbursement"] = "AWAITING_DISBURSEMENT";
@@ -9829,6 +10095,7 @@ var IHS_VALID_STATUSES = [
9829
10095
  "CREATING_APPLICATION" /* CreatingApplication */,
9830
10096
  "APPLICATION_FINALIZED" /* ApplicationFinalized */,
9831
10097
  "LENDER_EVALUATION" /* LenderEvaluation */,
10098
+ "EDITING_APPLICATION" /* EditingApplication */,
9832
10099
  "APPROVED" /* Approved */,
9833
10100
  "LOU_DELIVERED" /* LouDelivered */,
9834
10101
  "AWAITING_DISBURSEMENT" /* AwaitingDisbursement */,
@@ -9869,19 +10136,6 @@ var DocExtractionStatus = /* @__PURE__ */ ((DocExtractionStatus2) => {
9869
10136
  DocExtractionStatus2["Unknown"] = "unknown";
9870
10137
  return DocExtractionStatus2;
9871
10138
  })(DocExtractionStatus || {});
9872
- var FILE_TYPE_TO_GROUP = {
9873
- ["bankStatements" /* BankStatement */]: "bank_statements",
9874
- ["financialStatements" /* FinancialStatement */]: "financials",
9875
- ["epfStatements" /* Epf */]: "epf_statements",
9876
- ["payslips" /* Payslip */]: "payslip_statements",
9877
- ["ssm" /* Ssm */]: "ssm_documents",
9878
- ["form9" /* Form9 */]: "form9",
9879
- ["ic" /* Ic */]: "ic_documents"
9880
- };
9881
- var _specs = getBaseFieldSpecs();
9882
- var _fileFields = _specs.filter((f) => f.type === "file" && f.ihs_column_names?.length);
9883
- var _grouped = groupFieldsByPattern(_fileFields);
9884
- var _groupDisplayNames = getGroupDisplayNames();
9885
10139
  function isPopulated(value) {
9886
10140
  if (value === null || value === void 0 || value === "") return false;
9887
10141
  if (value === "Not Specified") return false;
@@ -9945,10 +10199,10 @@ function resolveDocStatus(columns, ihsRecord, uploaded, jobRecord, hasJobRecords
9945
10199
  function resolveExtractionStatus(ihsRecord, jobRecords) {
9946
10200
  const documents = [];
9947
10201
  const hasJobRecords = jobRecords !== void 0;
9948
- for (const fileType of Object.values(ExtractionFileType)) {
9949
- const groupName = FILE_TYPE_TO_GROUP[fileType];
9950
- const fields = _grouped[groupName] ?? [];
9951
- const displayName = _groupDisplayNames[groupName] ?? fileType;
10202
+ for (const group of getDocumentTypeGroups()) {
10203
+ const fileType = group.documentType;
10204
+ const fields = group.fields;
10205
+ const displayName = group.label;
9952
10206
  const uploadedCount = countUploadedFiles(ihsRecord, fileType);
9953
10207
  const isUploaded = uploadedCount > 0 || fields.some((f) => f.name && isPopulated(ihsRecord[f.name]));
9954
10208
  const matchingJobs = jobRecords?.filter((j) => j.fileType === fileType) ?? [];
@@ -10598,7 +10852,6 @@ function assertAdapterCategory(id) {
10598
10852
  BasicFormField,
10599
10853
  DEFAULT_VALIDATOR_DEFINITIONS,
10600
10854
  DocExtractionStatus,
10601
- ExtractionFileType,
10602
10855
  ExtractionJobStatus,
10603
10856
  FIELD_TYPE_DEFINITIONS,
10604
10857
  FieldType,
@@ -10609,6 +10862,7 @@ function assertAdapterCategory(id) {
10609
10862
  FormFieldValidator,
10610
10863
  FormSpec,
10611
10864
  IHS_FAILURE_STATUSES,
10865
+ IHS_FIELD_ORIGINS,
10612
10866
  IHS_TERMINAL_STATUSES,
10613
10867
  IHS_VALID_STATUSES,
10614
10868
  IhsStatus,
@@ -10618,8 +10872,10 @@ function assertAdapterCategory(id) {
10618
10872
  applyAggregation,
10619
10873
  applyDynamicTitles,
10620
10874
  assertAdapterCategory,
10875
+ assertDocumentType,
10621
10876
  buildDocumentRows,
10622
10877
  buildFileFieldTables,
10878
+ buildFileFieldTablesFromInstances,
10623
10879
  categoryFieldsOf,
10624
10880
  categoryForField,
10625
10881
  categorySchemaOf,
@@ -10638,6 +10894,7 @@ function assertAdapterCategory(id) {
10638
10894
  getDisplayName,
10639
10895
  getDisplayNames,
10640
10896
  getDocDisplayNames,
10897
+ getDocumentTypeGroups,
10641
10898
  getExtractableDocTypes,
10642
10899
  getGroupDisplayNames,
10643
10900
  getPastMonthLabel,
@@ -10645,13 +10902,16 @@ function assertAdapterCategory(id) {
10645
10902
  getReuploadableDocTypes,
10646
10903
  getStepDefaultValues,
10647
10904
  getStepSchema,
10905
+ groupColumnsByInstance,
10648
10906
  groupColumnsByTimePeriod,
10649
10907
  groupDetailsByCategory,
10650
10908
  groupFieldsByCategory,
10651
10909
  groupFieldsByPattern,
10652
10910
  isAdapterCategory,
10911
+ isDocumentType,
10653
10912
  isFailureIhsStatus,
10654
10913
  isTerminalIhsStatus,
10914
+ isValidIhsFieldOrigin,
10655
10915
  isValidIhsStatus,
10656
10916
  parseFileField,
10657
10917
  processIhsDetails,