@zeniai/client-epic-state 5.1.66 → 5.1.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/entity/approvalRule/approvalRuleState.d.ts +1 -0
- package/lib/entity/entityApprovalStatus/entityApprovalStatusPayload.d.ts +1 -0
- package/lib/entity/entityApprovalStatus/entityApprovalStatusPayload.js +1 -0
- package/lib/entity/entityApprovalStatus/entityApprovalStatusState.d.ts +1 -0
- package/lib/esm/entity/entityApprovalStatus/entityApprovalStatusPayload.js +1 -0
- package/lib/esm/view/spendManagement/billPay/billDetailView/billDetailViewSelector.js +76 -37
- package/lib/esm/view/spendManagement/billPay/billList/billListSelector.js +14 -17
- package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +1 -3
- package/lib/esm/view/spendManagement/billPay/editBillView/epics/fetchEditBillDetailPageEpic.js +0 -14
- package/lib/esm/view/spendManagement/helpers.js +14 -0
- package/lib/esm/view/spendManagement/reimbursement/remiDetailView/remiDetailViewSelector.js +44 -19
- package/lib/esm/view/spendManagement/reimbursement/remiListView/remiListSelector.js +14 -17
- package/lib/view/spendManagement/billPay/billDetailView/billDetailViewSelector.d.ts +2 -0
- package/lib/view/spendManagement/billPay/billDetailView/billDetailViewSelector.js +75 -36
- package/lib/view/spendManagement/billPay/billList/billListSelector.js +13 -16
- package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +1 -3
- package/lib/view/spendManagement/billPay/editBillView/epics/fetchEditBillDetailPageEpic.d.ts +1 -2
- package/lib/view/spendManagement/billPay/editBillView/epics/fetchEditBillDetailPageEpic.js +0 -14
- package/lib/view/spendManagement/helpers.d.ts +5 -1
- package/lib/view/spendManagement/helpers.js +18 -1
- package/lib/view/spendManagement/reimbursement/remiDetailView/remiDetailViewSelector.d.ts +2 -0
- package/lib/view/spendManagement/reimbursement/remiDetailView/remiDetailViewSelector.js +43 -18
- package/lib/view/spendManagement/reimbursement/remiListView/remiListSelector.js +13 -16
- package/package.json +1 -1
|
@@ -24,6 +24,7 @@ const toEntityApprovalStatus = (payload) => ({
|
|
|
24
24
|
currentPendingStepIndex: payload.current_pending_step_index,
|
|
25
25
|
isAdminFallbackApprover: payload.is_admin_fallback_approver_for_missing_user,
|
|
26
26
|
isRealTimeApprovalEnabled: payload.is_real_time_approval_enabled ?? false,
|
|
27
|
+
sodExcludedApproverUserId: payload.sod_excluded_approver_user_id ?? undefined,
|
|
27
28
|
});
|
|
28
29
|
exports.toEntityApprovalStatus = toEntityApprovalStatus;
|
|
29
30
|
const toEntityApprovalByUser = (payload) => {
|
|
@@ -21,6 +21,7 @@ export const toEntityApprovalStatus = (payload) => ({
|
|
|
21
21
|
currentPendingStepIndex: payload.current_pending_step_index,
|
|
22
22
|
isAdminFallbackApprover: payload.is_admin_fallback_approver_for_missing_user,
|
|
23
23
|
isRealTimeApprovalEnabled: payload.is_real_time_approval_enabled ?? false,
|
|
24
|
+
sodExcludedApproverUserId: payload.sod_excluded_approver_user_id ?? undefined,
|
|
24
25
|
});
|
|
25
26
|
const toEntityApprovalByUser = (payload) => {
|
|
26
27
|
const res = {};
|
|
@@ -13,7 +13,7 @@ import { getUserByUserId } from '../../../../entity/user/userSelector';
|
|
|
13
13
|
import { getUserRoleByUserId } from '../../../../entity/userRole/userRoleSelector';
|
|
14
14
|
import { getActivityHistory, } from '../../commonHistoryView/commonHistorySelector';
|
|
15
15
|
import { getAllFundingAccounts, } from '../../commonSetup/setupViewSelector';
|
|
16
|
-
import { getLatestApprovalDate, isAwaitingMarkAsPaid } from '../../helpers';
|
|
16
|
+
import { getLatestApprovalDate, isAwaitingMarkAsPaid, isSodAdminFallbackEligibleForStep, isSodExcludedViewerBlocked, } from '../../helpers';
|
|
17
17
|
import { getActivityRealTimeApproval, } from '../../realTimeApprovalView/realTimeApprovalSelector';
|
|
18
18
|
import { getEntityRealTimeApprovalDetailKey } from '../../realTimeApprovalView/realTimeApprovalState';
|
|
19
19
|
import { getBillPaymentSubConfigCodeKey, getInternationalSubConfigCodeKey, getInternationalWireMethodCodeKey, } from '../billPayConfig/billPayConfigPayload';
|
|
@@ -57,7 +57,7 @@ export const getBillActivities = (state, billId, billStageCode) => {
|
|
|
57
57
|
const approvalRules = getApprovalRulesByIds(approvalRuleState, billDetail.approvalRuleIds);
|
|
58
58
|
const entityApprovalStatusByIds = getEntityApprovalStatusByIds(entityApprovalStatusState, billDetail.entityApprovalIds);
|
|
59
59
|
billActivities = entityApprovalStatusByIds.map((entityApprovalStatus) => {
|
|
60
|
-
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, isRealTimeApprovalEnabled, currentPendingStepIndex, } = entityApprovalStatus;
|
|
60
|
+
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, isRealTimeApprovalEnabled, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
61
61
|
const approvalRule = approvalRules.find((rule) => rule.approvalRuleId === approvalRuleId);
|
|
62
62
|
return {
|
|
63
63
|
approvalRuleId,
|
|
@@ -69,21 +69,22 @@ export const getBillActivities = (state, billId, billStageCode) => {
|
|
|
69
69
|
isAdminFallbackApprover,
|
|
70
70
|
isRealTimeApprovalEnabled,
|
|
71
71
|
currentPendingStepIndex,
|
|
72
|
+
sodExcludedApproverUserId,
|
|
72
73
|
entityApprovalId: entityApprovalStatus.entityApprovalId,
|
|
73
74
|
stepsWithStatus: stepsApprovalStatus.map((step) => {
|
|
75
|
+
const actorsActivity = step.actorsActivity.map((activity) => ({
|
|
76
|
+
...activity,
|
|
77
|
+
actor: getUserByUserId(userState, activity.userId),
|
|
78
|
+
}));
|
|
74
79
|
return {
|
|
75
80
|
...step,
|
|
76
81
|
actors: step.actors
|
|
77
82
|
.map((actor) => getUserByUserId(userState, actor.userId))
|
|
78
83
|
.filter((user) => user != null),
|
|
79
84
|
nonUserActors: step.actors.filter((actor) => actor.userId == null && actor.type !== 'user'),
|
|
80
|
-
actorsActivity
|
|
81
|
-
return {
|
|
82
|
-
...activity,
|
|
83
|
-
actor: getUserByUserId(userState, activity.userId),
|
|
84
|
-
};
|
|
85
|
-
}),
|
|
85
|
+
actorsActivity,
|
|
86
86
|
isOriginalApprovalStep: step.isOriginalApprovalStep,
|
|
87
|
+
displayPendingApproverAsAdmin: isSodAdminFallbackEligibleForStep(sodExcludedApproverUserId, isAdminFallbackApprover, actorsActivity),
|
|
87
88
|
};
|
|
88
89
|
}),
|
|
89
90
|
};
|
|
@@ -248,7 +249,7 @@ export const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInU
|
|
|
248
249
|
let isMarkAsPaidBtnVisible = false;
|
|
249
250
|
let rejectedId = -1;
|
|
250
251
|
const stepsWithStatusData = billActivities[0].stepsWithStatus;
|
|
251
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = billActivities[0];
|
|
252
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = billActivities[0];
|
|
252
253
|
for (const [index, stepWithStatus] of stepsWithStatusData.entries()) {
|
|
253
254
|
if (stepWithStatus.action === 'require_approval') {
|
|
254
255
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
@@ -289,23 +290,42 @@ export const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInU
|
|
|
289
290
|
break;
|
|
290
291
|
}
|
|
291
292
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
293
|
+
const sodBlocked = isSodExcludedViewerBlocked(sodExcludedApproverUserId, signedInUser?.userId, pendingStep.actorsActivity);
|
|
294
|
+
if (isAllActivitiesPending) {
|
|
295
|
+
for (const actorActivity of pendingStep.actorsActivity) {
|
|
296
|
+
if (!sodBlocked &&
|
|
297
|
+
actorActivity.actor?.userId === signedInUser?.userId) {
|
|
298
|
+
isApprovalorRejectBtnVisible = true;
|
|
299
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
297
302
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
actorActivity.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
303
|
+
}
|
|
304
|
+
if (!isApprovalorRejectBtnVisible) {
|
|
305
|
+
for (const actorActivity of pendingStep.actorsActivity) {
|
|
306
|
+
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
307
|
+
if (actorActivity.type === 'attribute' &&
|
|
308
|
+
(actorActivity.subType === 'manager' ||
|
|
309
|
+
actorActivity.subType === 'vendor_owner') &&
|
|
310
|
+
actorActivity.userId === null &&
|
|
311
|
+
isAdminFallbackApprover &&
|
|
312
|
+
isUserAdmin &&
|
|
313
|
+
signedInUser?.userId != null &&
|
|
314
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
315
|
+
isApprovalorRejectBtnVisible = true;
|
|
316
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
307
319
|
}
|
|
308
320
|
}
|
|
321
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
322
|
+
isUserAdmin &&
|
|
323
|
+
signedInUser?.userId != null &&
|
|
324
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
325
|
+
pendingStep.displayPendingApproverAsAdmin) {
|
|
326
|
+
isApprovalorRejectBtnVisible = true;
|
|
327
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
328
|
+
}
|
|
309
329
|
}
|
|
310
330
|
}
|
|
311
331
|
}
|
|
@@ -319,23 +339,42 @@ export const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInU
|
|
|
319
339
|
break;
|
|
320
340
|
}
|
|
321
341
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
342
|
+
const sodBlocked = isSodExcludedViewerBlocked(sodExcludedApproverUserId, signedInUser?.userId, stepWithStatus.actorsActivity);
|
|
343
|
+
if (isAllActivitiesPending) {
|
|
344
|
+
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
345
|
+
if (!sodBlocked &&
|
|
346
|
+
actorActivity.actor?.userId === signedInUser?.userId) {
|
|
347
|
+
isApprovalorRejectBtnVisible = true;
|
|
348
|
+
isMarkAsPaidBtnVisible = true;
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
327
351
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
actorActivity.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
352
|
+
}
|
|
353
|
+
if (!isApprovalorRejectBtnVisible) {
|
|
354
|
+
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
355
|
+
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
356
|
+
if (actorActivity.type === 'attribute' &&
|
|
357
|
+
(actorActivity.subType === 'manager' ||
|
|
358
|
+
actorActivity.subType === 'vendor_owner') &&
|
|
359
|
+
actorActivity.userId === null &&
|
|
360
|
+
isAdminFallbackApprover &&
|
|
361
|
+
isUserAdmin &&
|
|
362
|
+
signedInUser?.userId != null &&
|
|
363
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
364
|
+
isApprovalorRejectBtnVisible = true;
|
|
365
|
+
isMarkAsPaidBtnVisible = true;
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
337
368
|
}
|
|
338
369
|
}
|
|
370
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
371
|
+
isUserAdmin &&
|
|
372
|
+
signedInUser?.userId != null &&
|
|
373
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
374
|
+
stepWithStatus.displayPendingApproverAsAdmin) {
|
|
375
|
+
isApprovalorRejectBtnVisible = true;
|
|
376
|
+
isMarkAsPaidBtnVisible = true;
|
|
377
|
+
}
|
|
339
378
|
}
|
|
340
379
|
if (isApprovalorRejectBtnVisible) {
|
|
341
380
|
break;
|
|
@@ -4,7 +4,7 @@ import orderBy from 'lodash/orderBy';
|
|
|
4
4
|
import { toAttributeTypeStrict, } from '../../../../entity/approvalRule/approvalRuleState';
|
|
5
5
|
import { getUserByUserId } from '../../../../entity/user/userSelector';
|
|
6
6
|
import { dateNow } from '../../../../zeniDayJS';
|
|
7
|
-
import { isAwaitingMarkAsPaid, isBulkProcessing, } from '../../helpers';
|
|
7
|
+
import { isAwaitingMarkAsPaid, isBulkProcessing, isSodAdminFallbackEligibleForStep, } from '../../helpers';
|
|
8
8
|
import { applyAdvancedFiltersOnList, isBillListDownloadable, } from '../../spendManagementFilterHelpers';
|
|
9
9
|
import { getSelectedWithdrawFromAccount } from '../billDetailView/billDetailViewSelector';
|
|
10
10
|
import { getBillPayConfigBotEmail } from '../billPayConfig/billPayConfigSelector';
|
|
@@ -290,7 +290,7 @@ export const getApproversOrRejectors = (billTransaction, entityApprovalStatusSta
|
|
|
290
290
|
};
|
|
291
291
|
if (billTransaction.entityApprovalId !== null) {
|
|
292
292
|
const entityApprovalStatus = entityApprovalStatusState.entityApprovalStatusById[billTransaction.entityApprovalId];
|
|
293
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = entityApprovalStatus;
|
|
293
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
294
294
|
const isBillSerailized = areApprovalsSerialized === true &&
|
|
295
295
|
currentPendingStepIndex != null &&
|
|
296
296
|
currentPendingStepIndex > -1;
|
|
@@ -318,23 +318,20 @@ export const getApproversOrRejectors = (billTransaction, entityApprovalStatusSta
|
|
|
318
318
|
if (isBillSerailized) {
|
|
319
319
|
requireApprovalInfo = [stepsApprovalStatus[currentPendingStepIndex]];
|
|
320
320
|
}
|
|
321
|
-
const pendingActivitiesList = [];
|
|
322
321
|
requireApprovalInfo.forEach((approvalStep) => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (isBillSerailized) {
|
|
326
|
-
pendingActivitiesList.push(...pendingActivities);
|
|
322
|
+
if (approvers.displayPendingApproverAsAdmin) {
|
|
323
|
+
return;
|
|
327
324
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
325
|
+
const pendingActivities = approvalStep.actorsActivity.filter((activity) => activity.activity === 'pending');
|
|
326
|
+
const sodDisplayAsAdmin = isSodAdminFallbackEligibleForStep(sodExcludedApproverUserId, isAdminFallbackApprover, approvalStep.actorsActivity);
|
|
327
|
+
const activitiesToShow = isBillSerailized
|
|
328
|
+
? pendingActivities
|
|
329
|
+
: pendingActivities.slice(0, 1);
|
|
330
|
+
if (sodDisplayAsAdmin) {
|
|
331
|
+
approvers.displayPendingApproverAsAdmin = true;
|
|
332
|
+
return;
|
|
334
333
|
}
|
|
335
|
-
|
|
336
|
-
if (pendingActivitiesList.length > 0) {
|
|
337
|
-
pendingActivitiesList.forEach((activity) => {
|
|
334
|
+
activitiesToShow.forEach((activity) => {
|
|
338
335
|
const user = getUserByUserId(userState, activity.userId);
|
|
339
336
|
if (user != null) {
|
|
340
337
|
approvers.users.push(user);
|
|
@@ -346,7 +343,7 @@ export const getApproversOrRejectors = (billTransaction, entityApprovalStatusSta
|
|
|
346
343
|
}
|
|
347
344
|
}
|
|
348
345
|
});
|
|
349
|
-
}
|
|
346
|
+
});
|
|
350
347
|
}
|
|
351
348
|
}
|
|
352
349
|
}
|
|
@@ -29,7 +29,7 @@ import { getDuplicateBills, } from '../billPayReview/billPayReviewSelector';
|
|
|
29
29
|
import { getBillPaySetupApproverView } from '../billPaySetupApproverView/billPaySetupApproverViewSelector';
|
|
30
30
|
import { getPreviousBills, } from '../previousBills/previousBillsSelector';
|
|
31
31
|
export const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, isZeniAccountsEnabled, billId) => {
|
|
32
|
-
const { accountListState, accountState, bankAccountState, billDetailViewState, paymentAccountListState, billTransactionState, billPayConfigState, classListState, classState, editBillDetailViewState, paymentAccountState, vendorState, tenantState, companyState, userState, commonHistoryState, contactState, paymentInstrumentState, recurringBillState, depositAccountListState, depositAccountState,
|
|
32
|
+
const { accountListState, accountState, bankAccountState, billDetailViewState, paymentAccountListState, billTransactionState, billPayConfigState, classListState, classState, editBillDetailViewState, paymentAccountState, vendorState, tenantState, companyState, userState, commonHistoryState, contactState, paymentInstrumentState, recurringBillState, depositAccountListState, depositAccountState, plaidAccountViewState, } = state;
|
|
33
33
|
const transaction = recordGet(billTransactionState.transactionById, billId ?? '', undefined);
|
|
34
34
|
let recommendations = {};
|
|
35
35
|
if (billId != null) {
|
|
@@ -177,7 +177,6 @@ export const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, i
|
|
|
177
177
|
const fetchStateList = [
|
|
178
178
|
sourceBillDetail.fetchStatus,
|
|
179
179
|
accountListState.byReportId.billPayAccountList,
|
|
180
|
-
billPaySetupApproverViewState,
|
|
181
180
|
];
|
|
182
181
|
if (getIsAccountingClassesEnabled(state)) {
|
|
183
182
|
fetchStateList.push(classListState);
|
|
@@ -198,7 +197,6 @@ export const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, i
|
|
|
198
197
|
else {
|
|
199
198
|
const newBillFetchStateList = [
|
|
200
199
|
accountListState.byReportId.billPayAccountList,
|
|
201
|
-
billPaySetupApproverViewState,
|
|
202
200
|
];
|
|
203
201
|
if (getIsAccountingClassesEnabled(state)) {
|
|
204
202
|
newBillFetchStateList.push(classListState);
|
package/lib/esm/view/spendManagement/billPay/editBillView/epics/fetchEditBillDetailPageEpic.js
CHANGED
|
@@ -8,7 +8,6 @@ import { fetchVendorTypeList } from '../../../../vendorTypeList/vendorTypeListRe
|
|
|
8
8
|
import { fetchDepositAccountList } from '../../../zeniAccounts/depositAccountList/depositAccountListReducer';
|
|
9
9
|
import { fetchPaymentAccountList } from '../../../zeniAccounts/paymentAccountList/paymentAccountListReducer';
|
|
10
10
|
import { fetchBillPayConfig } from '../../billPayConfig/billPayConfigReducer';
|
|
11
|
-
import { fetchBillPaySetupApproverView } from '../../billPaySetupApproverView/billPaySetupApproverViewReducer';
|
|
12
11
|
import { fetchBillAndInitializeLocalStore, fetchEditBillDetailPage, updateShowAutofill, } from '../editBillViewReducer';
|
|
13
12
|
export const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe(filter(fetchEditBillDetailPage.match), mergeMap((action) => {
|
|
14
13
|
const { cacheOverride, billId, isShowDeletedBillsEnabled, hasZeniAssistAccess, isInternationalWireEnabled, } = action.payload;
|
|
@@ -38,10 +37,6 @@ export const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe(f
|
|
|
38
37
|
else {
|
|
39
38
|
billDetailActions.push(updateShowAutofill(true));
|
|
40
39
|
}
|
|
41
|
-
// Side-fetch from the edit-bill page bootstrap. The triggering
|
|
42
|
-
// action doesn't carry the V3 flag, so we explicitly target v1
|
|
43
|
-
// here; tenants on v3 re-fetch through their own screen connector.
|
|
44
|
-
billDetailActions.push(fetchBillPaySetupApproverView(true, true, false));
|
|
45
40
|
}
|
|
46
41
|
else {
|
|
47
42
|
if (state.ownerListState.fetchState !== 'In-Progress' &&
|
|
@@ -80,15 +75,6 @@ export const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe(f
|
|
|
80
75
|
if (billId != null) {
|
|
81
76
|
billDetailActions.push(fetchBillAndInitializeLocalStore(billId, false, isShowDeletedBillsEnabled, hasZeniAssistAccess));
|
|
82
77
|
}
|
|
83
|
-
const approvalViewFetchState = state.billPaySetupApproverViewState.fetchState;
|
|
84
|
-
// While opening New Bill Refresh Approval Rules and Payment Accounts
|
|
85
|
-
if (approvalViewFetchState !== 'In-Progress' &&
|
|
86
|
-
approvalViewFetchState !== 'Completed') {
|
|
87
|
-
// Side-fetch from the edit-bill page bootstrap. The triggering
|
|
88
|
-
// action doesn't carry the V3 flag, so we explicitly target v1
|
|
89
|
-
// here; tenants on v3 re-fetch through their own screen connector.
|
|
90
|
-
billDetailActions.push(fetchBillPaySetupApproverView(true, true, false));
|
|
91
|
-
}
|
|
92
78
|
}
|
|
93
79
|
return concat(from(billDetailActions));
|
|
94
80
|
}));
|
|
@@ -5,6 +5,20 @@ import { endDate, isHoliday, startDate, } from '../../commonStateTypes/workingDa
|
|
|
5
5
|
import { VERIFIED_PAYMENT_ACCOUNT_PROVIDER_VERIFICATION_STATUS } from '../../entity/paymentAccount/paymentAccountState';
|
|
6
6
|
import { hasBillPayAccess, hasBillPayAdminLevelAccess, hasReimbursementAccess, hasReimbursementAdminLevelAccess, } from '../../entity/userRole/userRoleType';
|
|
7
7
|
import { date as zeniDate } from '../../zeniDayJS';
|
|
8
|
+
const getUserActorId = (activity) => activity.actor?.userId ?? activity.userId;
|
|
9
|
+
export const isUserActorOnApprovalStep = (userId, stepActorsActivity) => stepActorsActivity.some((activity) => getUserActorId(activity) === userId);
|
|
10
|
+
export const isSodExcludedViewerBlocked = (sodExcludedApproverUserId, signedInUserId, stepActorsActivity = []) => sodExcludedApproverUserId != null &&
|
|
11
|
+
signedInUserId != null &&
|
|
12
|
+
signedInUserId === sodExcludedApproverUserId &&
|
|
13
|
+
isUserActorOnApprovalStep(sodExcludedApproverUserId, stepActorsActivity);
|
|
14
|
+
export const isSodAdminFallbackEligibleForStep = (sodExcludedApproverUserId, isAdminFallbackApprover, stepActorsActivity = []) => {
|
|
15
|
+
if (sodExcludedApproverUserId == null || !isAdminFallbackApprover) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const pendingResolvedApprovers = stepActorsActivity.filter((activity) => activity.activity === 'pending' && getUserActorId(activity) != null);
|
|
19
|
+
return (pendingResolvedApprovers.length > 0 &&
|
|
20
|
+
pendingResolvedApprovers.every((activity) => getUserActorId(activity) === sodExcludedApproverUserId));
|
|
21
|
+
};
|
|
8
22
|
export const getLatestApprovalDate = (allActivities) => {
|
|
9
23
|
let allStepsWithStatus = [];
|
|
10
24
|
let allApprovedActions = [];
|
|
@@ -7,7 +7,7 @@ import { getEntityApprovalStatusByIds } from '../../../../entity/entityApprovalS
|
|
|
7
7
|
import { getUserByUserId } from '../../../../entity/user/userSelector';
|
|
8
8
|
import { getUserRoleByUserId } from '../../../../entity/userRole/userRoleSelector';
|
|
9
9
|
import { getActivityHistory, } from '../../commonHistoryView/commonHistorySelector';
|
|
10
|
-
import { getLatestApprovalDate } from '../../helpers';
|
|
10
|
+
import { getLatestApprovalDate, isSodAdminFallbackEligibleForStep, isSodExcludedViewerBlocked, } from '../../helpers';
|
|
11
11
|
import { getActivityRealTimeApproval, } from '../../realTimeApprovalView/realTimeApprovalSelector';
|
|
12
12
|
import { getReimbursementConfigByKey } from '../reimbursementConfig/reimbursementConfigSelector';
|
|
13
13
|
import { REIMBURSEMENT_PAYMENT_NUMBER_OF_DAYS } from '../reimbursementConfig/reimbursementConfigState';
|
|
@@ -144,7 +144,7 @@ export const getRemiActivities = (state, reimbursementId, billStageCode) => {
|
|
|
144
144
|
const approvalRules = getApprovalRulesByIds(approvalRuleState, remiTransactionDetails.approvalRuleIds);
|
|
145
145
|
const entityApprovalStatusByIds = getEntityApprovalStatusByIds(entityApprovalStatusState, remiTransactionDetails.entityApprovalIds);
|
|
146
146
|
remiActivities = entityApprovalStatusByIds.map((entityApprovalStatus) => {
|
|
147
|
-
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, isRealTimeApprovalEnabled, } = entityApprovalStatus;
|
|
147
|
+
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, isRealTimeApprovalEnabled, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
148
148
|
const approvalRule = approvalRules.find((rule) => rule.approvalRuleId === approvalRuleId);
|
|
149
149
|
return {
|
|
150
150
|
approvalRuleId,
|
|
@@ -156,21 +156,22 @@ export const getRemiActivities = (state, reimbursementId, billStageCode) => {
|
|
|
156
156
|
isAdminFallbackApprover,
|
|
157
157
|
currentPendingStepIndex,
|
|
158
158
|
isRealTimeApprovalEnabled,
|
|
159
|
+
sodExcludedApproverUserId,
|
|
159
160
|
entityApprovalId: entityApprovalStatus.entityApprovalId,
|
|
160
161
|
stepsWithStatus: stepsApprovalStatus.map((step) => {
|
|
162
|
+
const actorsActivity = step.actorsActivity.map((activity) => ({
|
|
163
|
+
...activity,
|
|
164
|
+
actor: getUserByUserId(userState, activity.userId),
|
|
165
|
+
}));
|
|
161
166
|
return {
|
|
162
167
|
...step,
|
|
163
168
|
actors: step.actors
|
|
164
169
|
.map((actor) => getUserByUserId(userState, actor.userId))
|
|
165
170
|
.filter((user) => user != null),
|
|
166
171
|
nonUserActors: step.actors.filter((actor) => actor.userId == null && actor.type !== 'user'),
|
|
167
|
-
actorsActivity
|
|
168
|
-
return {
|
|
169
|
-
...activity,
|
|
170
|
-
actor: getUserByUserId(userState, activity.userId),
|
|
171
|
-
};
|
|
172
|
-
}),
|
|
172
|
+
actorsActivity,
|
|
173
173
|
isOriginalApprovalStep: step.isOriginalApprovalStep,
|
|
174
|
+
displayPendingApproverAsAdmin: isSodAdminFallbackEligibleForStep(sodExcludedApproverUserId, isAdminFallbackApprover, actorsActivity),
|
|
174
175
|
};
|
|
175
176
|
}),
|
|
176
177
|
};
|
|
@@ -183,7 +184,7 @@ export const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInU
|
|
|
183
184
|
let isApprovalorRejectBtnVisible = false;
|
|
184
185
|
let rejectedId = -1;
|
|
185
186
|
const stepsWithStatusData = remiActivities[0].stepsWithStatus;
|
|
186
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = remiActivities[0];
|
|
187
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = remiActivities[0];
|
|
187
188
|
for (const [index, stepWithStatus] of stepsWithStatusData.entries()) {
|
|
188
189
|
if (stepWithStatus.action === 'require_approval') {
|
|
189
190
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
@@ -219,27 +220,39 @@ export const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInU
|
|
|
219
220
|
break;
|
|
220
221
|
}
|
|
221
222
|
}
|
|
223
|
+
const sodBlocked = isSodExcludedViewerBlocked(sodExcludedApproverUserId, signedInUser?.userId, pendingStep.actorsActivity);
|
|
222
224
|
for (const actorActivity of pendingStep.actorsActivity) {
|
|
223
|
-
if (
|
|
225
|
+
if (!sodBlocked &&
|
|
226
|
+
actorActivity.actor?.userId === signedInUser?.userId &&
|
|
224
227
|
isAllActivitiesPending) {
|
|
225
228
|
isApprovalorRejectBtnVisible = true;
|
|
226
229
|
}
|
|
227
230
|
else if (actorActivity.subType === 'admin' &&
|
|
228
231
|
isUserAdmin &&
|
|
229
|
-
isAllActivitiesPending
|
|
232
|
+
isAllActivitiesPending &&
|
|
233
|
+
signedInUser?.userId != null &&
|
|
234
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
230
235
|
isApprovalorRejectBtnVisible = true;
|
|
231
236
|
}
|
|
232
|
-
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
233
237
|
else if (actorActivity.type === 'attribute' &&
|
|
234
238
|
(actorActivity.subType === 'manager' ||
|
|
235
239
|
actorActivity.subType === 'vendor_owner' ||
|
|
236
240
|
actorActivity.subType === 'manager_of_manager') &&
|
|
237
241
|
actorActivity.userId === null &&
|
|
238
|
-
isAdminFallbackApprover
|
|
239
|
-
isUserAdmin
|
|
242
|
+
isAdminFallbackApprover &&
|
|
243
|
+
isUserAdmin &&
|
|
244
|
+
signedInUser?.userId != null &&
|
|
245
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
240
246
|
isApprovalorRejectBtnVisible = true;
|
|
241
247
|
}
|
|
242
248
|
}
|
|
249
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
250
|
+
isUserAdmin &&
|
|
251
|
+
signedInUser?.userId != null &&
|
|
252
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
253
|
+
pendingStep.displayPendingApproverAsAdmin) {
|
|
254
|
+
isApprovalorRejectBtnVisible = true;
|
|
255
|
+
}
|
|
243
256
|
}
|
|
244
257
|
}
|
|
245
258
|
}
|
|
@@ -253,27 +266,39 @@ export const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInU
|
|
|
253
266
|
break;
|
|
254
267
|
}
|
|
255
268
|
}
|
|
269
|
+
const sodBlocked = isSodExcludedViewerBlocked(sodExcludedApproverUserId, signedInUser?.userId, stepWithStatus.actorsActivity);
|
|
256
270
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
257
|
-
if (
|
|
271
|
+
if (!sodBlocked &&
|
|
272
|
+
actorActivity.actor?.userId === signedInUser?.userId &&
|
|
258
273
|
isAllActivitiesPending) {
|
|
259
274
|
isApprovalorRejectBtnVisible = true;
|
|
260
275
|
}
|
|
261
276
|
else if (actorActivity.subType === 'admin' &&
|
|
262
277
|
isUserAdmin &&
|
|
263
|
-
isAllActivitiesPending
|
|
278
|
+
isAllActivitiesPending &&
|
|
279
|
+
signedInUser?.userId != null &&
|
|
280
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
264
281
|
isApprovalorRejectBtnVisible = true;
|
|
265
282
|
}
|
|
266
|
-
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
267
283
|
else if (actorActivity.type === 'attribute' &&
|
|
268
284
|
(actorActivity.subType === 'manager' ||
|
|
269
285
|
actorActivity.subType === 'vendor_owner' ||
|
|
270
286
|
actorActivity.subType === 'manager_of_manager') &&
|
|
271
287
|
actorActivity.userId === null &&
|
|
272
|
-
isAdminFallbackApprover
|
|
273
|
-
isUserAdmin
|
|
288
|
+
isAdminFallbackApprover &&
|
|
289
|
+
isUserAdmin &&
|
|
290
|
+
signedInUser?.userId != null &&
|
|
291
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
274
292
|
isApprovalorRejectBtnVisible = true;
|
|
275
293
|
}
|
|
276
294
|
}
|
|
295
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
296
|
+
isUserAdmin &&
|
|
297
|
+
signedInUser?.userId != null &&
|
|
298
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
299
|
+
stepWithStatus.displayPendingApproverAsAdmin) {
|
|
300
|
+
isApprovalorRejectBtnVisible = true;
|
|
301
|
+
}
|
|
277
302
|
}
|
|
278
303
|
if (isApprovalorRejectBtnVisible) {
|
|
279
304
|
break;
|
|
@@ -7,7 +7,7 @@ import { getCurrentTenant } from '../../../../entity/tenant/tenantSelector';
|
|
|
7
7
|
import { getUserByUserId, getUsersByUserIds, } from '../../../../entity/user/userSelector';
|
|
8
8
|
import { hasAdminLevelAccess, hasReimbursementUserAccess, } from '../../../../entity/userRole/userRoleType';
|
|
9
9
|
import { dateNow } from '../../../../zeniDayJS';
|
|
10
|
-
import { isBulkProcessing } from '../../helpers';
|
|
10
|
+
import { isBulkProcessing, isSodAdminFallbackEligibleForStep } from '../../helpers';
|
|
11
11
|
import { getReimbursementConfigBotEmail } from '../../reimbursement/reimbursementConfig/reimbursementConfigSelector';
|
|
12
12
|
import { applyAdvancedFiltersOnList, isRemiListDownloadable, } from '../../spendManagementFilterHelpers';
|
|
13
13
|
import { ALL_REMI_TABS, getRemiListKey, } from './remiListState';
|
|
@@ -209,7 +209,7 @@ export const getApproversOrRejectors = (reimbursement, entityApprovalStatusState
|
|
|
209
209
|
};
|
|
210
210
|
if (reimbursement.entityApprovalId !== null) {
|
|
211
211
|
const entityApprovalStatus = entityApprovalStatusState.entityApprovalStatusById[reimbursement.entityApprovalId];
|
|
212
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = entityApprovalStatus;
|
|
212
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
213
213
|
const isReimbursementSerailized = areApprovalsSerialized === true &&
|
|
214
214
|
currentPendingStepIndex != null &&
|
|
215
215
|
currentPendingStepIndex > -1;
|
|
@@ -237,23 +237,20 @@ export const getApproversOrRejectors = (reimbursement, entityApprovalStatusState
|
|
|
237
237
|
if (isReimbursementSerailized) {
|
|
238
238
|
requireApprovalInfo = [stepsApprovalStatus[currentPendingStepIndex]];
|
|
239
239
|
}
|
|
240
|
-
const pendingActivitiesList = [];
|
|
241
240
|
requireApprovalInfo.forEach((approvalStep) => {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (isReimbursementSerailized) {
|
|
245
|
-
pendingActivitiesList.push(...pendingActivities);
|
|
241
|
+
if (approvers.displayPendingApproverAsAdmin) {
|
|
242
|
+
return;
|
|
246
243
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
const pendingActivities = approvalStep.actorsActivity.filter((activity) => activity.activity === 'pending');
|
|
245
|
+
const sodDisplayAsAdmin = isSodAdminFallbackEligibleForStep(sodExcludedApproverUserId, isAdminFallbackApprover, approvalStep.actorsActivity);
|
|
246
|
+
const activitiesToShow = isReimbursementSerailized
|
|
247
|
+
? pendingActivities
|
|
248
|
+
: pendingActivities.slice(0, 1);
|
|
249
|
+
if (sodDisplayAsAdmin) {
|
|
250
|
+
approvers.displayPendingApproverAsAdmin = true;
|
|
251
|
+
return;
|
|
253
252
|
}
|
|
254
|
-
|
|
255
|
-
if (pendingActivitiesList.length > 0) {
|
|
256
|
-
pendingActivitiesList.forEach((activity) => {
|
|
253
|
+
activitiesToShow.forEach((activity) => {
|
|
257
254
|
const user = getUserByUserId(userState, activity.userId);
|
|
258
255
|
if (user != null) {
|
|
259
256
|
approvers.users.push(user);
|
|
@@ -265,7 +262,7 @@ export const getApproversOrRejectors = (reimbursement, entityApprovalStatusState
|
|
|
265
262
|
}
|
|
266
263
|
}
|
|
267
264
|
});
|
|
268
|
-
}
|
|
265
|
+
});
|
|
269
266
|
}
|
|
270
267
|
}
|
|
271
268
|
}
|
|
@@ -54,6 +54,7 @@ export interface BillDetailViewSelector extends SelectorView {
|
|
|
54
54
|
export interface StepWithStatus extends StepWithUser {
|
|
55
55
|
actorsActivity: ActorActivityWithUser[];
|
|
56
56
|
isOriginalApprovalStep: boolean;
|
|
57
|
+
displayPendingApproverAsAdmin?: boolean;
|
|
57
58
|
}
|
|
58
59
|
export interface ActorActivityWithUser {
|
|
59
60
|
activity: ActivityStatus;
|
|
@@ -77,6 +78,7 @@ export interface BillActivity {
|
|
|
77
78
|
currentPendingStepIndex?: number;
|
|
78
79
|
entityApprovalId?: ID;
|
|
79
80
|
isAdminFallbackApprover?: boolean;
|
|
81
|
+
sodExcludedApproverUserId?: ID;
|
|
80
82
|
}
|
|
81
83
|
export declare const getBillActivities: (state: RootState, billId: ID, billStageCode?: BillStageCodeType) => BillActivity[];
|
|
82
84
|
export declare const getBillDetailView: (state: RootState, billId: ID) => BillDetailViewSelector;
|
|
@@ -63,7 +63,7 @@ const getBillActivities = (state, billId, billStageCode) => {
|
|
|
63
63
|
const approvalRules = (0, approvalRuleSelector_1.getApprovalRulesByIds)(approvalRuleState, billDetail.approvalRuleIds);
|
|
64
64
|
const entityApprovalStatusByIds = (0, entityApprovalStatusSelector_1.getEntityApprovalStatusByIds)(entityApprovalStatusState, billDetail.entityApprovalIds);
|
|
65
65
|
billActivities = entityApprovalStatusByIds.map((entityApprovalStatus) => {
|
|
66
|
-
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, isRealTimeApprovalEnabled, currentPendingStepIndex, } = entityApprovalStatus;
|
|
66
|
+
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, isRealTimeApprovalEnabled, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
67
67
|
const approvalRule = approvalRules.find((rule) => rule.approvalRuleId === approvalRuleId);
|
|
68
68
|
return {
|
|
69
69
|
approvalRuleId,
|
|
@@ -75,21 +75,22 @@ const getBillActivities = (state, billId, billStageCode) => {
|
|
|
75
75
|
isAdminFallbackApprover,
|
|
76
76
|
isRealTimeApprovalEnabled,
|
|
77
77
|
currentPendingStepIndex,
|
|
78
|
+
sodExcludedApproverUserId,
|
|
78
79
|
entityApprovalId: entityApprovalStatus.entityApprovalId,
|
|
79
80
|
stepsWithStatus: stepsApprovalStatus.map((step) => {
|
|
81
|
+
const actorsActivity = step.actorsActivity.map((activity) => ({
|
|
82
|
+
...activity,
|
|
83
|
+
actor: (0, userSelector_1.getUserByUserId)(userState, activity.userId),
|
|
84
|
+
}));
|
|
80
85
|
return {
|
|
81
86
|
...step,
|
|
82
87
|
actors: step.actors
|
|
83
88
|
.map((actor) => (0, userSelector_1.getUserByUserId)(userState, actor.userId))
|
|
84
89
|
.filter((user) => user != null),
|
|
85
90
|
nonUserActors: step.actors.filter((actor) => actor.userId == null && actor.type !== 'user'),
|
|
86
|
-
actorsActivity
|
|
87
|
-
return {
|
|
88
|
-
...activity,
|
|
89
|
-
actor: (0, userSelector_1.getUserByUserId)(userState, activity.userId),
|
|
90
|
-
};
|
|
91
|
-
}),
|
|
91
|
+
actorsActivity,
|
|
92
92
|
isOriginalApprovalStep: step.isOriginalApprovalStep,
|
|
93
|
+
displayPendingApproverAsAdmin: (0, helpers_1.isSodAdminFallbackEligibleForStep)(sodExcludedApproverUserId, isAdminFallbackApprover, actorsActivity),
|
|
93
94
|
};
|
|
94
95
|
}),
|
|
95
96
|
};
|
|
@@ -256,7 +257,7 @@ const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInUser) =>
|
|
|
256
257
|
let isMarkAsPaidBtnVisible = false;
|
|
257
258
|
let rejectedId = -1;
|
|
258
259
|
const stepsWithStatusData = billActivities[0].stepsWithStatus;
|
|
259
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = billActivities[0];
|
|
260
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = billActivities[0];
|
|
260
261
|
for (const [index, stepWithStatus] of stepsWithStatusData.entries()) {
|
|
261
262
|
if (stepWithStatus.action === 'require_approval') {
|
|
262
263
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
@@ -297,23 +298,42 @@ const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInUser) =>
|
|
|
297
298
|
break;
|
|
298
299
|
}
|
|
299
300
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
301
|
+
const sodBlocked = (0, helpers_1.isSodExcludedViewerBlocked)(sodExcludedApproverUserId, signedInUser?.userId, pendingStep.actorsActivity);
|
|
302
|
+
if (isAllActivitiesPending) {
|
|
303
|
+
for (const actorActivity of pendingStep.actorsActivity) {
|
|
304
|
+
if (!sodBlocked &&
|
|
305
|
+
actorActivity.actor?.userId === signedInUser?.userId) {
|
|
306
|
+
isApprovalorRejectBtnVisible = true;
|
|
307
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
305
310
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
actorActivity.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
311
|
+
}
|
|
312
|
+
if (!isApprovalorRejectBtnVisible) {
|
|
313
|
+
for (const actorActivity of pendingStep.actorsActivity) {
|
|
314
|
+
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
315
|
+
if (actorActivity.type === 'attribute' &&
|
|
316
|
+
(actorActivity.subType === 'manager' ||
|
|
317
|
+
actorActivity.subType === 'vendor_owner') &&
|
|
318
|
+
actorActivity.userId === null &&
|
|
319
|
+
isAdminFallbackApprover &&
|
|
320
|
+
isUserAdmin &&
|
|
321
|
+
signedInUser?.userId != null &&
|
|
322
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
323
|
+
isApprovalorRejectBtnVisible = true;
|
|
324
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
315
327
|
}
|
|
316
328
|
}
|
|
329
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
330
|
+
isUserAdmin &&
|
|
331
|
+
signedInUser?.userId != null &&
|
|
332
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
333
|
+
pendingStep.displayPendingApproverAsAdmin) {
|
|
334
|
+
isApprovalorRejectBtnVisible = true;
|
|
335
|
+
isMarkAsPaidBtnVisible = isLastApprovalStep;
|
|
336
|
+
}
|
|
317
337
|
}
|
|
318
338
|
}
|
|
319
339
|
}
|
|
@@ -327,23 +347,42 @@ const checkApproveRejectBtnShow = (billActivities, isUserAdmin, signedInUser) =>
|
|
|
327
347
|
break;
|
|
328
348
|
}
|
|
329
349
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
350
|
+
const sodBlocked = (0, helpers_1.isSodExcludedViewerBlocked)(sodExcludedApproverUserId, signedInUser?.userId, stepWithStatus.actorsActivity);
|
|
351
|
+
if (isAllActivitiesPending) {
|
|
352
|
+
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
353
|
+
if (!sodBlocked &&
|
|
354
|
+
actorActivity.actor?.userId === signedInUser?.userId) {
|
|
355
|
+
isApprovalorRejectBtnVisible = true;
|
|
356
|
+
isMarkAsPaidBtnVisible = true;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
335
359
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
actorActivity.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
360
|
+
}
|
|
361
|
+
if (!isApprovalorRejectBtnVisible) {
|
|
362
|
+
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
363
|
+
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
364
|
+
if (actorActivity.type === 'attribute' &&
|
|
365
|
+
(actorActivity.subType === 'manager' ||
|
|
366
|
+
actorActivity.subType === 'vendor_owner') &&
|
|
367
|
+
actorActivity.userId === null &&
|
|
368
|
+
isAdminFallbackApprover &&
|
|
369
|
+
isUserAdmin &&
|
|
370
|
+
signedInUser?.userId != null &&
|
|
371
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
372
|
+
isApprovalorRejectBtnVisible = true;
|
|
373
|
+
isMarkAsPaidBtnVisible = true;
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
345
376
|
}
|
|
346
377
|
}
|
|
378
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
379
|
+
isUserAdmin &&
|
|
380
|
+
signedInUser?.userId != null &&
|
|
381
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
382
|
+
stepWithStatus.displayPendingApproverAsAdmin) {
|
|
383
|
+
isApprovalorRejectBtnVisible = true;
|
|
384
|
+
isMarkAsPaidBtnVisible = true;
|
|
385
|
+
}
|
|
347
386
|
}
|
|
348
387
|
if (isApprovalorRejectBtnVisible) {
|
|
349
388
|
break;
|
|
@@ -297,7 +297,7 @@ const getApproversOrRejectors = (billTransaction, entityApprovalStatusState, use
|
|
|
297
297
|
};
|
|
298
298
|
if (billTransaction.entityApprovalId !== null) {
|
|
299
299
|
const entityApprovalStatus = entityApprovalStatusState.entityApprovalStatusById[billTransaction.entityApprovalId];
|
|
300
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = entityApprovalStatus;
|
|
300
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
301
301
|
const isBillSerailized = areApprovalsSerialized === true &&
|
|
302
302
|
currentPendingStepIndex != null &&
|
|
303
303
|
currentPendingStepIndex > -1;
|
|
@@ -325,23 +325,20 @@ const getApproversOrRejectors = (billTransaction, entityApprovalStatusState, use
|
|
|
325
325
|
if (isBillSerailized) {
|
|
326
326
|
requireApprovalInfo = [stepsApprovalStatus[currentPendingStepIndex]];
|
|
327
327
|
}
|
|
328
|
-
const pendingActivitiesList = [];
|
|
329
328
|
requireApprovalInfo.forEach((approvalStep) => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (isBillSerailized) {
|
|
333
|
-
pendingActivitiesList.push(...pendingActivities);
|
|
329
|
+
if (approvers.displayPendingApproverAsAdmin) {
|
|
330
|
+
return;
|
|
334
331
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
332
|
+
const pendingActivities = approvalStep.actorsActivity.filter((activity) => activity.activity === 'pending');
|
|
333
|
+
const sodDisplayAsAdmin = (0, helpers_1.isSodAdminFallbackEligibleForStep)(sodExcludedApproverUserId, isAdminFallbackApprover, approvalStep.actorsActivity);
|
|
334
|
+
const activitiesToShow = isBillSerailized
|
|
335
|
+
? pendingActivities
|
|
336
|
+
: pendingActivities.slice(0, 1);
|
|
337
|
+
if (sodDisplayAsAdmin) {
|
|
338
|
+
approvers.displayPendingApproverAsAdmin = true;
|
|
339
|
+
return;
|
|
341
340
|
}
|
|
342
|
-
|
|
343
|
-
if (pendingActivitiesList.length > 0) {
|
|
344
|
-
pendingActivitiesList.forEach((activity) => {
|
|
341
|
+
activitiesToShow.forEach((activity) => {
|
|
345
342
|
const user = (0, userSelector_1.getUserByUserId)(userState, activity.userId);
|
|
346
343
|
if (user != null) {
|
|
347
344
|
approvers.users.push(user);
|
|
@@ -353,7 +350,7 @@ const getApproversOrRejectors = (billTransaction, entityApprovalStatusState, use
|
|
|
353
350
|
}
|
|
354
351
|
}
|
|
355
352
|
});
|
|
356
|
-
}
|
|
353
|
+
});
|
|
357
354
|
}
|
|
358
355
|
}
|
|
359
356
|
}
|
|
@@ -38,7 +38,7 @@ const billPayReviewSelector_1 = require("../billPayReview/billPayReviewSelector"
|
|
|
38
38
|
const billPaySetupApproverViewSelector_1 = require("../billPaySetupApproverView/billPaySetupApproverViewSelector");
|
|
39
39
|
const previousBillsSelector_1 = require("../previousBills/previousBillsSelector");
|
|
40
40
|
const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, isZeniAccountsEnabled, billId) => {
|
|
41
|
-
const { accountListState, accountState, bankAccountState, billDetailViewState, paymentAccountListState, billTransactionState, billPayConfigState, classListState, classState, editBillDetailViewState, paymentAccountState, vendorState, tenantState, companyState, userState, commonHistoryState, contactState, paymentInstrumentState, recurringBillState, depositAccountListState, depositAccountState,
|
|
41
|
+
const { accountListState, accountState, bankAccountState, billDetailViewState, paymentAccountListState, billTransactionState, billPayConfigState, classListState, classState, editBillDetailViewState, paymentAccountState, vendorState, tenantState, companyState, userState, commonHistoryState, contactState, paymentInstrumentState, recurringBillState, depositAccountListState, depositAccountState, plaidAccountViewState, } = state;
|
|
42
42
|
const transaction = (0, get_1.default)(billTransactionState.transactionById, billId ?? '', undefined);
|
|
43
43
|
let recommendations = {};
|
|
44
44
|
if (billId != null) {
|
|
@@ -186,7 +186,6 @@ const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, isZeniAc
|
|
|
186
186
|
const fetchStateList = [
|
|
187
187
|
sourceBillDetail.fetchStatus,
|
|
188
188
|
accountListState.byReportId.billPayAccountList,
|
|
189
|
-
billPaySetupApproverViewState,
|
|
190
189
|
];
|
|
191
190
|
if ((0, tenantSelector_1.getIsAccountingClassesEnabled)(state)) {
|
|
192
191
|
fetchStateList.push(classListState);
|
|
@@ -207,7 +206,6 @@ const getEditBillDetail = (state, isVendorRecommendationFeatureEnabled, isZeniAc
|
|
|
207
206
|
else {
|
|
208
207
|
const newBillFetchStateList = [
|
|
209
208
|
accountListState.byReportId.billPayAccountList,
|
|
210
|
-
billPaySetupApproverViewState,
|
|
211
209
|
];
|
|
212
210
|
if ((0, tenantSelector_1.getIsAccountingClassesEnabled)(state)) {
|
|
213
211
|
newBillFetchStateList.push(classListState);
|
package/lib/view/spendManagement/billPay/editBillView/epics/fetchEditBillDetailPageEpic.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ import { fetchVendorTypeList } from '../../../../vendorTypeList/vendorTypeListRe
|
|
|
8
8
|
import { fetchDepositAccountList } from '../../../zeniAccounts/depositAccountList/depositAccountListReducer';
|
|
9
9
|
import { fetchPaymentAccountList } from '../../../zeniAccounts/paymentAccountList/paymentAccountListReducer';
|
|
10
10
|
import { fetchBillPayConfig } from '../../billPayConfig/billPayConfigReducer';
|
|
11
|
-
import { fetchBillPaySetupApproverView } from '../../billPaySetupApproverView/billPaySetupApproverViewReducer';
|
|
12
11
|
import { fetchBillAndInitializeLocalStore, fetchEditBillDetailPage, updateShowAutofill } from '../editBillViewReducer';
|
|
13
|
-
export type ActionType = ReturnType<typeof fetchEditBillDetailPage> | ReturnType<typeof fetchClassList> | ReturnType<typeof fetchVendorTypeList> | ReturnType<typeof fetchAccountList> | ReturnType<typeof fetchPaymentAccountList> | ReturnType<typeof fetchDepositAccountList> | ReturnType<typeof fetchBillPayConfig> | ReturnType<typeof updateShowAutofill> | ReturnType<typeof
|
|
12
|
+
export type ActionType = ReturnType<typeof fetchEditBillDetailPage> | ReturnType<typeof fetchClassList> | ReturnType<typeof fetchVendorTypeList> | ReturnType<typeof fetchAccountList> | ReturnType<typeof fetchPaymentAccountList> | ReturnType<typeof fetchDepositAccountList> | ReturnType<typeof fetchBillPayConfig> | ReturnType<typeof updateShowAutofill> | ReturnType<typeof fetchOwnerList> | ReturnType<typeof fetchBillAndInitializeLocalStore>;
|
|
14
13
|
export declare const fetchEditBillDetailPageEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>) => Observable<ActionType>;
|
|
@@ -11,7 +11,6 @@ const vendorTypeListReducer_1 = require("../../../../vendorTypeList/vendorTypeLi
|
|
|
11
11
|
const depositAccountListReducer_1 = require("../../../zeniAccounts/depositAccountList/depositAccountListReducer");
|
|
12
12
|
const paymentAccountListReducer_1 = require("../../../zeniAccounts/paymentAccountList/paymentAccountListReducer");
|
|
13
13
|
const billPayConfigReducer_1 = require("../../billPayConfig/billPayConfigReducer");
|
|
14
|
-
const billPaySetupApproverViewReducer_1 = require("../../billPaySetupApproverView/billPaySetupApproverViewReducer");
|
|
15
14
|
const editBillViewReducer_1 = require("../editBillViewReducer");
|
|
16
15
|
const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(editBillViewReducer_1.fetchEditBillDetailPage.match), (0, operators_1.mergeMap)((action) => {
|
|
17
16
|
const { cacheOverride, billId, isShowDeletedBillsEnabled, hasZeniAssistAccess, isInternationalWireEnabled, } = action.payload;
|
|
@@ -41,10 +40,6 @@ const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe((0, oper
|
|
|
41
40
|
else {
|
|
42
41
|
billDetailActions.push((0, editBillViewReducer_1.updateShowAutofill)(true));
|
|
43
42
|
}
|
|
44
|
-
// Side-fetch from the edit-bill page bootstrap. The triggering
|
|
45
|
-
// action doesn't carry the V3 flag, so we explicitly target v1
|
|
46
|
-
// here; tenants on v3 re-fetch through their own screen connector.
|
|
47
|
-
billDetailActions.push((0, billPaySetupApproverViewReducer_1.fetchBillPaySetupApproverView)(true, true, false));
|
|
48
43
|
}
|
|
49
44
|
else {
|
|
50
45
|
if (state.ownerListState.fetchState !== 'In-Progress' &&
|
|
@@ -83,15 +78,6 @@ const fetchEditBillDetailPageEpic = (actions$, state$) => actions$.pipe((0, oper
|
|
|
83
78
|
if (billId != null) {
|
|
84
79
|
billDetailActions.push((0, editBillViewReducer_1.fetchBillAndInitializeLocalStore)(billId, false, isShowDeletedBillsEnabled, hasZeniAssistAccess));
|
|
85
80
|
}
|
|
86
|
-
const approvalViewFetchState = state.billPaySetupApproverViewState.fetchState;
|
|
87
|
-
// While opening New Bill Refresh Approval Rules and Payment Accounts
|
|
88
|
-
if (approvalViewFetchState !== 'In-Progress' &&
|
|
89
|
-
approvalViewFetchState !== 'Completed') {
|
|
90
|
-
// Side-fetch from the edit-bill page bootstrap. The triggering
|
|
91
|
-
// action doesn't carry the V3 flag, so we explicitly target v1
|
|
92
|
-
// here; tenants on v3 re-fetch through their own screen connector.
|
|
93
|
-
billDetailActions.push((0, billPaySetupApproverViewReducer_1.fetchBillPaySetupApproverView)(true, true, false));
|
|
94
|
-
}
|
|
95
81
|
}
|
|
96
82
|
return (0, rxjs_1.concat)((0, rxjs_1.from)(billDetailActions));
|
|
97
83
|
}));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Amount } from '../../commonStateTypes/amount';
|
|
2
|
+
import { ID } from '../../commonStateTypes/common';
|
|
2
3
|
import { ReportIDPlusForecastID } from '../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
4
|
import { BillPayInfo, BulkProcessingStateType } from '../../entity/billPay/billTransaction/billTransactionState';
|
|
4
5
|
import { RecurringBillConfig } from '../../entity/billPay/recurringBills/recurringBillsState';
|
|
@@ -6,13 +7,16 @@ import { ReimbursementTypeCode } from '../../entity/reimbursement/reimbursementS
|
|
|
6
7
|
import { CurrentTenant } from '../../entity/tenant/tenantSelector';
|
|
7
8
|
import { RoleMap } from '../../entity/userRole/userRoleType';
|
|
8
9
|
import { ZeniDate } from '../../zeniDayJS';
|
|
9
|
-
import { BillActivity } from './billPay/billDetailView/billDetailViewSelector';
|
|
10
|
+
import { ActorActivityWithUser, BillActivity } from './billPay/billDetailView/billDetailViewSelector';
|
|
10
11
|
import { BillTransactionView } from './billPay/billList/billListSelector';
|
|
11
12
|
import { AccType, AccountTypeSubConfigCodeKeyType } from './billPay/billPayConfig/billPayConfigState';
|
|
12
13
|
import { RecurringBillConfigLocalData, RecurringBillInstance } from './billPay/editBillView/editBillViewState';
|
|
13
14
|
import { BusinessVerificationDetails, CompanyOfficersDetails } from './commonSetup/setupViewSelector';
|
|
14
15
|
import { SetupViewType } from './commonSetup/setupViewState';
|
|
15
16
|
import { RemiActivity } from './reimbursement/remiDetailView/remiDetailViewSelector';
|
|
17
|
+
export declare const isUserActorOnApprovalStep: (userId: ID, stepActorsActivity: ActorActivityWithUser[]) => boolean;
|
|
18
|
+
export declare const isSodExcludedViewerBlocked: (sodExcludedApproverUserId?: ID, signedInUserId?: ID, stepActorsActivity?: ActorActivityWithUser[]) => boolean;
|
|
19
|
+
export declare const isSodAdminFallbackEligibleForStep: (sodExcludedApproverUserId?: ID, isAdminFallbackApprover?: boolean, stepActorsActivity?: ActorActivityWithUser[]) => boolean;
|
|
16
20
|
export declare const getLatestApprovalDate: (allActivities: BillActivity[] | RemiActivity[]) => ZeniDate | undefined;
|
|
17
21
|
export declare function getSpendManagementEffectiveListPeriod(): import("../..").TimePeriod;
|
|
18
22
|
export declare const getSelectedCompanyOfficer: (verificationDetails: BusinessVerificationDetails) => CompanyOfficersDetails | undefined;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.toSameDayAchDisablementConfig = exports.checkIfLowBalance = exports.getReportIDPlusForecastIDFromSetupViewType = exports.isAwaitingMarkAsPaid = exports.isPaymentMethodOutsideZeni = exports.toAccountsPromoConfig = exports.getBulkOperationSuffix = exports.getRemiListUniqueType = exports.getBillListUniqueType = exports.isBulkProcessing = exports.getActualPaymentDate = exports.accountTypeSubConfigCodeToAccType = exports.isRecurringConfigChanged = exports.updateRecurringBillDetails = exports.getPaymentDateFromVendorReceiveDate = exports.getSelectedCompanyOfficer = exports.getLatestApprovalDate = void 0;
|
|
6
|
+
exports.toSameDayAchDisablementConfig = exports.checkIfLowBalance = exports.getReportIDPlusForecastIDFromSetupViewType = exports.isAwaitingMarkAsPaid = exports.isPaymentMethodOutsideZeni = exports.toAccountsPromoConfig = exports.getBulkOperationSuffix = exports.getRemiListUniqueType = exports.getBillListUniqueType = exports.isBulkProcessing = exports.getActualPaymentDate = exports.accountTypeSubConfigCodeToAccType = exports.isRecurringConfigChanged = exports.updateRecurringBillDetails = exports.getPaymentDateFromVendorReceiveDate = exports.getSelectedCompanyOfficer = exports.getLatestApprovalDate = exports.isSodAdminFallbackEligibleForStep = exports.isSodExcludedViewerBlocked = exports.isUserActorOnApprovalStep = void 0;
|
|
7
7
|
exports.getSpendManagementEffectiveListPeriod = getSpendManagementEffectiveListPeriod;
|
|
8
8
|
exports.showReimbursementPromoPage = showReimbursementPromoPage;
|
|
9
9
|
exports.showBillPayPromoPage = showBillPayPromoPage;
|
|
@@ -16,6 +16,23 @@ const workingDayHelper_1 = require("../../commonStateTypes/workingDayHelper");
|
|
|
16
16
|
const paymentAccountState_1 = require("../../entity/paymentAccount/paymentAccountState");
|
|
17
17
|
const userRoleType_1 = require("../../entity/userRole/userRoleType");
|
|
18
18
|
const zeniDayJS_1 = require("../../zeniDayJS");
|
|
19
|
+
const getUserActorId = (activity) => activity.actor?.userId ?? activity.userId;
|
|
20
|
+
const isUserActorOnApprovalStep = (userId, stepActorsActivity) => stepActorsActivity.some((activity) => getUserActorId(activity) === userId);
|
|
21
|
+
exports.isUserActorOnApprovalStep = isUserActorOnApprovalStep;
|
|
22
|
+
const isSodExcludedViewerBlocked = (sodExcludedApproverUserId, signedInUserId, stepActorsActivity = []) => sodExcludedApproverUserId != null &&
|
|
23
|
+
signedInUserId != null &&
|
|
24
|
+
signedInUserId === sodExcludedApproverUserId &&
|
|
25
|
+
(0, exports.isUserActorOnApprovalStep)(sodExcludedApproverUserId, stepActorsActivity);
|
|
26
|
+
exports.isSodExcludedViewerBlocked = isSodExcludedViewerBlocked;
|
|
27
|
+
const isSodAdminFallbackEligibleForStep = (sodExcludedApproverUserId, isAdminFallbackApprover, stepActorsActivity = []) => {
|
|
28
|
+
if (sodExcludedApproverUserId == null || !isAdminFallbackApprover) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const pendingResolvedApprovers = stepActorsActivity.filter((activity) => activity.activity === 'pending' && getUserActorId(activity) != null);
|
|
32
|
+
return (pendingResolvedApprovers.length > 0 &&
|
|
33
|
+
pendingResolvedApprovers.every((activity) => getUserActorId(activity) === sodExcludedApproverUserId));
|
|
34
|
+
};
|
|
35
|
+
exports.isSodAdminFallbackEligibleForStep = isSodAdminFallbackEligibleForStep;
|
|
19
36
|
const getLatestApprovalDate = (allActivities) => {
|
|
20
37
|
let allStepsWithStatus = [];
|
|
21
38
|
let allApprovedActions = [];
|
|
@@ -43,6 +43,7 @@ export interface RemiDetails extends Reimbursement {
|
|
|
43
43
|
export interface StepWithStatus extends StepWithUser {
|
|
44
44
|
actorsActivity: ActorActivityWithUser[];
|
|
45
45
|
isOriginalApprovalStep: boolean;
|
|
46
|
+
displayPendingApproverAsAdmin?: boolean;
|
|
46
47
|
}
|
|
47
48
|
export interface ActorActivityWithUser extends Actor {
|
|
48
49
|
activity: ActivityStatus;
|
|
@@ -66,6 +67,7 @@ export interface RemiActivity {
|
|
|
66
67
|
currentPendingStepIndex?: number;
|
|
67
68
|
entityApprovalId?: ID;
|
|
68
69
|
isAdminFallbackApprover?: boolean;
|
|
70
|
+
sodExcludedApproverUserId?: ID;
|
|
69
71
|
}
|
|
70
72
|
export declare const getRemiDetailView: (state: RootState, reimbursementId: ID) => RemiDetailViewSelector;
|
|
71
73
|
export declare const getRemiActivities: (state: RootState, reimbursementId: ID, billStageCode?: BillStageCodeType) => RemiActivity[];
|
|
@@ -151,7 +151,7 @@ const getRemiActivities = (state, reimbursementId, billStageCode) => {
|
|
|
151
151
|
const approvalRules = (0, approvalRuleSelector_1.getApprovalRulesByIds)(approvalRuleState, remiTransactionDetails.approvalRuleIds);
|
|
152
152
|
const entityApprovalStatusByIds = (0, entityApprovalStatusSelector_1.getEntityApprovalStatusByIds)(entityApprovalStatusState, remiTransactionDetails.entityApprovalIds);
|
|
153
153
|
remiActivities = entityApprovalStatusByIds.map((entityApprovalStatus) => {
|
|
154
|
-
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, isRealTimeApprovalEnabled, } = entityApprovalStatus;
|
|
154
|
+
const { approvalRuleId, entityType, createTime, updateTime, stepsApprovalStatus, areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, isRealTimeApprovalEnabled, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
155
155
|
const approvalRule = approvalRules.find((rule) => rule.approvalRuleId === approvalRuleId);
|
|
156
156
|
return {
|
|
157
157
|
approvalRuleId,
|
|
@@ -163,21 +163,22 @@ const getRemiActivities = (state, reimbursementId, billStageCode) => {
|
|
|
163
163
|
isAdminFallbackApprover,
|
|
164
164
|
currentPendingStepIndex,
|
|
165
165
|
isRealTimeApprovalEnabled,
|
|
166
|
+
sodExcludedApproverUserId,
|
|
166
167
|
entityApprovalId: entityApprovalStatus.entityApprovalId,
|
|
167
168
|
stepsWithStatus: stepsApprovalStatus.map((step) => {
|
|
169
|
+
const actorsActivity = step.actorsActivity.map((activity) => ({
|
|
170
|
+
...activity,
|
|
171
|
+
actor: (0, userSelector_1.getUserByUserId)(userState, activity.userId),
|
|
172
|
+
}));
|
|
168
173
|
return {
|
|
169
174
|
...step,
|
|
170
175
|
actors: step.actors
|
|
171
176
|
.map((actor) => (0, userSelector_1.getUserByUserId)(userState, actor.userId))
|
|
172
177
|
.filter((user) => user != null),
|
|
173
178
|
nonUserActors: step.actors.filter((actor) => actor.userId == null && actor.type !== 'user'),
|
|
174
|
-
actorsActivity
|
|
175
|
-
return {
|
|
176
|
-
...activity,
|
|
177
|
-
actor: (0, userSelector_1.getUserByUserId)(userState, activity.userId),
|
|
178
|
-
};
|
|
179
|
-
}),
|
|
179
|
+
actorsActivity,
|
|
180
180
|
isOriginalApprovalStep: step.isOriginalApprovalStep,
|
|
181
|
+
displayPendingApproverAsAdmin: (0, helpers_1.isSodAdminFallbackEligibleForStep)(sodExcludedApproverUserId, isAdminFallbackApprover, actorsActivity),
|
|
181
182
|
};
|
|
182
183
|
}),
|
|
183
184
|
};
|
|
@@ -191,7 +192,7 @@ const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInUser) =>
|
|
|
191
192
|
let isApprovalorRejectBtnVisible = false;
|
|
192
193
|
let rejectedId = -1;
|
|
193
194
|
const stepsWithStatusData = remiActivities[0].stepsWithStatus;
|
|
194
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = remiActivities[0];
|
|
195
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = remiActivities[0];
|
|
195
196
|
for (const [index, stepWithStatus] of stepsWithStatusData.entries()) {
|
|
196
197
|
if (stepWithStatus.action === 'require_approval') {
|
|
197
198
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
@@ -227,27 +228,39 @@ const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInUser) =>
|
|
|
227
228
|
break;
|
|
228
229
|
}
|
|
229
230
|
}
|
|
231
|
+
const sodBlocked = (0, helpers_1.isSodExcludedViewerBlocked)(sodExcludedApproverUserId, signedInUser?.userId, pendingStep.actorsActivity);
|
|
230
232
|
for (const actorActivity of pendingStep.actorsActivity) {
|
|
231
|
-
if (
|
|
233
|
+
if (!sodBlocked &&
|
|
234
|
+
actorActivity.actor?.userId === signedInUser?.userId &&
|
|
232
235
|
isAllActivitiesPending) {
|
|
233
236
|
isApprovalorRejectBtnVisible = true;
|
|
234
237
|
}
|
|
235
238
|
else if (actorActivity.subType === 'admin' &&
|
|
236
239
|
isUserAdmin &&
|
|
237
|
-
isAllActivitiesPending
|
|
240
|
+
isAllActivitiesPending &&
|
|
241
|
+
signedInUser?.userId != null &&
|
|
242
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
238
243
|
isApprovalorRejectBtnVisible = true;
|
|
239
244
|
}
|
|
240
|
-
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
241
245
|
else if (actorActivity.type === 'attribute' &&
|
|
242
246
|
(actorActivity.subType === 'manager' ||
|
|
243
247
|
actorActivity.subType === 'vendor_owner' ||
|
|
244
248
|
actorActivity.subType === 'manager_of_manager') &&
|
|
245
249
|
actorActivity.userId === null &&
|
|
246
|
-
isAdminFallbackApprover
|
|
247
|
-
isUserAdmin
|
|
250
|
+
isAdminFallbackApprover &&
|
|
251
|
+
isUserAdmin &&
|
|
252
|
+
signedInUser?.userId != null &&
|
|
253
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
248
254
|
isApprovalorRejectBtnVisible = true;
|
|
249
255
|
}
|
|
250
256
|
}
|
|
257
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
258
|
+
isUserAdmin &&
|
|
259
|
+
signedInUser?.userId != null &&
|
|
260
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
261
|
+
pendingStep.displayPendingApproverAsAdmin) {
|
|
262
|
+
isApprovalorRejectBtnVisible = true;
|
|
263
|
+
}
|
|
251
264
|
}
|
|
252
265
|
}
|
|
253
266
|
}
|
|
@@ -261,27 +274,39 @@ const checkApproveRejectBtnShow = (remiActivities, isUserAdmin, signedInUser) =>
|
|
|
261
274
|
break;
|
|
262
275
|
}
|
|
263
276
|
}
|
|
277
|
+
const sodBlocked = (0, helpers_1.isSodExcludedViewerBlocked)(sodExcludedApproverUserId, signedInUser?.userId, stepWithStatus.actorsActivity);
|
|
264
278
|
for (const actorActivity of stepWithStatus.actorsActivity) {
|
|
265
|
-
if (
|
|
279
|
+
if (!sodBlocked &&
|
|
280
|
+
actorActivity.actor?.userId === signedInUser?.userId &&
|
|
266
281
|
isAllActivitiesPending) {
|
|
267
282
|
isApprovalorRejectBtnVisible = true;
|
|
268
283
|
}
|
|
269
284
|
else if (actorActivity.subType === 'admin' &&
|
|
270
285
|
isUserAdmin &&
|
|
271
|
-
isAllActivitiesPending
|
|
286
|
+
isAllActivitiesPending &&
|
|
287
|
+
signedInUser?.userId != null &&
|
|
288
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
272
289
|
isApprovalorRejectBtnVisible = true;
|
|
273
290
|
}
|
|
274
|
-
// admin will be fallback approver if vendor-owner/manager are not assigned any user id
|
|
275
291
|
else if (actorActivity.type === 'attribute' &&
|
|
276
292
|
(actorActivity.subType === 'manager' ||
|
|
277
293
|
actorActivity.subType === 'vendor_owner' ||
|
|
278
294
|
actorActivity.subType === 'manager_of_manager') &&
|
|
279
295
|
actorActivity.userId === null &&
|
|
280
|
-
isAdminFallbackApprover
|
|
281
|
-
isUserAdmin
|
|
296
|
+
isAdminFallbackApprover &&
|
|
297
|
+
isUserAdmin &&
|
|
298
|
+
signedInUser?.userId != null &&
|
|
299
|
+
signedInUser.userId !== sodExcludedApproverUserId) {
|
|
282
300
|
isApprovalorRejectBtnVisible = true;
|
|
283
301
|
}
|
|
284
302
|
}
|
|
303
|
+
if (!isApprovalorRejectBtnVisible &&
|
|
304
|
+
isUserAdmin &&
|
|
305
|
+
signedInUser?.userId != null &&
|
|
306
|
+
signedInUser.userId !== sodExcludedApproverUserId &&
|
|
307
|
+
stepWithStatus.displayPendingApproverAsAdmin) {
|
|
308
|
+
isApprovalorRejectBtnVisible = true;
|
|
309
|
+
}
|
|
285
310
|
}
|
|
286
311
|
if (isApprovalorRejectBtnVisible) {
|
|
287
312
|
break;
|
|
@@ -216,7 +216,7 @@ const getApproversOrRejectors = (reimbursement, entityApprovalStatusState, userS
|
|
|
216
216
|
};
|
|
217
217
|
if (reimbursement.entityApprovalId !== null) {
|
|
218
218
|
const entityApprovalStatus = entityApprovalStatusState.entityApprovalStatusById[reimbursement.entityApprovalId];
|
|
219
|
-
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, } = entityApprovalStatus;
|
|
219
|
+
const { areApprovalsSerialized, isAdminFallbackApprover, currentPendingStepIndex, sodExcludedApproverUserId, } = entityApprovalStatus;
|
|
220
220
|
const isReimbursementSerailized = areApprovalsSerialized === true &&
|
|
221
221
|
currentPendingStepIndex != null &&
|
|
222
222
|
currentPendingStepIndex > -1;
|
|
@@ -244,23 +244,20 @@ const getApproversOrRejectors = (reimbursement, entityApprovalStatusState, userS
|
|
|
244
244
|
if (isReimbursementSerailized) {
|
|
245
245
|
requireApprovalInfo = [stepsApprovalStatus[currentPendingStepIndex]];
|
|
246
246
|
}
|
|
247
|
-
const pendingActivitiesList = [];
|
|
248
247
|
requireApprovalInfo.forEach((approvalStep) => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (isReimbursementSerailized) {
|
|
252
|
-
pendingActivitiesList.push(...pendingActivities);
|
|
248
|
+
if (approvers.displayPendingApproverAsAdmin) {
|
|
249
|
+
return;
|
|
253
250
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
251
|
+
const pendingActivities = approvalStep.actorsActivity.filter((activity) => activity.activity === 'pending');
|
|
252
|
+
const sodDisplayAsAdmin = (0, helpers_1.isSodAdminFallbackEligibleForStep)(sodExcludedApproverUserId, isAdminFallbackApprover, approvalStep.actorsActivity);
|
|
253
|
+
const activitiesToShow = isReimbursementSerailized
|
|
254
|
+
? pendingActivities
|
|
255
|
+
: pendingActivities.slice(0, 1);
|
|
256
|
+
if (sodDisplayAsAdmin) {
|
|
257
|
+
approvers.displayPendingApproverAsAdmin = true;
|
|
258
|
+
return;
|
|
260
259
|
}
|
|
261
|
-
|
|
262
|
-
if (pendingActivitiesList.length > 0) {
|
|
263
|
-
pendingActivitiesList.forEach((activity) => {
|
|
260
|
+
activitiesToShow.forEach((activity) => {
|
|
264
261
|
const user = (0, userSelector_1.getUserByUserId)(userState, activity.userId);
|
|
265
262
|
if (user != null) {
|
|
266
263
|
approvers.users.push(user);
|
|
@@ -272,7 +269,7 @@ const getApproversOrRejectors = (reimbursement, entityApprovalStatusState, userS
|
|
|
272
269
|
}
|
|
273
270
|
}
|
|
274
271
|
});
|
|
275
|
-
}
|
|
272
|
+
});
|
|
276
273
|
}
|
|
277
274
|
}
|
|
278
275
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.67",
|
|
4
4
|
"description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/esm/index.js",
|