@zeniai/client-epic-state 5.0.1 → 5.0.2-betaRD2
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/commonPayloadTypes/subAccountView/reportBySubAccountPayload.d.ts +2 -0
- package/lib/commonStateTypes/coaBalance/coaBalancesFilterProjectView.d.ts +13 -0
- package/lib/commonStateTypes/coaBalance/coaBalancesFilterProjectView.js +9 -0
- package/lib/commonStateTypes/common.d.ts +1 -1
- package/lib/commonStateTypes/projectView/projectViewParentID.d.ts +5 -0
- package/lib/commonStateTypes/projectView/projectViewParentID.js +2 -0
- package/lib/commonStateTypes/viewAndReport/reportIDHelper.d.ts +1 -0
- package/lib/commonStateTypes/viewAndReport/reportIDHelper.js +3 -1
- package/lib/commonStateTypes/viewAndReport/viewAndReport.d.ts +2 -2
- package/lib/commonStateTypes/viewAndReport/viewAndReport.js +1 -0
- package/lib/entity/account/accountReducer.js +6 -3
- package/lib/entity/account/accountSelector.d.ts +7 -0
- package/lib/entity/account/accountSelector.js +4 -2
- package/lib/entity/account/accountState.d.ts +3 -1
- package/lib/entity/account/accountState.js +4 -1
- package/lib/entity/account/pickAndMergeForecastAccountReport.d.ts +1 -0
- package/lib/entity/account/subAccountSelector.d.ts +2 -0
- package/lib/entity/account/subAccountSelector.js +2 -0
- package/lib/entity/accountGroup/accountGroupSelector.d.ts +22 -0
- package/lib/entity/accountGroup/accountGroupState.d.ts +1 -1
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.d.ts +44 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +55 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.d.ts +10 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +51 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.d.ts +48 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +66 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.d.ts +52 -0
- package/lib/entity/aiAccountantCustomer/aiAccountantCustomerState.js +37 -0
- package/lib/entity/billPay/billTransaction/billTransactionState.d.ts +2 -2
- package/lib/entity/chargeCard/chargeCard.d.ts +1 -1
- package/lib/entity/class/classReducer.d.ts +4 -4
- package/lib/entity/class/classState.d.ts +1 -1
- package/lib/entity/depositAccountTransaction/depositAccountTransaction.d.ts +1 -1
- package/lib/entity/entityApprovalStatus/entityApprovalStatusState.d.ts +2 -2
- package/lib/entity/forecast/forecastState.d.ts +1 -1
- package/lib/entity/jeSchedules/jeSchedulesTypes.d.ts +1 -1
- package/lib/entity/project/projectPayload.d.ts +13 -0
- package/lib/entity/project/projectPayload.js +30 -0
- package/lib/entity/project/projectReducer.d.ts +10 -0
- package/lib/entity/project/projectReducer.js +31 -0
- package/lib/entity/project/projectSelector.d.ts +5 -0
- package/lib/entity/project/projectSelector.js +12 -0
- package/lib/entity/project/projectState.d.ts +13 -0
- package/lib/entity/project/projectState.js +2 -0
- package/lib/entity/sectionAccountsView/sectionAccountsView.d.ts +1 -1
- package/lib/entity/sectionClassesViewV2/sectionClassesView.d.ts +1 -1
- package/lib/entity/sectionClassesViewV2/sectionClassesViewReducer.d.ts +2 -2
- package/lib/entity/sectionProjectView/sectionProjectView.d.ts +11 -0
- package/lib/entity/sectionProjectView/sectionProjectView.js +6 -0
- package/lib/entity/sectionProjectView/sectionProjectViewEpic.d.ts +6 -0
- package/lib/entity/sectionProjectView/sectionProjectViewEpic.js +56 -0
- package/lib/entity/sectionProjectView/sectionProjectViewHelper.d.ts +10 -0
- package/lib/entity/sectionProjectView/sectionProjectViewHelper.js +14 -0
- package/lib/entity/sectionProjectView/sectionProjectViewReducer.d.ts +15 -0
- package/lib/entity/sectionProjectView/sectionProjectViewReducer.js +56 -0
- package/lib/entity/sectionProjectView/sectionProjectViewSelector.d.ts +11 -0
- package/lib/entity/sectionProjectView/sectionProjectViewSelector.js +94 -0
- package/lib/entity/sectionProjectView/sectionProjectViewSelectorTypes.d.ts +16 -0
- package/lib/entity/sectionProjectView/sectionProjectViewSelectorTypes.js +2 -0
- package/lib/entity/sectionProjectView/sectionProjectViewState.d.ts +4 -0
- package/lib/entity/sectionProjectView/sectionProjectViewState.js +2 -0
- package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
- package/lib/entity/tenant/clearAllEpic.d.ts +7 -2
- package/lib/entity/tenant/clearAllEpic.js +10 -0
- package/lib/entity/tenant/tenantPayload.d.ts +1 -0
- package/lib/entity/tenant/tenantReducer.js +1 -0
- package/lib/entity/tenant/tenantSelector.d.ts +1 -0
- package/lib/entity/tenant/tenantSelector.js +9 -1
- package/lib/entity/tenant/tenantState.d.ts +1 -0
- package/lib/entity/transaction/payloadTypes/transactionPayload.js +0 -21
- package/lib/entity/userRole/userRoleType.d.ts +2 -2
- package/lib/epic.d.ts +8 -1
- package/lib/epic.js +8 -1
- package/lib/esm/commonStateTypes/coaBalance/coaBalancesFilterProjectView.js +5 -0
- package/lib/esm/commonStateTypes/projectView/projectViewParentID.js +1 -0
- package/lib/esm/commonStateTypes/viewAndReport/reportIDHelper.js +1 -0
- package/lib/esm/commonStateTypes/viewAndReport/viewAndReport.js +1 -0
- package/lib/esm/entity/account/accountReducer.js +6 -3
- package/lib/esm/entity/account/accountSelector.js +4 -2
- package/lib/esm/entity/account/accountState.js +4 -1
- package/lib/esm/entity/account/subAccountSelector.js +2 -0
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerPayload.js +49 -0
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerReducer.js +47 -0
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerSelector.js +62 -0
- package/lib/esm/entity/aiAccountantCustomer/aiAccountantCustomerState.js +31 -0
- package/lib/esm/entity/project/projectPayload.js +26 -0
- package/lib/esm/entity/project/projectReducer.js +27 -0
- package/lib/esm/entity/project/projectSelector.js +8 -0
- package/lib/esm/entity/project/projectState.js +1 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectView.js +3 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewEpic.js +52 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewHelper.js +10 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewReducer.js +52 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewSelector.js +87 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewSelectorTypes.js +1 -0
- package/lib/esm/entity/sectionProjectView/sectionProjectViewState.js +1 -0
- package/lib/esm/entity/tenant/clearAllEpic.js +10 -0
- package/lib/esm/entity/tenant/tenantReducer.js +1 -0
- package/lib/esm/entity/tenant/tenantSelector.js +7 -0
- package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +0 -21
- package/lib/esm/epic.js +8 -1
- package/lib/esm/index.js +14 -4
- package/lib/esm/reducer.js +15 -0
- package/lib/esm/view/aiAccountantView/aiAccountantViewPayload.js +2 -0
- package/lib/esm/view/aiAccountantView/aiAccountantViewReducer.js +149 -0
- package/lib/esm/view/aiAccountantView/aiAccountantViewSelector.js +72 -0
- package/lib/esm/view/aiAccountantView/aiAccountantViewState.js +11 -0
- package/lib/esm/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +46 -0
- package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +27 -0
- package/lib/esm/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +47 -0
- package/lib/esm/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +52 -0
- package/lib/esm/view/financeStatement/financeStatementSelector.js +12 -1
- package/lib/esm/view/profitAndLossProjectView/profitAndLossForTimeframeProjectViewEpic.js +47 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewEpic.js +30 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewPayload.js +1 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewReducer.js +113 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewSelector.js +65 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewSelectorTypes.js +1 -0
- package/lib/esm/view/profitAndLossProjectView/profitAndLossProjectViewState.js +1 -0
- package/lib/esm/view/reportsResync/reportsClassViewRefetchingEpic.js +4 -0
- package/lib/index.d.ts +20 -4
- package/lib/index.js +73 -34
- package/lib/reducer.d.ts +15 -0
- package/lib/reducer.js +15 -0
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
- package/lib/view/aiAccountantView/aiAccountantViewPayload.d.ts +31 -0
- package/lib/view/aiAccountantView/aiAccountantViewPayload.js +8 -0
- package/lib/view/aiAccountantView/aiAccountantViewReducer.d.ts +29 -0
- package/lib/view/aiAccountantView/aiAccountantViewReducer.js +153 -0
- package/lib/view/aiAccountantView/aiAccountantViewSelector.d.ts +14 -0
- package/lib/view/aiAccountantView/aiAccountantViewSelector.js +78 -0
- package/lib/view/aiAccountantView/aiAccountantViewState.d.ts +26 -0
- package/lib/view/aiAccountantView/aiAccountantViewState.js +13 -0
- package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.d.ts +33 -0
- package/lib/view/aiAccountantView/epics/cancelAiAccountantOnboardingEpic.js +50 -0
- package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.d.ts +23 -0
- package/lib/view/aiAccountantView/epics/fetchAiAccountantCustomersEpic.js +31 -0
- package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.d.ts +33 -0
- package/lib/view/aiAccountantView/epics/fetchAiAccountantJobsEpic.js +51 -0
- package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.d.ts +28 -0
- package/lib/view/aiAccountantView/epics/triggerAiAccountantJobEpic.js +56 -0
- package/lib/view/auditReportView/auditReportViewState.d.ts +1 -1
- package/lib/view/billPayCard/billPayCardSelector.d.ts +1 -1
- package/lib/view/cardBalance/cardBalanceSelector.d.ts +2 -1
- package/lib/view/cashBalance/cashBalanceSelector.d.ts +2 -1
- package/lib/view/cashInCashOut/cashInCashOutSelector.d.ts +1 -1
- package/lib/view/cashPosition/cashPositionSelector.d.ts +1 -1
- package/lib/view/companyView/types/cockpitTypes.d.ts +6 -5
- package/lib/view/dashboard/dashboardReducer.d.ts +2 -2
- package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
- package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -1
- package/lib/view/financeStatement/financeStatementReducer.d.ts +1 -1
- package/lib/view/financeStatement/financeStatementSelector.d.ts +2 -0
- package/lib/view/financeStatement/financeStatementSelector.js +12 -1
- package/lib/view/globalMerchantView/globalMerchantViewReducer.d.ts +2 -2
- package/lib/view/onboardingView/cockpitView/types/onboardingCockpitViewTypes.d.ts +1 -1
- package/lib/view/profitAndLossProjectView/profitAndLossForTimeframeProjectViewEpic.d.ts +9 -0
- package/lib/view/profitAndLossProjectView/profitAndLossForTimeframeProjectViewEpic.js +51 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewEpic.d.ts +6 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewEpic.js +34 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewPayload.d.ts +33 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewPayload.js +2 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewReducer.d.ts +33 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewReducer.js +117 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewSelector.d.ts +9 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewSelector.js +69 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewSelectorTypes.d.ts +19 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewSelectorTypes.js +2 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewState.d.ts +22 -0
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewState.js +2 -0
- package/lib/view/reimbursementCard/reimbursementCardSelector.d.ts +1 -1
- package/lib/view/reportsResync/reportsClassViewRefetchingEpic.d.ts +2 -1
- package/lib/view/reportsResync/reportsClassViewRefetchingEpic.js +4 -0
- package/lib/view/reportsResync/reportsResyncReducer.d.ts +2 -2
- package/lib/view/reviewCompanyView/reviewCompanyViewState.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billList/billListReducer.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billList/billListState.d.ts +1 -1
- package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetail.d.ts +1 -1
- package/lib/view/spendManagement/chargeCards/chargeCardDetail/chargeCardDetailReducer.d.ts +4 -4
- package/lib/view/spendManagement/reimbursement/remiListView/remiListReducer.d.ts +1 -1
- package/lib/view/spendManagement/reimbursement/remiListView/remiListState.d.ts +3 -3
- package/lib/view/subscriptionView/types/subscriptionTypes.d.ts +1 -1
- package/lib/view/tasksCard/tasksCardSelector.d.ts +1 -1
- package/lib/view/topEx/topExSelector.d.ts +1 -1
- package/package.json +1 -1
package/lib/esm/reducer.js
CHANGED
|
@@ -14,6 +14,7 @@ import chargeCard, { initialState as initialChargeCardState, } from './entity/ch
|
|
|
14
14
|
import chargeCardRepayment, { initialState as initialChargeCardRepaymentState, } from './entity/chargeCardRepayment/chargeCardRepaymentReducer';
|
|
15
15
|
import chargeCardTransaction, { initialState as initialChargeCardTransactionState, } from './entity/chargeCardTransaction/chargeCardTransactionReducer';
|
|
16
16
|
import classes, { initialState as initialClassState, } from './entity/class/classReducer';
|
|
17
|
+
import project, { initialState as initialProjectState, } from './entity/project/projectReducer';
|
|
17
18
|
import company, { initialState as initialCompanyState, } from './entity/company/companyReducer';
|
|
18
19
|
import companyHealthMetric, { initialState as initialCompanyHealthMetricState, } from './entity/companyHealthMetric/companyHealthMetricReducer';
|
|
19
20
|
import connectedAccount, { initialState as initialConnectedAccountState, } from './entity/connectedAccount/connectedAccountReducer';
|
|
@@ -41,6 +42,7 @@ import accountingSummary, { initialState as initialAccountingSummaryState, } fro
|
|
|
41
42
|
import reimbursement, { initialState as initialReimbursementState, } from './entity/reimbursement/reimbursementReducer';
|
|
42
43
|
import sectionAccountsView, { initialState as initialSectionAccountsViewState, } from './entity/sectionAccountsView/sectionAccountsViewReducer';
|
|
43
44
|
import sectionClassesViewV2, { initialState as initialSectionClassesViewStateV2, } from './entity/sectionClassesViewV2/sectionClassesViewReducer';
|
|
45
|
+
import sectionProjectView, { initialState as initialSectionProjectViewState, } from './entity/sectionProjectView/sectionProjectViewReducer';
|
|
44
46
|
import snackbar, { initialSnackbarState, } from './entity/snackbar/snackbarReducer';
|
|
45
47
|
import subscription, { initialState as initialSubscriptionState, } from './entity/subscription/subscription/subscriptionReducer';
|
|
46
48
|
import subscriptionAddOn, { initialState as initialSubscriptionAddOnState, } from './entity/subscription/subscriptionAddOn/subscriptionAddOnReducer';
|
|
@@ -67,6 +69,8 @@ import accountMapping, { initialState as initialAccountMappingState, } from './v
|
|
|
67
69
|
import addressView, { initialState as initialAddressViewState, } from './view/addressView/addressViewReducer';
|
|
68
70
|
import aggregatedReport, { initialState as initialAggregatedReportViewState, } from './view/aiAgentPerformance/aggregatedReportViewReducer';
|
|
69
71
|
import aiCfoView, { initialAiCfoViewState, } from './view/aiCfoView/aiCfoViewReducer';
|
|
72
|
+
import aiAccountantCustomer, { initialAiAccountantCustomerState, } from './entity/aiAccountantCustomer/aiAccountantCustomerReducer';
|
|
73
|
+
import aiAccountantView, { initialAiAccountantViewState, } from './view/aiAccountantView/aiAccountantViewReducer';
|
|
70
74
|
import apAgingDetail, { initialState as initialApAgingDetailState, } from './view/apAgingView/apAgingDetail/apAgingDetailReducer';
|
|
71
75
|
import apAging, { initialState as initialApAgingState, } from './view/apAgingView/apAgingReport/apAgingReducer';
|
|
72
76
|
import arAgingDetail, { initialState as initialArAgingDetailState, } from './view/arAgingView/arAgingDetail/arAgingDetailReducer';
|
|
@@ -122,6 +126,7 @@ import ownerList, { initialState as initialOwnerListState, } from './view/ownerL
|
|
|
122
126
|
import people, { initialState as initialPeopleState, } from './view/people/peopleReducer';
|
|
123
127
|
import profitAndLoss, { initialState as initialProfitAndLossState, } from './view/profitAndLoss/profitAndLossReducer';
|
|
124
128
|
import profitAndLossClassesView, { initialState as initialProfitAndLossClassesViewState, } from './view/profitAndLossClassesView/profitAndLossClassesViewReducer';
|
|
129
|
+
import profitAndLossProjectView, { initialState as initialProfitAndLossProjectViewState, } from './view/profitAndLossProjectView/profitAndLossProjectViewReducer';
|
|
125
130
|
import recommendation, { initialState as initialEntityRecommendationState, } from './view/recommendation/recommendationReducer';
|
|
126
131
|
import referralView, { initialState as initialReferralViewState, } from './view/referralView/referralReducer';
|
|
127
132
|
import reimbursementCard, { initialState as initialReimbursementCardState, } from './view/reimbursementCard/reimbursementCardReducer';
|
|
@@ -220,6 +225,7 @@ const initialEntitiesState = {
|
|
|
220
225
|
accountReconState: initialAccountReconState,
|
|
221
226
|
accountState: initialAccountState,
|
|
222
227
|
addressState: initialAddressState,
|
|
228
|
+
aiAccountantCustomerState: initialAiAccountantCustomerState,
|
|
223
229
|
aiCfoState: initialAiCfoState,
|
|
224
230
|
approvalRuleState: initialApprovalRuleState,
|
|
225
231
|
bankAccountState: initialBankAccountState,
|
|
@@ -229,6 +235,7 @@ const initialEntitiesState = {
|
|
|
229
235
|
chargeCardRepaymentState: initialChargeCardRepaymentState,
|
|
230
236
|
chargeCardTransactionState: initialChargeCardTransactionState,
|
|
231
237
|
classState: initialClassState,
|
|
238
|
+
projectState: initialProjectState,
|
|
232
239
|
companyHealthMetricState: initialCompanyHealthMetricState,
|
|
233
240
|
companyState: initialCompanyState,
|
|
234
241
|
connectedAccountState: initialConnectedAccountState,
|
|
@@ -257,6 +264,7 @@ const initialEntitiesState = {
|
|
|
257
264
|
reimbursementState: initialReimbursementState,
|
|
258
265
|
sectionAccountsViewState: initialSectionAccountsViewState,
|
|
259
266
|
sectionClassesViewStateV2: initialSectionClassesViewStateV2,
|
|
267
|
+
sectionProjectViewState: initialSectionProjectViewState,
|
|
260
268
|
snackbarState: initialSnackbarState,
|
|
261
269
|
subscriptionAddOnState: initialSubscriptionAddOnState,
|
|
262
270
|
subscriptionCouponState: initialSubscriptionCouponState,
|
|
@@ -286,6 +294,7 @@ const initialViewsState = {
|
|
|
286
294
|
accountMappingState: initialAccountMappingState,
|
|
287
295
|
addressViewState: initialAddressViewState,
|
|
288
296
|
aggregatedReportViewState: initialAggregatedReportViewState,
|
|
297
|
+
aiAccountantViewState: initialAiAccountantViewState,
|
|
289
298
|
aiCfoViewState: initialAiCfoViewState,
|
|
290
299
|
apAgingDetailState: initialApAgingDetailState,
|
|
291
300
|
apAgingState: initialApAgingState,
|
|
@@ -371,6 +380,7 @@ const initialViewsState = {
|
|
|
371
380
|
plaidAccountViewState: initialPlaidAccountViewState,
|
|
372
381
|
previousBillsState: initialPreviousBillsState,
|
|
373
382
|
profitAndLossClassesViewState: initialProfitAndLossClassesViewState,
|
|
383
|
+
profitAndLossProjectViewState: initialProfitAndLossProjectViewState,
|
|
374
384
|
profitAndLossState: initialProfitAndLossState,
|
|
375
385
|
realTimeApprovalState: initialRealTimeApprovalState,
|
|
376
386
|
referralViewState: initialReferralViewState,
|
|
@@ -444,6 +454,7 @@ const entityReducers = {
|
|
|
444
454
|
accountingSummaryState: accountingSummary,
|
|
445
455
|
accountState: account,
|
|
446
456
|
addressState: address,
|
|
457
|
+
aiAccountantCustomerState: aiAccountantCustomer,
|
|
447
458
|
aiCfoState: aiCfo,
|
|
448
459
|
approvalRuleState: approvalRule,
|
|
449
460
|
bankAccountState: bankAccount,
|
|
@@ -454,6 +465,7 @@ const entityReducers = {
|
|
|
454
465
|
chargeCardRepaymentState: chargeCardRepayment,
|
|
455
466
|
chargeCardTransactionState: chargeCardTransaction,
|
|
456
467
|
classState: classes,
|
|
468
|
+
projectState: project,
|
|
457
469
|
companyHealthMetricState: companyHealthMetric,
|
|
458
470
|
companyState: company,
|
|
459
471
|
connectedAccountState: connectedAccount,
|
|
@@ -482,6 +494,7 @@ const entityReducers = {
|
|
|
482
494
|
reimbursementState: reimbursement,
|
|
483
495
|
sectionAccountsViewState: sectionAccountsView,
|
|
484
496
|
sectionClassesViewStateV2: sectionClassesViewV2,
|
|
497
|
+
sectionProjectViewState: sectionProjectView,
|
|
485
498
|
snackbarState: snackbar,
|
|
486
499
|
subscriptionAddOnState: subscriptionAddOn,
|
|
487
500
|
subscriptionCouponState: subscriptionCoupon,
|
|
@@ -511,6 +524,7 @@ const viewReducers = {
|
|
|
511
524
|
accountMappingState: accountMapping,
|
|
512
525
|
addressViewState: addressView,
|
|
513
526
|
aggregatedReportViewState: aggregatedReport,
|
|
527
|
+
aiAccountantViewState: aiAccountantView,
|
|
514
528
|
aiCfoViewState: aiCfoView,
|
|
515
529
|
apAgingDetailState: apAgingDetail,
|
|
516
530
|
apAgingState: apAging,
|
|
@@ -596,6 +610,7 @@ const viewReducers = {
|
|
|
596
610
|
plaidAccountViewState: plaidAccountView,
|
|
597
611
|
previousBillsState: previousBills,
|
|
598
612
|
profitAndLossClassesViewState: profitAndLossClassesView,
|
|
613
|
+
profitAndLossProjectViewState: profitAndLossProjectView,
|
|
599
614
|
profitAndLossState: profitAndLoss,
|
|
600
615
|
realTimeApprovalState: realTimeApproval,
|
|
601
616
|
referralViewState: referralView,
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
export const initialAiAccountantViewState = {
|
|
3
|
+
customersByTenantId: {},
|
|
4
|
+
customersFetchStatus: { fetchState: 'Not-Started' },
|
|
5
|
+
selectedTenantIdsForJobTrigger: [],
|
|
6
|
+
triggerJobStatus: { fetchState: 'Not-Started' },
|
|
7
|
+
uiState: {
|
|
8
|
+
filterText: '',
|
|
9
|
+
filters: {},
|
|
10
|
+
selectedCustomerTenantId: '',
|
|
11
|
+
sortKey: 'companyName',
|
|
12
|
+
sortOrder: 'ascending',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
const aiAccountantView = createSlice({
|
|
16
|
+
name: 'aiAccountantView',
|
|
17
|
+
initialState: initialAiAccountantViewState,
|
|
18
|
+
reducers: {
|
|
19
|
+
// ── Customers ──
|
|
20
|
+
fetchAiAccountantCustomers(draft) {
|
|
21
|
+
draft.customersFetchStatus = { fetchState: 'In-Progress' };
|
|
22
|
+
},
|
|
23
|
+
updateAiAccountantCustomers(draft, action) {
|
|
24
|
+
draft.customersByTenantId = toCustomersByTenantId(action.payload, draft.customersByTenantId);
|
|
25
|
+
draft.customersFetchStatus = { fetchState: 'Completed' };
|
|
26
|
+
},
|
|
27
|
+
updateAiAccountantCustomersFailure(draft, action) {
|
|
28
|
+
draft.customersFetchStatus = {
|
|
29
|
+
fetchState: 'Error',
|
|
30
|
+
error: action.payload,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
// ── Jobs ──
|
|
34
|
+
fetchAiAccountantJobs: {
|
|
35
|
+
reducer(draft, action) {
|
|
36
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
37
|
+
if (customerView != null) {
|
|
38
|
+
customerView.jobsFetchStatus = { fetchState: 'In-Progress' };
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
prepare(tenantId, fetchNextPage) {
|
|
42
|
+
return { payload: { tenantId, fetchNextPage: fetchNextPage ?? false } };
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
updateAiAccountantJobs: {
|
|
46
|
+
reducer(draft, action) {
|
|
47
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
48
|
+
if (customerView != null) {
|
|
49
|
+
customerView.jobsFetchStatus = { fetchState: 'Completed' };
|
|
50
|
+
customerView.jobsPageToken = action.payload.nextPageToken;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
prepare(tenantId, nextPageToken) {
|
|
54
|
+
return { payload: { tenantId, nextPageToken: nextPageToken ?? null } };
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
updateAiAccountantJobsFailure(draft, action) {
|
|
58
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
59
|
+
if (customerView != null) {
|
|
60
|
+
customerView.jobsFetchStatus = {
|
|
61
|
+
fetchState: 'Error',
|
|
62
|
+
error: action.payload.error,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
setSelectedTenantIdsForJobTrigger(draft, action) {
|
|
67
|
+
draft.selectedTenantIdsForJobTrigger = action.payload;
|
|
68
|
+
},
|
|
69
|
+
// ── Trigger Job ──
|
|
70
|
+
triggerAiAccountantJob: {
|
|
71
|
+
reducer(draft,
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
73
|
+
_action) {
|
|
74
|
+
draft.triggerJobStatus = { fetchState: 'In-Progress' };
|
|
75
|
+
},
|
|
76
|
+
prepare(operationType, startDate, endDate) {
|
|
77
|
+
return { payload: { operationType, startDate, endDate } };
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
triggerAiAccountantJobSuccess(draft) {
|
|
81
|
+
draft.triggerJobStatus = { fetchState: 'Completed' };
|
|
82
|
+
},
|
|
83
|
+
triggerAiAccountantJobFailure(draft, action) {
|
|
84
|
+
draft.triggerJobStatus = { fetchState: 'Error', error: action.payload };
|
|
85
|
+
},
|
|
86
|
+
// ── Cancel Onboarding ──
|
|
87
|
+
cancelAiAccountantOnboarding: {
|
|
88
|
+
reducer(draft, action) {
|
|
89
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
90
|
+
if (customerView != null) {
|
|
91
|
+
customerView.cancelOnboardingStatus = { fetchState: 'In-Progress' };
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
prepare(companyId, tenantId) {
|
|
95
|
+
return { payload: { companyId, tenantId } };
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
cancelAiAccountantOnboardingSuccess: {
|
|
99
|
+
reducer(draft, action) {
|
|
100
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
101
|
+
if (customerView != null) {
|
|
102
|
+
customerView.cancelOnboardingStatus = { fetchState: 'Completed' };
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
prepare(tenantId) {
|
|
106
|
+
return { payload: { tenantId } };
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
cancelAiAccountantOnboardingFailure: {
|
|
110
|
+
reducer(draft, action) {
|
|
111
|
+
const customerView = draft.customersByTenantId[action.payload.tenantId];
|
|
112
|
+
if (customerView != null) {
|
|
113
|
+
customerView.cancelOnboardingStatus = {
|
|
114
|
+
fetchState: 'Error',
|
|
115
|
+
error: action.payload.error,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
prepare(tenantId, error) {
|
|
120
|
+
return { payload: { tenantId, error } };
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
// ── UI State ──
|
|
124
|
+
updateAiAccountantUIState(draft, action) {
|
|
125
|
+
Object.assign(draft.uiState, action.payload);
|
|
126
|
+
},
|
|
127
|
+
// ── Clear ──
|
|
128
|
+
clearAiAccountantView() {
|
|
129
|
+
return initialAiAccountantViewState;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
export const { cancelAiAccountantOnboarding, cancelAiAccountantOnboardingFailure, cancelAiAccountantOnboardingSuccess, clearAiAccountantView, fetchAiAccountantCustomers, fetchAiAccountantJobs, setSelectedTenantIdsForJobTrigger, triggerAiAccountantJob, triggerAiAccountantJobFailure, triggerAiAccountantJobSuccess, updateAiAccountantCustomers, updateAiAccountantCustomersFailure, updateAiAccountantJobs, updateAiAccountantJobsFailure, updateAiAccountantUIState, } = aiAccountantView.actions;
|
|
134
|
+
export default aiAccountantView.reducer;
|
|
135
|
+
// ── Helpers ──
|
|
136
|
+
const toCustomersByTenantId = (customers, existing) => {
|
|
137
|
+
const result = {};
|
|
138
|
+
for (const payload of customers) {
|
|
139
|
+
const tenantId = payload.tenant_id;
|
|
140
|
+
const existingState = existing[tenantId];
|
|
141
|
+
result[tenantId] = existingState ?? {
|
|
142
|
+
cancelOnboardingStatus: { fetchState: 'Not-Started' },
|
|
143
|
+
jobsFetchStatus: { fetchState: 'Not-Started' },
|
|
144
|
+
jobsPageToken: null,
|
|
145
|
+
tenantId,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createSelector } from '@reduxjs/toolkit';
|
|
2
|
+
import orderBy from 'lodash/orderBy';
|
|
3
|
+
import { getAiAccountantCustomers, } from '../../entity/aiAccountantCustomer/aiAccountantCustomerSelector';
|
|
4
|
+
export const getAiAccountantCockpitView = createSelector((state) => state.aiAccountantViewState, (state) => state.aiAccountantCustomerState, (state) => state.userState, (viewState, customerEntityState, userState) => {
|
|
5
|
+
const { customersByTenantId, customersFetchStatus, selectedTenantIdsForJobTrigger, triggerJobStatus, uiState, } = viewState;
|
|
6
|
+
const allCustomers = getAiAccountantCustomers(customerEntityState, userState);
|
|
7
|
+
let filteredCustomers = allCustomers;
|
|
8
|
+
// Text filter
|
|
9
|
+
const trimmedFilterText = uiState.filterText.trim();
|
|
10
|
+
if (trimmedFilterText.length > 0) {
|
|
11
|
+
const query = trimmedFilterText.toLowerCase();
|
|
12
|
+
filteredCustomers = filteredCustomers.filter((customer) => customer.companyName.toLowerCase().includes(query) ||
|
|
13
|
+
customer.tenantId.toLowerCase().includes(query));
|
|
14
|
+
}
|
|
15
|
+
// Cockpit filters (e.g. enrollmentStatus)
|
|
16
|
+
const enrollmentStatusFilter = uiState.filters.categories?.find((category) => category.field === 'enrollmentStatus');
|
|
17
|
+
if (enrollmentStatusFilter != null &&
|
|
18
|
+
enrollmentStatusFilter.values.length > 0) {
|
|
19
|
+
const selectedStatuses = enrollmentStatusFilter.values.map(String);
|
|
20
|
+
const isEqual = enrollmentStatusFilter.matchingOperator === 'equal';
|
|
21
|
+
filteredCustomers = filteredCustomers.filter((customer) => {
|
|
22
|
+
const status = customer.enrollment?.status ?? 'unknown';
|
|
23
|
+
const matches = selectedStatuses.includes(status);
|
|
24
|
+
return isEqual ? matches : !matches;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
// Sorting
|
|
28
|
+
const sortedCustomers = getSortedCustomers(filteredCustomers, uiState.sortKey, uiState.sortOrder);
|
|
29
|
+
const selectedCustomersForJobTrigger = allCustomers.filter((customer) => selectedTenantIdsForJobTrigger.includes(customer.tenantId));
|
|
30
|
+
return {
|
|
31
|
+
averageAccuracy: calcOverallAverageAccuracy(allCustomers),
|
|
32
|
+
fetchState: customersFetchStatus.fetchState,
|
|
33
|
+
error: customersFetchStatus.error,
|
|
34
|
+
customers: sortedCustomers,
|
|
35
|
+
customerViewStateByTenantId: customersByTenantId,
|
|
36
|
+
selectedCustomersForJobTrigger,
|
|
37
|
+
triggerJobStatus,
|
|
38
|
+
uiState,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
// ── Helpers ──
|
|
42
|
+
const getSortedCustomers = (customers, sortKey, sortOrder) => {
|
|
43
|
+
const direction = sortOrder === 'ascending' ? 'asc' : 'desc';
|
|
44
|
+
return orderBy(customers, (customer) => {
|
|
45
|
+
switch (sortKey) {
|
|
46
|
+
case 'companyName':
|
|
47
|
+
return customer.companyName.toLowerCase();
|
|
48
|
+
case 'status':
|
|
49
|
+
return (customer.enrollment?.status ?? 'unknown').toLowerCase();
|
|
50
|
+
case 'bookcloseDate':
|
|
51
|
+
return customer.bookcloseDate?.valueOf() ?? 0;
|
|
52
|
+
case 'latestTraining':
|
|
53
|
+
return customer.enrollment?.latestTraining?.valueOf() ?? 0;
|
|
54
|
+
case 'latestSync':
|
|
55
|
+
return customer.enrollment?.latestTransactionSync?.valueOf() ?? 0;
|
|
56
|
+
case 'accuracy':
|
|
57
|
+
return customer.averageAccuracy;
|
|
58
|
+
default:
|
|
59
|
+
return customer.companyName.toLowerCase();
|
|
60
|
+
}
|
|
61
|
+
}, direction);
|
|
62
|
+
};
|
|
63
|
+
const calcOverallAverageAccuracy = (customers) => {
|
|
64
|
+
const customerAccuracies = customers
|
|
65
|
+
.map((customer) => customer.averageAccuracy)
|
|
66
|
+
.filter((accuracy) => accuracy > 0);
|
|
67
|
+
if (customerAccuracies.length === 0) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
return (customerAccuracies.reduce((sum, accuracy) => sum + accuracy, 0) /
|
|
71
|
+
customerAccuracies.length);
|
|
72
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
+
const ALL_AI_ACCOUNTANT_SORT_KEYS = [
|
|
3
|
+
'companyName',
|
|
4
|
+
'status',
|
|
5
|
+
'bookcloseDate',
|
|
6
|
+
'latestTraining',
|
|
7
|
+
'latestSync',
|
|
8
|
+
'accuracy',
|
|
9
|
+
];
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
|
+
const toAiAccountantSortKeyType = (v) => stringToUnion(v, ALL_AI_ACCOUNTANT_SORT_KEYS);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { from } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
+
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
4
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
5
|
+
import { cancelAiAccountantOnboarding, cancelAiAccountantOnboardingFailure, cancelAiAccountantOnboardingSuccess, fetchAiAccountantCustomers, } from '../aiAccountantViewReducer';
|
|
6
|
+
export const cancelAiAccountantOnboardingEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(cancelAiAccountantOnboarding.match), mergeMap((action) => {
|
|
7
|
+
const { tenantId, companyId } = action.payload;
|
|
8
|
+
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
9
|
+
const url = `${base}/ai-accountant/cancel-onboarding`;
|
|
10
|
+
return zeniAPI
|
|
11
|
+
.postAndGetJSON(url, {
|
|
12
|
+
tenant_id: tenantId,
|
|
13
|
+
company_id: companyId,
|
|
14
|
+
})
|
|
15
|
+
.pipe(mergeMap((response) => {
|
|
16
|
+
if (isSuccessResponse(response)) {
|
|
17
|
+
return from([
|
|
18
|
+
cancelAiAccountantOnboardingSuccess(tenantId),
|
|
19
|
+
fetchAiAccountantCustomers(),
|
|
20
|
+
openSnackbar({
|
|
21
|
+
messageSection: 'common',
|
|
22
|
+
messageText: 'success',
|
|
23
|
+
type: 'success',
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return from([
|
|
29
|
+
cancelAiAccountantOnboardingFailure(tenantId, response.status),
|
|
30
|
+
openSnackbar({
|
|
31
|
+
messageSection: 'common',
|
|
32
|
+
messageText: 'failed',
|
|
33
|
+
type: 'error',
|
|
34
|
+
}),
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
}), catchError((error) => from([
|
|
38
|
+
cancelAiAccountantOnboardingFailure(tenantId, createZeniAPIStatus('Unexpected error', 'AI Accountant cancel onboarding failed: ' +
|
|
39
|
+
JSON.stringify(error))),
|
|
40
|
+
openSnackbar({
|
|
41
|
+
messageSection: 'common',
|
|
42
|
+
messageText: 'failed',
|
|
43
|
+
type: 'error',
|
|
44
|
+
}),
|
|
45
|
+
])));
|
|
46
|
+
}));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { from, of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { updateAiAccountantCustomers as updateAiAccountantCustomerEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
|
|
4
|
+
import { updateAllUsers } from '../../../entity/user/userReducer';
|
|
5
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
6
|
+
import { fetchAiAccountantCustomers, updateAiAccountantCustomers, updateAiAccountantCustomersFailure, } from '../aiAccountantViewReducer';
|
|
7
|
+
export const fetchAiAccountantCustomersEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(fetchAiAccountantCustomers.match), switchMap(() => {
|
|
8
|
+
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
9
|
+
const url = `${base}/ai-accountant/customers`;
|
|
10
|
+
return zeniAPI
|
|
11
|
+
.getJSON(url)
|
|
12
|
+
.pipe(mergeMap((response) => {
|
|
13
|
+
if (isSuccessResponse(response)) {
|
|
14
|
+
const customers = response.data?.customers ?? [];
|
|
15
|
+
const users = response.data?.users ?? [];
|
|
16
|
+
return from([
|
|
17
|
+
updateAiAccountantCustomerEntities(customers),
|
|
18
|
+
updateAllUsers({ users }),
|
|
19
|
+
updateAiAccountantCustomers(customers),
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return of(updateAiAccountantCustomersFailure(response.status));
|
|
24
|
+
}
|
|
25
|
+
}), catchError((error) => of(updateAiAccountantCustomersFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant customers fetch failed: ' +
|
|
26
|
+
JSON.stringify(error))))));
|
|
27
|
+
}));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { from, of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { updateAiAccountantJobs as updateAiAccountantJobEntities } from '../../../entity/aiAccountantCustomer/aiAccountantCustomerReducer';
|
|
4
|
+
import { updateAllUsers } from '../../../entity/user/userReducer';
|
|
5
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
6
|
+
import { fetchAiAccountantJobs, updateAiAccountantJobs, updateAiAccountantJobsFailure, } from '../aiAccountantViewReducer';
|
|
7
|
+
export const fetchAiAccountantJobsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchAiAccountantJobs.match), switchMap((action) => {
|
|
8
|
+
const { tenantId, fetchNextPage } = action.payload;
|
|
9
|
+
const rootState = state$.value;
|
|
10
|
+
const customerView = rootState.aiAccountantViewState.customersByTenantId[tenantId];
|
|
11
|
+
const pageToken = fetchNextPage && customerView?.jobsPageToken != null
|
|
12
|
+
? customerView.jobsPageToken
|
|
13
|
+
: null;
|
|
14
|
+
const params = new URLSearchParams({
|
|
15
|
+
page_size: '50',
|
|
16
|
+
tenant_id: tenantId,
|
|
17
|
+
});
|
|
18
|
+
if (pageToken != null) {
|
|
19
|
+
params.set('page_token', pageToken);
|
|
20
|
+
}
|
|
21
|
+
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
22
|
+
const url = `${base}/ai-accountant/jobs?${params.toString()}`;
|
|
23
|
+
return zeniAPI
|
|
24
|
+
.getJSON(url)
|
|
25
|
+
.pipe(mergeMap((response) => {
|
|
26
|
+
if (isSuccessResponse(response)) {
|
|
27
|
+
const jobs = response.data?.jobs ?? [];
|
|
28
|
+
const users = response.data?.users ?? [];
|
|
29
|
+
const nextPageToken = response.data?.next_page_token ?? null;
|
|
30
|
+
return from([
|
|
31
|
+
updateAllUsers({ users }),
|
|
32
|
+
updateAiAccountantJobEntities(tenantId, jobs, fetchNextPage),
|
|
33
|
+
updateAiAccountantJobs(tenantId, nextPageToken),
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return of(updateAiAccountantJobsFailure({
|
|
38
|
+
tenantId,
|
|
39
|
+
error: response.status,
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
}), catchError((error) => of(updateAiAccountantJobsFailure({
|
|
43
|
+
tenantId,
|
|
44
|
+
error: createZeniAPIStatus('Unexpected error', 'AI Accountant jobs fetch failed: ' +
|
|
45
|
+
JSON.stringify(error)),
|
|
46
|
+
}))));
|
|
47
|
+
}));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { from } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
+
import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
|
|
4
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
|
|
5
|
+
import { fetchAiAccountantCustomers, triggerAiAccountantJob, triggerAiAccountantJobFailure, triggerAiAccountantJobSuccess, } from '../aiAccountantViewReducer';
|
|
6
|
+
export const triggerAiAccountantJobEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(triggerAiAccountantJob.match), mergeMap((action) => {
|
|
7
|
+
const { operationType, startDate, endDate } = action.payload;
|
|
8
|
+
const rootState = state$.value;
|
|
9
|
+
const selectedTenantIds = rootState.aiAccountantViewState.selectedTenantIdsForJobTrigger;
|
|
10
|
+
const base = `${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/cockpit-panels`;
|
|
11
|
+
const url = `${base}/ai-accountant/jobs`;
|
|
12
|
+
const params = operationType === 'offboard'
|
|
13
|
+
? {}
|
|
14
|
+
: { start_date: startDate, end_date: endDate };
|
|
15
|
+
return zeniAPI
|
|
16
|
+
.postAndGetJSON(url, {
|
|
17
|
+
tenant_ids: selectedTenantIds,
|
|
18
|
+
operation_type: operationType,
|
|
19
|
+
params,
|
|
20
|
+
})
|
|
21
|
+
.pipe(mergeMap((response) => {
|
|
22
|
+
if (isSuccessResponse(response)) {
|
|
23
|
+
return from([
|
|
24
|
+
triggerAiAccountantJobSuccess(),
|
|
25
|
+
fetchAiAccountantCustomers(),
|
|
26
|
+
openSnackbar({
|
|
27
|
+
messageSection: 'common',
|
|
28
|
+
messageText: 'success',
|
|
29
|
+
type: 'success',
|
|
30
|
+
}),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return from([
|
|
35
|
+
triggerAiAccountantJobFailure(response.status),
|
|
36
|
+
openSnackbar({
|
|
37
|
+
messageSection: 'common',
|
|
38
|
+
messageText: 'failed',
|
|
39
|
+
type: 'error',
|
|
40
|
+
}),
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
}), catchError((error) => from([
|
|
44
|
+
triggerAiAccountantJobFailure(createZeniAPIStatus('Unexpected error', 'AI Accountant trigger job failed: ' +
|
|
45
|
+
JSON.stringify(error))),
|
|
46
|
+
openSnackbar({
|
|
47
|
+
messageSection: 'common',
|
|
48
|
+
messageText: 'failed',
|
|
49
|
+
type: 'error',
|
|
50
|
+
}),
|
|
51
|
+
])));
|
|
52
|
+
}));
|
|
@@ -9,8 +9,10 @@ import { extractThisPeriod } from '../../commonStateTypes/viewAndReport/thisPeri
|
|
|
9
9
|
import { getBalanceSheet } from '../balanceSheet/balanceSheetSelector';
|
|
10
10
|
import { getCashFlow } from '../cashFlow/cashFlowSelector';
|
|
11
11
|
import { getProfitAndLossReport, } from '../profitAndLoss/profitAndLossSelector';
|
|
12
|
+
import { newBalancesFilterProjectView } from '../../commonStateTypes/coaBalance/coaBalancesFilterProjectView';
|
|
12
13
|
import { getProfitAndLossClassesHorizontalView } from '../profitAndLossClassesView/profitAndLossClassesByClassHorizontalSelector';
|
|
13
14
|
import { getProfitAndLossClassesView } from '../profitAndLossClassesView/profitAndLossClassesViewSelector';
|
|
15
|
+
import { getProfitAndLossProjectView } from '../profitAndLossProjectView/profitAndLossProjectViewSelector';
|
|
14
16
|
function getDateRangeForFinanceReports(profitAndLossState, balanceSheetState, cashFlowState) {
|
|
15
17
|
const datesSorted = [
|
|
16
18
|
profitAndLossState.dataAvailable?.startDate,
|
|
@@ -35,7 +37,7 @@ function getFirstMonthOfFY(profitAndLossState, balanceSheetState, cashFlowState)
|
|
|
35
37
|
cashFlowState.firstMonthOfFY ??
|
|
36
38
|
1);
|
|
37
39
|
}
|
|
38
|
-
export const getFinanceStatement = createSelector((state) => state.accountState, (state) => state.accountGroupState, (state) => state.classState, (state) => state.sectionClassesViewStateV2, (state) => state.profitAndLossState, (state) => state.profitAndLossClassesViewState, (state) => state.balanceSheetState, (state) => state.cashFlowState, (state) => state.financeStatementState, (state) => state.sectionAccountsViewState, (state) => state.forecastState, (accountState, accountGroupState, classState, sectionsState, profitAndLossState, profitAndLossClassesViewState, balanceSheetState, cashFlowState, financeStatementState, sectionAccountsViewState, forecastState) => {
|
|
40
|
+
export const getFinanceStatement = createSelector((state) => state.accountState, (state) => state.accountGroupState, (state) => state.classState, (state) => state.sectionClassesViewStateV2, (state) => state.profitAndLossState, (state) => state.profitAndLossClassesViewState, (state) => state.projectState, (state) => state.sectionProjectViewState, (state) => state.profitAndLossProjectViewState, (state) => state.balanceSheetState, (state) => state.cashFlowState, (state) => state.financeStatementState, (state) => state.sectionAccountsViewState, (state) => state.forecastState, (accountState, accountGroupState, classState, sectionsState, profitAndLossState, profitAndLossClassesViewState, projectState, sectionProjectViewState, profitAndLossProjectViewState, balanceSheetState, cashFlowState, financeStatementState, sectionAccountsViewState, forecastState) => {
|
|
39
41
|
// to get min and max dates across three reports
|
|
40
42
|
let allTimeframeTicks = [];
|
|
41
43
|
let balancesInTimeframe = [];
|
|
@@ -69,6 +71,8 @@ export const getFinanceStatement = createSelector((state) => state.accountState,
|
|
|
69
71
|
const profitAndLossReport = getProfitAndLossReport(filter, undefined, accountState, accountGroupState, sectionAccountsViewState, profitAndLossState, forecastState);
|
|
70
72
|
const classFilter = newBalancesFilterClassesView(filter.firstMonthOfFY, filter.timeframe, filter.balancesRange.numberOfPeriods, filter.balancesRange.thisPeriod, filter.balancesRange.orderBy, filter.additionalBalances, profitAndLossClassesViewState.uiState.classesToFilterOut);
|
|
71
73
|
const profitAndLossByClassReport = getProfitAndLossClassesView(classFilter, accountState, classState, sectionsState, profitAndLossClassesViewState);
|
|
74
|
+
const projectFilter = newBalancesFilterProjectView(filter.firstMonthOfFY, filter.timeframe, filter.balancesRange.numberOfPeriods, filter.balancesRange.thisPeriod, filter.balancesRange.orderBy, filter.additionalBalances, profitAndLossProjectViewState.uiState.projectsToFilterOut);
|
|
75
|
+
const profitAndLossByProjectReport = getProfitAndLossProjectView(projectFilter, accountState, projectState, sectionProjectViewState, profitAndLossProjectViewState);
|
|
72
76
|
const profitAndLossByClassHorizontalReport = getProfitAndLossClassesHorizontalView(classFilter, accountState, classState, sectionsState, profitAndLossClassesViewState, profitAndLossClassesViewState.uiState.classViewLayout === 'horizontal'
|
|
73
77
|
? thisPeriod
|
|
74
78
|
: undefined);
|
|
@@ -89,6 +93,12 @@ export const getFinanceStatement = createSelector((state) => state.accountState,
|
|
|
89
93
|
error: profitAndLossReport.error,
|
|
90
94
|
};
|
|
91
95
|
break;
|
|
96
|
+
case 'profit_and_loss_by_projects':
|
|
97
|
+
selectedReportAndTimeframeFetchState = {
|
|
98
|
+
fetchState: profitAndLossByProjectReport.fetchState,
|
|
99
|
+
error: profitAndLossByProjectReport.error,
|
|
100
|
+
};
|
|
101
|
+
break;
|
|
92
102
|
case 'balance_sheet':
|
|
93
103
|
selectedReportAndTimeframeFetchState = {
|
|
94
104
|
fetchState: balanceSheetReport.fetchState,
|
|
@@ -119,6 +129,7 @@ export const getFinanceStatement = createSelector((state) => state.accountState,
|
|
|
119
129
|
dataAvailable,
|
|
120
130
|
profitAndLossReport,
|
|
121
131
|
profitAndLossByClassReport,
|
|
132
|
+
profitAndLossByProjectReport,
|
|
122
133
|
profitAndLossByClassHorizontalReport,
|
|
123
134
|
balanceSheetReport,
|
|
124
135
|
cashFlowReport,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { from, of } from 'rxjs';
|
|
2
|
+
import { catchError, filter, mergeMap } from 'rxjs/operators';
|
|
3
|
+
import { updateProjects } from '../../entity/project/projectReducer';
|
|
4
|
+
import { updateSectionProjectView } from '../../entity/sectionProjectView/sectionProjectViewReducer';
|
|
5
|
+
import { createZeniAPIStatus, isSuccessResponse } from '../../responsePayload';
|
|
6
|
+
import { fetchProfitAndLossForTimeframeProjectView, updateProfitAndLossForTimeframeProjectView, updateProfitAndLossForTimeframeProjectViewFailure, } from './profitAndLossProjectViewReducer';
|
|
7
|
+
export const fetchProfitAndLossForTimeframeProjectViewEpic = (actions$, _, zeniAPI) => actions$.pipe(filter(fetchProfitAndLossForTimeframeProjectView.match), mergeMap((action) => {
|
|
8
|
+
const getTimeSeriesGroup = (timeframe) => {
|
|
9
|
+
switch (timeframe) {
|
|
10
|
+
case 'month':
|
|
11
|
+
return 'months';
|
|
12
|
+
case 'quarter':
|
|
13
|
+
return 'quarters';
|
|
14
|
+
case 'year':
|
|
15
|
+
return 'years';
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const queryValue = {
|
|
19
|
+
is_full_response: action.payload.fetchFullReport,
|
|
20
|
+
time_series_groups: [getTimeSeriesGroup(action.payload.timeframe)],
|
|
21
|
+
is_group_by_project: true,
|
|
22
|
+
};
|
|
23
|
+
return zeniAPI
|
|
24
|
+
.getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/2.0/reports/profit_and_loss?query=${encodeURIComponent(JSON.stringify(queryValue))}`)
|
|
25
|
+
.pipe(mergeMap((response) => {
|
|
26
|
+
if (response.data != null && isSuccessResponse(response)) {
|
|
27
|
+
const actions = [];
|
|
28
|
+
const report = response.data.report;
|
|
29
|
+
const currency = report.currency;
|
|
30
|
+
actions.push(updateProjects(report.projects));
|
|
31
|
+
actions.push(updateSectionProjectView(action.payload.timeframe, 'cogs', 'profit_and_loss_by_projects', report.cogs, report.accounts, currency));
|
|
32
|
+
actions.push(updateSectionProjectView(action.payload.timeframe, 'expenses', 'profit_and_loss_by_projects', report.expenses, report.accounts, currency));
|
|
33
|
+
actions.push(updateSectionProjectView(action.payload.timeframe, 'income', 'profit_and_loss_by_projects', report.income, report.accounts, currency));
|
|
34
|
+
actions.push(updateSectionProjectView(action.payload.timeframe, 'otherExpenses', 'profit_and_loss_by_projects', report.other_expenses, report.accounts, currency));
|
|
35
|
+
actions.push(updateSectionProjectView(action.payload.timeframe, 'otherIncome', 'profit_and_loss_by_projects', report.other_income, report.accounts, currency));
|
|
36
|
+
actions.push(updateProfitAndLossForTimeframeProjectView({
|
|
37
|
+
timeframe: action.payload.timeframe,
|
|
38
|
+
report: response.data,
|
|
39
|
+
}));
|
|
40
|
+
return from(actions);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return of(updateProfitAndLossForTimeframeProjectViewFailure(response.status, action.payload.timeframe));
|
|
44
|
+
}
|
|
45
|
+
}), catchError((error) => of(updateProfitAndLossForTimeframeProjectViewFailure(createZeniAPIStatus('Unexpected Error', 'P&L by Projects REST API call errored out' +
|
|
46
|
+
JSON.stringify(error)), action.payload.timeframe))));
|
|
47
|
+
}));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { from } from 'rxjs';
|
|
2
|
+
import { filter, switchMap } from 'rxjs/operators';
|
|
3
|
+
import { fetchProfitAndLossForTimeframeProjectView, fetchProfitAndLossProjectView, } from './profitAndLossProjectViewReducer';
|
|
4
|
+
export const fetchProfitAndLossProjectViewEpic = (actions$, state) => actions$.pipe(filter(fetchProfitAndLossProjectView.match), switchMap((action) => {
|
|
5
|
+
const { cacheOverride } = action.payload;
|
|
6
|
+
if (cacheOverride === true) {
|
|
7
|
+
return from([
|
|
8
|
+
fetchProfitAndLossForTimeframeProjectView('month'),
|
|
9
|
+
fetchProfitAndLossForTimeframeProjectView('quarter'),
|
|
10
|
+
fetchProfitAndLossForTimeframeProjectView('year'),
|
|
11
|
+
]);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
const fetchActions = [];
|
|
15
|
+
const projectFetchState = state.value.profitAndLossProjectViewState.fetchState;
|
|
16
|
+
if (projectFetchState['month'].fetchState !== 'In-Progress' &&
|
|
17
|
+
projectFetchState['month'].fetchState !== 'Completed') {
|
|
18
|
+
fetchActions.push(fetchProfitAndLossForTimeframeProjectView('month'));
|
|
19
|
+
}
|
|
20
|
+
if (projectFetchState['quarter'].fetchState !== 'In-Progress' &&
|
|
21
|
+
projectFetchState['quarter'].fetchState !== 'Completed') {
|
|
22
|
+
fetchActions.push(fetchProfitAndLossForTimeframeProjectView('quarter'));
|
|
23
|
+
}
|
|
24
|
+
if (projectFetchState['year'].fetchState !== 'In-Progress' &&
|
|
25
|
+
projectFetchState['year'].fetchState !== 'Completed') {
|
|
26
|
+
fetchActions.push(fetchProfitAndLossForTimeframeProjectView('year'));
|
|
27
|
+
}
|
|
28
|
+
return from(fetchActions);
|
|
29
|
+
}
|
|
30
|
+
}));
|