@zeniai/client-epic-state 5.0.53 → 5.0.55-betaAR1
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/approvalRulePayload.d.ts +27 -5
- package/lib/entity/approvalRule/approvalRulePayload.js +131 -10
- package/lib/entity/approvalRule/approvalRuleSelector.d.ts +25 -1
- package/lib/entity/approvalRule/approvalRuleSelector.js +40 -0
- package/lib/entity/approvalRule/approvalRuleState.d.ts +48 -7
- package/lib/entity/tenant/epic/deleteConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/epic/saveAPIKeyConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/epic/saveConnectorCredentialsEpic.d.ts +21 -0
- package/lib/entity/tenant/epic/saveConnectorCredentialsEpic.js +42 -0
- package/lib/entity/tenant/epic/saveOAuthConnectionEpic.d.ts +1 -1
- package/lib/entity/tenant/tenantReducer.d.ts +64 -16
- package/lib/entity/tenant/tenantReducer.js +86 -7
- package/lib/entity/tenant/tenantState.d.ts +3 -1
- package/lib/epic.js +2 -1
- package/lib/esm/entity/approvalRule/approvalRulePayload.js +131 -10
- package/lib/esm/entity/approvalRule/approvalRuleSelector.js +35 -0
- package/lib/esm/entity/tenant/epic/saveConnectorCredentialsEpic.js +38 -0
- package/lib/esm/entity/tenant/tenantReducer.js +84 -5
- package/lib/esm/epic.js +2 -1
- package/lib/esm/index.js +4 -3
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +5 -7
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +46 -16
- package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +7 -2
- package/lib/esm/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +5 -7
- package/lib/esm/view/spendManagement/zeniAccounts/depositAccountDetail/depositAccountDetailSelector.js +1 -1
- package/lib/esm/view/spendManagement/zeniAccounts/depositAccountDetail/fetchDepositAccountDetailEpic.js +7 -2
- package/lib/index.d.ts +6 -4
- package/lib/index.js +38 -31
- package/lib/tsconfig.typecheck.tsbuildinfo +1 -1
- package/lib/view/companyTaskManagerView/companyTaskManagerViewReducer.d.ts +2 -2
- package/lib/view/companyView/types/cockpitTypes.d.ts +1 -1
- package/lib/view/people/peopleTypes.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +4 -6
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.d.ts +1 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +46 -16
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonState.d.ts +15 -3
- package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +7 -2
- package/lib/view/spendManagement/chargeCards/chargeCardList/chargeCardList.d.ts +1 -1
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +4 -6
- package/lib/view/spendManagement/zeniAccounts/depositAccountDetail/depositAccountDetailSelector.js +1 -1
- package/lib/view/spendManagement/zeniAccounts/depositAccountDetail/fetchDepositAccountDetailEpic.js +7 -2
- package/lib/view/taskManager/taskListView/taskList.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { ApprovalRule } from './approvalRuleState';
|
|
2
|
+
/**
|
|
3
|
+
* Condition Payload — one entry inside criteria.conditions[].
|
|
4
|
+
*
|
|
5
|
+
* field examples: 'amount' | 'vendor_id' | 'department_id'
|
|
6
|
+
* type examples: 'gte' | 'lte' | 'eq' | 'in' | 'not_in'
|
|
7
|
+
* value: number for amount comparisons; string[] for in / not_in lookups.
|
|
8
|
+
*/
|
|
9
|
+
export interface ConditionPayload {
|
|
10
|
+
field: string;
|
|
11
|
+
type: string;
|
|
12
|
+
value: number | string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Criteria Payload — list of conditions joined by `criteria_operator`.
|
|
16
|
+
*
|
|
17
|
+
* `currency_code` / `currency_symbol` apply to amount conditions inside
|
|
18
|
+
* `conditions[]`. Kept here pending confirmation that they should remain.
|
|
19
|
+
*/
|
|
2
20
|
export interface CriteriaPayload {
|
|
21
|
+
conditions: ConditionPayload[];
|
|
22
|
+
criteria_operator: string;
|
|
3
23
|
currency_code: string;
|
|
4
24
|
currency_symbol: string;
|
|
5
|
-
min: number;
|
|
6
|
-
range_entity: string;
|
|
7
|
-
type: string;
|
|
8
|
-
max?: number | null;
|
|
9
25
|
}
|
|
10
26
|
export interface ActorPayload {
|
|
11
27
|
type: string;
|
|
@@ -25,11 +41,17 @@ export interface StepPayload {
|
|
|
25
41
|
export interface ApprovalRulePayload {
|
|
26
42
|
approval_rule_id: string;
|
|
27
43
|
create_time: string;
|
|
28
|
-
criteria: CriteriaPayload
|
|
44
|
+
criteria: CriteriaPayload;
|
|
29
45
|
entity_type: string;
|
|
30
46
|
name: string | null;
|
|
31
47
|
steps: StepPayload[];
|
|
32
48
|
update_time: string;
|
|
49
|
+
are_approvals_serialized?: boolean;
|
|
50
|
+
description?: string | null;
|
|
51
|
+
is_fallback?: boolean;
|
|
52
|
+
pending_approvals_count?: number;
|
|
53
|
+
pending_entity_approval_update_status?: string;
|
|
54
|
+
priority?: number;
|
|
33
55
|
version?: number | string;
|
|
34
56
|
}
|
|
35
57
|
/**
|
|
@@ -17,19 +17,140 @@ const toApprovalRule = (payload) => ({
|
|
|
17
17
|
version: payload.version,
|
|
18
18
|
criteria: toApprovalCriteria(payload.criteria),
|
|
19
19
|
steps: toApprovalSteps(payload.steps),
|
|
20
|
+
description: payload.description ?? undefined,
|
|
21
|
+
priority: payload.priority,
|
|
22
|
+
isFallback: payload.is_fallback ?? false,
|
|
23
|
+
// separationOfDuties: backend doesn't ship this field yet; left undefined
|
|
24
|
+
// until the spec is finalized.
|
|
25
|
+
areApprovalsSerialized: payload.are_approvals_serialized,
|
|
26
|
+
pendingApprovalsCount: payload.pending_approvals_count,
|
|
27
|
+
pendingEntityApprovalUpdateStatus: payload.pending_entity_approval_update_status,
|
|
20
28
|
});
|
|
21
29
|
exports.toApprovalRule = toApprovalRule;
|
|
30
|
+
/**
|
|
31
|
+
* Maps the wire-level criteria block into the state-side discriminated
|
|
32
|
+
* `Criteria[]` union.
|
|
33
|
+
*
|
|
34
|
+
* The wire keeps each condition as a flat row inside `conditions[]`.
|
|
35
|
+
* Amount comparisons can show up as a `gte` only, a `lte` only, or a
|
|
36
|
+
* `gte` + `lte` pair — those collapse into a single AmountCriteria whose
|
|
37
|
+
* `comparator` is `greater_than`, `less_than`, or `range` respectively.
|
|
38
|
+
*
|
|
39
|
+
* Vendor and department conditions map one-to-one: `in` becomes `is`,
|
|
40
|
+
* `not_in` becomes `is_not`.
|
|
41
|
+
*
|
|
42
|
+
* Resilient to two forms of upstream drift:
|
|
43
|
+
* - Missing / null criteria → returns [].
|
|
44
|
+
* - Legacy criteria shape (array of amount-range objects, the pre-3.0
|
|
45
|
+
* wire) → converted to an AmountCriteria so existing rules in production
|
|
46
|
+
* still render while the backend rolls out.
|
|
47
|
+
*/
|
|
22
48
|
const toApprovalCriteria = (payload) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
49
|
+
if (payload == null) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(payload)) {
|
|
53
|
+
// Legacy pre-3.0 wire: an array of amount-range entries.
|
|
54
|
+
return legacyAmountRangeToCriteria(payload);
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(payload.conditions)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const results = [];
|
|
60
|
+
const amountCriteria = toAmountCriteria(payload);
|
|
61
|
+
if (amountCriteria != null) {
|
|
62
|
+
results.push(amountCriteria);
|
|
63
|
+
}
|
|
64
|
+
payload.conditions
|
|
65
|
+
.filter((condition) => condition.field === 'vendor_id')
|
|
66
|
+
.forEach((condition) => {
|
|
67
|
+
const vendor = toVendorCriteria(condition);
|
|
68
|
+
if (vendor != null) {
|
|
69
|
+
results.push(vendor);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
payload.conditions
|
|
73
|
+
.filter((condition) => condition.field === 'department_id')
|
|
74
|
+
.forEach((condition) => {
|
|
75
|
+
const department = toDepartmentCriteria(condition);
|
|
76
|
+
if (department != null) {
|
|
77
|
+
results.push(department);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return results;
|
|
81
|
+
};
|
|
82
|
+
const legacyAmountRangeToCriteria = (legacy) => {
|
|
83
|
+
if (legacy.length === 0) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const first = legacy[0] ?? {};
|
|
87
|
+
const currency = first.currency_code ?? 'USD';
|
|
88
|
+
const symbol = first.currency_symbol ?? '$';
|
|
89
|
+
const min = typeof first.min === 'number'
|
|
90
|
+
? (0, amount_1.toAmount)(first.min, currency, symbol)
|
|
91
|
+
: undefined;
|
|
92
|
+
const max = typeof first.max === 'number'
|
|
93
|
+
? (0, amount_1.toAmount)(first.max, currency, symbol)
|
|
94
|
+
: undefined;
|
|
95
|
+
if (min == null && max == null) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
const comparator = min != null && max != null
|
|
99
|
+
? 'range'
|
|
100
|
+
: min != null
|
|
101
|
+
? 'greater_than'
|
|
102
|
+
: 'less_than';
|
|
103
|
+
return [{ type: 'amount', comparator, min, max }];
|
|
104
|
+
};
|
|
105
|
+
const toAmountCriteria = (payload) => {
|
|
106
|
+
if (!Array.isArray(payload.conditions)) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
const amountConditions = payload.conditions.filter((condition) => condition.field === 'amount');
|
|
110
|
+
const gteCondition = amountConditions.find((condition) => condition.type === 'gte' || condition.type === 'eq');
|
|
111
|
+
const lteCondition = amountConditions.find((condition) => condition.type === 'lte');
|
|
112
|
+
if (gteCondition == null && lteCondition == null) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const currencyCode = payload.currency_code ?? 'USD';
|
|
116
|
+
const currencySymbol = payload.currency_symbol ?? '$';
|
|
117
|
+
const min = typeof gteCondition?.value === 'number'
|
|
118
|
+
? (0, amount_1.toAmount)(gteCondition.value, currencyCode, currencySymbol)
|
|
119
|
+
: undefined;
|
|
120
|
+
const max = typeof lteCondition?.value === 'number'
|
|
121
|
+
? (0, amount_1.toAmount)(lteCondition.value, currencyCode, currencySymbol)
|
|
122
|
+
: undefined;
|
|
123
|
+
let comparator;
|
|
124
|
+
if (min != null && max != null) {
|
|
125
|
+
comparator = 'range';
|
|
126
|
+
}
|
|
127
|
+
else if (min != null) {
|
|
128
|
+
comparator = 'greater_than';
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
comparator = 'less_than';
|
|
132
|
+
}
|
|
133
|
+
return { type: 'amount', comparator, min, max };
|
|
134
|
+
};
|
|
135
|
+
const toVendorCriteria = (condition) => {
|
|
136
|
+
if (!Array.isArray(condition.value)) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
type: 'vendor',
|
|
141
|
+
operator: condition.type === 'not_in' ? 'is_not' : 'is',
|
|
142
|
+
vendorIds: condition.value,
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
const toDepartmentCriteria = (condition) => {
|
|
146
|
+
if (!Array.isArray(condition.value)) {
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
type: 'department',
|
|
151
|
+
operator: condition.type === 'not_in' ? 'is_not' : 'is',
|
|
152
|
+
departmentIds: condition.value,
|
|
153
|
+
};
|
|
33
154
|
};
|
|
34
155
|
const toApprovalSteps = (payload) => {
|
|
35
156
|
return payload.map((step) => ({
|
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
import { ID } from '../../commonStateTypes/common';
|
|
2
|
-
import {
|
|
2
|
+
import { EntityType } from '../entityApprovalStatus/entityApprovalStatusState';
|
|
3
|
+
import { AmountCriteria, ApprovalRule, ApprovalRuleState, Criteria, DepartmentCriteria, VendorCriteria } from './approvalRuleState';
|
|
3
4
|
export declare function getApprovalRuleById(approvalRuleState: ApprovalRuleState, approvalRuleId: ID): ApprovalRule | undefined;
|
|
4
5
|
export declare function getApprovalRulesByIds(approvalRuleState: ApprovalRuleState, approvalRuleIds: ID[]): ApprovalRule[];
|
|
6
|
+
/**
|
|
7
|
+
* Returns the amount-range portion of a rule's criteria, if any.
|
|
8
|
+
*
|
|
9
|
+
* Use this whenever a caller needs to read amount min/max from the new
|
|
10
|
+
* discriminated `Criteria` union without inlining a type guard.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getAmountCriteria(criteria: Criteria[]): AmountCriteria | undefined;
|
|
13
|
+
export declare function getVendorCriteria(criteria: Criteria[]): VendorCriteria | undefined;
|
|
14
|
+
export declare function getDepartmentCriteria(criteria: Criteria[]): DepartmentCriteria | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Returns all rules of the given entityType, sorted by `priority` ascending.
|
|
17
|
+
*
|
|
18
|
+
* Rules without a `priority` value sort to the end (treated as Infinity).
|
|
19
|
+
* Use this for the list page where rules render in evaluation order.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getApprovalRulesByEntityType(approvalRuleState: ApprovalRuleState, entityType: EntityType): ApprovalRule[];
|
|
22
|
+
/**
|
|
23
|
+
* Returns the tenant's fallback rule for the given entityType, if one exists.
|
|
24
|
+
*
|
|
25
|
+
* The fallback rule is shown by the "fallback engine active" banner on the
|
|
26
|
+
* list page and is used to handle bills/reimbursements that match no other rule.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getFallbackApprovalRule(approvalRuleState: ApprovalRuleState, entityType: EntityType): ApprovalRule | undefined;
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getApprovalRuleById = getApprovalRuleById;
|
|
4
4
|
exports.getApprovalRulesByIds = getApprovalRulesByIds;
|
|
5
|
+
exports.getAmountCriteria = getAmountCriteria;
|
|
6
|
+
exports.getVendorCriteria = getVendorCriteria;
|
|
7
|
+
exports.getDepartmentCriteria = getDepartmentCriteria;
|
|
8
|
+
exports.getApprovalRulesByEntityType = getApprovalRulesByEntityType;
|
|
9
|
+
exports.getFallbackApprovalRule = getFallbackApprovalRule;
|
|
5
10
|
function getApprovalRuleById(approvalRuleState, approvalRuleId) {
|
|
6
11
|
return approvalRuleState.approvalRuleById[approvalRuleId] ?? undefined;
|
|
7
12
|
}
|
|
@@ -11,3 +16,38 @@ function getApprovalRulesByIds(approvalRuleState, approvalRuleIds) {
|
|
|
11
16
|
.filter((value) => value != null);
|
|
12
17
|
return approvalRulesByIds;
|
|
13
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns the amount-range portion of a rule's criteria, if any.
|
|
21
|
+
*
|
|
22
|
+
* Use this whenever a caller needs to read amount min/max from the new
|
|
23
|
+
* discriminated `Criteria` union without inlining a type guard.
|
|
24
|
+
*/
|
|
25
|
+
function getAmountCriteria(criteria) {
|
|
26
|
+
return criteria.find((c) => c.type === 'amount');
|
|
27
|
+
}
|
|
28
|
+
function getVendorCriteria(criteria) {
|
|
29
|
+
return criteria.find((c) => c.type === 'vendor');
|
|
30
|
+
}
|
|
31
|
+
function getDepartmentCriteria(criteria) {
|
|
32
|
+
return criteria.find((c) => c.type === 'department');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns all rules of the given entityType, sorted by `priority` ascending.
|
|
36
|
+
*
|
|
37
|
+
* Rules without a `priority` value sort to the end (treated as Infinity).
|
|
38
|
+
* Use this for the list page where rules render in evaluation order.
|
|
39
|
+
*/
|
|
40
|
+
function getApprovalRulesByEntityType(approvalRuleState, entityType) {
|
|
41
|
+
return Object.values(approvalRuleState.approvalRuleById)
|
|
42
|
+
.filter((rule) => rule.entityType === entityType)
|
|
43
|
+
.sort((a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns the tenant's fallback rule for the given entityType, if one exists.
|
|
47
|
+
*
|
|
48
|
+
* The fallback rule is shown by the "fallback engine active" banner on the
|
|
49
|
+
* list page and is used to handle bills/reimbursements that match no other rule.
|
|
50
|
+
*/
|
|
51
|
+
function getFallbackApprovalRule(approvalRuleState, entityType) {
|
|
52
|
+
return Object.values(approvalRuleState.approvalRuleById).find((rule) => rule.entityType === entityType && rule.isFallback === true);
|
|
53
|
+
}
|
|
@@ -25,14 +25,37 @@ export interface Actor {
|
|
|
25
25
|
subType?: AttributeType | RoleType;
|
|
26
26
|
userId?: ID;
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Approval rule criteria — discriminated union over the three condition
|
|
30
|
+
* types the wire format supports: amount, vendor, and department.
|
|
31
|
+
*
|
|
32
|
+
* State-side, each rule carries a `Criteria[]` with at most one variant of
|
|
33
|
+
* each kind (e.g. one AmountCriteria + one VendorCriteria + one DepartmentCriteria).
|
|
34
|
+
*
|
|
35
|
+
* Form-side, the rule create/edit form uses `ApprovalRuleFormCriteria`
|
|
36
|
+
* (defined in commonState) — a structured object with named slots for
|
|
37
|
+
* amount/vendor/department. Epics translate between the two.
|
|
38
|
+
*/
|
|
39
|
+
export type AmountComparator = 'greater_than' | 'less_than' | 'range';
|
|
40
|
+
export interface AmountCriteria {
|
|
41
|
+
comparator: AmountComparator;
|
|
42
|
+
type: 'amount';
|
|
43
|
+
/** Upper bound. Present for `less_than` and `range`. */
|
|
44
|
+
max?: Amount;
|
|
45
|
+
/** Lower bound. Present for `greater_than` and `range`. */
|
|
46
|
+
min?: Amount;
|
|
47
|
+
}
|
|
48
|
+
export interface VendorCriteria {
|
|
49
|
+
operator: 'is' | 'is_not';
|
|
50
|
+
type: 'vendor';
|
|
51
|
+
vendorIds: ID[];
|
|
52
|
+
}
|
|
53
|
+
export interface DepartmentCriteria {
|
|
54
|
+
departmentIds: ID[];
|
|
55
|
+
operator: 'is' | 'is_not';
|
|
56
|
+
type: 'department';
|
|
35
57
|
}
|
|
58
|
+
export type Criteria = AmountCriteria | VendorCriteria | DepartmentCriteria;
|
|
36
59
|
export interface Step {
|
|
37
60
|
actors: Actor[];
|
|
38
61
|
operator: StepOperatorType;
|
|
@@ -51,7 +74,25 @@ export interface ApprovalRule {
|
|
|
51
74
|
entityType: EntityType;
|
|
52
75
|
steps: Step[];
|
|
53
76
|
updateTime: ZeniDate;
|
|
77
|
+
/** Backend bookkeeping: whether approval steps must run serialized. */
|
|
78
|
+
areApprovalsSerialized?: boolean;
|
|
79
|
+
/** Free-text description shown beneath the rule name on the list page. */
|
|
80
|
+
description?: string;
|
|
81
|
+
/** True when this rule is the tenant's default fallback rule. */
|
|
82
|
+
isFallback?: boolean;
|
|
54
83
|
name?: string;
|
|
84
|
+
/** Backend bookkeeping: number of entities currently pending against this rule. */
|
|
85
|
+
pendingApprovalsCount?: number;
|
|
86
|
+
/** Backend bookkeeping: status of background updates against this rule. */
|
|
87
|
+
pendingEntityApprovalUpdateStatus?: string;
|
|
88
|
+
/** Rule's position in the evaluation order; lower number = higher priority. */
|
|
89
|
+
priority?: number;
|
|
90
|
+
/**
|
|
91
|
+
* When on, the creator of a bill/reimbursement cannot auto-approve
|
|
92
|
+
* their own request even if they are also an approver. Backend spec
|
|
93
|
+
* is still pending — kept optional for now.
|
|
94
|
+
*/
|
|
95
|
+
separationOfDuties?: boolean;
|
|
55
96
|
version?: number | string;
|
|
56
97
|
}
|
|
57
98
|
export interface Approvers {
|
|
@@ -7,7 +7,7 @@ export declare const deleteConnectionEpic: (actions$: ActionsObservable<ActionTy
|
|
|
7
7
|
payload: {
|
|
8
8
|
tenantId: string;
|
|
9
9
|
connectionId: string;
|
|
10
|
-
connectionType: "revenue";
|
|
10
|
+
connectionType: "revenue" | "payments";
|
|
11
11
|
};
|
|
12
12
|
type: "tenant/deleteConnectionSuccess";
|
|
13
13
|
} | {
|
|
@@ -6,7 +6,7 @@ export type ActionType = ReturnType<typeof saveAPIKeyConnection> | ReturnType<ty
|
|
|
6
6
|
export declare const saveAPIKeyConnectionEpic: (actions$: ActionsObservable<ActionType>, _: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<{
|
|
7
7
|
payload: {
|
|
8
8
|
tenantId: string;
|
|
9
|
-
connectionType: "revenue";
|
|
9
|
+
connectionType: "revenue" | "payments";
|
|
10
10
|
connectionPayload: import("../tenantPayload").ConnectionDataPayload;
|
|
11
11
|
};
|
|
12
12
|
type: "tenant/saveAPIKeyConnectionSuccess";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ActionsObservable, StateObservable } from 'redux-observable';
|
|
2
|
+
import { RootState } from '../../../reducer';
|
|
3
|
+
import { ZeniAPI } from '../../../zeniAPI';
|
|
4
|
+
import { saveConnectorCredentials, saveConnectorCredentialsFailure, saveConnectorCredentialsSuccess } from '../tenantReducer';
|
|
5
|
+
export type ActionType = ReturnType<typeof saveConnectorCredentials> | ReturnType<typeof saveConnectorCredentialsSuccess> | ReturnType<typeof saveConnectorCredentialsFailure>;
|
|
6
|
+
export declare const saveConnectorCredentialsEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<{
|
|
7
|
+
payload: {
|
|
8
|
+
tenantId: string;
|
|
9
|
+
connectionType: "revenue" | "payments";
|
|
10
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
11
|
+
connectionPayload: import("../tenantPayload").ConnectionDataPayload;
|
|
12
|
+
};
|
|
13
|
+
type: "tenant/saveConnectorCredentialsSuccess";
|
|
14
|
+
} | {
|
|
15
|
+
payload: {
|
|
16
|
+
tenantId: string;
|
|
17
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
18
|
+
status: import("../../../responsePayload").ZeniAPIStatus<Record<string, unknown>>;
|
|
19
|
+
};
|
|
20
|
+
type: "tenant/saveConnectorCredentialsFailure";
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.saveConnectorCredentialsEpic = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const responsePayload_1 = require("../../../responsePayload");
|
|
7
|
+
const tenantReducer_1 = require("../tenantReducer");
|
|
8
|
+
// Backs the new POST /1.0/connectors/<slug>/credentials endpoint used by
|
|
9
|
+
// Phase 1 connectors (Stripe + Mercury api_key, PayPal client_credentials).
|
|
10
|
+
// The endpoint is slug-keyed and creates-or-updates the Connection row, so the
|
|
11
|
+
// FE doesn't need a connection_id in the URL. The credentials payload is
|
|
12
|
+
// connector-specific (api_key, or client_id+client_secret) and is forwarded
|
|
13
|
+
// verbatim to the BE — connector-side validation lives in
|
|
14
|
+
// prepare_credential_update_args on the tenant service.
|
|
15
|
+
const saveConnectorCredentialsEpic = (actions$,
|
|
16
|
+
// Underscore prefix marks the parameter as intentionally unused today but
|
|
17
|
+
// names what it will become — when we wire an in-progress guard (so a
|
|
18
|
+
// second save click can't `switchMap`-cancel an in-flight save and leave
|
|
19
|
+
// the BE in an indeterminate state), drop the underscore and read state
|
|
20
|
+
// here.
|
|
21
|
+
_state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(tenantReducer_1.saveConnectorCredentials.match), (0, operators_1.switchMap)((action) => zeniAPI
|
|
22
|
+
.postAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/connectors/${action.payload.connectionName}/credentials`, action.payload.credentials, { 'zeni-tenant-id': action.payload.tenantId })
|
|
23
|
+
.pipe((0, operators_1.mergeMap)((response) => {
|
|
24
|
+
if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
|
|
25
|
+
return (0, rxjs_1.from)([
|
|
26
|
+
(0, tenantReducer_1.saveConnectorCredentialsSuccess)(action.payload.tenantId, action.payload.connectionType, action.payload.connectionName, response.data),
|
|
27
|
+
]);
|
|
28
|
+
}
|
|
29
|
+
const status = response.status ??
|
|
30
|
+
(0, responsePayload_1.createZeniAPIStatus)('Failed to save connection. Please try again.');
|
|
31
|
+
return (0, rxjs_1.from)([
|
|
32
|
+
(0, tenantReducer_1.saveConnectorCredentialsFailure)(action.payload.tenantId, action.payload.connectionName, status),
|
|
33
|
+
]);
|
|
34
|
+
}), (0, operators_1.catchError)((error) => {
|
|
35
|
+
const message = error instanceof Error
|
|
36
|
+
? error.message
|
|
37
|
+
: 'Unexpected error saving connection.';
|
|
38
|
+
return (0, rxjs_1.from)([
|
|
39
|
+
(0, tenantReducer_1.saveConnectorCredentialsFailure)(action.payload.tenantId, action.payload.connectionName, (0, responsePayload_1.createZeniAPIStatus)(message)),
|
|
40
|
+
]);
|
|
41
|
+
}))));
|
|
42
|
+
exports.saveConnectorCredentialsEpic = saveConnectorCredentialsEpic;
|
|
@@ -6,7 +6,7 @@ export type ActionType = ReturnType<typeof saveOAuthConnection> | ReturnType<typ
|
|
|
6
6
|
export declare const saveOAuthConnectionEpic: (actions$: ActionsObservable<ActionType>, _: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<{
|
|
7
7
|
payload: {
|
|
8
8
|
tenantId: string;
|
|
9
|
-
connectionType: "revenue";
|
|
9
|
+
connectionType: "revenue" | "payments";
|
|
10
10
|
connectionPayload: import("../tenantPayload").ConnectionDataPayload;
|
|
11
11
|
};
|
|
12
12
|
type: "tenant/saveOAuthConnectionSuccess";
|
|
@@ -13,10 +13,27 @@ export interface DoSignInPayload {
|
|
|
13
13
|
redirectUri: ZeniUrl;
|
|
14
14
|
sourceUri: ZeniUrl;
|
|
15
15
|
}
|
|
16
|
-
export declare const toExternalIntegrationType: (v: string) => "revenue";
|
|
16
|
+
export declare const toExternalIntegrationType: (v: string) => "revenue" | "payments";
|
|
17
17
|
export type ExternalIntegrationType = ReturnType<typeof toExternalIntegrationType>;
|
|
18
|
-
export declare const toExternalSupportedTool: (v: string) => "chargebee" | "hubspot";
|
|
18
|
+
export declare const toExternalSupportedTool: (v: string) => "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
19
19
|
export type ExternalSupportedTool = ReturnType<typeof toExternalSupportedTool>;
|
|
20
|
+
export type ConnectorCredentialsBySlug = {
|
|
21
|
+
connectionName: 'stripe';
|
|
22
|
+
credentials: {
|
|
23
|
+
api_key: string;
|
|
24
|
+
};
|
|
25
|
+
} | {
|
|
26
|
+
connectionName: 'mercury';
|
|
27
|
+
credentials: {
|
|
28
|
+
api_key: string;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
connectionName: 'paypal';
|
|
32
|
+
credentials: {
|
|
33
|
+
client_id: string;
|
|
34
|
+
client_secret: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
20
37
|
export declare const initialState: TenantState;
|
|
21
38
|
export declare const updateTenants: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenants: TenantPayload[], userTenantPayload?: TenantUserPayload | undefined, tenantUpdated?: any], {
|
|
22
39
|
tenants: TenantPayload[];
|
|
@@ -84,26 +101,26 @@ export declare const updateTenants: import("@reduxjs/toolkit").ActionCreatorWith
|
|
|
84
101
|
}, "tenant/fetchExternalConnectionsFailure", never, never>, fetchExternalConnectionsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, externalConnections: ConnectionsPayload], {
|
|
85
102
|
tenantId: string;
|
|
86
103
|
externalConnections: ConnectionsPayload;
|
|
87
|
-
}, "tenant/fetchExternalConnectionsSuccess", never, never>, saveAPIKeyConnection: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue", connectionName: "chargebee" | "hubspot", credentials: {
|
|
104
|
+
}, "tenant/fetchExternalConnectionsSuccess", never, never>, saveAPIKeyConnection: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue" | "payments", connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal", credentials: {
|
|
88
105
|
api_key: string;
|
|
89
106
|
site: string;
|
|
90
107
|
}], {
|
|
91
108
|
tenantId: string;
|
|
92
109
|
connectionId: string;
|
|
93
|
-
connectionType: "revenue";
|
|
94
|
-
connectionName: "chargebee" | "hubspot";
|
|
110
|
+
connectionType: "revenue" | "payments";
|
|
111
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
95
112
|
credentials: {
|
|
96
113
|
api_key: string;
|
|
97
114
|
site: string;
|
|
98
115
|
};
|
|
99
|
-
}, "tenant/saveAPIKeyConnection", never, never>, saveAPIKeyConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue", connectionPayload: ConnectionDataPayload], {
|
|
116
|
+
}, "tenant/saveAPIKeyConnection", never, never>, saveAPIKeyConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue" | "payments", connectionPayload: ConnectionDataPayload], {
|
|
100
117
|
tenantId: string;
|
|
101
|
-
connectionType: "revenue";
|
|
118
|
+
connectionType: "revenue" | "payments";
|
|
102
119
|
connectionPayload: ConnectionDataPayload;
|
|
103
120
|
}, "tenant/saveAPIKeyConnectionSuccess", never, never>, saveAPIKeyConnectionFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, status: ZeniAPIStatus<Record<string, unknown>>], {
|
|
104
121
|
tenantId: string;
|
|
105
122
|
status: ZeniAPIStatus<Record<string, unknown>>;
|
|
106
|
-
}, "tenant/saveAPIKeyConnectionFailure", never, never>, saveOAuthConnection: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue", connectionName: "chargebee" | "hubspot", credentials: {
|
|
123
|
+
}, "tenant/saveAPIKeyConnectionFailure", never, never>, saveOAuthConnection: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue" | "payments", connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal", credentials: {
|
|
107
124
|
authorization_code: string;
|
|
108
125
|
client_id: string;
|
|
109
126
|
client_secret: string;
|
|
@@ -111,29 +128,60 @@ export declare const updateTenants: import("@reduxjs/toolkit").ActionCreatorWith
|
|
|
111
128
|
}], {
|
|
112
129
|
tenantId: string;
|
|
113
130
|
connectionId: string;
|
|
114
|
-
connectionType: "revenue";
|
|
115
|
-
connectionName: "chargebee" | "hubspot";
|
|
131
|
+
connectionType: "revenue" | "payments";
|
|
132
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
116
133
|
credentials: {
|
|
117
134
|
authorization_code: string;
|
|
118
135
|
client_id: string;
|
|
119
136
|
client_secret: string;
|
|
120
137
|
redirect_uri: string;
|
|
121
138
|
};
|
|
122
|
-
}, "tenant/saveOAuthConnection", never, never>, saveOAuthConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue", connectionPayload: ConnectionDataPayload], {
|
|
139
|
+
}, "tenant/saveOAuthConnection", never, never>, saveOAuthConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue" | "payments", connectionPayload: ConnectionDataPayload], {
|
|
123
140
|
tenantId: string;
|
|
124
|
-
connectionType: "revenue";
|
|
141
|
+
connectionType: "revenue" | "payments";
|
|
125
142
|
connectionPayload: ConnectionDataPayload;
|
|
126
143
|
}, "tenant/saveOAuthConnectionSuccess", never, never>, saveOAuthConnectionFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, status: ZeniAPIStatus<Record<string, unknown>>], {
|
|
127
144
|
tenantId: string;
|
|
128
145
|
status: ZeniAPIStatus<Record<string, unknown>>;
|
|
129
|
-
}, "tenant/saveOAuthConnectionFailure", never, never>,
|
|
146
|
+
}, "tenant/saveOAuthConnectionFailure", never, never>, saveConnectorCredentials: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue" | "payments", args: ConnectorCredentialsBySlug], {
|
|
147
|
+
connectionName: "stripe";
|
|
148
|
+
credentials: {
|
|
149
|
+
api_key: string;
|
|
150
|
+
};
|
|
151
|
+
tenantId: string;
|
|
152
|
+
connectionType: "revenue" | "payments";
|
|
153
|
+
} | {
|
|
154
|
+
connectionName: "mercury";
|
|
155
|
+
credentials: {
|
|
156
|
+
api_key: string;
|
|
157
|
+
};
|
|
158
|
+
tenantId: string;
|
|
159
|
+
connectionType: "revenue" | "payments";
|
|
160
|
+
} | {
|
|
161
|
+
connectionName: "paypal";
|
|
162
|
+
credentials: {
|
|
163
|
+
client_id: string;
|
|
164
|
+
client_secret: string;
|
|
165
|
+
};
|
|
166
|
+
tenantId: string;
|
|
167
|
+
connectionType: "revenue" | "payments";
|
|
168
|
+
}, "tenant/saveConnectorCredentials", never, never>, saveConnectorCredentialsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionType: "revenue" | "payments", connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal", connectionPayload: ConnectionDataPayload], {
|
|
169
|
+
tenantId: string;
|
|
170
|
+
connectionType: "revenue" | "payments";
|
|
171
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
172
|
+
connectionPayload: ConnectionDataPayload;
|
|
173
|
+
}, "tenant/saveConnectorCredentialsSuccess", never, never>, saveConnectorCredentialsFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal", status: ZeniAPIStatus<Record<string, unknown>>], {
|
|
174
|
+
tenantId: string;
|
|
175
|
+
connectionName: "chargebee" | "hubspot" | "stripe" | "mercury" | "paypal";
|
|
176
|
+
status: ZeniAPIStatus<Record<string, unknown>>;
|
|
177
|
+
}, "tenant/saveConnectorCredentialsFailure", never, never>, deleteConnection: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue" | "payments"], {
|
|
130
178
|
tenantId: string;
|
|
131
179
|
connectionId: string;
|
|
132
|
-
connectionType: "revenue";
|
|
133
|
-
}, "tenant/deleteConnection", never, never>, deleteConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue"], {
|
|
180
|
+
connectionType: "revenue" | "payments";
|
|
181
|
+
}, "tenant/deleteConnection", never, never>, deleteConnectionSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, connectionId: string, connectionType: "revenue" | "payments"], {
|
|
134
182
|
tenantId: string;
|
|
135
183
|
connectionId: string;
|
|
136
|
-
connectionType: "revenue";
|
|
184
|
+
connectionType: "revenue" | "payments";
|
|
137
185
|
}, "tenant/deleteConnectionSuccess", never, never>, deleteConnectionFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[tenantId: string, status: ZeniAPIStatus<Record<string, unknown>>], {
|
|
138
186
|
tenantId: string;
|
|
139
187
|
status: ZeniAPIStatus<Record<string, unknown>>;
|