@zeniai/client-epic-state 5.0.90-betaAR1 → 5.0.90-betaAR2
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/esm/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +24 -21
- package/lib/esm/view/spendManagement/billPay/editBillView/editBillViewSelector.js +5 -39
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.d.ts +27 -33
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +24 -21
- package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.d.ts +1 -1
- package/lib/view/spendManagement/billPay/editBillView/editBillViewSelector.js +4 -38
- package/package.json +1 -1
package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js
CHANGED
|
@@ -91,19 +91,15 @@ export const toApprovalChangableInfoPayload = (approverViewUpdateData) => {
|
|
|
91
91
|
return payload;
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
94
|
-
* V1 wire mapper — used when
|
|
95
|
-
* for the current tenant.
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
94
|
+
* V1 wire mapper — used when `approval_rule_v3_config` resolves to OFF
|
|
95
|
+
* for the current tenant. Translates the form-side amount criteria into
|
|
96
|
+
* the legacy `{rangeType, rangeEntity, range: {min, max}}` shape. The
|
|
97
|
+
* V1 backend does not understand vendor / department criteria or the
|
|
98
|
+
* rule-level 3.0 fields, so those are dropped on the wire.
|
|
99
99
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* one-sided after rollback rather than collapsing into a closed range.
|
|
104
|
-
*
|
|
105
|
-
* The V1 backend does not understand vendor / department criteria or
|
|
106
|
-
* the rule-level 3.0 fields, so those are dropped on the wire.
|
|
100
|
+
* The form-side amount slot is always read as a `range`-style criteria
|
|
101
|
+
* here: V1 schemas only supported ranges, so an absent `min` or `max`
|
|
102
|
+
* falls back to `0` / `Number.MAX_SAFE_INTEGER`.
|
|
107
103
|
*/
|
|
108
104
|
export const toApprovalChangableInfoPayloadV1 = (approverViewUpdateData) => {
|
|
109
105
|
const amount = approverViewUpdateData.criteria?.amount;
|
|
@@ -129,18 +125,25 @@ export const toApprovalChangableInfoPayloadV1 = (approverViewUpdateData) => {
|
|
|
129
125
|
};
|
|
130
126
|
});
|
|
131
127
|
const isUpdate = approverViewUpdateData.approvalRuleId != null;
|
|
132
|
-
const criteriaEntry = {
|
|
133
|
-
type: 'range',
|
|
134
|
-
range_entity: 'currency',
|
|
135
|
-
min: minAmount?.amount ?? null,
|
|
136
|
-
max: maxAmount?.amount ?? null,
|
|
137
|
-
currency_code: currencyCode,
|
|
138
|
-
currency_symbol: currencySymbol,
|
|
139
|
-
};
|
|
140
128
|
const payload = {
|
|
141
129
|
steps,
|
|
142
130
|
is_applicable_on_pending_approval_entity: approverViewUpdateData.isApplicableOnPendingApprovalEntity ?? true,
|
|
143
|
-
criteria:
|
|
131
|
+
criteria: {
|
|
132
|
+
rangeType: 'range',
|
|
133
|
+
rangeEntity: 'currency',
|
|
134
|
+
range: {
|
|
135
|
+
min: {
|
|
136
|
+
amount: minAmount?.amount ?? 0,
|
|
137
|
+
currencyCode,
|
|
138
|
+
currencySymbol,
|
|
139
|
+
},
|
|
140
|
+
max: {
|
|
141
|
+
amount: maxAmount?.amount ?? Number.MAX_SAFE_INTEGER,
|
|
142
|
+
currencyCode,
|
|
143
|
+
currencySymbol,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
144
147
|
};
|
|
145
148
|
if (isUpdate) {
|
|
146
149
|
payload.approval_rule_id = approverViewUpdateData.approvalRuleId;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import recordGet from 'lodash/get';
|
|
2
2
|
import has from 'lodash/has';
|
|
3
|
-
import { getAmountCriteria
|
|
3
|
+
import { getAmountCriteria } from '../../../../entity/approvalRule/approvalRuleSelector';
|
|
4
4
|
import { reduceFetchState } from '../../../../commonStateTypes/reduceFetchState';
|
|
5
5
|
import { getBankAccountByBankAccountId, getBankAccountsByBankAccountIds, } from '../../../../entity/bankAccount/bankAccountSelector';
|
|
6
6
|
import { getContactById, getContactsByIds, } from '../../../../entity/billPay/contact/contactSelector';
|
|
@@ -679,50 +679,16 @@ export const getDefaultWithdrawFromAccount = (state, depositAccounts, companyId,
|
|
|
679
679
|
}
|
|
680
680
|
return undefined;
|
|
681
681
|
};
|
|
682
|
-
export const checkIfCreatorIsApprover = (billAmount, approvalRules, signedInUser
|
|
682
|
+
export const checkIfCreatorIsApprover = (billAmount, approvalRules, signedInUser) => {
|
|
683
683
|
let isCreatorAlsoApprover = false;
|
|
684
|
-
// Approval Rules 3.0 — a rule is applicable when every criterion it
|
|
685
|
-
// carries matches the bill. Amount uses inclusive bounds ('gte'/'lte'
|
|
686
|
-
// on the wire), and either bound may be absent for a one-sided
|
|
687
|
-
// 'greater_than' or 'less_than' rule. Vendor / department criteria
|
|
688
|
-
// narrow the rule by entity; an absent criterion means 'no narrowing
|
|
689
|
-
// on this axis'. Rules without an amount criterion at all are not
|
|
690
|
-
// considered here, preserving the pre-3.0 behaviour where this
|
|
691
|
-
// selector only ever matched amount-bearing rules.
|
|
692
684
|
const approvalRule = approvalRules.find((rule) => {
|
|
693
685
|
const amountCriteria = getAmountCriteria(rule.criteria);
|
|
694
|
-
if (amountCriteria == null) {
|
|
686
|
+
if (amountCriteria?.min == null) {
|
|
695
687
|
return false;
|
|
696
688
|
}
|
|
697
689
|
const { min, max } = amountCriteria;
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
if (!matchesMin || !matchesMax) {
|
|
701
|
-
return false;
|
|
702
|
-
}
|
|
703
|
-
const vendorCriteria = getVendorCriteria(rule.criteria);
|
|
704
|
-
if (vendorCriteria != null) {
|
|
705
|
-
const includesVendor = billVendorId != null &&
|
|
706
|
-
vendorCriteria.vendorIds.includes(billVendorId);
|
|
707
|
-
if (vendorCriteria.operator === 'is' && !includesVendor) {
|
|
708
|
-
return false;
|
|
709
|
-
}
|
|
710
|
-
if (vendorCriteria.operator === 'is_not' && includesVendor) {
|
|
711
|
-
return false;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
const departmentCriteria = getDepartmentCriteria(rule.criteria);
|
|
715
|
-
if (departmentCriteria != null) {
|
|
716
|
-
const includesDepartment = billDepartmentId != null &&
|
|
717
|
-
departmentCriteria.departmentIds.includes(billDepartmentId);
|
|
718
|
-
if (departmentCriteria.operator === 'is' && !includesDepartment) {
|
|
719
|
-
return false;
|
|
720
|
-
}
|
|
721
|
-
if (departmentCriteria.operator === 'is_not' && includesDepartment) {
|
|
722
|
-
return false;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
return true;
|
|
690
|
+
return (billAmount > min.amount &&
|
|
691
|
+
(max?.amount != null ? billAmount <= max.amount : true));
|
|
726
692
|
});
|
|
727
693
|
if (approvalRule != null) {
|
|
728
694
|
const requireApprovalSteps = approvalRule.steps.filter((step) => step.action === 'require_approval');
|
|
@@ -30,48 +30,42 @@ interface ApprovalUpdatableInfoPayload {
|
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* V1 / pre-3.0 wire shape. Kept so the rollback flag (gated by
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* The wire historically expected:
|
|
38
|
-
* criteria: [{type, range_entity, min, max, currency_code, currency_symbol}]
|
|
39
|
-
* with 'min' and 'max' as scalar numbers, and 'null' representing an
|
|
40
|
-
* absent bound for one-sided rules. See 'LegacyAmountRangeCriterionPayload'
|
|
41
|
-
* in '../../../../../entity/approvalRule/approvalRulePayload.ts' for the
|
|
42
|
-
* matching read-side shape.
|
|
33
|
+
* `approval_rule_v3_config` dynamic config) can target the original
|
|
34
|
+
* `/approval-rules` endpoint with the legacy `{rangeType, rangeEntity, range}`
|
|
35
|
+
* criteria. None of the 3.0 rule-level fields are sent.
|
|
43
36
|
*/
|
|
44
|
-
interface ApprovalUpdatableInfoPayloadV1CriterionEntry {
|
|
45
|
-
currency_code: string;
|
|
46
|
-
currency_symbol: string;
|
|
47
|
-
/** Upper bound. 'null' for a 'greater_than' rule. */
|
|
48
|
-
max: number | null;
|
|
49
|
-
/** Lower bound. 'null' for a 'less_than' rule. */
|
|
50
|
-
min: number | null;
|
|
51
|
-
range_entity: 'currency';
|
|
52
|
-
type: 'range';
|
|
53
|
-
}
|
|
54
37
|
interface ApprovalUpdatableInfoPayloadV1 {
|
|
55
|
-
criteria:
|
|
38
|
+
criteria: {
|
|
39
|
+
range: {
|
|
40
|
+
max: {
|
|
41
|
+
amount: number;
|
|
42
|
+
currencyCode: string;
|
|
43
|
+
currencySymbol: string;
|
|
44
|
+
};
|
|
45
|
+
min: {
|
|
46
|
+
amount: number;
|
|
47
|
+
currencyCode: string;
|
|
48
|
+
currencySymbol: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
rangeEntity: 'currency';
|
|
52
|
+
rangeType: 'range';
|
|
53
|
+
};
|
|
56
54
|
is_applicable_on_pending_approval_entity: boolean;
|
|
57
55
|
steps: ApproverViewStepPayload[];
|
|
58
56
|
approval_rule_id?: ID;
|
|
59
57
|
}
|
|
60
58
|
export declare const toApprovalChangableInfoPayload: (approverViewUpdateData: ApprovalRuleUpdateData | ApprovalRuleCreateData) => Partial<ApprovalUpdatableInfoPayload>;
|
|
61
59
|
/**
|
|
62
|
-
* V1 wire mapper — used when
|
|
63
|
-
* for the current tenant.
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* Open-ended semantics are preserved on the wire: an absent 'min' or
|
|
69
|
-
* 'max' is sent as 'null' rather than synthesised to '0' or
|
|
70
|
-
* 'MAX_SAFE_INTEGER', so a 'greater_than' / 'less_than' rule stays
|
|
71
|
-
* one-sided after rollback rather than collapsing into a closed range.
|
|
60
|
+
* V1 wire mapper — used when `approval_rule_v3_config` resolves to OFF
|
|
61
|
+
* for the current tenant. Translates the form-side amount criteria into
|
|
62
|
+
* the legacy `{rangeType, rangeEntity, range: {min, max}}` shape. The
|
|
63
|
+
* V1 backend does not understand vendor / department criteria or the
|
|
64
|
+
* rule-level 3.0 fields, so those are dropped on the wire.
|
|
72
65
|
*
|
|
73
|
-
* The
|
|
74
|
-
*
|
|
66
|
+
* The form-side amount slot is always read as a `range`-style criteria
|
|
67
|
+
* here: V1 schemas only supported ranges, so an absent `min` or `max`
|
|
68
|
+
* falls back to `0` / `Number.MAX_SAFE_INTEGER`.
|
|
75
69
|
*/
|
|
76
70
|
export declare const toApprovalChangableInfoPayloadV1: (approverViewUpdateData: ApprovalRuleUpdateData | ApprovalRuleCreateData) => Partial<ApprovalUpdatableInfoPayloadV1>;
|
|
77
71
|
export {};
|
|
@@ -95,19 +95,15 @@ const toApprovalChangableInfoPayload = (approverViewUpdateData) => {
|
|
|
95
95
|
};
|
|
96
96
|
exports.toApprovalChangableInfoPayload = toApprovalChangableInfoPayload;
|
|
97
97
|
/**
|
|
98
|
-
* V1 wire mapper — used when
|
|
99
|
-
* for the current tenant.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
98
|
+
* V1 wire mapper — used when `approval_rule_v3_config` resolves to OFF
|
|
99
|
+
* for the current tenant. Translates the form-side amount criteria into
|
|
100
|
+
* the legacy `{rangeType, rangeEntity, range: {min, max}}` shape. The
|
|
101
|
+
* V1 backend does not understand vendor / department criteria or the
|
|
102
|
+
* rule-level 3.0 fields, so those are dropped on the wire.
|
|
103
103
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* one-sided after rollback rather than collapsing into a closed range.
|
|
108
|
-
*
|
|
109
|
-
* The V1 backend does not understand vendor / department criteria or
|
|
110
|
-
* the rule-level 3.0 fields, so those are dropped on the wire.
|
|
104
|
+
* The form-side amount slot is always read as a `range`-style criteria
|
|
105
|
+
* here: V1 schemas only supported ranges, so an absent `min` or `max`
|
|
106
|
+
* falls back to `0` / `Number.MAX_SAFE_INTEGER`.
|
|
111
107
|
*/
|
|
112
108
|
const toApprovalChangableInfoPayloadV1 = (approverViewUpdateData) => {
|
|
113
109
|
const amount = approverViewUpdateData.criteria?.amount;
|
|
@@ -133,18 +129,25 @@ const toApprovalChangableInfoPayloadV1 = (approverViewUpdateData) => {
|
|
|
133
129
|
};
|
|
134
130
|
});
|
|
135
131
|
const isUpdate = approverViewUpdateData.approvalRuleId != null;
|
|
136
|
-
const criteriaEntry = {
|
|
137
|
-
type: 'range',
|
|
138
|
-
range_entity: 'currency',
|
|
139
|
-
min: minAmount?.amount ?? null,
|
|
140
|
-
max: maxAmount?.amount ?? null,
|
|
141
|
-
currency_code: currencyCode,
|
|
142
|
-
currency_symbol: currencySymbol,
|
|
143
|
-
};
|
|
144
132
|
const payload = {
|
|
145
133
|
steps,
|
|
146
134
|
is_applicable_on_pending_approval_entity: approverViewUpdateData.isApplicableOnPendingApprovalEntity ?? true,
|
|
147
|
-
criteria:
|
|
135
|
+
criteria: {
|
|
136
|
+
rangeType: 'range',
|
|
137
|
+
rangeEntity: 'currency',
|
|
138
|
+
range: {
|
|
139
|
+
min: {
|
|
140
|
+
amount: minAmount?.amount ?? 0,
|
|
141
|
+
currencyCode,
|
|
142
|
+
currencySymbol,
|
|
143
|
+
},
|
|
144
|
+
max: {
|
|
145
|
+
amount: maxAmount?.amount ?? Number.MAX_SAFE_INTEGER,
|
|
146
|
+
currencyCode,
|
|
147
|
+
currencySymbol,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
148
151
|
};
|
|
149
152
|
if (isUpdate) {
|
|
150
153
|
payload.approval_rule_id = approverViewUpdateData.approvalRuleId;
|
|
@@ -157,4 +157,4 @@ export declare const getDefaultWithdrawFromAccount: (state: RootState, depositAc
|
|
|
157
157
|
accountId: ID;
|
|
158
158
|
accountType: AccountTypeSubConfigCodeKeyType;
|
|
159
159
|
}) => FundingAccount | undefined;
|
|
160
|
-
export declare const checkIfCreatorIsApprover: (billAmount: number, approvalRules: ApprovalRuleWithUser[], signedInUser?: LoggedInUser
|
|
160
|
+
export declare const checkIfCreatorIsApprover: (billAmount: number, approvalRules: ApprovalRuleWithUser[], signedInUser?: LoggedInUser) => boolean;
|
|
@@ -696,50 +696,16 @@ const getDefaultWithdrawFromAccount = (state, depositAccounts, companyId, lastSe
|
|
|
696
696
|
return undefined;
|
|
697
697
|
};
|
|
698
698
|
exports.getDefaultWithdrawFromAccount = getDefaultWithdrawFromAccount;
|
|
699
|
-
const checkIfCreatorIsApprover = (billAmount, approvalRules, signedInUser
|
|
699
|
+
const checkIfCreatorIsApprover = (billAmount, approvalRules, signedInUser) => {
|
|
700
700
|
let isCreatorAlsoApprover = false;
|
|
701
|
-
// Approval Rules 3.0 — a rule is applicable when every criterion it
|
|
702
|
-
// carries matches the bill. Amount uses inclusive bounds ('gte'/'lte'
|
|
703
|
-
// on the wire), and either bound may be absent for a one-sided
|
|
704
|
-
// 'greater_than' or 'less_than' rule. Vendor / department criteria
|
|
705
|
-
// narrow the rule by entity; an absent criterion means 'no narrowing
|
|
706
|
-
// on this axis'. Rules without an amount criterion at all are not
|
|
707
|
-
// considered here, preserving the pre-3.0 behaviour where this
|
|
708
|
-
// selector only ever matched amount-bearing rules.
|
|
709
701
|
const approvalRule = approvalRules.find((rule) => {
|
|
710
702
|
const amountCriteria = (0, approvalRuleSelector_1.getAmountCriteria)(rule.criteria);
|
|
711
|
-
if (amountCriteria == null) {
|
|
703
|
+
if (amountCriteria?.min == null) {
|
|
712
704
|
return false;
|
|
713
705
|
}
|
|
714
706
|
const { min, max } = amountCriteria;
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
if (!matchesMin || !matchesMax) {
|
|
718
|
-
return false;
|
|
719
|
-
}
|
|
720
|
-
const vendorCriteria = (0, approvalRuleSelector_1.getVendorCriteria)(rule.criteria);
|
|
721
|
-
if (vendorCriteria != null) {
|
|
722
|
-
const includesVendor = billVendorId != null &&
|
|
723
|
-
vendorCriteria.vendorIds.includes(billVendorId);
|
|
724
|
-
if (vendorCriteria.operator === 'is' && !includesVendor) {
|
|
725
|
-
return false;
|
|
726
|
-
}
|
|
727
|
-
if (vendorCriteria.operator === 'is_not' && includesVendor) {
|
|
728
|
-
return false;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
const departmentCriteria = (0, approvalRuleSelector_1.getDepartmentCriteria)(rule.criteria);
|
|
732
|
-
if (departmentCriteria != null) {
|
|
733
|
-
const includesDepartment = billDepartmentId != null &&
|
|
734
|
-
departmentCriteria.departmentIds.includes(billDepartmentId);
|
|
735
|
-
if (departmentCriteria.operator === 'is' && !includesDepartment) {
|
|
736
|
-
return false;
|
|
737
|
-
}
|
|
738
|
-
if (departmentCriteria.operator === 'is_not' && includesDepartment) {
|
|
739
|
-
return false;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
return true;
|
|
707
|
+
return (billAmount > min.amount &&
|
|
708
|
+
(max?.amount != null ? billAmount <= max.amount : true));
|
|
743
709
|
});
|
|
744
710
|
if (approvalRule != null) {
|
|
745
711
|
const requireApprovalSteps = approvalRule.steps.filter((step) => step.action === 'require_approval');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeniai/client-epic-state",
|
|
3
|
-
"version": "5.0.90-
|
|
3
|
+
"version": "5.0.90-betaAR2",
|
|
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",
|