@zeniai/client-epic-state 5.1.35-betaRD3 → 5.1.35-betaRR1
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/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +0 -1
- package/lib/entity/jeSchedules/jeSchedulesPayload.js +0 -1
- package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +0 -1
- package/lib/entity/jeSchedules/jeSchedulesSelector.js +1 -2
- package/lib/entity/jeSchedules/jeSchedulesState.d.ts +0 -1
- package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +0 -1
- package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +1 -2
- package/lib/esm/index.js +8 -8
- package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +5 -31
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -18
- package/lib/esm/view/expenseAutomationView/types/jeSchedulesViewState.js +6 -2
- package/lib/esm/view/transactionDetail/epics/saveTransactionHelper.js +19 -0
- package/lib/esm/view/transactionDetail/epics/updateTransactionDetailEpic.js +69 -2
- package/lib/esm/view/transactionDetail/journalEntryLinesViewModel.js +58 -0
- package/lib/esm/view/transactionDetail/transactionDetailReducer.js +66 -1
- package/lib/index.d.ts +10 -10
- package/lib/index.js +25 -25
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +2 -6
- package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +6 -32
- package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +0 -8
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -18
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.d.ts +3 -6
- package/lib/view/expenseAutomationView/types/jeSchedulesViewState.js +8 -4
- package/lib/view/transactionDetail/epics/saveTransactionHelper.js +19 -0
- package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.d.ts +5 -1
- package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.js +71 -3
- package/lib/view/transactionDetail/journalEntryLinesViewModel.d.ts +27 -0
- package/lib/view/transactionDetail/journalEntryLinesViewModel.js +61 -1
- package/lib/view/transactionDetail/transactionDetailReducer.d.ts +11 -2
- package/lib/view/transactionDetail/transactionDetailReducer.js +67 -2
- package/lib/view/transactionDetail/transactionDetailState.d.ts +8 -1
- package/lib/view/transactionDetail/transactionDetailTypes.d.ts +2 -0
- package/package.json +6 -7
|
@@ -72,7 +72,6 @@ export interface JEScheduledTransactionPayload {
|
|
|
72
72
|
updated_by: UserPayload;
|
|
73
73
|
vendor: VendorPayload;
|
|
74
74
|
ai_summaries?: JEScheduleAISummariesPayload;
|
|
75
|
-
confidence_score?: number | null;
|
|
76
75
|
created_by?: UserPayload;
|
|
77
76
|
end_date?: string | null;
|
|
78
77
|
recommendations?: JEScheduleRecommendationsPayload;
|
|
@@ -285,7 +285,6 @@ function toJEScheduledTransaction(payload) {
|
|
|
285
285
|
: {},
|
|
286
286
|
scheduledJournalEntry: [],
|
|
287
287
|
aiSummaries: toJEScheduleAISummaries(payload.ai_summaries),
|
|
288
|
-
confidenceScore: payload.confidence_score ?? undefined,
|
|
289
288
|
createdByUserID: payload.created_by?.user_id ?? undefined,
|
|
290
289
|
recommendations: toJEScheduleRecommendations(payload.recommendations),
|
|
291
290
|
};
|
|
@@ -77,7 +77,7 @@ exports.getJEAccruedScheduleByJEScheduleKey = getJEAccruedScheduleByJEScheduleKe
|
|
|
77
77
|
const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTransactionKey, state) => {
|
|
78
78
|
const { jeSchedulesState, vendorState, accountState, userState, classState, transactionState, } = state;
|
|
79
79
|
const jeScheduleTransactionState = (0, get_1.default)(jeSchedulesState.schedulesByTransactionKey, jeScheduleTransactionKey);
|
|
80
|
-
const { period, updatedByUserID: updatedBy, createdByUserID: createdBy, vendorId, jeCredit, jeDebit, currencyCode, currencySymbol, balanceAsOfToday, baseTransaction, startDate, endDate, status, updatedAt, jeScheduleId, scheduledJournalEntry, dayOfPostingDate: postingDate, lastDayOfMonth, otherAttributes, jeScheduleType, aiSummaries,
|
|
80
|
+
const { period, updatedByUserID: updatedBy, createdByUserID: createdBy, vendorId, jeCredit, jeDebit, currencyCode, currencySymbol, balanceAsOfToday, baseTransaction, startDate, endDate, status, updatedAt, jeScheduleId, scheduledJournalEntry, dayOfPostingDate: postingDate, lastDayOfMonth, otherAttributes, jeScheduleType, aiSummaries, recommendations, } = jeScheduleTransactionState;
|
|
81
81
|
const vendorDetails = (0, vendorSelector_1.getVendorByVendorId)(vendorState, vendorId);
|
|
82
82
|
if (vendorDetails == null) {
|
|
83
83
|
throw new Error(`Vendor with ${vendorId} doesn't exist`);
|
|
@@ -136,7 +136,6 @@ const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTransacti
|
|
|
136
136
|
},
|
|
137
137
|
scheduledJournalEntry,
|
|
138
138
|
aiSummaries,
|
|
139
|
-
confidenceScore,
|
|
140
139
|
createdByUser: createdByUserDetails,
|
|
141
140
|
recommendations,
|
|
142
141
|
};
|
|
@@ -275,7 +275,6 @@ export function toJEScheduledTransaction(payload) {
|
|
|
275
275
|
: {},
|
|
276
276
|
scheduledJournalEntry: [],
|
|
277
277
|
aiSummaries: toJEScheduleAISummaries(payload.ai_summaries),
|
|
278
|
-
confidenceScore: payload.confidence_score ?? undefined,
|
|
279
278
|
createdByUserID: payload.created_by?.user_id ?? undefined,
|
|
280
279
|
recommendations: toJEScheduleRecommendations(payload.recommendations),
|
|
281
280
|
};
|
|
@@ -70,7 +70,7 @@ export const getJEAccruedScheduleByJEScheduleKey = (JEScheduleKey, state) => {
|
|
|
70
70
|
export const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTransactionKey, state) => {
|
|
71
71
|
const { jeSchedulesState, vendorState, accountState, userState, classState, transactionState, } = state;
|
|
72
72
|
const jeScheduleTransactionState = recordGet(jeSchedulesState.schedulesByTransactionKey, jeScheduleTransactionKey);
|
|
73
|
-
const { period, updatedByUserID: updatedBy, createdByUserID: createdBy, vendorId, jeCredit, jeDebit, currencyCode, currencySymbol, balanceAsOfToday, baseTransaction, startDate, endDate, status, updatedAt, jeScheduleId, scheduledJournalEntry, dayOfPostingDate: postingDate, lastDayOfMonth, otherAttributes, jeScheduleType, aiSummaries,
|
|
73
|
+
const { period, updatedByUserID: updatedBy, createdByUserID: createdBy, vendorId, jeCredit, jeDebit, currencyCode, currencySymbol, balanceAsOfToday, baseTransaction, startDate, endDate, status, updatedAt, jeScheduleId, scheduledJournalEntry, dayOfPostingDate: postingDate, lastDayOfMonth, otherAttributes, jeScheduleType, aiSummaries, recommendations, } = jeScheduleTransactionState;
|
|
74
74
|
const vendorDetails = getVendorByVendorId(vendorState, vendorId);
|
|
75
75
|
if (vendorDetails == null) {
|
|
76
76
|
throw new Error(`Vendor with ${vendorId} doesn't exist`);
|
|
@@ -129,7 +129,6 @@ export const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTr
|
|
|
129
129
|
},
|
|
130
130
|
scheduledJournalEntry,
|
|
131
131
|
aiSummaries,
|
|
132
|
-
confidenceScore,
|
|
133
132
|
createdByUser: createdByUserDetails,
|
|
134
133
|
recommendations,
|
|
135
134
|
};
|
package/lib/esm/index.js
CHANGED
|
@@ -171,7 +171,7 @@ import { toExpenseAutomationViewType, } from './view/expenseAutomationView/expen
|
|
|
171
171
|
import { isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardCreditType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, } from './view/expenseAutomationView/helpers/reconciliationHelpers';
|
|
172
172
|
import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
|
|
173
173
|
import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview, } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
|
|
174
|
-
import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryJeSchedule as retryExpenseAutomationJESchedule, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData,
|
|
174
|
+
import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryJeSchedule as retryExpenseAutomationJESchedule, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
|
|
175
175
|
import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess, } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
|
|
176
176
|
import { clearStatementDateConflict, deleteAccountStatement, excludeAccountFromReconciliation, fetchReconciliation as fetchReconciliationView, includeAccountInReconciliation, parseStatement, parseStatementFailure, parseStatementSuccess, reparseStatement, reparseStatementFailure, reparseStatementSuccess, resetReparseStatementStatus, saveReconciliationDetail as saveExpenseAutomationReconciliationDetail, saveReconciliationReview as saveExpenseAutomationReconciliationReview, setConnectionInProgressForAccount as setConnectionInProgressForAccountReconciliation, setStatementParseInProgress, submitStatementUpdate, updateAccountReconciliationLocalData as updateExpenseAutomationAccountReconciliationLocalData, updateSelectedAccountId as updateExpenseAutomationAccountReconciliationSelectedAccountId, updateSelectedTab as updateExpenseAutomationAccountReconciliationSelectedTab, updateReconListScrollPosition as updateExpenseAutomationReconListScrollPosition, updateReviewTabSortState as updateExpenseAutomationReconReviewTabListSortState, updateReviewTabLocalData as updateExpenseAutomationReconReviewTabLocalData, updateReconcileTabListScrollState as updateExpenseAutomationReconcileTabListScrollState, updateReconcileTabListSortState as updateExpenseAutomationReconcileTabListSortState, updateReconcileTabLocalData as updateExpenseAutomationReconcileTabLocalData, updateSelectedDrawerAccountId as updateExpenseAutomationSelectedDrawerAccountId, updateNodeCollapseState, updateParsedStatementData, updateStatementProcessingFailed, updateStatementUpdateLocalData, updateStatementUploadChosen, uploadAccountStatement, } from './view/expenseAutomationView/reducers/reconciliationViewReducer';
|
|
177
177
|
import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markCategoryClassRecommendationsFailureForCategorization, markTransactionAsNotMiscategorized, removeTransactionFromAllTabs, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
|
|
@@ -180,7 +180,7 @@ import { getExpenseAutomationReconciliationView, getReparseStatementStatusByAcco
|
|
|
180
180
|
import { getExpenseAutomationTransactionView, getLastTransferEntryReplacement, } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
|
|
181
181
|
import { TRANSACTION_FILTER_CATEGORIES, applyTransactionFilters, } from './view/expenseAutomationView/transactionFilterHelpers';
|
|
182
182
|
import { DEFAULT_COMPLETED_SUB_TAB, toCompletedSubTab, } from './view/expenseAutomationView/types/completedSubTab';
|
|
183
|
-
import {
|
|
183
|
+
import { toJEScheduleMainTab as toExpenseAutomationJEScheduleMainTab, toJEScheduleSortKey as toExpenseAutomationJEScheduleSortKey, } from './view/expenseAutomationView/types/jeSchedulesViewState';
|
|
184
184
|
import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toMatchSource, toMissingReceiptsTab, } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
185
185
|
import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
|
|
186
186
|
import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
|
|
@@ -394,9 +394,9 @@ import { getAllTopExpenses, getTop6Expenses, getTopExpenses, } from './view/topE
|
|
|
394
394
|
*/
|
|
395
395
|
import { TOP_EX_TIME_PERIODS, } from './view/topEx/topExState';
|
|
396
396
|
import { getAccountingProviderAttachment, } from './view/transactionDetail/getAccountingProviderAttachmentSelector';
|
|
397
|
-
import { JOURNAL_ENTRY_SORT_KEYS, filterJournalEntryLinesExcludingLinked, journalEntryDefaultSortConfig, journalEntryTotalsByPostingSide, sortJournalEntryLines, sumJournalEntryAmounts, toJournalEntrySortKey, } from './view/transactionDetail/journalEntryLinesViewModel';
|
|
397
|
+
import { JOURNAL_ENTRY_SORT_KEYS, filterJournalEntryLinesExcludingLinked, journalEntryDefaultSortConfig, journalEntrySplitReconciliation, journalEntryTotalsByPostingSide, sortJournalEntryLines, sumJournalEntryAmounts, toJournalEntrySortKey, } from './view/transactionDetail/journalEntryLinesViewModel';
|
|
398
398
|
import { getChangedLineItemCountFromLocalData, isAccountUncategorized, } from './view/transactionDetail/transactionDetailLocalDataHelper';
|
|
399
|
-
import { clearTransactionDetailSaveStatus, deleteTransactionAttachment, downloadAccountingProviderAttachment, downloadAccountingProviderAttachmentFailure, downloadAccountingProviderAttachmentSuccess, fetchTransactionDetail, initializeTransactionDetailLocalData, markCategoryClassRecommendationsFailureForTransactionDetail, removeEntityRecommendationForLineIdForTransactionDetail, resetAllLineItemsToVendor, resetLineItemsCategoryClassInLocalData, resetSelectedCustomer, resetVendor, saveTransactionDetail, saveTransactionDetailLocalData, setAllLineItemsLocalDataIsUpdateAllChecked, setAllLineItemsToCategoryClassInLocalData, setIsVendorUpdateAllChecked, updateLatestSelectedEntity, updateLocalDataWithTransactionsUpdateWithVendorCheckbox, updateSelectedCustomer, updateSelectedVendor, updateTransactionDetail, updateVendorBulkRecommendationsFetchStatus, updateVendorToAllLineItems, uploadMissingAttachmentSuccess, } from './view/transactionDetail/transactionDetailReducer';
|
|
399
|
+
import { addSplitLine, clearTransactionDetailSaveStatus, deleteSplitLine, deleteTransactionAttachment, downloadAccountingProviderAttachment, downloadAccountingProviderAttachmentFailure, downloadAccountingProviderAttachmentSuccess, fetchTransactionDetail, initializeTransactionDetailLocalData, markCategoryClassRecommendationsFailureForTransactionDetail, removeEntityRecommendationForLineIdForTransactionDetail, resetAllLineItemsToVendor, resetLineItemsCategoryClassInLocalData, resetSelectedCustomer, resetVendor, saveTransactionDetail, saveTransactionDetailLocalData, setAllLineItemsLocalDataIsUpdateAllChecked, setAllLineItemsToCategoryClassInLocalData, setIsVendorUpdateAllChecked, toggleSplitEditMode, updateLatestSelectedEntity, updateLocalDataWithTransactionsUpdateWithVendorCheckbox, updateSelectedCustomer, updateSelectedVendor, updateTransactionDetail, updateVendorBulkRecommendationsFetchStatus, updateVendorToAllLineItems, uploadMissingAttachmentSuccess, } from './view/transactionDetail/transactionDetailReducer';
|
|
400
400
|
import { getInitialUpdatablePeriodsForTransactionRecommendations, getTransactionDetail, getTransactionDetailForTransaction, } from './view/transactionDetail/transactionDetailSelector';
|
|
401
401
|
import { getThirdPartyIdFromTransactionId, } from './view/transactionDetail/transactionDetailState';
|
|
402
402
|
import { getTransactionListByAccount, getTransactionListUIStateByAccountKey, } from './view/transactionList/transactionListByAccountSelector';
|
|
@@ -459,7 +459,7 @@ export { stringToUnion, stringToUnionStrict };
|
|
|
459
459
|
export { fetchMonthEndCloseChecks, fetchMonthClosePerformanceTrend, getMonthEndCloseChecksViewByTenantId, ALL_MONTH_END_CLOSE_CHECKS_FREQUENCY, };
|
|
460
460
|
export {
|
|
461
461
|
// Bulk Upload Types
|
|
462
|
-
BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab,
|
|
462
|
+
BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleMainTab, toExpenseAutomationJEScheduleSortKey, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, fetchExpenseAutomationMissingReceipts,
|
|
463
463
|
// Bulk Upload Actions
|
|
464
464
|
bulkUploadReceipts, bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, clearBulkUploadBatchDetailsForScopeChange, markBatchDetailRefreshAttempted, refreshBatchDetailsForBatchId, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, getExpenseAutomationFluxAnalysisView, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, getLastTransferEntryReplacement, updateFluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, excludeAccountFromReconciliation, includeAccountInReconciliation, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, getExpenseAutomationReconciliationView, getReparseStatementStatusByAccountId, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, updateStatementProcessingFailed, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, uploadAccountStatement, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateNodeCollapseState, updateStatementUploadChosen, submitStatementUpdate, clearStatementDateConflict, updateStatementUpdateLocalData, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
|
|
465
465
|
export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, markCategoryClassRecommendationsFailureForCategorization, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, resetCreateTransferEntryStatus, clearTransferEntryRouteReplacement, fetchAccountsForTransferFlow, removeTransactionFromAllTabs, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
|
|
@@ -515,7 +515,7 @@ export { isTransferTransaction };
|
|
|
515
515
|
export { getSupportedTransactionById, };
|
|
516
516
|
export { clearTransactionList, updateLatestTransactionId, parallelFetchAccountTransactionList, parallelFetchEntityTransactionList, fetchAccountTransactionList, updateTransactionListByAccount, updateTransactionListByAccountFailure, updateTransactionListByAccountUIState, parallelFetchClassTransactionList, updateTransactionListByClassUIState, updateTransactionListByClass, parallelFetchProjectTransactionList, updateTransactionListByProjectUIState, updateTransactionListByProject, updateTransactionListUIStateByCategoryType, parallelFetchTransactionListByCategoryType, };
|
|
517
517
|
export { getTransactionListByAccount, getTransactionListUIStateByAccountKey, };
|
|
518
|
-
export { fetchEntityTransactionList, updateTransactionListByEntity, saveTransactionDetailLocalData, clearTransactionDetailSaveStatus, updateTransactionListByEntityFailure, resetLineItemsCategoryClassInLocalData, setAllLineItemsToCategoryClassInLocalData, saveTransactionDetail, setAllLineItemsLocalDataIsUpdateAllChecked, initializeTransactionDetailLocalData, markCategoryClassRecommendationsFailureForTransactionDetail, removeEntityRecommendationForLineIdForTransactionDetail, updateSelectedVendor, updateSelectedCustomer, resetSelectedCustomer, resetVendor, updateLocalDataWithTransactionsUpdateWithVendorCheckbox, updateVendorToAllLineItems, resetAllLineItemsToVendor, updateLatestSelectedEntity, updateVendorBulkRecommendationsFetchStatus, setIsVendorUpdateAllChecked, };
|
|
518
|
+
export { fetchEntityTransactionList, updateTransactionListByEntity, saveTransactionDetailLocalData, clearTransactionDetailSaveStatus, updateTransactionListByEntityFailure, resetLineItemsCategoryClassInLocalData, setAllLineItemsToCategoryClassInLocalData, saveTransactionDetail, setAllLineItemsLocalDataIsUpdateAllChecked, initializeTransactionDetailLocalData, markCategoryClassRecommendationsFailureForTransactionDetail, removeEntityRecommendationForLineIdForTransactionDetail, updateSelectedVendor, updateSelectedCustomer, resetSelectedCustomer, resetVendor, updateLocalDataWithTransactionsUpdateWithVendorCheckbox, updateVendorToAllLineItems, resetAllLineItemsToVendor, updateLatestSelectedEntity, updateVendorBulkRecommendationsFetchStatus, setIsVendorUpdateAllChecked, addSplitLine, deleteSplitLine, toggleSplitEditMode, };
|
|
519
519
|
export { downloadAccountingProviderAttachment, downloadAccountingProviderAttachmentSuccess, downloadAccountingProviderAttachmentFailure, fetchTransactionDetail, updateTransactionDetail, uploadMissingAttachmentSuccess, deleteTransactionAttachment, getThirdPartyIdFromTransactionId, };
|
|
520
520
|
export { getTransactionListByEntity };
|
|
521
521
|
export { getTransactionListByClass, getTransactionListUIStateByClassKey, getTransactionListByProject, getTransactionListUIStateByProjectKey, getTransactionListByEntityForSinglePeriod, };
|
|
@@ -594,7 +594,7 @@ export { getNextNthWorkingDay, getNextTransferDate, getPreviousNthWorkingDay, is
|
|
|
594
594
|
export { fetchCompanyOnboardingView, fetchQBOConnectionPool, updateQBOConnectionPoolExternalConnection, fetchOnboardingCompletedCompanies, saveOnboardingCustomerCompletedStatus, toProductType, toProductTypeStrict, getOnboardingCockpitView, getNewOnboardingCustomerView, getOnboardingEmailGroup, initializeOnboardingCustomerViewUpdateData, clearOnboardingCustomerViewUpdateData, saveOnboardingCustomerViewUpdateData, updateOnboardingCustomerListUIState, updateCustomerCreationStatus, updateStatusAfterOnboardingCompleted, saveOnboardingCustomerViewUpdates, saveOnboardingCustomerNotes, saveOnboardingCustomerDataInLocalStore, updateOnboardingCustomerDataInLocalStore, resetNewOnboardedCustomerId, sendOnboardingCustomerViewInvite, retryBankAccountConnectionForOnboarding, };
|
|
595
595
|
export { getTransactionsListByCategoryType, getTransactionListUIStateByCategoryType, };
|
|
596
596
|
export { getChangedLineItemCountFromLocalData, isAccountUncategorized };
|
|
597
|
-
export { JOURNAL_ENTRY_SORT_KEYS, filterJournalEntryLinesExcludingLinked, journalEntryDefaultSortConfig, journalEntryTotalsByPostingSide, sortJournalEntryLines, sumJournalEntryAmounts, toJournalEntrySortKey, };
|
|
597
|
+
export { JOURNAL_ENTRY_SORT_KEYS, filterJournalEntryLinesExcludingLinked, journalEntryDefaultSortConfig, journalEntryTotalsByPostingSide, journalEntrySplitReconciliation, sortJournalEntryLines, sumJournalEntryAmounts, toJournalEntrySortKey, };
|
|
598
598
|
export { openSnackbar, closeSnackbar, getSnackbar, };
|
|
599
599
|
export { getSpendManagementEffectiveListPeriod, getSelectedCompanyOfficer, showBillPayPromoPage, showReimbursementPromoPage, getActualPaymentDate, isVerifiedStatusCode, isVerifiedPaymentAccountProviderStatusCode, isBulkProcessing, getBillListUniqueType, getRemiListUniqueType, getBulkOperationSuffix, toAccountsPromoConfig, toSameDayAchDisablementConfig, isPaymentMethodOutsideZeni, isAwaitingMarkAsPaid, checkIfLowBalance, };
|
|
600
600
|
export { canSendMonthEndEmailReport, shouldEnableCalendarPickerForLastReportSent, };
|
|
@@ -623,7 +623,7 @@ export { updateChargeCardTransactionAttachments, updateChargeCardStatusFromPushe
|
|
|
623
623
|
export { TIME_SERIES_DURATIONS, convertToTimeSeriesSelectionRange, toTimeSeriesDuration, fetchAggregatedReport, aggregatedReportView, };
|
|
624
624
|
export { fetchApAging, getApAgingReport, updateApAgingUIState, };
|
|
625
625
|
export { fetchApAgingDetail, getApAgingDetailForVendor, updateApAgingDetailUIState, };
|
|
626
|
-
export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryExpenseAutomationJESchedule,
|
|
626
|
+
export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryExpenseAutomationJESchedule, updateExpenseAutomationJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, };
|
|
627
627
|
export { createNewSchedulesAccrued, deleteScheduleAccruedDetail, cancelScheduleAccruedJournalEntry, fetchScheduleAccruedDetails, fetchScheduleAccruedDetailsPage, resetJEAccruedLinkInLocalData, saveScheduleAccruedDetails, updateAmountsInScheduleAccruedDetail, updatedJEAccruedLinkWithRecommendedLocalData, updatedJELinkInLocalDataAccruedExpenses, fetchRecommendedTransactionRowIndex, clearSelectedJELinkRowIndex, updateLinkBillExpenseLocalData, updateScheduleAccruedDetailsLocalData, updateSelectedJEAccruedScheduleKey, resetSelectedJEAccruedScheduleKey, resetAccruedDetailNewScheduleState, };
|
|
628
628
|
export { getJEScheduleTransactionKey, ALL_SCHEDULES_TYPES, getScheduleListReport, getAccruedScheduleListReport, fetchScheduleList, fetchAccruedScheduleList, fetchDownloadSchedules, fetchSchedulesAccount, updateScheduleListLocalData, getFetchStateForScheduleAccountList, toScheduleTypesType, toScheduleTypesTypeStrict, toScheduleListTabsFileTypeStrict, toScheduleSubTabType, updateScheduleListSubTab, updateScheduleListSearchText, updateScheduleListScrollState, updateScheduleListSortState, updateSelectedJEScheduleKey, fetchScheduleDetails, getScheduleDetailsView, getAccruedScheduleDetailsView, fetchScheduleDetailsPage, saveScheduleDetails, deleteScheduleDetail, createNewSchedules, updateScheduleDetailsLocalData, updateScheduleListDownloadState, updateAccruedJEScheduleAccruedByListKey, updatedSelectedJELinkRowIndex, getQBOUrlForLink, getThirdPartyIDFromQBOURL, updatedJELinkInLocalData, updateAmountsInScheduleDetail, resetJELinkInLocalData, updatedJELinkWithRecommendedLocalData, getFetchStateForScheduleListByType, getDefaultSelectedTimeframeForScheduleType, markAsCompleteScheduleDetail, resetMarkAsCompleteStatus, fetchVendorTabView, updateVendorTabViewTab, getVendorTabView, };
|
|
629
629
|
export { toVendorFirstReviewViewColumnKeyType, getGlobalMerchantAutoCompleteResults, getVendorFirstReviewView, getVendorFirstReviewAttachmentView, fetchVendorFirstReviewView, fetchVendorFirstReviewAttachments, updateVendorFirstReviewViewScrollYOffset, resetVendorFirstReviewLocalData, updateVendorFirstReviewViewPageToken, clearRecentlySavedErroredVendorData, saveVendorFirstReviewView, updateVendorFirstReviewViewLocalData, updateVendorFirstReviewSortUiState, fetchGlobalMerchantAutoCompleteView, clearGlobalMerchantAutoCompleteResults, updateReviewVendorDetailLocalData, saveVendorDetailsView, getVendorDetailSelectorView, };
|
|
@@ -44,10 +44,7 @@ export const initialState = {
|
|
|
44
44
|
uiState: {
|
|
45
45
|
searchString: '',
|
|
46
46
|
scrollPosition: { scrollTop: 0, scrollLeft: undefined },
|
|
47
|
-
|
|
48
|
-
selectedJETypeFilter: null,
|
|
49
|
-
pendingGroupCollapsed: false,
|
|
50
|
-
recordedGroupCollapsed: false,
|
|
47
|
+
selectedMainTab: 'pending_review',
|
|
51
48
|
sortKey: 'transactionDate',
|
|
52
49
|
sortOrder: 'descending',
|
|
53
50
|
totalCount: 0,
|
|
@@ -384,39 +381,16 @@ const expenseAutomationJESchedulesView = createSlice({
|
|
|
384
381
|
if (action.payload.scrollPosition != null) {
|
|
385
382
|
draft.uiState.scrollPosition = action.payload.scrollPosition;
|
|
386
383
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
return { payload: { selectedJEHighLevelTab } };
|
|
391
|
-
},
|
|
392
|
-
reducer(draft, action) {
|
|
393
|
-
draft.uiState.selectedJEHighLevelTab =
|
|
394
|
-
action.payload.selectedJEHighLevelTab;
|
|
395
|
-
},
|
|
396
|
-
},
|
|
397
|
-
updateJEScheduleTypeFilter: {
|
|
398
|
-
prepare(selectedJETypeFilter) {
|
|
399
|
-
return { payload: { selectedJETypeFilter } };
|
|
400
|
-
},
|
|
401
|
-
reducer(draft, action) {
|
|
402
|
-
draft.uiState.selectedJETypeFilter =
|
|
403
|
-
action.payload.selectedJETypeFilter;
|
|
404
|
-
},
|
|
405
|
-
},
|
|
406
|
-
toggleJEPendingGroupCollapsed(draft) {
|
|
407
|
-
draft.uiState.pendingGroupCollapsed =
|
|
408
|
-
!draft.uiState.pendingGroupCollapsed;
|
|
409
|
-
},
|
|
410
|
-
toggleJERecordedGroupCollapsed(draft) {
|
|
411
|
-
draft.uiState.recordedGroupCollapsed =
|
|
412
|
-
!draft.uiState.recordedGroupCollapsed;
|
|
384
|
+
if (action.payload.selectedMainTab != null) {
|
|
385
|
+
draft.uiState.selectedMainTab = action.payload.selectedMainTab;
|
|
386
|
+
}
|
|
413
387
|
},
|
|
414
388
|
clearExpenseAutomationJESchedulesView(draft) {
|
|
415
389
|
Object.assign(draft, initialState);
|
|
416
390
|
},
|
|
417
391
|
},
|
|
418
392
|
});
|
|
419
|
-
export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, removeJeScheduleTransactionKey, retryJeSchedule, retryJeScheduleFailure, retryJeScheduleSuccess, saveAccountSettings, saveAccountSettingsFailure, saveAccountSettingsLocalData, saveAccountSettingsSuccess,
|
|
393
|
+
export const { clearExpenseAutomationJESchedulesView, clearJeAccountSettingsLocalData, clearJeScheduleLocalData, fetchAccountSettingsListForAccountTypes, fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesPage, fetchJeSchedulesSuccess, fetchRecommendationForAccountSettings, ignoreRecommendedJeSchedule, ignoreRecommendedJeScheduleFailure, ignoreRecommendedJeScheduleSuccess, initializeAccountSettingsView, initializeJeScheduleLocalData, removeFailedJeScheduleTransactionKey, removeJeScheduleLocalDataById, removeJeScheduleTransactionKey, retryJeSchedule, retryJeScheduleFailure, retryJeScheduleSuccess, saveAccountSettings, saveAccountSettingsFailure, saveAccountSettingsLocalData, saveAccountSettingsSuccess, updateAccountSettingsListForAccountTypes, updateAccountSettingsListForAccountTypesFailure, updateJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, updateRecommendationForAccountSettings, updateRecommendationForAccountSettingsFailure, } = expenseAutomationJESchedulesView.actions;
|
|
420
394
|
export default expenseAutomationJESchedulesView.reducer;
|
|
421
395
|
const doUpdateRecommendationForAccountSettings = (draft, payload) => {
|
|
422
396
|
const { prepaidExpensesRecommendations, fixedAssetsRecommendations, accruedExpensesRecommendations, } = mapAccountTypeRecommendationPayloadToAccountRecommendationByType(payload);
|
|
@@ -113,24 +113,11 @@ export function getExpenseAutomationJESchedulesView(state) {
|
|
|
113
113
|
const jeScheduleDetails = getJEScheduledTransactionByJEScheduleTransactionKey(jeScheduleKey, state);
|
|
114
114
|
failedJeScheduledTransaction.push(jeScheduleDetails);
|
|
115
115
|
});
|
|
116
|
-
const { sortKey, sortOrder
|
|
117
|
-
const matchesTypeFilter = (schedule) => selectedJETypeFilter == null ||
|
|
118
|
-
schedule.jeScheduleType === selectedJETypeFilter;
|
|
116
|
+
const { sortKey, sortOrder } = uiState;
|
|
119
117
|
const draftSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'draft'), sortKey, sortOrder);
|
|
120
118
|
const ongoingSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'ongoing'), sortKey, sortOrder);
|
|
121
119
|
const completedSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => schedule.status.code === 'completed' ||
|
|
122
120
|
schedule.status.code === 'marked_as_completed'), sortKey, sortOrder);
|
|
123
|
-
const recordedSchedules = sortJEScheduledTransactions(jeScheduledTransaction.filter((schedule) => (schedule.status.code === 'ongoing' ||
|
|
124
|
-
schedule.status.code === 'completed' ||
|
|
125
|
-
schedule.status.code === 'marked_as_completed') &&
|
|
126
|
-
matchesTypeFilter(schedule)), sortKey, sortOrder);
|
|
127
|
-
const allDraftSchedules = jeScheduledTransaction.filter((schedule) => schedule.status.code === 'draft');
|
|
128
|
-
const kpiSummary = {
|
|
129
|
-
aiAccountant: jeScheduledTransaction.filter((schedule) => schedule.confidenceScore != null).length,
|
|
130
|
-
manual: jeScheduledTransaction.filter((schedule) => schedule.confidenceScore == null).length,
|
|
131
|
-
needsReview: allDraftSchedules.length,
|
|
132
|
-
total: jeScheduledTransaction.length,
|
|
133
|
-
};
|
|
134
121
|
const unsortedResolveSchedules = [];
|
|
135
122
|
failedJeScheduledTransaction.forEach((schedule) => {
|
|
136
123
|
schedule.scheduledJournalEntry.forEach((journalEntry) => {
|
|
@@ -143,8 +130,8 @@ export function getExpenseAutomationJESchedulesView(state) {
|
|
|
143
130
|
const resolveSchedules = sortJEScheduledTransactions(unsortedResolveSchedules, sortKey, sortOrder);
|
|
144
131
|
const validResolveForPending = unsortedResolveSchedules.filter((r) => jeScheduleLocalDataById[r.scheduledJournalEntry.scheduledJournalEntryID] != null);
|
|
145
132
|
const pendingReviewSchedules = sortJEScheduledTransactions([
|
|
146
|
-
...
|
|
147
|
-
...validResolveForPending
|
|
133
|
+
...jeScheduledTransaction.filter((schedule) => schedule.status.code === 'draft'),
|
|
134
|
+
...validResolveForPending,
|
|
148
135
|
], sortKey, sortOrder);
|
|
149
136
|
const allSteps = monthYearPeriodId != null
|
|
150
137
|
? getAllSteps(monthEndCloseChecksState, monthYearPeriodId, currentTenant.tenantId)
|
|
@@ -168,10 +155,8 @@ export function getExpenseAutomationJESchedulesView(state) {
|
|
|
168
155
|
allClassList: allClasses,
|
|
169
156
|
completedSchedules,
|
|
170
157
|
draftSchedules,
|
|
171
|
-
kpiSummary,
|
|
172
158
|
ongoingSchedules,
|
|
173
159
|
pendingReviewSchedules,
|
|
174
|
-
recordedSchedules,
|
|
175
160
|
resolveSchedules: resolveSchedules,
|
|
176
161
|
accountSettingsView,
|
|
177
162
|
postStatusById: postStatusById,
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
|
|
2
|
-
const JE_HIGH_LEVEL_TABS = ['je', 'ongoing_schedules'];
|
|
3
|
-
export const toJEHighLevelTab = (v) => stringToUnion(v, JE_HIGH_LEVEL_TABS);
|
|
4
2
|
const JE_SCHEDULE_SORT_KEYS = [
|
|
5
3
|
'vendor',
|
|
6
4
|
'category',
|
|
@@ -18,3 +16,9 @@ const JE_SCHEDULE_SORT_KEYS = [
|
|
|
18
16
|
'memo',
|
|
19
17
|
];
|
|
20
18
|
export const toJEScheduleSortKey = (v) => stringToUnion(v, JE_SCHEDULE_SORT_KEYS);
|
|
19
|
+
const JE_SCHEDULE_MAIN_TABS = [
|
|
20
|
+
'pending_review',
|
|
21
|
+
'ongoing',
|
|
22
|
+
'completed',
|
|
23
|
+
];
|
|
24
|
+
export const toJEScheduleMainTab = (v) => stringToUnion(v, JE_SCHEDULE_MAIN_TABS);
|
|
@@ -45,7 +45,15 @@ export const toTransactionUpdatesFromTransactionDetailLocalData = (transactionDe
|
|
|
45
45
|
let lastUpdatedCategory;
|
|
46
46
|
let lastUpdatedClass;
|
|
47
47
|
// single recommendation to just pick the last recommendation in the list of lines
|
|
48
|
+
const deletedLineIds = new Set(transactionDetailLocalData.deletedLineIds ?? []);
|
|
49
|
+
const existingLineIds = new Set(transaction.lines?.map((l) => l.id) ?? []);
|
|
50
|
+
// Collect new lines — in lineItemById but not yet in transaction.lines.
|
|
51
|
+
const addedLines = Object.values(transactionDetailLocalData.lineItemById).filter((item) => !existingLineIds.has(item.id));
|
|
48
52
|
transaction.lines?.forEach((line) => {
|
|
53
|
+
// Skip lines the user deleted in edit mode.
|
|
54
|
+
if (deletedLineIds.has(line.id)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
49
57
|
const lineItem = transactionDetailLocalData.lineItemById[line.id];
|
|
50
58
|
if (line.type === 'transaction_with_account_and_class_line' ||
|
|
51
59
|
line.type === 'transaction_with_product_or_service_line' ||
|
|
@@ -56,6 +64,7 @@ export const toTransactionUpdatesFromTransactionDetailLocalData = (transactionDe
|
|
|
56
64
|
const entityDetails = getEntityDetails(selectedEntity, lineItem, transactionDetailLocalData.vendorUpdates, transactionDetailLocalData.customerUpdates);
|
|
57
65
|
updatesByLineId[line.id] = {
|
|
58
66
|
lineDescription: lineItem.lineDescription,
|
|
67
|
+
amount: lineItem.amount,
|
|
59
68
|
class: lineItem.class,
|
|
60
69
|
account: lineItem.account,
|
|
61
70
|
// Project is at the transaction level for invoice/credit_memo; omit from lines.
|
|
@@ -77,6 +86,14 @@ export const toTransactionUpdatesFromTransactionDetailLocalData = (transactionDe
|
|
|
77
86
|
currentSelectedEntityLine.type === 'vendor'
|
|
78
87
|
? lineItem.vendor
|
|
79
88
|
: undefined,
|
|
89
|
+
// Carry the JE debit/credit side so a split edit that flips an
|
|
90
|
+
// existing line's posting side persists through the line patch.
|
|
91
|
+
...(line.type === 'journal_entry_transaction_line'
|
|
92
|
+
? {
|
|
93
|
+
postingType: lineItem.postingType,
|
|
94
|
+
postingTypeName: lineItem.postingTypeName,
|
|
95
|
+
}
|
|
96
|
+
: {}),
|
|
80
97
|
};
|
|
81
98
|
}
|
|
82
99
|
let hasCategoryChanged = false;
|
|
@@ -163,6 +180,8 @@ export const toTransactionUpdatesFromTransactionDetailLocalData = (transactionDe
|
|
|
163
180
|
and all the line items are NOT uncategorized*/
|
|
164
181
|
markAsMiscatUpdates: isTransactionMisCategorized,
|
|
165
182
|
anyBulkUpdates: isBulkUpdate,
|
|
183
|
+
addedLines: addedLines.length > 0 ? addedLines : undefined,
|
|
184
|
+
deletedLineIds: deletedLineIds.size > 0 ? [...deletedLineIds] : undefined,
|
|
166
185
|
};
|
|
167
186
|
};
|
|
168
187
|
const doUpdateEntityUpdates = (entityUpdates, entityId, entityType, recommendation, isBulkUpdate = false, updatedEntityId, entityName) => {
|
|
@@ -159,7 +159,7 @@ function preparePayload(transactionState, vendorState, transactionDetailState, t
|
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
if (detail != null) {
|
|
162
|
-
const transUpdates = toTransactionUpdatePayload(saveUpdates.updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, currentSelectedEntity);
|
|
162
|
+
const transUpdates = toTransactionUpdatePayload(saveUpdates.updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, currentSelectedEntity, saveUpdates.deletedLineIds, saveUpdates.addedLines);
|
|
163
163
|
const entityUpdates = toEntityUpdatePayload(saveUpdates.entityRelatedUpdates);
|
|
164
164
|
return {
|
|
165
165
|
entity_related_updates: entityUpdates,
|
|
@@ -169,7 +169,7 @@ function preparePayload(transactionState, vendorState, transactionDetailState, t
|
|
|
169
169
|
}
|
|
170
170
|
return undefined;
|
|
171
171
|
}
|
|
172
|
-
export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, tranSelectedEntity) => {
|
|
172
|
+
export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, tranSelectedEntity, deletedLineIds, addedLines) => {
|
|
173
173
|
const transaction = Object.assign({}, detail);
|
|
174
174
|
transaction.memo = updates.memo ?? '';
|
|
175
175
|
// Unlike `memo` (always reset to '' when absent), `documentId` falls back to
|
|
@@ -178,6 +178,11 @@ export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracki
|
|
|
178
178
|
// either the unchanged current value or undefined, and we must not send an
|
|
179
179
|
// empty `document_id` that the server would treat as clearing the number.
|
|
180
180
|
transaction.documentId = updates.documentId ?? transaction.documentId;
|
|
181
|
+
// Remove lines deleted by the user in edit mode before patching or serializing.
|
|
182
|
+
if (deletedLineIds != null && deletedLineIds.length > 0) {
|
|
183
|
+
const deletedSet = new Set(deletedLineIds);
|
|
184
|
+
transaction.lines = transaction.lines?.filter((line) => !deletedSet.has(line.id));
|
|
185
|
+
}
|
|
181
186
|
const recommendationUpdates = {};
|
|
182
187
|
for (const key in updates.updatesByLineId) {
|
|
183
188
|
const lineUpdates = updates.updatesByLineId[key];
|
|
@@ -185,6 +190,9 @@ export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracki
|
|
|
185
190
|
if (line.id === key) {
|
|
186
191
|
const lineTobeUpdated = Object.assign({}, line);
|
|
187
192
|
lineTobeUpdated.lineDescription = lineUpdates.lineDescription ?? '';
|
|
193
|
+
if (lineUpdates.amount != null) {
|
|
194
|
+
lineTobeUpdated.amount = lineUpdates.amount;
|
|
195
|
+
}
|
|
188
196
|
if (lineUpdates.class != null) {
|
|
189
197
|
lineTobeUpdated.class = lineUpdates.class;
|
|
190
198
|
}
|
|
@@ -206,6 +214,16 @@ export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracki
|
|
|
206
214
|
else {
|
|
207
215
|
lineTobeUpdated.vendor = undefined;
|
|
208
216
|
}
|
|
217
|
+
// Persist a debit↔credit flip on an existing JE line. `lineTobeUpdated`
|
|
218
|
+
// is typed as the account-and-class shape, but for a JE the runtime
|
|
219
|
+
// object is a JournalEntryTransactionLine, so cast to set the side.
|
|
220
|
+
if (lineUpdates.postingType != null) {
|
|
221
|
+
const journalEntryLine = lineTobeUpdated;
|
|
222
|
+
journalEntryLine.postingType = lineUpdates.postingType;
|
|
223
|
+
if (lineUpdates.postingTypeName != null) {
|
|
224
|
+
journalEntryLine.postingTypeName = lineUpdates.postingTypeName;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
209
227
|
if (lineUpdates.recommendation != null) {
|
|
210
228
|
recommendationUpdates[line.id] = lineUpdates.recommendation;
|
|
211
229
|
}
|
|
@@ -225,6 +243,12 @@ export const toTransactionUpdatePayload = (updates, detail, cotTransactionTracki
|
|
|
225
243
|
});
|
|
226
244
|
transaction.lines = newLineMap;
|
|
227
245
|
}
|
|
246
|
+
// Append lines added by the user in edit mode. Sending id='' tells the
|
|
247
|
+
// backend to create a new QBO line rather than updating an existing one.
|
|
248
|
+
if (addedLines != null && addedLines.length > 0) {
|
|
249
|
+
const newLines = addedLines.map(toNewTransactionLine);
|
|
250
|
+
transaction.lines = [...(transaction.lines ?? []), ...newLines];
|
|
251
|
+
}
|
|
228
252
|
transaction.recommendations = recommendationUpdates;
|
|
229
253
|
// Convert transaction to payload first
|
|
230
254
|
let basePayload;
|
|
@@ -299,6 +323,49 @@ const checkIfVendorOrCustomerMissingForAnyLineItem = (transactionPayload) => {
|
|
|
299
323
|
}
|
|
300
324
|
return isAnyVendorOrCustomerMissing;
|
|
301
325
|
};
|
|
326
|
+
// Converts a locally-created line item (from edit mode) into the wire shape
|
|
327
|
+
// expected by the categorize endpoint. Sending id='' signals the backend to
|
|
328
|
+
// create a new QBO line rather than update an existing one.
|
|
329
|
+
//
|
|
330
|
+
// Type-dispatched so each transaction family contributes its own new-line
|
|
331
|
+
// shape: journal entries carry debit/credit `postingType`, expenses carry
|
|
332
|
+
// `billable`. Phase 3 types extend this by adding a branch rather than forking
|
|
333
|
+
// the function.
|
|
334
|
+
const EMPTY_ACCOUNT = {
|
|
335
|
+
accountDescription: '',
|
|
336
|
+
accountId: '',
|
|
337
|
+
accountName: '',
|
|
338
|
+
labels: [],
|
|
339
|
+
};
|
|
340
|
+
export const toNewTransactionLine = (item) => {
|
|
341
|
+
if (item.type === 'journal_entry_transaction_line') {
|
|
342
|
+
const journalEntryLine = {
|
|
343
|
+
...item,
|
|
344
|
+
id: '',
|
|
345
|
+
type: 'journal_entry_transaction_line',
|
|
346
|
+
platformLineDetailType: item.platformLineDetailType ?? 'journal_entry_line_detail',
|
|
347
|
+
account: item.account ?? EMPTY_ACCOUNT,
|
|
348
|
+
billable: item.billable ?? 'not_billable',
|
|
349
|
+
isCategoryMiscategorized: false,
|
|
350
|
+
isClassMiscategorized: false,
|
|
351
|
+
lineTransactionType: item.lineTransactionType ?? 'journal_entry',
|
|
352
|
+
postingType: item.postingType ?? 'debit',
|
|
353
|
+
postingTypeName: item.postingTypeName ?? '',
|
|
354
|
+
};
|
|
355
|
+
return journalEntryLine;
|
|
356
|
+
}
|
|
357
|
+
const accountAndClassLine = {
|
|
358
|
+
...item,
|
|
359
|
+
id: '',
|
|
360
|
+
type: 'transaction_with_account_and_class_line',
|
|
361
|
+
platformLineDetailType: item.platformLineDetailType ?? 'account_based_expense_line_detail',
|
|
362
|
+
account: item.account ?? EMPTY_ACCOUNT,
|
|
363
|
+
billable: item.billable ?? 'not_billable',
|
|
364
|
+
isCategoryMiscategorized: false,
|
|
365
|
+
isClassMiscategorized: false,
|
|
366
|
+
};
|
|
367
|
+
return accountAndClassLine;
|
|
368
|
+
};
|
|
302
369
|
const toEntityUpdatePayload = (entityUpdates) => {
|
|
303
370
|
const entityUpdatesPayload = [];
|
|
304
371
|
let entityKey;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Big from 'big.js';
|
|
1
2
|
import orderBy from 'lodash/orderBy';
|
|
2
3
|
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
3
4
|
import { LINE_TYPE_LINKED, } from '../../entity/transaction/stateTypes/transactionLine';
|
|
@@ -101,6 +102,63 @@ export const journalEntryTotalsByPostingSide = (lines) => {
|
|
|
101
102
|
};
|
|
102
103
|
};
|
|
103
104
|
// ---------------------------------------------------------------------------
|
|
105
|
+
// Split reconciliation & validation (Phase 2 — JE split)
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Half-cent tolerance for the balance equality checks, matching the expense
|
|
108
|
+
// reconciliation row's epsilon. Sums use big.js so repeated decimal addition
|
|
109
|
+
// doesn't drift before the comparison.
|
|
110
|
+
const JOURNAL_ENTRY_BALANCE_EPSILON = 0.005;
|
|
111
|
+
/**
|
|
112
|
+
* Sums debit and credit sides (big.js-exact) and reports whether the split is
|
|
113
|
+
* balanced: total debits equal total credits AND equal the original
|
|
114
|
+
* transaction total. The original total of a valid JE equals its total debits,
|
|
115
|
+
* so it is passed in by the caller (`transaction.amount.amount`).
|
|
116
|
+
*/
|
|
117
|
+
export const journalEntrySplitReconciliation = (lines, originalTotal) => {
|
|
118
|
+
let debit = new Big(0);
|
|
119
|
+
let credit = new Big(0);
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const amount = new Big(line.amount?.amount ?? 0);
|
|
122
|
+
if (line.postingType === 'debit') {
|
|
123
|
+
debit = debit.plus(amount);
|
|
124
|
+
}
|
|
125
|
+
else if (line.postingType === 'credit') {
|
|
126
|
+
credit = credit.plus(amount);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const balancedToEachOther = debit
|
|
130
|
+
.minus(credit)
|
|
131
|
+
.abs()
|
|
132
|
+
.lt(JOURNAL_ENTRY_BALANCE_EPSILON);
|
|
133
|
+
const balancedToOriginal = debit
|
|
134
|
+
.minus(originalTotal)
|
|
135
|
+
.abs()
|
|
136
|
+
.lt(JOURNAL_ENTRY_BALANCE_EPSILON);
|
|
137
|
+
return {
|
|
138
|
+
debitTotal: debit.toNumber(),
|
|
139
|
+
creditTotal: credit.toNumber(),
|
|
140
|
+
isBalanced: balancedToEachOther && balancedToOriginal,
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Save-time validation for a JE split (Figma `4165:33028` / `4165:45379`):
|
|
145
|
+
* 1. every line needs a non-zero debit or credit, and
|
|
146
|
+
* 2. total debits == total credits == original total.
|
|
147
|
+
* Returns the first failing rule's `errorKey` (maps to a strings entry). Does
|
|
148
|
+
* NOT require category/class to be chosen — balance is the only gate.
|
|
149
|
+
*/
|
|
150
|
+
export const validateJournalEntrySplit = (lines, originalTotal) => {
|
|
151
|
+
const everyLineHasSide = lines.every((line) => (line.postingType === 'debit' || line.postingType === 'credit') &&
|
|
152
|
+
Math.abs(line.amount?.amount ?? 0) > JOURNAL_ENTRY_BALANCE_EPSILON);
|
|
153
|
+
if (!everyLineHasSide) {
|
|
154
|
+
return { ok: false, errorKey: 'lineNeedsDebitOrCredit' };
|
|
155
|
+
}
|
|
156
|
+
if (!journalEntrySplitReconciliation(lines, originalTotal).isBalanced) {
|
|
157
|
+
return { ok: false, errorKey: 'totalsMustEqual' };
|
|
158
|
+
}
|
|
159
|
+
return { ok: true };
|
|
160
|
+
};
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
104
162
|
// Filter
|
|
105
163
|
// ---------------------------------------------------------------------------
|
|
106
164
|
/**
|