@zeniai/client-epic-state 5.3.21-betaAK1 → 5.3.21

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 (55) hide show
  1. package/lib/entity/genericEntity/customerWithSubCustomersId.d.ts +7 -0
  2. package/lib/entity/genericEntity/customerWithSubCustomersId.js +17 -0
  3. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  4. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  5. package/lib/entity/tenant/tenantPayload.d.ts +6 -0
  6. package/lib/entity/tenant/tenantPayload.js +5 -0
  7. package/lib/entity/tenant/tenantReducer.d.ts +6 -2
  8. package/lib/entity/tenant/tenantReducer.js +28 -4
  9. package/lib/entity/tenant/tenantSelector.d.ts +2 -1
  10. package/lib/entity/tenant/tenantSelector.js +4 -1
  11. package/lib/entity/tenant/tenantState.d.ts +10 -0
  12. package/lib/entity/tenant/tenantState.js +5 -0
  13. package/lib/epic.d.ts +2 -1
  14. package/lib/epic.js +2 -0
  15. package/lib/esm/entity/genericEntity/customerWithSubCustomersId.js +12 -0
  16. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  17. package/lib/esm/entity/tenant/tenantPayload.js +4 -1
  18. package/lib/esm/entity/tenant/tenantReducer.js +27 -3
  19. package/lib/esm/entity/tenant/tenantSelector.js +2 -0
  20. package/lib/esm/entity/tenant/tenantState.js +4 -1
  21. package/lib/esm/epic.js +2 -0
  22. package/lib/esm/index.js +7 -6
  23. package/lib/esm/view/companyView/companyViewReducer.js +26 -1
  24. package/lib/esm/view/companyView/epic/companyPassport/updateCustomersTabSettingEpic.js +47 -0
  25. package/lib/esm/view/companyView/selector/companyPassportViewSelector.js +2 -0
  26. package/lib/esm/view/companyView/types/companyPassport/companyPassportViewState.js +4 -0
  27. package/lib/esm/view/customerSummaryView/customerSummaryViewReducer.js +39 -6
  28. package/lib/esm/view/customerSummaryView/customerSummaryViewSelector.js +41 -11
  29. package/lib/esm/view/customerSummaryView/epic/fetchCustomerSummaryListEpic.js +6 -1
  30. package/lib/esm/view/transactionList/fetchTransactionListByEntityEpic.js +11 -2
  31. package/lib/esm/view/transactionList/transactionListReducer.js +24 -15
  32. package/lib/esm/view/trend/fetchIncomeTrendEpic.js +6 -2
  33. package/lib/index.d.ts +9 -8
  34. package/lib/index.js +53 -46
  35. package/lib/view/companyView/companyViewReducer.d.ts +8 -1
  36. package/lib/view/companyView/companyViewReducer.js +28 -3
  37. package/lib/view/companyView/epic/companyPassport/updateCustomersTabSettingEpic.d.ts +11 -0
  38. package/lib/view/companyView/epic/companyPassport/updateCustomersTabSettingEpic.js +51 -0
  39. package/lib/view/companyView/selector/companyPassportViewSelector.d.ts +1 -0
  40. package/lib/view/companyView/selector/companyPassportViewSelector.js +4 -1
  41. package/lib/view/companyView/types/companyPassport/companyPassportViewState.d.ts +1 -0
  42. package/lib/view/companyView/types/companyPassport/companyPassportViewState.js +4 -0
  43. package/lib/view/customerSummaryView/customerSummaryViewPayload.d.ts +20 -1
  44. package/lib/view/customerSummaryView/customerSummaryViewReducer.d.ts +3 -1
  45. package/lib/view/customerSummaryView/customerSummaryViewReducer.js +42 -6
  46. package/lib/view/customerSummaryView/customerSummaryViewSelector.d.ts +13 -1
  47. package/lib/view/customerSummaryView/customerSummaryViewSelector.js +45 -12
  48. package/lib/view/customerSummaryView/customerSummaryViewState.d.ts +24 -10
  49. package/lib/view/customerSummaryView/epic/fetchCustomerSummaryListEpic.js +6 -1
  50. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  51. package/lib/view/transactionList/fetchTransactionListByEntityEpic.js +11 -2
  52. package/lib/view/transactionList/transactionListReducer.d.ts +3 -1
  53. package/lib/view/transactionList/transactionListReducer.js +24 -15
  54. package/lib/view/trend/fetchIncomeTrendEpic.js +6 -2
  55. package/package.json +1 -1
package/lib/esm/epic.js CHANGED
@@ -161,6 +161,7 @@ import { updateCapitalizationAccountThresholdEpic, } from './view/companyView/ep
161
161
  import { updateCompanyDetailsEpic, } from './view/companyView/epic/companyPassport/updateCompanyDetailsEpic';
162
162
  import { updateCompanyOfficerEpic, } from './view/companyView/epic/companyPassport/updateCompanyOfficerEpic';
163
163
  import { updateCompanyPassportLocalStoreDataEpic, } from './view/companyView/epic/companyPassport/updateCompanyPassportLocalStoreDataEpic';
164
+ import { updateCustomersTabSettingEpic, } from './view/companyView/epic/companyPassport/updateCustomersTabSettingEpic';
164
165
  import { updatePrimaryContactEpic, } from './view/companyView/epic/companyPassport/updatePrimaryContactEpic';
165
166
  import { fetchAllCockpitViewsEpic, } from './view/companyView/epic/fetchAllCockpitViewsEpic';
166
167
  import { fetchCompanyManagementViewEpic, } from './view/companyView/epic/fetchCompanyManagementViewEpic';
@@ -1517,6 +1518,7 @@ const ALL_EPICS = [
1517
1518
  updateCompanyProductServicesEpic,
1518
1519
  updateCompanyQboRealmIdEpic,
1519
1520
  updateCompanyTaskManagerViewFiltersEpic,
1521
+ updateCustomersTabSettingEpic,
1520
1522
  updateDashboardLayoutEpic,
1521
1523
  updateDebitCardPinAttemptEpic,
1522
1524
  updateDepositAccountEpic,
package/lib/esm/index.js CHANGED
@@ -73,7 +73,7 @@ import { getSnackbar } from './entity/snackbar/snackbarSelector';
73
73
  import { ALL_WEEK_DAYS, toDayOfWeek, toPriorityCodeType, toTaskStatusCodeType, } from './entity/task/taskState';
74
74
  import { getTaskGroupById } from './entity/taskGroup/taskGroupSelector';
75
75
  import { deleteConnection, doMagicLinkSignIn, doSignIn, doSignOut, fetchActiveTenant, fetchAllTenants, fetchExcludedResources as fetchExcludedResourcesForTenant, fetchExternalConnections as fetchExternalConnectionsForTenant, fetchSubscriptionSummaryForTenant, initEmailConnectOAuth, resendVerifyDeviceOTP, resetSignInState, saveAPIKeyConnection, saveConnectorCredentials, saveExternalConnection as saveExternalConnectionForTenant, saveOAuthConnection, seedTenantSummary, sendEmailMagicLinkToUser, sendSessionHeartbeat, toExternalIntegrationType, updateCurrentTenant, updateSignInState, verifyDeviceWithTwoFA, } from './entity/tenant/tenantReducer';
76
- import { DEFAULT_RECEIPTS_EMAIL, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getReceiptsEmail, getTenantBaseById, getTenantBaseViewForTenantId, getTenantBaseViewForTenantView, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, isCurrentTenantLoaded, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantLoaded, isTenantUsingZeniCOA, isZeniDomainTenant, toTenantCoreDetailsView, } from './entity/tenant/tenantSelector';
76
+ import { DEFAULT_RECEIPTS_EMAIL, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getReceiptsEmail, getTenantBaseById, getTenantBaseViewForTenantId, getTenantBaseViewForTenantView, getTenantCustomersTabSettings, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, isCurrentTenantLoaded, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantLoaded, isTenantUsingZeniCOA, isZeniDomainTenant, toTenantCoreDetailsView, } from './entity/tenant/tenantSelector';
77
77
  import { toExternalSupportedTool } from './entity/tenant/tenantTypes';
78
78
  import { pushToastNotification } from './entity/toastNotification/toastNotificationReducer';
79
79
  import { getLastNotificationTime, getNotifications, } from './entity/toastNotification/toastNotificationSelector';
@@ -169,11 +169,11 @@ import { fetchCompanyMonthEndReportHistoricData, fetchCompanyMonthEndReportHisto
169
169
  import { getCompanyMonthEndReportHistoricData, getCompanyMonthEndReportSelectorView, } from './view/companyMonthEndReportView/companyMonthEndReportViewSelector';
170
170
  import { fetchCockpitContext, fetchCompanyTaskManagerView, fetchTaskManagerMetrics, updateCompanyTaskManagerViewFilters, } from './view/companyTaskManagerView/companyTaskManagerViewReducer';
171
171
  import { getCompanyTaskManagerView, } from './view/companyTaskManagerView/companyTaskManagerViewSelector';
172
- import { clearQboProjectsReconnectRequest, companyManagementSaveUpdates, companyPassportClearDataInLocalStore, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, disableAccountingProjects, dismissCapitalizationOnboarding, enableAccountingProjects, fetchAllCockpitViews, fetchCompanyManagementView, fetchCompanyPassportView, fetchCompanyPortfolioView, fetchManagementView, fetchOnboardingView, fetchParentSubsidiaryManagementView, fetchPortfolioView, fetchSubscriptionView, fetchZeniUsers, resumeEnableAccountingProjects, saveCompanyPassportDetails, saveIndustryAndIncDateInCompanyPassportLocalStore, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCapitalizationAccountThreshold, updateCompanyDownloadState, updateCompanyManagementUIState, updateCompanyPassportLocalStoreData, updateCompanyPortfolioUIState, updateCompanyProductServices, updateCompanyQboRealmId, } from './view/companyView/companyViewReducer';
172
+ import { clearQboProjectsReconnectRequest, companyManagementSaveUpdates, companyPassportClearDataInLocalStore, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, disableAccountingProjects, dismissCapitalizationOnboarding, enableAccountingProjects, fetchAllCockpitViews, fetchCompanyManagementView, fetchCompanyPassportView, fetchCompanyPortfolioView, fetchManagementView, fetchOnboardingView, fetchParentSubsidiaryManagementView, fetchPortfolioView, fetchSubscriptionView, fetchZeniUsers, resumeEnableAccountingProjects, saveCompanyPassportDetails, saveIndustryAndIncDateInCompanyPassportLocalStore, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCapitalizationAccountThreshold, updateCompanyDownloadState, updateCompanyManagementUIState, updateCompanyPassportLocalStoreData, updateCompanyPortfolioUIState, updateCompanyProductServices, updateCompanyQboRealmId, updateCustomersTabSetting, } from './view/companyView/companyViewReducer';
173
173
  import { canSendMonthEndEmailReport, shouldEnableCalendarPickerForLastReportSent, } from './view/companyView/helpers/cockpitHelpers';
174
174
  import { getParentSubsidiaryManagementView } from './view/companyView/parentSubsidiaryView/parentSubsidiaryViewSelector';
175
175
  import { getAddonListZeniSku, getCompanyManagementView, getCompanyProductServicesUpdateStatus, getCompanyQboRealmIdUpdateStatus, getPlanListZeniSku, } from './view/companyView/selector/companyManagementViewSelector';
176
- import { getCompanyPassportLocalStoreData, getCompanyPassportView, isCompanyPassportDataToBeSaved, } from './view/companyView/selector/companyPassportViewSelector';
176
+ import { getCompanyPassportLocalStoreData, getCompanyPassportView, getIsCustomersTabSettingsUpdateInProgress, isCompanyPassportDataToBeSaved, } from './view/companyView/selector/companyPassportViewSelector';
177
177
  import { getCompanyPortfolioView, isInfiniteRunway, } from './view/companyView/selector/companyPortfolioViewSelector';
178
178
  import { getAllCockpitTabsFilterView, } from './view/companyView/selector/getAllCockpitTabsFilterView';
179
179
  import { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsFileTypeStrict, toCockpitTabsIDStrict, } from './view/companyView/types/cockpitTabsID';
@@ -509,7 +509,7 @@ export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsolute
509
509
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorSpendTrendFilterTabType';
510
510
  export { getNumberOfPeriods };
511
511
  export { SCHEDULE_DAYS_OF_MONTH, toScheduleDaysOfMonth, toMonth, toMonthStrict, toQuarter, toQuarterStrict, };
512
- export { getTenantBaseById, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, isCurrentTenantLoaded, isTenantLoaded, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, toTenantCoreDetailsView, getTenantBaseViewForTenantView, getTenantBaseViewForTenantId, isZeniDomainTenant, isTenantUsingZeniCOA, fetchActiveTenant, fetchAllTenants, seedTenantSummary, updateCurrentTenant, clearAll, doMagicLinkSignIn, verifyDeviceWithTwoFA, resendVerifyDeviceOTP, sendEmailMagicLinkToUser, doSignIn, updateSignInState, doSignOut, sendSessionHeartbeat, resetSignInState, fetchExcludedResourcesForTenant, fetchExternalConnectionsForTenant, saveExternalConnectionForTenant, deleteConnection, saveAPIKeyConnection, saveConnectorCredentials, saveOAuthConnection, initEmailConnectOAuth, toExternalIntegrationType, toExternalSupportedTool, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, DEFAULT_RECEIPTS_EMAIL, getReceiptsEmail, };
512
+ export { getTenantBaseById, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, isCurrentTenantLoaded, isTenantLoaded, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getTenantCustomersTabSettings, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, toTenantCoreDetailsView, getTenantBaseViewForTenantView, getTenantBaseViewForTenantId, isZeniDomainTenant, isTenantUsingZeniCOA, fetchActiveTenant, fetchAllTenants, seedTenantSummary, updateCurrentTenant, clearAll, doMagicLinkSignIn, verifyDeviceWithTwoFA, resendVerifyDeviceOTP, sendEmailMagicLinkToUser, doSignIn, updateSignInState, doSignOut, sendSessionHeartbeat, resetSignInState, fetchExcludedResourcesForTenant, fetchExternalConnectionsForTenant, saveExternalConnectionForTenant, deleteConnection, saveAPIKeyConnection, saveConnectorCredentials, saveOAuthConnection, initEmailConnectOAuth, toExternalIntegrationType, toExternalSupportedTool, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, DEFAULT_RECEIPTS_EMAIL, getReceiptsEmail, };
513
513
  export { toAccountType, toAccountGroupType, getAccountGroupKey, getAllAccounts, getTransactionFilterAccountOptions, };
514
514
  export { getAllClasses, getClassById, getClassFilterOptions, } from './entity/class/classSelector';
515
515
  export { getForecast };
@@ -599,7 +599,7 @@ export { newAddressInLocalStore, getAddress, getNewAddress, getAllNewAddresses,
599
599
  export { toManagementSortKeyType, toOnboardingSortKeyType, toPortfolioSortKeyType, toHealthSortKeyType, toTaskManagerSortKeyType, updateCompanyTaskManagerViewFilters, };
600
600
  export { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsIDStrict, toCockpitTabsFileTypeStrict, };
601
601
  export { isAllowedValueWithCode, isAllowedValueWithID, };
602
- export { fetchCompanyPassportView, getCompanyPassportView, getCompanyPassportLocalStoreData, isCompanyPassportDataToBeSaved, companyPassportSaveDataInLocalStore, saveIndustryAndIncDateInCompanyPassportLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, updateCompanyPassportLocalStoreData, saveCompanyPassportDetails, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, clearQboProjectsReconnectRequest, updateCompanyProductServices, getCompanyProductServicesUpdateStatus, updateCompanyQboRealmId, getCompanyQboRealmIdUpdateStatus, updateCapitalizationAccountThreshold, dismissCapitalizationOnboarding, };
602
+ export { fetchCompanyPassportView, getCompanyPassportView, getCompanyPassportLocalStoreData, getIsCustomersTabSettingsUpdateInProgress, isCompanyPassportDataToBeSaved, companyPassportSaveDataInLocalStore, saveIndustryAndIncDateInCompanyPassportLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, updateCompanyPassportLocalStoreData, saveCompanyPassportDetails, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCustomersTabSetting, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, clearQboProjectsReconnectRequest, updateCompanyProductServices, getCompanyProductServicesUpdateStatus, updateCompanyQboRealmId, getCompanyQboRealmIdUpdateStatus, updateCapitalizationAccountThreshold, dismissCapitalizationOnboarding, };
603
603
  export { toCompanyPassportLocalData, };
604
604
  export { COMPANY_ONBOARDING_INDUSTRY_TYPE_CODES, COMPANY_ONBOARDING_SUB_INDUSTRY_CODES_BY_INDUSTRY, COMPANY_PURPOSE_OF_ACCOUNT_CODES, COMPANY_SOURCE_OF_FUNDS_CODES, COMPANY_TRANSACTION_VOLUME_CODES, COMPANY_US_NEXUS_TYPE_CODES, getCompanyOnboardingSubIndustryCodesForIndustry, };
605
605
  export { getUncategorizedAccounts, getNestedAccountListHierarchy, };
@@ -876,5 +876,6 @@ export { getInvoicingOnboardingGateView } from './view/invoicing/invoicingConfig
876
876
  export { getExpenseAutomationJEOneTimeAccrualDetailView, getJEScheduleRowType, isAccruedScheduleRow, isAiAccountantSchedule, isExistingTabRow, isOneTimeAccrualRow, isRenderableOneTimeAccrual, isPendingReviewRow, } from './view/expenseAutomationView/selectors/jeSchedulesViewSelector';
877
877
  export { getActualMatchingAmount, getActualMatchingReversalDate, getActualMatchingMatchModalConfirmStatus, getCloseMatchAfterIgnoreMatchId, getCloseMatchAfterUndo, getCloseMatchAfterUndoMatchId, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
878
878
  export { fetchCustomerSummaryDetail, fetchCustomerSummaryList, resetCustomerSummaryDetailUiState, saveCustomerSummaryDetail, updateCustomerAllTransactionsTabData, updateCustomerDetailSelectedTab, updateCustomerSummaryRevenueSelection, updateCustomerSummaryScrollYOffset, updateCustomerSummarySortUiState, updateCustomerTrendFilter, } from './view/customerSummaryView/customerSummaryViewReducer';
879
- export { getCustomerSummaryAllTransactionsTabData, getCustomerSummaryDetail, getCustomerSummaryList, getCustomerSummarySelectedTabType, getCustomerSummaryTrendFilter, isCustomersTabVisible, } from './view/customerSummaryView/customerSummaryViewSelector';
879
+ export { getCustomerSummaryAllTransactionsTabData, getCustomerSummaryDetail, getCustomerSummaryList, getCustomerSummarySelectedTabType, getCustomerSummaryTrendFilter, getCustomersTabSettings, isCustomersTabVisible, } from './view/customerSummaryView/customerSummaryViewSelector';
880
880
  export { CUSTOMER_REVENUE_KEYS } from './view/customerSummaryView/customerSummaryViewState';
881
+ export { fromCustomerEntityId, toCustomerWithSubCustomersId, } from './entity/genericEntity/customerWithSubCustomersId';
@@ -335,6 +335,31 @@ const companyView = createSlice({
335
335
  error: action.payload.status,
336
336
  };
337
337
  },
338
+ updateCustomersTabSetting: {
339
+ reducer(draft,
340
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
341
+ _action) {
342
+ draft.passportView.customersTabSettingsUpdateStatus = {
343
+ fetchState: 'In-Progress',
344
+ error: undefined,
345
+ };
346
+ },
347
+ prepare(companyId, setting, enabled, tenantId) {
348
+ return { payload: { companyId, enabled, setting, tenantId } };
349
+ },
350
+ },
351
+ updateCustomersTabSettingSuccess(draft) {
352
+ draft.passportView.customersTabSettingsUpdateStatus = {
353
+ fetchState: 'Completed',
354
+ error: undefined,
355
+ };
356
+ },
357
+ updateCustomersTabSettingFailure(draft, action) {
358
+ draft.passportView.customersTabSettingsUpdateStatus = {
359
+ fetchState: 'Error',
360
+ error: action.payload.status,
361
+ };
362
+ },
338
363
  enableAccountingProjects: {
339
364
  reducer(draft,
340
365
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -779,5 +804,5 @@ const companyView = createSlice({
779
804
  });
780
805
  },
781
806
  });
782
- export const { fetchCompanyPassportView, fetchAllCockpitViews, fetchOnboardingView, fetchManagementView, fetchSubscriptionView, fetchPortfolioView, fetchCompanyManagementView, companyManagementSaveUpdates, companyManagementSavePendingUpdates, companyManagementDiscardUpdates, companyManagementSaveUpdatesSuccess, companyManagementSaveUpdatesFailure, updateCompanyViewOnSuccess, updateCompanyViewOnFailure, fetchCompanyPortfolioView, fetchZeniUsers, updateZeniUsersOnSuccess, updateZeniUsersOnFailure, updateCompanyPortfolioUIState, updateCompanyManagementUIState, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, companyPassportUpdateCompanyDetails, companyPassportUpdateCompanyDetailsSuccess, companyPassportUpdateCompanyDetailsFailure, updateAccountingClassesEnabled, updateAccountingClassesEnabledSuccess, updateAccountingClassesEnabledFailure, updateAutoReviewIncomeWithoutCustomer, updateAutoReviewIncomeWithoutCustomerSuccess, updateAutoReviewIncomeWithoutCustomerFailure, updateCompanyProductServices, updateCompanyProductServicesSuccess, updateCompanyProductServicesFailure, updateCompanyQboRealmId, updateCompanyQboRealmIdSuccess, updateCompanyQboRealmIdFailure, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, updateAccountingProjectsEnabledSuccess, updateAccountingProjectsEnabledFailure, requestQboProjectsReconnect, clearQboProjectsReconnectRequest, updateCapitalizationAccountThreshold, updateCapitalizationAccountThresholdSuccess, updateCapitalizationAccountThresholdFailure, dismissCapitalizationOnboarding, companyPassportUpdatePrimaryContact, companyPassportUpdatePrimaryContactSuccess, companyPassportUpdatePrimaryContactFailure, companyPassportUpdateCompanyOfficer, companyPassportUpdateCompanyOfficerSuccess, companyPassportUpdateCompanyOfficerFailure, companyPassportCreateCompanyOfficers, companyPassportCreateCompanyOfficersSuccess, companyPassportCreateCompanyOfficersFailure, updateCompanyPassportLocalStoreData, saveIndustryAndIncDateInCompanyPassportLocalStore, saveCompanyPassportDetails, fetchParentSubsidiaryManagementView, updateParentSubsidiaryView, updateParentSubsidiaryViewOnFailure, updateCompanyDownloadState, fetchCompanyMetaData, updateCompanyMetaDataOnSuccess, updateCompanyMetaDataOnFailure, updateMetaDataOnSendMonthEndReport, } = companyView.actions;
807
+ export const { fetchCompanyPassportView, fetchAllCockpitViews, fetchOnboardingView, fetchManagementView, fetchSubscriptionView, fetchPortfolioView, fetchCompanyManagementView, companyManagementSaveUpdates, companyManagementSavePendingUpdates, companyManagementDiscardUpdates, companyManagementSaveUpdatesSuccess, companyManagementSaveUpdatesFailure, updateCompanyViewOnSuccess, updateCompanyViewOnFailure, fetchCompanyPortfolioView, fetchZeniUsers, updateZeniUsersOnSuccess, updateZeniUsersOnFailure, updateCompanyPortfolioUIState, updateCompanyManagementUIState, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, companyPassportUpdateCompanyDetails, companyPassportUpdateCompanyDetailsSuccess, companyPassportUpdateCompanyDetailsFailure, updateAccountingClassesEnabled, updateAccountingClassesEnabledSuccess, updateAccountingClassesEnabledFailure, updateAutoReviewIncomeWithoutCustomer, updateAutoReviewIncomeWithoutCustomerSuccess, updateAutoReviewIncomeWithoutCustomerFailure, updateCustomersTabSetting, updateCustomersTabSettingSuccess, updateCustomersTabSettingFailure, updateCompanyProductServices, updateCompanyProductServicesSuccess, updateCompanyProductServicesFailure, updateCompanyQboRealmId, updateCompanyQboRealmIdSuccess, updateCompanyQboRealmIdFailure, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, updateAccountingProjectsEnabledSuccess, updateAccountingProjectsEnabledFailure, requestQboProjectsReconnect, clearQboProjectsReconnectRequest, updateCapitalizationAccountThreshold, updateCapitalizationAccountThresholdSuccess, updateCapitalizationAccountThresholdFailure, dismissCapitalizationOnboarding, companyPassportUpdatePrimaryContact, companyPassportUpdatePrimaryContactSuccess, companyPassportUpdatePrimaryContactFailure, companyPassportUpdateCompanyOfficer, companyPassportUpdateCompanyOfficerSuccess, companyPassportUpdateCompanyOfficerFailure, companyPassportCreateCompanyOfficers, companyPassportCreateCompanyOfficersSuccess, companyPassportCreateCompanyOfficersFailure, updateCompanyPassportLocalStoreData, saveIndustryAndIncDateInCompanyPassportLocalStore, saveCompanyPassportDetails, fetchParentSubsidiaryManagementView, updateParentSubsidiaryView, updateParentSubsidiaryViewOnFailure, updateCompanyDownloadState, fetchCompanyMetaData, updateCompanyMetaDataOnSuccess, updateCompanyMetaDataOnFailure, updateMetaDataOnSendMonthEndReport, } = companyView.actions;
783
808
  export default companyView.reducer;
@@ -0,0 +1,47 @@
1
+ import { from } from 'rxjs';
2
+ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
+ import { updateCompanies } from '../../../../entity/company/companyReducer';
4
+ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
5
+ import { CUSTOMERS_TAB_SETTING_API_KEYS } from '../../../../entity/tenant/tenantPayload';
6
+ import { updateTenantCustomersTabSetting } from '../../../../entity/tenant/tenantReducer';
7
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
8
+ import { updateCustomersTabSetting, updateCustomersTabSettingFailure, updateCustomersTabSettingSuccess, } from '../../companyViewReducer';
9
+ const failureActions = (status) => [
10
+ updateCustomersTabSettingFailure({ status }),
11
+ openSnackbar({
12
+ messageSection: 'customers_tab_settings_update',
13
+ messageText: 'failed',
14
+ type: 'error',
15
+ }),
16
+ ];
17
+ /** Settings › Accounting › Customers: save one Customers tab setting (accounting_config is deep-merged). */
18
+ export const updateCustomersTabSettingEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(updateCustomersTabSetting.match),
19
+ // The two settings are separate keys: a quick second toggle mustn't cancel the first save
20
+ mergeMap((action) => {
21
+ const { companyId, enabled, setting, tenantId } = action.payload;
22
+ return zeniAPI
23
+ .putAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/companies/${companyId}`, {
24
+ accounting_config: {
25
+ customers: { [CUSTOMERS_TAB_SETTING_API_KEYS[setting]]: enabled },
26
+ },
27
+ })
28
+ .pipe(mergeMap((response) => {
29
+ const companies = response.data?.companies ?? [];
30
+ if (!isSuccessResponse(response) || companies.length === 0) {
31
+ return from(failureActions(response.status));
32
+ }
33
+ return from([
34
+ updateCompanies({ payload: companies, schema: {} }),
35
+ updateTenantCustomersTabSetting({ enabled, setting, tenantId }),
36
+ updateCustomersTabSettingSuccess(),
37
+ openSnackbar({
38
+ messageSection: 'customers_tab_settings_update',
39
+ messageText: 'success',
40
+ type: 'success',
41
+ }),
42
+ ]);
43
+ }), catchError((error) => from(failureActions(createZeniAPIStatus('Unexpected Error', 'Update Customers tab setting errored out: ' +
44
+ (error instanceof Error
45
+ ? error.message
46
+ : JSON.stringify(error)))))));
47
+ }));
@@ -153,3 +153,5 @@ export const isCompanyPassportDataToBeSaved = (companyLocalStoreData, companyVie
153
153
  .reduce((isDetailsUpdated, isCurDetailsUpdated) => isDetailsUpdated || isCurDetailsUpdated, false);
154
154
  return isCompanyDataUpdated;
155
155
  };
156
+ export const getIsCustomersTabSettingsUpdateInProgress = (state) => state.companyViewState.passportView.customersTabSettingsUpdateStatus
157
+ .fetchState === 'In-Progress';
@@ -17,6 +17,10 @@ export const initialCompanyPassportView = {
17
17
  fetchState: 'Not-Started',
18
18
  error: undefined,
19
19
  },
20
+ customersTabSettingsUpdateStatus: {
21
+ fetchState: 'Not-Started',
22
+ error: undefined,
23
+ },
20
24
  needsQboProjectsReconnect: false,
21
25
  companyDetails: {
22
26
  localData: undefined,
@@ -1,4 +1,6 @@
1
1
  import { createSlice } from '@reduxjs/toolkit';
2
+ import isEqual from 'lodash/isEqual';
3
+ import { updateTenantCustomersTabSetting } from '../../entity/tenant/tenantReducer';
2
4
  import { clearAll } from '../../rootActions';
3
5
  import { CUSTOMER_REVENUE_KEYS, } from './customerSummaryViewState';
4
6
  export const initialState = {
@@ -20,6 +22,9 @@ export const initialState = {
20
22
  detailCustomerId: undefined,
21
23
  error: undefined,
22
24
  };
25
+ const toReference = (payload) => payload != null
26
+ ? { id: payload.customer_id, name: payload.customer_name ?? '' }
27
+ : undefined;
23
28
  export const toCustomerSummary = (payload) => ({
24
29
  id: payload.customer_id,
25
30
  qboId: payload.qbo_id ?? undefined,
@@ -28,6 +33,22 @@ export const toCustomerSummary = (payload) => ({
28
33
  currencyCode: payload.currency_code ?? undefined,
29
34
  currencySymbol: payload.currency_symbol ?? undefined,
30
35
  revenue: Object.fromEntries(CUSTOMER_REVENUE_KEYS.map((key) => [key, payload[key] ?? 0])),
36
+ hasChildren: payload.has_children === true,
37
+ isProject: payload.is_project === true,
38
+ isSubCustomer: payload.is_sub_customer === true,
39
+ parentId: payload.parent_customer_id ?? undefined,
40
+ parentPath: (payload.parent_path ?? []).flatMap((parent) => toReference(parent) ?? []),
41
+ familyTree: payload.family_tree?.map(toCustomerSummary),
42
+ // Only the details response carries them
43
+ totals: payload.total_balance != null
44
+ ? {
45
+ balance: payload.total_balance,
46
+ revenue: Object.fromEntries(CUSTOMER_REVENUE_KEYS.map((key) => [
47
+ key,
48
+ payload[`total_${key}`] ?? 0,
49
+ ])),
50
+ }
51
+ : undefined,
31
52
  account: payload.account?.account_id != null
32
53
  ? {
33
54
  id: payload.account.account_id,
@@ -73,11 +94,16 @@ const customerSummaryView = createSlice({
73
94
  },
74
95
  },
75
96
  updateCustomerSummaryList: {
76
- prepare(response, keepExistingListItems) {
77
- return { payload: { keepExistingListItems, response } };
97
+ prepare(response, keepExistingListItems, settings) {
98
+ return { payload: { keepExistingListItems, response, settings } };
78
99
  },
79
100
  reducer(draft, action) {
80
- const { response, keepExistingListItems } = action.payload;
101
+ const { response, keepExistingListItems, settings } = action.payload;
102
+ // A next page fetched under other settings than the listed rows: drop it, the list refetches
103
+ if (keepExistingListItems && !isEqual(draft.listSettings, settings)) {
104
+ return;
105
+ }
106
+ draft.listSettings = settings;
81
107
  const customers = (response.data?.customers ?? []).map(toCustomerSummary);
82
108
  const existingIds = new Set(draft.customers.map(({ id }) => id));
83
109
  draft.customers = keepExistingListItems
@@ -126,12 +152,13 @@ const customerSummaryView = createSlice({
126
152
  detail.customer = toCustomerSummary(action.payload.customer);
127
153
  detail.fetchState = 'Completed';
128
154
  // Keep the list row in sync after an edit.
155
+ const { account, accountingClass } = detail.customer;
129
156
  const index = draft.customers.findIndex(({ id }) => id === action.payload.customerId);
130
157
  if (index >= 0) {
131
158
  draft.customers[index] = {
132
159
  ...draft.customers[index],
133
- account: detail.customer.account,
134
- accountingClass: detail.customer.accountingClass,
160
+ account,
161
+ accountingClass,
135
162
  };
136
163
  }
137
164
  },
@@ -188,8 +215,14 @@ const customerSummaryView = createSlice({
188
215
  },
189
216
  },
190
217
  extraReducers: (builder) => {
191
- builder.addCase(clearAll, (draft) => {
218
+ builder
219
+ .addCase(clearAll, (draft) => {
192
220
  Object.assign(draft, initialState);
221
+ })
222
+ // Totals on / off switch the detail page's All transactions tab to another entity: restart its window.
223
+ // (The list refetches through `getCustomerSummaryList`; the details carry both figures.)
224
+ .addCase(updateTenantCustomersTabSetting, (draft) => {
225
+ draft.allTransactionsTabData = undefined;
193
226
  });
194
227
  },
195
228
  });
@@ -1,5 +1,8 @@
1
1
  import { createSelector } from '@reduxjs/toolkit';
2
- import { getIsAccountingClassesEnabled } from '../../entity/tenant/tenantSelector';
2
+ import isEqual from 'lodash/isEqual';
3
+ import { toCustomerWithSubCustomersId } from '../../entity/genericEntity/customerWithSubCustomersId';
4
+ import { getIsAccountingClassesEnabled, getTenantCustomersTabSettings, } from '../../entity/tenant/tenantSelector';
5
+ import { DEFAULT_CUSTOMERS_TAB_SETTINGS, } from '../../entity/tenant/tenantState';
3
6
  import { getNestedAccountListHierarchy } from '../accountList/accountListSelector';
4
7
  import { getNestedClassListHierarchy } from '../classList/classListSelector';
5
8
  const isLoadingFetchState = (fetchState) => fetchState === 'Not-Started' || fetchState === 'In-Progress';
@@ -7,16 +10,43 @@ const NOT_STARTED_DETAIL = {
7
10
  fetchState: 'Not-Started',
8
11
  saveState: 'Not-Started',
9
12
  };
10
- export const getCustomerSummaryList = (state) => state.customerSummaryViewState;
11
- export const getCustomerSummaryDetail = createSelector((state, customerId) => state.customerSummaryViewState.detailById[customerId], (state) => state.accountListState, (state) => state.classListState, getIsAccountingClassesEnabled, (detail, accountListState, classListState, isAccountingClassesEnabled) => ({
12
- ...(detail ?? NOT_STARTED_DETAIL),
13
- accountsHierarchyList: getNestedAccountListHierarchy(accountListState, 'accountList'),
14
- classHierarchyList: getNestedClassListHierarchy(classListState),
15
- isAccountingClassesEnabled,
16
- isReferenceDataLoading: isLoadingFetchState(accountListState.byReportId.accountList.fetchState) ||
17
- (isAccountingClassesEnabled &&
18
- isLoadingFetchState(classListState.fetchState)),
19
- }));
13
+ export const getCustomersTabSettings = (state) => {
14
+ const { currentTenantId } = state.tenantState;
15
+ return ((currentTenantId != null
16
+ ? getTenantCustomersTabSettings(state.tenantState, currentTenantId)
17
+ : undefined) ?? DEFAULT_CUSTOMERS_TAB_SETTINGS);
18
+ };
19
+ /** Rows fetched under other Customers tab settings (however those changed) read as not fetched yet. */
20
+ export const getCustomerSummaryList = createSelector((state) => state.customerSummaryViewState, getCustomersTabSettings, (view, settings) => view.listSettings == null || isEqual(view.listSettings, settings)
21
+ ? view
22
+ : {
23
+ ...view,
24
+ customers: [],
25
+ error: undefined,
26
+ fetchState: 'Not-Started',
27
+ totalCount: 0,
28
+ uiState: { ...view.uiState, pageToken: null, scrollYOffset: 0 },
29
+ });
30
+ export const getCustomerSummaryDetail = createSelector((state, customerId) => state.customerSummaryViewState.detailById[customerId], (state) => state.accountListState, (state) => state.classListState, getIsAccountingClassesEnabled, (state) => getCustomersTabSettings(state).includeSubCustomersInTotals, (_state, customerId) => customerId, (detail, accountListState, classListState, isAccountingClassesEnabled, includeSubCustomersInTotals, customerId) => {
31
+ const customer = detail?.customer;
32
+ // Rolled up from the start (in parallel with the details); own figures if the details turn out to have no totals
33
+ const includesSubCustomers = includeSubCustomersInTotals &&
34
+ (customer == null || customer.totals != null);
35
+ return {
36
+ ...(detail ?? NOT_STARTED_DETAIL),
37
+ accountsHierarchyList: getNestedAccountListHierarchy(accountListState, 'accountList'),
38
+ classHierarchyList: getNestedClassListHierarchy(classListState),
39
+ isAccountingClassesEnabled,
40
+ isReferenceDataLoading: isLoadingFetchState(accountListState.byReportId.accountList.fetchState) ||
41
+ (isAccountingClassesEnabled &&
42
+ isLoadingFetchState(classListState.fetchState)),
43
+ includesSubCustomers,
44
+ figures: includesSubCustomers ? customer?.totals : customer,
45
+ trendEntityId: includesSubCustomers
46
+ ? toCustomerWithSubCustomersId(customerId)
47
+ : customerId,
48
+ };
49
+ });
20
50
  export const getCustomerSummarySelectedTabType = (state) => state.customerSummaryViewState.selectedTabType;
21
51
  export const getCustomerSummaryAllTransactionsTabData = (state) => state.customerSummaryViewState.allTransactionsTabData;
22
52
  export const getCustomerSummaryTrendFilter = (state) => state.customerSummaryViewState.trendFilter;
@@ -2,21 +2,26 @@ import { of } from 'rxjs';
2
2
  import { catchError, exhaustMap, filter, map, startWith, switchMap, } from 'rxjs/operators';
3
3
  import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
4
4
  import { fetchCustomerSummaryList, updateCustomerSummaryList, updateCustomerSummaryListFailure, } from '../customerSummaryViewReducer';
5
+ import { getCustomersTabSettings } from '../customerSummaryViewSelector';
5
6
  export const fetchCustomerSummaryListEpic = (actions$, state$, zeniAPI) => {
6
7
  const fetch$ = actions$.pipe(filter(fetchCustomerSummaryList.match));
7
8
  const fetchPage = (action) => {
8
9
  const { keepExistingListItems, pageToken, searchString } = action.payload;
9
10
  const { uiState } = state$.value.customerSummaryViewState;
11
+ const settings = getCustomersTabSettings(state$.value);
10
12
  const query = {
11
13
  page_token: pageToken,
12
14
  sort_by: uiState.sortKey,
13
15
  sort_order: uiState.sortOrder === 'ascending' ? 'asc' : 'desc',
14
16
  search_text: searchString,
17
+ // Top-level only: a search also finds a customer by its sub-customers' and projects' names
18
+ top_level_only: settings.listTopLevelCustomersOnly,
19
+ include_sub_customers: settings.includeSubCustomersInTotals,
15
20
  };
16
21
  return zeniAPI
17
22
  .getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/customers/summary?query=${encodeURIComponent(JSON.stringify(query))}`)
18
23
  .pipe(map((response) => isSuccessResponse(response)
19
- ? updateCustomerSummaryList(response, keepExistingListItems)
24
+ ? updateCustomerSummaryList(response, keepExistingListItems, settings)
20
25
  : updateCustomerSummaryListFailure(response.status)), catchError((error) => of(updateCustomerSummaryListFailure(createZeniAPIStatus('Unexpected Error', 'Fetch customer summary list REST API call errored out' +
21
26
  JSON.stringify(error))))));
22
27
  };
@@ -2,6 +2,7 @@ import lodashGet from 'lodash/get';
2
2
  import { from, of } from 'rxjs';
3
3
  import { catchError, filter, mergeMap } from 'rxjs/operators';
4
4
  import { toString } from '../../commonStateTypes/timePeriod';
5
+ import { fromCustomerEntityId } from '../../entity/genericEntity/customerWithSubCustomersId';
5
6
  import { updateTransactions } from '../../entity/transaction/transactionReducer';
6
7
  import { createZeniAPIStatus, isSuccessResponse } from '../../responsePayload';
7
8
  import { fetchEntityTransactionList, updateTransactionListByEntity, updateTransactionListByEntityFailure, } from './transactionListReducer';
@@ -13,12 +14,20 @@ export const fetchTransactionListByEntityEpic = (actions$, state$, zeniAPI) => a
13
14
  if (action.payload.cacheOverride === true ||
14
15
  entityTransactions == null ||
15
16
  entityTransactions.hasValidState() === false) {
17
+ // Customers tab rolled-up view: cached under its own id, sent as the customer id plus the flag
18
+ const { customerId: entityId, includeSubCustomers } = action.payload.entity.type === 'customer'
19
+ ? fromCustomerEntityId(action.payload.entity.id)
20
+ : {
21
+ customerId: action.payload.entity.id,
22
+ includeSubCustomers: false,
23
+ };
16
24
  const queryParam = {
17
25
  start_date: toString(action.payload.period.start),
18
26
  end_date: toString(action.payload.period.end),
19
27
  sort_by: 'create_time',
20
28
  sort_order: 'desc',
21
- entity_id: action.payload.entity.id,
29
+ entity_id: entityId,
30
+ ...(includeSubCustomers ? { include_sub_customers: true } : {}),
22
31
  entity_name: action.payload.entity.name,
23
32
  entity_type: action.payload.entity.type,
24
33
  is_fetch_all_transactions: action.payload.isFetchAllTransactions === true
@@ -31,7 +40,7 @@ export const fetchTransactionListByEntityEpic = (actions$, state$, zeniAPI) => a
31
40
  if (isSuccessResponse(response) && response.data != null) {
32
41
  const updateActions = [];
33
42
  updateActions.push(updateTransactions(response.data.transactions, (value) => value.transaction_id));
34
- updateActions.push(updateTransactionListByEntity(response.data));
43
+ updateActions.push(updateTransactionListByEntity(response.data, action.payload.entity.id));
35
44
  return from(updateActions);
36
45
  }
37
46
  else {
@@ -164,21 +164,30 @@ const transactionList = createSlice({
164
164
  };
165
165
  },
166
166
  },
167
- updateTransactionListByEntity(draft, action) {
168
- const transactionIDs = action.payload.transactions.map((transactionPayload) => transactionPayload.transaction_id);
169
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
170
- const entity = mapTransactionQueryMetaDataToEntity(action.payload.query);
171
- const key = getEntityTranKey(entity, {
172
- start: toAbsoluteDay(action.payload.query.start_date),
173
- end: toAbsoluteDay(action.payload.query.end_date),
174
- });
175
- draft.byEntity.transactionListByEntityKey[key] = {
176
- ...initialEntityTransactionState,
177
- fetchState: 'Completed',
178
- error: undefined,
179
- entity: entity,
180
- transactionIDs,
181
- };
167
+ updateTransactionListByEntity: {
168
+ // `entityId`: the requested entity's id when it differs from the query's (a rolled-up customer)
169
+ prepare(payload, entityId) {
170
+ return { payload, meta: { entityId } };
171
+ },
172
+ reducer(draft, action) {
173
+ const transactionIDs = action.payload.transactions.map((transactionPayload) => transactionPayload.transaction_id);
174
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
175
+ const entity = {
176
+ ...mapTransactionQueryMetaDataToEntity(action.payload.query),
177
+ ...(action.meta.entityId != null && { id: action.meta.entityId }),
178
+ };
179
+ const key = getEntityTranKey(entity, {
180
+ start: toAbsoluteDay(action.payload.query.start_date),
181
+ end: toAbsoluteDay(action.payload.query.end_date),
182
+ });
183
+ draft.byEntity.transactionListByEntityKey[key] = {
184
+ ...initialEntityTransactionState,
185
+ fetchState: 'Completed',
186
+ error: undefined,
187
+ entity: entity,
188
+ transactionIDs,
189
+ };
190
+ },
182
191
  },
183
192
  updateTransactionListByEntityFailure: {
184
193
  reducer(draft, action) {
@@ -3,6 +3,7 @@ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { toTimePeriod, } from '../../commonStateTypes/timeframeTick';
4
4
  import { getCustomerIncomeTrendKey } from '../../entity/customerIncome/customerIncomeTrendKey';
5
5
  import { updateCustomerIncomeTrend } from '../../entity/customerIncome/customerIncomeTrendReducer';
6
+ import { fromCustomerEntityId } from '../../entity/genericEntity/customerWithSubCustomersId';
6
7
  import { createZeniAPIStatus, isSuccessResponse } from '../../responsePayload';
7
8
  import { date as zeniDate } from '../../zeniDayJS';
8
9
  import { fetchIncomeTrend, updateTrendFailure, updateTrendSuccess, } from './trendReducer';
@@ -25,11 +26,14 @@ switchMap((action) => {
25
26
  return of(updateTrendSuccess(requestedPeriod));
26
27
  }
27
28
  }
29
+ // The rolled-up view is cached under its own id; the API takes the customer id plus the flag
30
+ const { customerId: apiCustomerId, includeSubCustomers } = fromCustomerEntityId(customerId);
28
31
  const query = {
29
- entity_id: customerId,
32
+ entity_id: apiCustomerId,
30
33
  entity_type: 'customer',
31
- customer_id: customerId,
34
+ customer_id: apiCustomerId,
32
35
  customer_name: customerName,
36
+ ...(includeSubCustomers ? { include_sub_customers: true } : {}),
33
37
  ...(dateRange != null
34
38
  ? { start_date: dateRange.startDate, end_date: dateRange.endDate }
35
39
  : {}),
package/lib/index.d.ts CHANGED
@@ -147,8 +147,8 @@ import { getTaskGroupById } from './entity/taskGroup/taskGroupSelector';
147
147
  import { TaskGroupState } from './entity/taskGroup/taskGroupState';
148
148
  import { TaskGroupTemplate } from './entity/taskGroupTemplate/taskGroupTemplateState';
149
149
  import { DoSignInPayload, deleteConnection, doMagicLinkSignIn, doSignIn, doSignOut, fetchActiveTenant, fetchAllTenants, fetchExcludedResources as fetchExcludedResourcesForTenant, fetchExternalConnections as fetchExternalConnectionsForTenant, fetchSubscriptionSummaryForTenant, initEmailConnectOAuth, resendVerifyDeviceOTP, resetSignInState, saveAPIKeyConnection, saveConnectorCredentials, saveExternalConnection as saveExternalConnectionForTenant, saveOAuthConnection, seedTenantSummary, sendEmailMagicLinkToUser, sendSessionHeartbeat, toExternalIntegrationType, updateCurrentTenant, updateSignInState, verifyDeviceWithTwoFA } from './entity/tenant/tenantReducer';
150
- import { CurrentTenant, CurrentTenantIds, DEFAULT_RECEIPTS_EMAIL, TenantBaseView, TenantCoreDetailsView, TenantView, TenantsBaseOrdered, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getReceiptsEmail, getTenantBaseById, getTenantBaseViewForTenantId, getTenantBaseViewForTenantView, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, isCurrentTenantLoaded, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantLoaded, isTenantUsingZeniCOA, isZeniDomainTenant, toTenantCoreDetailsView } from './entity/tenant/tenantSelector';
151
- import { CapitalizableAccount, CapitalizableAccounts, CapitalizableClassificationType, CapitalizableMatchPattern, Connection, LoggedInUser, RoleResource, Tenant, TenantProductSettings } from './entity/tenant/tenantState';
150
+ import { CurrentTenant, CurrentTenantIds, DEFAULT_RECEIPTS_EMAIL, TenantBaseView, TenantCoreDetailsView, TenantView, TenantsBaseOrdered, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getReceiptsEmail, getTenantBaseById, getTenantBaseViewForTenantId, getTenantBaseViewForTenantView, getTenantCustomersTabSettings, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, isCurrentTenantLoaded, isOtherProductsEnabledForTenant, isTenantBankingOnly, isTenantBookkeepingEnabled, isTenantCardsOnly, isTenantLoaded, isTenantUsingZeniCOA, isZeniDomainTenant, toTenantCoreDetailsView } from './entity/tenant/tenantSelector';
151
+ import { CapitalizableAccount, CapitalizableAccounts, CapitalizableClassificationType, CapitalizableMatchPattern, Connection, CustomersTabSettingKey, CustomersTabSettings, LoggedInUser, RoleResource, Tenant, TenantProductSettings } from './entity/tenant/tenantState';
152
152
  import { toExternalSupportedTool } from './entity/tenant/tenantTypes';
153
153
  import { ToastNotificationPayload } from './entity/toastNotification/toastNotificationPayload';
154
154
  import { pushToastNotification } from './entity/toastNotification/toastNotificationReducer';
@@ -284,11 +284,11 @@ import { AuditSummaryData, CompanyMonthEndReportData, CompanyMonthReportTemplate
284
284
  import { fetchCockpitContext, fetchCompanyTaskManagerView, fetchTaskManagerMetrics, updateCompanyTaskManagerViewFilters } from './view/companyTaskManagerView/companyTaskManagerViewReducer';
285
285
  import { CompanyTaskManagerSelectorView, TaskWithCompanyDetail, getCompanyTaskManagerView } from './view/companyTaskManagerView/companyTaskManagerViewSelector';
286
286
  import { CompanyTaskManagerViewUIState, TaskManagerMetrics } from './view/companyTaskManagerView/companyTaskManagerViewState';
287
- import { CompanyProductServicesInput, clearQboProjectsReconnectRequest, companyManagementSaveUpdates, companyPassportClearDataInLocalStore, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, disableAccountingProjects, dismissCapitalizationOnboarding, enableAccountingProjects, fetchAllCockpitViews, fetchCompanyManagementView, fetchCompanyPassportView, fetchCompanyPortfolioView, fetchManagementView, fetchOnboardingView, fetchParentSubsidiaryManagementView, fetchPortfolioView, fetchSubscriptionView, fetchZeniUsers, resumeEnableAccountingProjects, saveCompanyPassportDetails, saveIndustryAndIncDateInCompanyPassportLocalStore, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCapitalizationAccountThreshold, updateCompanyDownloadState, updateCompanyManagementUIState, updateCompanyPassportLocalStoreData, updateCompanyPortfolioUIState, updateCompanyProductServices, updateCompanyQboRealmId } from './view/companyView/companyViewReducer';
287
+ import { CompanyProductServicesInput, clearQboProjectsReconnectRequest, companyManagementSaveUpdates, companyPassportClearDataInLocalStore, companyPassportSaveDataInLocalStore, deleteCompanyOfficerInLocalStore, disableAccountingProjects, dismissCapitalizationOnboarding, enableAccountingProjects, fetchAllCockpitViews, fetchCompanyManagementView, fetchCompanyPassportView, fetchCompanyPortfolioView, fetchManagementView, fetchOnboardingView, fetchParentSubsidiaryManagementView, fetchPortfolioView, fetchSubscriptionView, fetchZeniUsers, resumeEnableAccountingProjects, saveCompanyPassportDetails, saveIndustryAndIncDateInCompanyPassportLocalStore, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCapitalizationAccountThreshold, updateCompanyDownloadState, updateCompanyManagementUIState, updateCompanyPassportLocalStoreData, updateCompanyPortfolioUIState, updateCompanyProductServices, updateCompanyQboRealmId, updateCustomersTabSetting } from './view/companyView/companyViewReducer';
288
288
  import { canSendMonthEndEmailReport, shouldEnableCalendarPickerForLastReportSent } from './view/companyView/helpers/cockpitHelpers';
289
289
  import { getParentSubsidiaryManagementView } from './view/companyView/parentSubsidiaryView/parentSubsidiaryViewSelector';
290
290
  import { CompanyManagementView, getAddonListZeniSku, getCompanyManagementView, getCompanyProductServicesUpdateStatus, getCompanyQboRealmIdUpdateStatus, getPlanListZeniSku } from './view/companyView/selector/companyManagementViewSelector';
291
- import { CompanyPassportLocalStoreDataView, CompanyPassportView, getCompanyPassportLocalStoreData, getCompanyPassportView, isCompanyPassportDataToBeSaved } from './view/companyView/selector/companyPassportViewSelector';
291
+ import { CompanyPassportLocalStoreDataView, CompanyPassportView, getCompanyPassportLocalStoreData, getCompanyPassportView, getIsCustomersTabSettingsUpdateInProgress, isCompanyPassportDataToBeSaved } from './view/companyView/selector/companyPassportViewSelector';
292
292
  import { CompanyPortfolioView, getCompanyPortfolioView, isInfiniteRunway } from './view/companyView/selector/companyPortfolioViewSelector';
293
293
  import { AllCockpitTabsView, getAllCockpitTabsFilterView } from './view/companyView/selector/getAllCockpitTabsFilterView';
294
294
  import { ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, CockpitDownloadTabsID, CockpitTabsFileType, CockpitTabsID, toCockpitTabsFileTypeStrict, toCockpitTabsIDStrict } from './view/companyView/types/cockpitTabsID';
@@ -754,7 +754,7 @@ export { TimeframeTick, TimeframeTickWithMetaData, toTimeframeTick, mapTimePerio
754
754
  export { VendorSpendTrendFilterTabType, toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorSpendTrendFilterTabType';
755
755
  export { getNumberOfPeriods };
756
756
  export { SCHEDULE_DAYS_OF_MONTH, ScheduleDaysOfMonth, toScheduleDaysOfMonth, Day, Month, toMonth, toMonthStrict, Quarter, toQuarter, toQuarterStrict, AbsoluteDay, TimePeriod, };
757
- export { CapitalizableAccount, CapitalizableAccounts, CapitalizableClassificationType, CapitalizableMatchPattern, Tenant, TenantView, LoggedInUser, TenantBaseView, CurrentTenant, CurrentTenantIds, TenantProductSettings, getTenantBaseById, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, isCurrentTenantLoaded, isTenantLoaded, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, toTenantCoreDetailsView, getTenantBaseViewForTenantView, getTenantBaseViewForTenantId, isZeniDomainTenant, isTenantUsingZeniCOA, TenantsBaseOrdered, TenantCoreDetailsView, fetchActiveTenant, fetchAllTenants, seedTenantSummary, updateCurrentTenant, clearAll, doMagicLinkSignIn, verifyDeviceWithTwoFA, resendVerifyDeviceOTP, sendEmailMagicLinkToUser, doSignIn, updateSignInState, DoSignInPayload, doSignOut, sendSessionHeartbeat, resetSignInState, RoleResource, Connection, fetchExcludedResourcesForTenant, fetchExternalConnectionsForTenant, saveExternalConnectionForTenant, deleteConnection, saveAPIKeyConnection, saveConnectorCredentials, saveOAuthConnection, initEmailConnectOAuth, toExternalIntegrationType, toExternalSupportedTool, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, DEFAULT_RECEIPTS_EMAIL, getReceiptsEmail, };
757
+ export { CapitalizableAccount, CapitalizableAccounts, CapitalizableClassificationType, CapitalizableMatchPattern, Tenant, TenantView, LoggedInUser, TenantBaseView, CurrentTenant, CurrentTenantIds, TenantProductSettings, CustomersTabSettings, CustomersTabSettingKey, getTenantBaseById, getCurrentTenant, getCurrentTenantId, getCurrentTenantIds, isCurrentTenantLoaded, isTenantLoaded, getIsAccountingClassesEnabled, getIsAccountingProjectsEnabled, getIsAutoReviewIncomeWithoutCustomerEnabled, getTenantCustomersTabSettings, getTenantsBaseByCheckInDateSelector, getTenantsCoreDetailsByCheckInDateSelector, toTenantCoreDetailsView, getTenantBaseViewForTenantView, getTenantBaseViewForTenantId, isZeniDomainTenant, isTenantUsingZeniCOA, TenantsBaseOrdered, TenantCoreDetailsView, fetchActiveTenant, fetchAllTenants, seedTenantSummary, updateCurrentTenant, clearAll, doMagicLinkSignIn, verifyDeviceWithTwoFA, resendVerifyDeviceOTP, sendEmailMagicLinkToUser, doSignIn, updateSignInState, DoSignInPayload, doSignOut, sendSessionHeartbeat, resetSignInState, RoleResource, Connection, fetchExcludedResourcesForTenant, fetchExternalConnectionsForTenant, saveExternalConnectionForTenant, deleteConnection, saveAPIKeyConnection, saveConnectorCredentials, saveOAuthConnection, initEmailConnectOAuth, toExternalIntegrationType, toExternalSupportedTool, fetchSubscriptionSummaryForTenant, isTenantBankingOnly, isTenantCardsOnly, isTenantBookkeepingEnabled, isOtherProductsEnabledForTenant, DEFAULT_RECEIPTS_EMAIL, getReceiptsEmail, };
758
758
  export { Account, AccountType, AccountBase, StatementCloseDay, toAccountType, AccountReport, NestedAccountReport, AccountWithBalanceReport, AccountGroup, AccountGroupReportV2, AccountGroupType, toAccountGroupType, AccountGroupReport, getAccountGroupKey, AccountGroupKey, RecommendedAccountBase, AccountFilterOption, getAllAccounts, getTransactionFilterAccountOptions, };
759
759
  export { Class, ClassBase, RecommendedClassBase, } from './entity/class/classState';
760
760
  export { ClassFilterOption, getAllClasses, getClassById, getClassFilterOptions, } from './entity/class/classSelector';
@@ -867,7 +867,7 @@ export { CockpitFilterCategory, CockpitFilters, DownloadCockpitTabOptions, Filte
867
867
  export { CockpitDownloadTabsID, CockpitTabsFileType, CockpitTabsID, ALL_COCKPIT_TABS_FILE_TYPES, ALL_COCKPIT_TABS_IDS, toCockpitTabsIDStrict, toCockpitTabsFileTypeStrict, };
868
868
  export { AllowedValueWithCode, AllowedValue, AllowedValueWithID, isAllowedValueWithCode, isAllowedValueWithID, };
869
869
  export { ManagementUIState, PortfolioUIState };
870
- export { fetchCompanyPassportView, CompanyPassportView, getCompanyPassportView, getCompanyPassportLocalStoreData, isCompanyPassportDataToBeSaved, companyPassportSaveDataInLocalStore, saveIndustryAndIncDateInCompanyPassportLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, updateCompanyPassportLocalStoreData, saveCompanyPassportDetails, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, clearQboProjectsReconnectRequest, updateCompanyProductServices, CompanyProductServicesInput, getCompanyProductServicesUpdateStatus, updateCompanyQboRealmId, getCompanyQboRealmIdUpdateStatus, updateCapitalizationAccountThreshold, dismissCapitalizationOnboarding, UpdateActionType, CompanyPassportLocalStoreDataView, };
870
+ export { fetchCompanyPassportView, CompanyPassportView, getCompanyPassportView, getCompanyPassportLocalStoreData, getIsCustomersTabSettingsUpdateInProgress, isCompanyPassportDataToBeSaved, companyPassportSaveDataInLocalStore, saveIndustryAndIncDateInCompanyPassportLocalStore, deleteCompanyOfficerInLocalStore, companyPassportClearDataInLocalStore, updateCompanyPassportLocalStoreData, saveCompanyPassportDetails, updateAccountingClassesEnabled, updateAutoReviewIncomeWithoutCustomer, updateCustomersTabSetting, enableAccountingProjects, resumeEnableAccountingProjects, disableAccountingProjects, clearQboProjectsReconnectRequest, updateCompanyProductServices, CompanyProductServicesInput, getCompanyProductServicesUpdateStatus, updateCompanyQboRealmId, getCompanyQboRealmIdUpdateStatus, updateCapitalizationAccountThreshold, dismissCapitalizationOnboarding, UpdateActionType, CompanyPassportLocalStoreDataView, };
871
871
  export { CompanyInfoLocalData, IncInfoLocalData, TaxDetailsLocalData, CompanyDetailsLocalData, PrimaryContactLocalData, CompanyOfficerLocalData, CompanyOfficerType, CompanyPassportLocalData, toCompanyPassportLocalData, };
872
872
  export type { CompanyOnboardingIndustryTypeCode, CompanyOnboardingSubIndustryTypeCode, CompanyPurposeOfAccountCode, CompanySourceOfFundsCode, CompanyTransactionVolumeCode, CompanyUsNexusTypeCode, };
873
873
  export { COMPANY_ONBOARDING_INDUSTRY_TYPE_CODES, COMPANY_ONBOARDING_SUB_INDUSTRY_CODES_BY_INDUSTRY, COMPANY_PURPOSE_OF_ACCOUNT_CODES, COMPANY_SOURCE_OF_FUNDS_CODES, COMPANY_TRANSACTION_VOLUME_CODES, COMPANY_US_NEXUS_TYPE_CODES, getCompanyOnboardingSubIndustryCodesForIndustry, };
@@ -1276,7 +1276,8 @@ export type { ActualMatchingMatchId } from './entity/actualMatching/actualMatchi
1276
1276
  export type { SessionEndpointsLoader } from './sessionEndpointsLoader';
1277
1277
  export type { DisplayCurrencyFallback } from './entity/actualMatching/actualMatchingPayload';
1278
1278
  export { fetchCustomerSummaryDetail, fetchCustomerSummaryList, resetCustomerSummaryDetailUiState, saveCustomerSummaryDetail, updateCustomerAllTransactionsTabData, updateCustomerDetailSelectedTab, updateCustomerSummaryRevenueSelection, updateCustomerSummaryScrollYOffset, updateCustomerSummarySortUiState, updateCustomerTrendFilter, } from './view/customerSummaryView/customerSummaryViewReducer';
1279
- export { getCustomerSummaryAllTransactionsTabData, getCustomerSummaryDetail, getCustomerSummaryList, getCustomerSummarySelectedTabType, getCustomerSummaryTrendFilter, isCustomersTabVisible, } from './view/customerSummaryView/customerSummaryViewSelector';
1279
+ export { getCustomerSummaryAllTransactionsTabData, getCustomerSummaryDetail, getCustomerSummaryList, getCustomerSummarySelectedTabType, getCustomerSummaryTrendFilter, getCustomersTabSettings, isCustomersTabVisible, } from './view/customerSummaryView/customerSummaryViewSelector';
1280
1280
  export type { CustomerSummaryDetailView } from './view/customerSummaryView/customerSummaryViewSelector';
1281
1281
  export { CUSTOMER_REVENUE_KEYS } from './view/customerSummaryView/customerSummaryViewState';
1282
- export type { CustomerAllTransactionsTabData, CustomerDetailTabType, CustomerRevenueKey, CustomerSummary, CustomerSummaryDetailChanges, CustomerSummaryDetailState, CustomerSummarySortKey, CustomerSummaryViewState, } from './view/customerSummaryView/customerSummaryViewState';
1282
+ export type { CustomerAllTransactionsTabData, CustomerDetailTabType, CustomerRevenueKey, CustomerSummary, CustomerSummaryDetailChanges, CustomerSummaryDetailState, CustomerSummaryFigures, CustomerSummaryReference, CustomerSummarySortKey, CustomerSummaryViewState, } from './view/customerSummaryView/customerSummaryViewState';
1283
+ export { fromCustomerEntityId, toCustomerWithSubCustomersId, } from './entity/genericEntity/customerWithSubCustomersId';