@zeniai/client-epic-state 5.1.68-betaDI2 → 5.1.68-betaNB1

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.
Files changed (54) hide show
  1. package/lib/entity/accountRecon/accountReconReducer.js +4 -0
  2. package/lib/entity/accountRecon/accountReconState.d.ts +4 -1
  3. package/lib/entity/accountRecon/accountReconState.js +1 -0
  4. package/lib/epic.d.ts +2 -1
  5. package/lib/epic.js +2 -1
  6. package/lib/esm/entity/accountRecon/accountReconReducer.js +4 -0
  7. package/lib/esm/entity/accountRecon/accountReconState.js +1 -0
  8. package/lib/esm/epic.js +2 -1
  9. package/lib/esm/index.js +5 -5
  10. package/lib/esm/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +37 -0
  11. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +74 -5
  12. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  13. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +10 -2
  14. package/lib/esm/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +29 -5
  15. package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +106 -0
  16. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +86 -13
  17. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -6
  18. package/lib/esm/view/expenseAutomationView/selectors/statementParseViewSelector.js +51 -10
  19. package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +15 -1
  20. package/lib/esm/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +12 -9
  21. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewPayload.js +2 -7
  22. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewReducer.js +2 -47
  23. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewSelector.js +0 -9
  24. package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewState.js +0 -1
  25. package/lib/index.d.ts +5 -5
  26. package/lib/index.js +54 -47
  27. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.d.ts +21 -0
  28. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +41 -0
  29. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +73 -4
  30. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.d.ts +1 -1
  31. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  32. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +9 -1
  33. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.d.ts +2 -0
  34. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +30 -4
  35. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +98 -4
  36. package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +113 -0
  37. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +31 -4
  38. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +87 -14
  39. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +4 -1
  40. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -6
  41. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.d.ts +4 -2
  42. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.js +53 -10
  43. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +66 -0
  44. package/lib/view/expenseAutomationView/types/reconciliationViewState.js +19 -1
  45. package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.d.ts +8 -2
  46. package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +9 -6
  47. package/lib/view/notificationPreferencesView/notificationPreferencesViewPayload.d.ts +0 -1
  48. package/lib/view/notificationPreferencesView/notificationPreferencesViewPayload.js +2 -7
  49. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.d.ts +1 -6
  50. package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.js +3 -48
  51. package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.js +0 -9
  52. package/lib/view/notificationPreferencesView/notificationPreferencesViewState.d.ts +0 -1
  53. package/lib/view/notificationPreferencesView/notificationPreferencesViewState.js +0 -1
  54. package/package.json +1 -1
@@ -0,0 +1,21 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { RootState } from '../../../../reducer';
3
+ import { ZeniAPI } from '../../../../zeniAPI';
4
+ import { confirmStatementMapping, confirmStatementMappingFailure, confirmStatementMappingSuccess } from '../../reducers/reconciliationViewReducer';
5
+ export type ActionType = ReturnType<typeof confirmStatementMapping> | ReturnType<typeof confirmStatementMappingSuccess> | ReturnType<typeof confirmStatementMappingFailure>;
6
+ export declare const confirmStatementMappingEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<{
7
+ payload: {
8
+ accountId: import("../../../..").ID;
9
+ selectedPeriod: import("../../../..").MonthYearPeriod;
10
+ statementUploads: import("../../types/reconciliationViewState").ConfirmedCombinedStatementUpload[];
11
+ };
12
+ type: "expenseAutomationReconciliationView/confirmStatementMappingSuccess";
13
+ } | {
14
+ payload: {
15
+ accountId: import("../../../..").ID;
16
+ error: import("../../../../responsePayload").ZeniAPIStatus;
17
+ selectedPeriod: import("../../../..").MonthYearPeriod;
18
+ mappingConflict?: import("../../types/reconciliationViewState").ConfirmStatementMappingConflict | null;
19
+ };
20
+ type: "expenseAutomationReconciliationView/confirmStatementMappingFailure";
21
+ }>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.confirmStatementMappingEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const responsePayload_1 = require("../../../../responsePayload");
7
+ const reconciliationPayload_1 = require("../../payload/reconciliationPayload");
8
+ const reconciliationViewReducer_1 = require("../../reducers/reconciliationViewReducer");
9
+ const confirmStatementMappingEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(reconciliationViewReducer_1.confirmStatementMapping.match), (0, operators_1.switchMap)((action) => {
10
+ const { accountId, selectedPeriod, statementUploadId, accountMappings } = action.payload;
11
+ const confirmMappingApi$ = zeniAPI.postAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/statements/${statementUploadId}/confirm-mapping`, {
12
+ account_mappings: accountMappings.map((mapping) => ({
13
+ ledger_identifier: mapping.ledgerIdentifier,
14
+ account_id: mapping.accountId,
15
+ })),
16
+ });
17
+ return confirmMappingApi$.pipe((0, operators_1.mergeMap)((response) => {
18
+ if ((0, responsePayload_1.isSuccessResponse)(response) === true && response.data != null) {
19
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.confirmStatementMappingSuccess)({
20
+ accountId,
21
+ selectedPeriod,
22
+ statementUploads: (0, reconciliationPayload_1.transformConfirmStatementMappingPayloadToState)(response.data),
23
+ }));
24
+ }
25
+ const mappingConflict = (0, reconciliationPayload_1.isConfirmStatementMappingConflictResponse)(response)
26
+ ? (0, reconciliationPayload_1.transformConfirmStatementMappingConflictToState)(response)
27
+ : null;
28
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.confirmStatementMappingFailure)({
29
+ accountId,
30
+ selectedPeriod,
31
+ error: response.status,
32
+ mappingConflict,
33
+ }));
34
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, reconciliationViewReducer_1.confirmStatementMappingFailure)({
35
+ accountId,
36
+ selectedPeriod,
37
+ error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Confirm Statement Mapping REST API call errored out ' +
38
+ (error instanceof Error ? error.message : String(error))),
39
+ }))));
40
+ }));
41
+ exports.confirmStatementMappingEpic = confirmStatementMappingEpic;
@@ -7,15 +7,84 @@ const timePeriod_1 = require("../../../../commonStateTypes/timePeriod");
7
7
  const responsePayload_1 = require("../../../../responsePayload");
8
8
  const mapStatementUpdateLocalDataToRequestBody_1 = require("../../helpers/mapStatementUpdateLocalDataToRequestBody");
9
9
  const reconciliationPayload_1 = require("../../payload/reconciliationPayload");
10
+ const statementParseViewSelector_1 = require("../../selectors/statementParseViewSelector");
10
11
  const reconciliationViewReducer_1 = require("../../reducers/reconciliationViewReducer");
11
12
  const updateStatementInfoEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(reconciliationViewReducer_1.submitStatementUpdate.match), (0, operators_1.switchMap)((action) => {
12
13
  const { accountId, selectedPeriod, statementUploadId } = action.payload;
13
14
  const state = state$.value;
14
15
  const reconciliationView = state.expenseAutomationReconciliationViewState;
15
16
  const accountRecon = reconciliationView.accountReconciliationRecordsBySelectedPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)]?.reconciliationByAccountID[accountId];
16
- const localData = accountRecon?.localData?.statementUpdateLocalData;
17
17
  const parsedStatementData = accountRecon?.parsedStatementData;
18
- if (localData == null || parsedStatementData == null) {
18
+ const isCombined = (0, statementParseViewSelector_1.isCombinedParsedStatementData)(parsedStatementData) === true;
19
+ const localDataByUploadId = accountRecon?.localData?.statementUpdateLocalDataByUploadId;
20
+ const localData = accountRecon?.localData?.statementUpdateLocalData;
21
+ if (parsedStatementData == null) {
22
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
23
+ accountId,
24
+ selectedPeriod,
25
+ error: (0, responsePayload_1.createZeniAPIStatus)('Missing Data', 'No statement update data found'),
26
+ }));
27
+ }
28
+ if (isCombined === true) {
29
+ if ((0, mapStatementUpdateLocalDataToRequestBody_1.hasCombinedStatementUpdateLocalData)(parsedStatementData, localDataByUploadId) === false ||
30
+ localDataByUploadId == null) {
31
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
32
+ accountId,
33
+ selectedPeriod,
34
+ error: (0, responsePayload_1.createZeniAPIStatus)('Missing Data', 'No statement update data found for combined accounts'),
35
+ }));
36
+ }
37
+ const hasInvalidUpdates = Object.values(localDataByUploadId).some((uploadLocalData) => uploadLocalData.statementTransactions.updated.some((txn) => txn.statementTransactionId == null));
38
+ if (hasInvalidUpdates === true) {
39
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
40
+ accountId,
41
+ selectedPeriod,
42
+ error: (0, responsePayload_1.createZeniAPIStatus)('Invalid Data', 'One or more edited transactions are missing statement transaction ids'),
43
+ }));
44
+ }
45
+ let body;
46
+ try {
47
+ body = (0, mapStatementUpdateLocalDataToRequestBody_1.mapCombinedStatementUpdateLocalDataToRequestBody)(localDataByUploadId, parsedStatementData);
48
+ }
49
+ catch (error) {
50
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
51
+ accountId,
52
+ selectedPeriod,
53
+ error: (0, responsePayload_1.createZeniAPIStatus)('Missing Data', error instanceof Error
54
+ ? error.message
55
+ : 'Failed to build combined statement update body'),
56
+ }));
57
+ }
58
+ const updateStatementApi$ = zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/statement-uploads/${statementUploadId}`, body);
59
+ return updateStatementApi$.pipe((0, operators_1.mergeMap)((response) => {
60
+ if ((0, responsePayload_1.isSuccessResponse)(response) === true && response.data != null) {
61
+ const nextParsedStatementData = (0, reconciliationPayload_1.transformUpdateStatementInfoPayloadToState)(response.data);
62
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.updateParsedStatementData)({
63
+ accountId,
64
+ selectedPeriod,
65
+ parsedStatementData: nextParsedStatementData,
66
+ }), (0, reconciliationViewReducer_1.submitStatementUpdateSuccess)({
67
+ accountId,
68
+ selectedPeriod,
69
+ }));
70
+ }
71
+ const dateConflict = (0, reconciliationPayload_1.isStatementDateConflictResponse)(response)
72
+ ? (0, reconciliationPayload_1.transformStatementDateConflictToState)(response)
73
+ : null;
74
+ return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
75
+ accountId,
76
+ selectedPeriod,
77
+ error: response.status,
78
+ dateConflict,
79
+ }));
80
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
81
+ accountId,
82
+ selectedPeriod,
83
+ error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Update Statement REST API call errored out ' +
84
+ (error instanceof Error ? error.message : String(error))),
85
+ }))));
86
+ }
87
+ if (localData == null) {
19
88
  return (0, rxjs_1.of)((0, reconciliationViewReducer_1.submitStatementUpdateFailure)({
20
89
  accountId,
21
90
  selectedPeriod,
@@ -34,11 +103,11 @@ const updateStatementInfoEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
34
103
  const updateStatementApi$ = zeniAPI.putAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/2.0/statement-uploads/${statementUploadId}`, body);
35
104
  return updateStatementApi$.pipe((0, operators_1.mergeMap)((response) => {
36
105
  if ((0, responsePayload_1.isSuccessResponse)(response) === true && response.data != null) {
37
- const parsedStatementData = (0, reconciliationPayload_1.transformUpdateStatementInfoPayloadToState)(response.data);
106
+ const nextParsedStatementData = (0, reconciliationPayload_1.transformUpdateStatementInfoPayloadToState)(response.data);
38
107
  return (0, rxjs_1.of)((0, reconciliationViewReducer_1.updateParsedStatementData)({
39
108
  accountId,
40
109
  selectedPeriod,
41
- parsedStatementData,
110
+ parsedStatementData: nextParsedStatementData,
42
111
  }), (0, reconciliationViewReducer_1.submitStatementUpdateSuccess)({
43
112
  accountId,
44
113
  selectedPeriod,
@@ -10,4 +10,4 @@ export interface AuthParamsPayload {
10
10
  zeni_tenant_id: string;
11
11
  zeni_user_id: string;
12
12
  }
13
- export default function uploadAccountStatementIntoDocumentAI(accountType: AccountType, fileBlob: Blob, authParams: AuthParams): Promise<UploadStatementDocumentAIPayload | undefined>;
13
+ export default function uploadAccountStatementIntoDocumentAI(accountType: AccountType, fileBlob: Blob, authParams: AuthParams, isCombinedStatement?: boolean): Promise<UploadStatementDocumentAIPayload | undefined>;
@@ -6,15 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = uploadAccountStatementIntoDocumentAI;
7
7
  const cross_fetch_1 = __importDefault(require("cross-fetch"));
8
8
  const init_1 = require("../../../../init");
9
- async function uploadAccountStatementIntoDocumentAI(accountType, fileBlob, authParams) {
9
+ function toStatementDocumentType(accountType, isCombinedStatement) {
10
+ if (isCombinedStatement === true) {
11
+ return accountType === 'credit_card'
12
+ ? 'reconciliation_combined_card_statement_upload'
13
+ : 'reconciliation_combined_bank_statement_upload';
14
+ }
15
+ return accountType === 'credit_card'
16
+ ? 'reconciliation_card_statement_upload'
17
+ : 'reconciliation_bank_statement_upload';
18
+ }
19
+ async function uploadAccountStatementIntoDocumentAI(accountType, fileBlob, authParams, isCombinedStatement = false) {
10
20
  let statementUpload;
11
21
  const urlEndPoint = `${init_1.zeniAPI.apiEndPoints.documentAIMicroServiceBaseUrl}/1.0/processors/statement`;
12
22
  const data = new FormData();
13
23
  data.append('attachment_file_0', fileBlob);
14
24
  const attachment_json = JSON.stringify({
15
- document_type: accountType === 'credit_card'
16
- ? 'reconciliation_card_statement_upload'
17
- : 'reconciliation_bank_statement_upload',
25
+ document_type: toStatementDocumentType(accountType, isCombinedStatement),
18
26
  purpose_id: 'reconciliation',
19
27
  });
20
28
  data.append('attachment_json_0', attachment_json);
@@ -11,7 +11,7 @@ const fileReducer_1 = require("../../../../entity/file/fileReducer");
11
11
  const responsePayload_1 = require("../../../../responsePayload");
12
12
  const reconciliationViewReducer_1 = require("../../reducers/reconciliationViewReducer");
13
13
  const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(reconciliationViewReducer_1.uploadAccountStatement.match), (0, operators_1.mergeMap)((action) => {
14
- const { accountId, selectedPeriod, payload } = action.payload;
14
+ const { accountId, selectedPeriod, payload, statementAccountScope } = action.payload;
15
15
  const { start, end } = (0, timePeriod_1.convertToPeriod)(selectedPeriod, true);
16
16
  const accountBase = (0, accountSelector_1.getAccountBase)(state$.value.accountState, accountId, 'account_reconciliation');
17
17
  if (accountBase == null) {
@@ -22,6 +22,13 @@ const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions$.pipe(
22
22
  }));
23
23
  }
24
24
  const statementType = accountBase.accountType == 'credit_card' ? 'card' : 'bank';
25
+ const localStatementAccountScope = state$.value.expenseAutomationReconciliationViewState
26
+ .accountReconciliationRecordsBySelectedPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)]?.reconciliationByAccountID[accountId]?.localData
27
+ ?.statementAccountScope;
28
+ const resolvedStatementAccountScope = statementAccountScope ??
29
+ localStatementAccountScope ??
30
+ 'single_account';
31
+ const isCombinedStatement = resolvedStatementAccountScope === 'multi_account';
25
32
  const requestPayload = {
26
33
  account_id: accountId,
27
34
  statement_start_date: start.toString(),
@@ -29,6 +36,7 @@ const uploadAccountStatementEpic = (actions$, state$, zeniAPI) => actions$.pipe(
29
36
  processor_run_id: payload.processor_run_id,
30
37
  file_id: payload.files[0].file_id,
31
38
  statement_type: statementType,
39
+ is_combined_statement: isCombinedStatement,
32
40
  };
33
41
  const uploadAccountStatementApi$ = zeniAPI.postAndGetJSON(`${zeniAPI.apiEndPoints.reconciliationMicroServiceBaseUrl}/1.0/reconciliation/statements`, requestPayload);
34
42
  return uploadAccountStatementApi$.pipe((0, operators_1.mergeMap)((response) => {
@@ -1,2 +1,4 @@
1
1
  import { ParsedStatementData, StatementUpdateLocalData } from '../types/reconciliationViewState';
2
2
  export declare const mapStatementUpdateLocalDataToRequestBody: (localData: StatementUpdateLocalData, parsedStatementData: ParsedStatementData) => Record<string, unknown>;
3
+ export declare const mapCombinedStatementUpdateLocalDataToRequestBody: (localDataByUploadId: Record<string, StatementUpdateLocalData>, parsedStatementData: ParsedStatementData) => Record<string, unknown>;
4
+ export declare const hasCombinedStatementUpdateLocalData: (parsedStatementData: ParsedStatementData | undefined, localDataByUploadId: Record<string, StatementUpdateLocalData> | undefined) => boolean;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapStatementUpdateLocalDataToRequestBody = void 0;
3
+ exports.hasCombinedStatementUpdateLocalData = exports.mapCombinedStatementUpdateLocalDataToRequestBody = exports.mapStatementUpdateLocalDataToRequestBody = void 0;
4
4
  const reconciliationPayload_1 = require("../payload/reconciliationPayload");
5
5
  const statementParseViewSelector_1 = require("../selectors/statementParseViewSelector");
6
- const prepareStatementUpdateLocalData = (localData, parsedStatementData) => {
7
- const { statementMeta, statementTransactions } = parsedStatementData.statementUpload;
6
+ const prepareStatementUpdateLocalData = (localData, statementUpload) => {
7
+ const { statementMeta, statementTransactions } = statementUpload;
8
8
  const statementPeriod = (0, statementParseViewSelector_1.getEffectiveStatementPeriod)(statementMeta, localData.statementMeta);
9
9
  const localDeletedIds = localData.statementTransactions?.deletedIds ?? [];
10
10
  const currentTransactionIds = new Set(statementTransactions
@@ -30,5 +30,31 @@ const prepareStatementUpdateLocalData = (localData, parsedStatementData) => {
30
30
  },
31
31
  };
32
32
  };
33
- const mapStatementUpdateLocalDataToRequestBody = (localData, parsedStatementData) => (0, reconciliationPayload_1.toStatementUpdateRequestBody)(prepareStatementUpdateLocalData(localData, parsedStatementData));
33
+ const mapStatementUpdateLocalDataToRequestBody = (localData, parsedStatementData) => (0, reconciliationPayload_1.toStatementUpdateRequestBody)(prepareStatementUpdateLocalData(localData, parsedStatementData.statementUpload));
34
34
  exports.mapStatementUpdateLocalDataToRequestBody = mapStatementUpdateLocalDataToRequestBody;
35
+ const mapCombinedStatementUpdateLocalDataToRequestBody = (localDataByUploadId, parsedStatementData) => {
36
+ const statementUploads = (0, statementParseViewSelector_1.getStatementUploadsFromParsedData)(parsedStatementData);
37
+ const updates = statementUploads.map((statementUpload) => {
38
+ const statementUploadId = statementUpload.statementMeta.statementUploadId;
39
+ const localData = localDataByUploadId[statementUploadId];
40
+ if (localData == null) {
41
+ throw new Error(`Missing statement update local data for upload ${statementUploadId}`);
42
+ }
43
+ return {
44
+ statementUploadId,
45
+ localData: prepareStatementUpdateLocalData(localData, statementUpload),
46
+ };
47
+ });
48
+ return (0, reconciliationPayload_1.toBulkStatementUpdateRequestBody)(updates);
49
+ };
50
+ exports.mapCombinedStatementUpdateLocalDataToRequestBody = mapCombinedStatementUpdateLocalDataToRequestBody;
51
+ const hasCombinedStatementUpdateLocalData = (parsedStatementData, localDataByUploadId) => {
52
+ if ((0, statementParseViewSelector_1.isCombinedParsedStatementData)(parsedStatementData) === false ||
53
+ localDataByUploadId == null) {
54
+ return false;
55
+ }
56
+ const statementUploads = (0, statementParseViewSelector_1.getStatementUploadsFromParsedData)(parsedStatementData);
57
+ return statementUploads.every((statementUpload) => localDataByUploadId[statementUpload.statementMeta.statementUploadId] !=
58
+ null);
59
+ };
60
+ exports.hasCombinedStatementUpdateLocalData = hasCombinedStatementUpdateLocalData;
@@ -9,7 +9,7 @@ import { MatchedTransactionPayload } from '../../../entity/transaction/payloadTy
9
9
  import { UserPayload } from '../../../entity/user/userPayload';
10
10
  import { RootState } from '../../../reducer';
11
11
  import { ZeniAPIResponse, ZeniAPIStatus } from '../../../responsePayload';
12
- import { BalancesLocalData, ParsedStatementData, SaveReconcileDetailActionPayload, StatementDateConflict, StatementUpdateLocalData, StatementUpdateLocalDataPayload } from '../types/reconciliationViewState';
12
+ import { BalancesLocalData, ConfirmStatementMappingConflict, ConfirmedCombinedStatementUpload, ParsedStatementData, SaveReconcileDetailActionPayload, StatementDateConflict, StatementUpdateLocalData, StatementUpdateLocalDataPayload } from '../types/reconciliationViewState';
13
13
  export interface DetectionInfoPayload {
14
14
  account_id: string;
15
15
  bank_balance: number | null;
@@ -119,6 +119,9 @@ export interface StatementUploadSummaryPayload {
119
119
  statement_start_date: string;
120
120
  statement_status: StatusCodeWithLabelPayload;
121
121
  statement_upload_id: string;
122
+ combined_statement_group_id?: string | null;
123
+ is_combined_statement?: boolean | null;
124
+ is_combined_statement_anchor?: boolean | null;
122
125
  }
123
126
  export interface UploadStatementResponsePayload {
124
127
  file: FilePayload;
@@ -162,6 +165,10 @@ export interface StatementMetaPayload {
162
165
  statement_upload_id: string;
163
166
  total_deposits: number;
164
167
  total_payments: number;
168
+ balance_source?: string | null;
169
+ combined_statement_group_id?: string | null;
170
+ is_combined_statement?: boolean | null;
171
+ is_combined_statement_anchor?: boolean | null;
165
172
  }
166
173
  export interface AccountInfoPayload {
167
174
  account_id: string;
@@ -199,17 +206,75 @@ export interface AiSummaryPayload {
199
206
  fields_captured: AiSummaryFieldPayload[];
200
207
  transactions_extracted: number;
201
208
  }
209
+ export interface CombinedStatementAccountSuggestionPayload {
210
+ account_id: string;
211
+ account_name: string;
212
+ match_confidence: number;
213
+ matched_by: string;
214
+ }
215
+ export interface CombinedStatementAccountPayload {
216
+ account_name: string;
217
+ account_type: string;
218
+ closing_balance: number;
219
+ is_upload_context: boolean;
220
+ ledger_identifier: string;
221
+ masked_account_number: string;
222
+ opening_balance: number;
223
+ transaction_count: number;
224
+ existing_statement_status?: StatusCodeWithLabelPayload | null;
225
+ suggestion?: CombinedStatementAccountSuggestionPayload | null;
226
+ }
227
+ export interface ConfirmedCombinedStatementUploadPayload {
228
+ account_id: string;
229
+ is_combined_statement_anchor: boolean;
230
+ ledger_identifiers: string[];
231
+ statement_upload_id: string;
232
+ }
233
+ export interface CombinedStatementDetailsPayload {
234
+ accounts: CombinedStatementAccountPayload[];
235
+ combined_statement_group_id: string;
236
+ is_mapping_confirmed: boolean;
237
+ statement_uploads: ConfirmedCombinedStatementUploadPayload[];
238
+ }
202
239
  export interface StatementUploadPayload {
203
240
  account: AccountInfoPayload;
204
241
  file: FileInfoPayload | null;
205
242
  statement_meta: StatementMetaPayload;
206
243
  statement_transactions: StatementTransactionPayload[];
207
244
  ai_summary?: AiSummaryPayload | null;
245
+ combined_statement_details?: CombinedStatementDetailsPayload | null;
208
246
  }
209
- export interface ParseStatementResponsePayload {
210
- reconciliation: ReconciliationMetaPayload;
247
+ /** Single-account parse GET — unchanged. */
248
+ export interface ParseStatementSingleResponsePayload {
249
+ reconciliation: ReconciliationMetaPayload | null;
211
250
  statement_upload: StatementUploadPayload;
212
251
  }
252
+ /** Combined multi-account parse GET (after mapping confirm). */
253
+ export interface ParseStatementCombinedResponsePayload {
254
+ reconciliation: ReconciliationMetaPayload | null;
255
+ statement_uploads: StatementUploadPayload[];
256
+ }
257
+ export type ParseStatementResponsePayload = ParseStatementSingleResponsePayload | ParseStatementCombinedResponsePayload;
258
+ export declare function isParseStatementCombinedResponsePayload(payload: ParseStatementResponsePayload): payload is ParseStatementCombinedResponsePayload;
259
+ export interface ConfirmStatementMappingRequestPayload {
260
+ account_mappings: Array<{
261
+ account_id: string;
262
+ ledger_identifier: string;
263
+ }>;
264
+ }
265
+ export interface ConfirmStatementMappingResponsePayload {
266
+ statement_uploads: ConfirmedCombinedStatementUploadPayload[];
267
+ }
268
+ export type ConfirmStatementMappingSuccessResponse = ZeniAPIResponse<ConfirmStatementMappingResponsePayload>;
269
+ export interface ConfirmStatementMappingConflictResponse extends ZeniAPIResponse<ConfirmStatementMappingResponsePayload | undefined> {
270
+ status: ZeniAPIStatus & {
271
+ code: 409;
272
+ };
273
+ colliding_account_id?: string | null;
274
+ colliding_ledger_identifiers?: string[] | null;
275
+ previous_reconciliation_info?: PreviousReconciliationInfoPayload | null;
276
+ }
277
+ export type ConfirmStatementMappingResponse = ConfirmStatementMappingSuccessResponse | ConfirmStatementMappingConflictResponse;
213
278
  export interface ReparseStatementResponsePayload {
214
279
  statement_upload: StatementUploadSummaryPayload;
215
280
  }
@@ -232,11 +297,28 @@ export interface StatementDateAdjustmentPayload {
232
297
  previous_reconciliation_info: PreviousReconciliationInfoPayload;
233
298
  reason: string;
234
299
  }
235
- export interface UpdateStatementInfoResponsePayload {
300
+ /** Single-account Confirm & Save response — unchanged. */
301
+ export interface UpdateStatementInfoSingleResponsePayload {
236
302
  reconciliation: ReconciliationMetaPayload;
237
303
  statement_upload: StatementUploadPayload;
238
304
  date_adjustment?: StatementDateAdjustmentPayload | null;
239
305
  }
306
+ /** Combined multi-account bulk Confirm & Save response. */
307
+ export interface UpdateStatementInfoCombinedResponsePayload {
308
+ reconciliation: ReconciliationMetaPayload;
309
+ statement_uploads: StatementUploadPayload[];
310
+ date_adjustment?: StatementDateAdjustmentPayload | null;
311
+ }
312
+ export type UpdateStatementInfoResponsePayload = UpdateStatementInfoSingleResponsePayload | UpdateStatementInfoCombinedResponsePayload;
313
+ export declare function isUpdateStatementInfoCombinedResponsePayload(payload: UpdateStatementInfoResponsePayload): payload is UpdateStatementInfoCombinedResponsePayload;
314
+ export interface BulkStatementUpdateUploadPayload {
315
+ statement_meta: StatementUpdateLocalDataPayload['statement_meta'];
316
+ statement_transactions: StatementUpdateLocalDataPayload['statement_transactions'];
317
+ statement_upload_id: string;
318
+ }
319
+ export interface BulkStatementUpdateRequestPayload {
320
+ statement_uploads: BulkStatementUpdateUploadPayload[];
321
+ }
240
322
  /** 2xx Confirm & Save — carries parsed statement data, no chain-validation errors. */
241
323
  export interface UpdateStatementInfoSuccessResponse extends ZeniAPIResponse<UpdateStatementInfoResponsePayload> {
242
324
  error_code?: undefined;
@@ -260,8 +342,20 @@ export declare function isStatementDateConflictResponse(response: UpdateStatemen
260
342
  */
261
343
  export declare function transformStatementDateConflictToState(response: UpdateStatementInfoResponse): StatementDateConflict | null;
262
344
  export declare function transformParseStatementPayloadToState(payload: ParseStatementResponsePayload): ParsedStatementData;
345
+ export declare function isConfirmStatementMappingConflictResponse(response: ConfirmStatementMappingResponse): response is ConfirmStatementMappingConflictResponse;
346
+ export declare function transformConfirmStatementMappingPayloadToState(payload: ConfirmStatementMappingResponsePayload): ConfirmedCombinedStatementUpload[];
347
+ export declare function transformConfirmStatementMappingConflictToState(response: ConfirmStatementMappingResponse): ConfirmStatementMappingConflict | null;
263
348
  export declare function transformUpdateStatementInfoPayloadToState(payload: UpdateStatementInfoResponsePayload): ParsedStatementData;
264
349
  export declare function transformStatementUpdateStateToPayload(localData: StatementUpdateLocalData): StatementUpdateLocalDataPayload;
265
350
  /** API request body for PUT statement-uploads; cast lives here for putAndGetJSON. */
266
351
  export declare function toStatementUpdateRequestBody(localData: StatementUpdateLocalData): Record<string, unknown>;
352
+ export declare function transformBulkStatementUpdateStateToPayload(updates: Array<{
353
+ localData: StatementUpdateLocalData;
354
+ statementUploadId: string;
355
+ }>): BulkStatementUpdateRequestPayload;
356
+ /** Bulk PUT body for combined multi-account Confirm & Save. */
357
+ export declare function toBulkStatementUpdateRequestBody(updates: Array<{
358
+ localData: StatementUpdateLocalData;
359
+ statementUploadId: string;
360
+ }>): Record<string, unknown>;
267
361
  export {};
@@ -1,15 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSaveReconciliationPayloadBasedOnActionAndMethod = createSaveReconciliationPayloadBasedOnActionAndMethod;
4
+ exports.isParseStatementCombinedResponsePayload = isParseStatementCombinedResponsePayload;
5
+ exports.isUpdateStatementInfoCombinedResponsePayload = isUpdateStatementInfoCombinedResponsePayload;
4
6
  exports.isStatementDateConflictResponse = isStatementDateConflictResponse;
5
7
  exports.transformStatementDateConflictToState = transformStatementDateConflictToState;
6
8
  exports.transformParseStatementPayloadToState = transformParseStatementPayloadToState;
9
+ exports.isConfirmStatementMappingConflictResponse = isConfirmStatementMappingConflictResponse;
10
+ exports.transformConfirmStatementMappingPayloadToState = transformConfirmStatementMappingPayloadToState;
11
+ exports.transformConfirmStatementMappingConflictToState = transformConfirmStatementMappingConflictToState;
7
12
  exports.transformUpdateStatementInfoPayloadToState = transformUpdateStatementInfoPayloadToState;
8
13
  exports.transformStatementUpdateStateToPayload = transformStatementUpdateStateToPayload;
9
14
  exports.toStatementUpdateRequestBody = toStatementUpdateRequestBody;
15
+ exports.transformBulkStatementUpdateStateToPayload = transformBulkStatementUpdateStateToPayload;
16
+ exports.toBulkStatementUpdateRequestBody = toBulkStatementUpdateRequestBody;
10
17
  const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
11
18
  const accountReconPayload_1 = require("../../../entity/accountRecon/accountReconPayload");
12
19
  const reconciliationTransactionPayloads_1 = require("../../../entity/transaction/payloadTypes/reconciliationTransactionPayloads");
20
+ const reconciliationViewState_1 = require("../types/reconciliationViewState");
13
21
  function createSaveReconciliationPayloadBasedOnActionAndMethod(state, selectedPeriod, localData, accountReconciliationEntity, action, method) {
14
22
  const { balance, initialClearedBalance } = accountReconciliationEntity;
15
23
  const { expenseAutomationReconciliationViewState: { selectedAccountId, reconTabsState: { reconcile: { localData: { selectedTransactionIds }, }, }, }, } = state;
@@ -76,10 +84,58 @@ function createReviewTransactionPayload(accountReconciliationEntity) {
76
84
  });
77
85
  return reviewTransactionsPayload;
78
86
  }
87
+ function isParseStatementCombinedResponsePayload(payload) {
88
+ return ('statement_uploads' in payload &&
89
+ Array.isArray(payload.statement_uploads) &&
90
+ payload.statement_uploads.length > 0);
91
+ }
92
+ function isUpdateStatementInfoCombinedResponsePayload(payload) {
93
+ return ('statement_uploads' in payload &&
94
+ Array.isArray(payload.statement_uploads) &&
95
+ payload.statement_uploads.length > 0);
96
+ }
79
97
  function isStatementDateConflictResponse(response) {
80
98
  return response.status.code === 409 && response.error_code != null;
81
99
  }
100
+ function transformConfirmedCombinedStatementUploadsToState(statementUploads) {
101
+ return (statementUploads ?? []).map((statementUpload) => ({
102
+ accountId: statementUpload.account_id,
103
+ isCombinedStatementAnchor: statementUpload.is_combined_statement_anchor,
104
+ ledgerIdentifiers: statementUpload.ledger_identifiers ?? [],
105
+ statementUploadId: statementUpload.statement_upload_id,
106
+ }));
107
+ }
108
+ function transformCombinedStatementDetailsToState(details) {
109
+ if (details == null) {
110
+ return undefined;
111
+ }
112
+ return {
113
+ combinedStatementGroupId: details.combined_statement_group_id,
114
+ isMappingConfirmed: details.is_mapping_confirmed,
115
+ accounts: (details.accounts ?? []).map((account) => ({
116
+ ledgerIdentifier: account.ledger_identifier,
117
+ accountName: account.account_name,
118
+ accountType: account.account_type,
119
+ maskedAccountNumber: account.masked_account_number,
120
+ openingBalance: account.opening_balance,
121
+ closingBalance: account.closing_balance,
122
+ transactionCount: account.transaction_count,
123
+ isUploadContext: account.is_upload_context,
124
+ existingStatementStatus: account.existing_statement_status ?? null,
125
+ suggestion: account.suggestion != null
126
+ ? {
127
+ accountId: account.suggestion.account_id,
128
+ accountName: account.suggestion.account_name,
129
+ matchedBy: account.suggestion.matched_by,
130
+ matchConfidence: account.suggestion.match_confidence,
131
+ }
132
+ : null,
133
+ })),
134
+ statementUploads: transformConfirmedCombinedStatementUploadsToState(details.statement_uploads),
135
+ };
136
+ }
82
137
  function transformStatementUploadPayloadToState(statementUploadPayload) {
138
+ const balanceSource = (0, reconciliationViewState_1.toStatementBalanceSourceStrict)(statementUploadPayload.statement_meta.balance_source);
83
139
  return {
84
140
  account: {
85
141
  accountId: statementUploadPayload.account.account_id,
@@ -105,6 +161,12 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
105
161
  statementUploadId: statementUploadPayload.statement_meta.statement_upload_id,
106
162
  totalDeposits: statementUploadPayload.statement_meta.total_deposits,
107
163
  totalPayments: statementUploadPayload.statement_meta.total_payments,
164
+ isCombinedStatement: statementUploadPayload.statement_meta.is_combined_statement ??
165
+ undefined,
166
+ isCombinedStatementAnchor: statementUploadPayload.statement_meta.is_combined_statement_anchor ??
167
+ undefined,
168
+ combinedStatementGroupId: statementUploadPayload.statement_meta.combined_statement_group_id ?? undefined,
169
+ ...(balanceSource != null ? { balanceSource } : {}),
108
170
  },
109
171
  statementTransactions: (statementUploadPayload.statement_transactions ?? []).map((txn) => ({
110
172
  amount: txn.amount,
@@ -126,6 +188,7 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
126
188
  transactionMemo: txn.transaction_memo,
127
189
  })),
128
190
  aiSummary: transformAiSummaryPayloadToState(statementUploadPayload.ai_summary),
191
+ combinedStatementDetails: transformCombinedStatementDetailsToState(statementUploadPayload.combined_statement_details),
129
192
  };
130
193
  }
131
194
  function transformPreviousReconciliationInfoToState(payload) {
@@ -186,11 +249,45 @@ function transformStatementDateConflictToState(response) {
186
249
  };
187
250
  }
188
251
  function transformParseStatementPayloadToState(payload) {
252
+ if (isParseStatementCombinedResponsePayload(payload) === true) {
253
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
254
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
255
+ return {
256
+ statementUpload: anchorUpload,
257
+ statementUploads,
258
+ };
259
+ }
189
260
  return {
190
261
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
191
262
  };
192
263
  }
264
+ function isConfirmStatementMappingConflictResponse(response) {
265
+ return response.status.code === 409;
266
+ }
267
+ function transformConfirmStatementMappingPayloadToState(payload) {
268
+ return transformConfirmedCombinedStatementUploadsToState(payload.statement_uploads);
269
+ }
270
+ function transformConfirmStatementMappingConflictToState(response) {
271
+ if (isConfirmStatementMappingConflictResponse(response) === false) {
272
+ return null;
273
+ }
274
+ return {
275
+ collidingAccountId: response.colliding_account_id != null
276
+ ? response.colliding_account_id
277
+ : undefined,
278
+ collidingLedgerIdentifiers: response.colliding_ledger_identifiers ?? [],
279
+ previousReconciliationInfo: transformPreviousReconciliationInfoToState(response.previous_reconciliation_info),
280
+ };
281
+ }
193
282
  function transformUpdateStatementInfoPayloadToState(payload) {
283
+ if (isUpdateStatementInfoCombinedResponsePayload(payload) === true) {
284
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
285
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
286
+ return {
287
+ statementUpload: anchorUpload,
288
+ statementUploads,
289
+ };
290
+ }
194
291
  return {
195
292
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
196
293
  };
@@ -230,3 +327,19 @@ function transformStatementUpdateStateToPayload(localData) {
230
327
  function toStatementUpdateRequestBody(localData) {
231
328
  return transformStatementUpdateStateToPayload(localData);
232
329
  }
330
+ function transformBulkStatementUpdateStateToPayload(updates) {
331
+ return {
332
+ statement_uploads: updates.map(({ localData, statementUploadId }) => {
333
+ const body = transformStatementUpdateStateToPayload(localData);
334
+ return {
335
+ statement_upload_id: statementUploadId,
336
+ statement_meta: body.statement_meta,
337
+ statement_transactions: body.statement_transactions,
338
+ };
339
+ }),
340
+ };
341
+ }
342
+ /** Bulk PUT body for combined multi-account Confirm & Save. */
343
+ function toBulkStatementUpdateRequestBody(updates) {
344
+ return transformBulkStatementUpdateStateToPayload(updates);
345
+ }