@zeniai/client-epic-state 5.3.2 → 5.3.3-betaGS1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.d.ts +100 -0
  2. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.js +156 -0
  3. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.d.ts +87 -0
  4. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.js +2 -0
  5. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.d.ts +29 -0
  6. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.js +55 -0
  7. package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +2 -0
  8. package/lib/entity/jeSchedules/jeSchedulesPayload.js +3 -0
  9. package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +6 -0
  10. package/lib/entity/jeSchedules/jeSchedulesSelector.js +14 -1
  11. package/lib/entity/jeSchedules/jeSchedulesState.d.ts +2 -0
  12. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  13. package/lib/entity/snackbar/snackbarTypes.js +5 -0
  14. package/lib/entity/userRole/userRoleTenantAccess.d.ts +9 -0
  15. package/lib/entity/userRole/userRoleTenantAccess.js +25 -1
  16. package/lib/entity/userRole/userRoleType.d.ts +2 -2
  17. package/lib/epic.d.ts +7 -1
  18. package/lib/epic.js +12 -0
  19. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.js +145 -0
  20. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.js +1 -0
  21. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.js +45 -0
  22. package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +3 -0
  23. package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +12 -0
  24. package/lib/esm/entity/snackbar/snackbarTypes.js +5 -0
  25. package/lib/esm/entity/userRole/userRoleTenantAccess.js +22 -0
  26. package/lib/esm/epic.js +12 -0
  27. package/lib/esm/index.js +9 -2
  28. package/lib/esm/reducer.js +3 -0
  29. package/lib/esm/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +2 -1
  30. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.js +38 -0
  31. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.js +28 -0
  32. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.js +22 -0
  33. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.js +43 -0
  34. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.js +42 -0
  35. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.js +45 -0
  36. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.js +23 -0
  37. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.js +244 -0
  38. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.js +65 -0
  39. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.js +1 -0
  40. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.js +1 -0
  41. package/lib/esm/view/settingsView/settingsViewHelpers.js +5 -2
  42. package/lib/esm/view/transactionDetail/createTransaction/createTransactionPayload.js +0 -1
  43. package/lib/index.d.ts +12 -3
  44. package/lib/index.js +86 -43
  45. package/lib/reducer.d.ts +1 -0
  46. package/lib/reducer.js +3 -0
  47. package/lib/rootStateTypes.d.ts +2 -0
  48. package/lib/view/companyView/types/cockpitTypes.d.ts +1 -1
  49. package/lib/view/expenseAutomationView/epics/accountRecon/fetchReconciliationViewEpic.js +2 -1
  50. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  51. package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +1 -1
  52. package/lib/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.d.ts +8 -0
  53. package/lib/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.js +42 -0
  54. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.d.ts +8 -0
  55. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.js +32 -0
  56. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.d.ts +8 -0
  57. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.js +26 -0
  58. package/lib/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.d.ts +10 -0
  59. package/lib/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.js +47 -0
  60. package/lib/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.d.ts +12 -0
  61. package/lib/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.js +46 -0
  62. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.d.ts +8 -0
  63. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.js +49 -0
  64. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.d.ts +36 -0
  65. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.js +29 -0
  66. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.d.ts +41 -0
  67. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.js +249 -0
  68. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.d.ts +8 -0
  69. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.js +72 -0
  70. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.d.ts +23 -0
  71. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.js +2 -0
  72. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.d.ts +28 -0
  73. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.js +2 -0
  74. package/lib/view/settingsView/settingsViewHelpers.js +4 -1
  75. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.d.ts +2 -4
  76. package/lib/view/transactionDetail/createTransaction/createTransactionPayload.js +0 -1
  77. package/lib/view/transactionDetail/createTransaction/createTransactionState.d.ts +0 -2
  78. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ import { ID } from '../../commonStateTypes/common';
2
+ import { ZeniAPIResponse, ZeniAPIStatus } from '../../responsePayload';
3
+ import { JEScheduleApprovalAPIStatus, JEScheduleApprovalInfo, JEScheduleApprovalRuleFormData, JEScheduleApprovalRuleState, JEScheduleApprovalStepState, JEScheduleApprover, JEScheduleApproverRole } from './jeScheduleApprovalRuleState';
4
+ import { JEScheduleType } from './jeScheduleApprovalRuleTypes';
5
+ export interface JEScheduleApprovalUserActorPayload {
6
+ id: ID;
7
+ type: 'user';
8
+ }
9
+ export interface JEScheduleApprovalRoleActorPayload {
10
+ sub_type: string;
11
+ type: 'role';
12
+ }
13
+ export type JEScheduleApprovalActorPayload = JEScheduleApprovalUserActorPayload | JEScheduleApprovalRoleActorPayload;
14
+ export interface JEScheduleApprovalStepPayload {
15
+ action: string;
16
+ actors: JEScheduleApprovalActorPayload[];
17
+ }
18
+ export interface JEScheduleApprovalRulePayload {
19
+ create_time: string;
20
+ created_by_user_id: ID | null;
21
+ description: string | null;
22
+ id: ID;
23
+ is_separation_of_duty_enabled: boolean;
24
+ monthly_amount_min: number;
25
+ name: string;
26
+ owner: string;
27
+ priority: number;
28
+ schedule_types: string[];
29
+ step: JEScheduleApprovalStepPayload;
30
+ update_time: string;
31
+ updated_by_user_id: ID | null;
32
+ }
33
+ export interface JEScheduleApprovalRulesListPayload {
34
+ can_edit: boolean;
35
+ rules: JEScheduleApprovalRulePayload[];
36
+ rules_version: number;
37
+ viewer_owner: string;
38
+ }
39
+ export interface JEScheduleApprovalRuleSavePayload extends JEScheduleApprovalRulesListPayload {
40
+ rule: JEScheduleApprovalRulePayload;
41
+ }
42
+ /** Body for POST / PUT `/1.0/je-schedules/approval-rules[/<id>]`. */
43
+ export interface JEScheduleApprovalRuleRequestBody {
44
+ description: string | null;
45
+ is_applicable_on_pending_approval_entity: boolean;
46
+ is_separation_of_duty_enabled: boolean;
47
+ monthly_amount_min: number;
48
+ name: string;
49
+ schedule_types: JEScheduleType[];
50
+ step: JEScheduleApprovalStepPayload;
51
+ [key: string]: unknown;
52
+ }
53
+ export interface JEScheduleApproverPayload {
54
+ email: string;
55
+ first_name: string;
56
+ is_zeni: boolean;
57
+ je_level: number | null;
58
+ je_level_label: string | null;
59
+ last_name: string;
60
+ user_id: ID;
61
+ }
62
+ export interface JEScheduleApproverRolePayload {
63
+ label: string;
64
+ level: number;
65
+ sub_type: string;
66
+ }
67
+ export interface JEScheduleApproversPayload {
68
+ roles: JEScheduleApproverRolePayload[];
69
+ users: JEScheduleApproverPayload[];
70
+ viewer_owner: string;
71
+ }
72
+ export interface JEScheduleApprovalInfoPayload {
73
+ approver_labels: string[];
74
+ approver_roles: string[];
75
+ approver_user_ids: ID[];
76
+ can_approve: boolean;
77
+ matched_rule_ids: ID[];
78
+ matched_rule_name: string | null;
79
+ matched_rule_owner: string | null;
80
+ message: string;
81
+ monthly_amount: number | null;
82
+ preparer_user_id: ID | null;
83
+ requires_approval: boolean;
84
+ rule_min: number | null;
85
+ separation_of_duties: boolean;
86
+ unevaluable_reason: string | null;
87
+ }
88
+ export type JEScheduleApprovalRulesListResponse = ZeniAPIResponse<JEScheduleApprovalRulesListPayload>;
89
+ export type JEScheduleApprovalRuleSaveResponse = ZeniAPIResponse<JEScheduleApprovalRuleSavePayload>;
90
+ export type JEScheduleApproversResponse = ZeniAPIResponse<JEScheduleApproversPayload>;
91
+ export declare const toJEScheduleApprovalStepState: (payload: JEScheduleApprovalStepPayload) => JEScheduleApprovalStepState;
92
+ export declare const toJEScheduleTypes: (scheduleTypes: string[]) => JEScheduleType[];
93
+ export declare const toJEScheduleApprovalRuleState: (payload: JEScheduleApprovalRulePayload) => JEScheduleApprovalRuleState;
94
+ /** Reverse mapper for create / update. The contract carries exactly one step. */
95
+ export declare const toJEScheduleApprovalRulePayload: (formData: JEScheduleApprovalRuleFormData) => JEScheduleApprovalRuleRequestBody;
96
+ export declare const toJEScheduleApprover: (payload: JEScheduleApproverPayload) => JEScheduleApprover;
97
+ export declare const toJEScheduleApproverRole: (payload: JEScheduleApproverRolePayload) => JEScheduleApproverRole;
98
+ export declare const toJEScheduleApprovalInfo: (payload: JEScheduleApprovalInfoPayload | null | undefined) => JEScheduleApprovalInfo | undefined;
99
+ /** Wraps an API status with a typed `kind` and a user-facing message for 403 / 409. */
100
+ export declare const toJEScheduleApprovalAPIStatus: (status: ZeniAPIStatus) => JEScheduleApprovalAPIStatus;
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toJEScheduleApprovalAPIStatus = exports.toJEScheduleApprovalInfo = exports.toJEScheduleApproverRole = exports.toJEScheduleApprover = exports.toJEScheduleApprovalRulePayload = exports.toJEScheduleApprovalRuleState = exports.toJEScheduleTypes = exports.toJEScheduleApprovalStepState = void 0;
4
+ const zeniDayJS_1 = require("../../zeniDayJS");
5
+ const jeScheduleApprovalRuleTypes_1 = require("./jeScheduleApprovalRuleTypes");
6
+ const isUserActor = (actor) => actor.type === 'user';
7
+ const toJEScheduleApprovalStepState = (payload) => {
8
+ const nonUserActors = [];
9
+ payload.actors.forEach((actor) => {
10
+ if (isUserActor(actor)) {
11
+ return;
12
+ }
13
+ const subType = (0, jeScheduleApprovalRuleTypes_1.toJEApprovalRoleSubTypeStrict)(actor.sub_type);
14
+ if (subType == null) {
15
+ console.warn(`[jeScheduleApprovalRule] dropping unknown role actor "${actor.sub_type}"`);
16
+ return;
17
+ }
18
+ nonUserActors.push({ subType });
19
+ });
20
+ return {
21
+ action: (0, jeScheduleApprovalRuleTypes_1.toJEApprovalStepAction)(payload.action),
22
+ actorUserIds: payload.actors.filter(isUserActor).map((actor) => actor.id),
23
+ nonUserActors,
24
+ };
25
+ };
26
+ exports.toJEScheduleApprovalStepState = toJEScheduleApprovalStepState;
27
+ const toJEScheduleTypes = (scheduleTypes) => {
28
+ const result = [];
29
+ scheduleTypes.forEach((scheduleType) => {
30
+ const known = (0, jeScheduleApprovalRuleTypes_1.toJEScheduleTypeStrict)(scheduleType);
31
+ if (known == null) {
32
+ console.warn(`[jeScheduleApprovalRule] dropping unknown schedule type "${scheduleType}"`);
33
+ return;
34
+ }
35
+ result.push(known);
36
+ });
37
+ return result;
38
+ };
39
+ exports.toJEScheduleTypes = toJEScheduleTypes;
40
+ const toJEScheduleApprovalRuleState = (payload) => ({
41
+ approvalRuleId: payload.id,
42
+ owner: (0, jeScheduleApprovalRuleTypes_1.toJEApprovalOwner)(payload.owner),
43
+ priority: payload.priority,
44
+ name: payload.name,
45
+ description: payload.description ?? undefined,
46
+ separationOfDuties: payload.is_separation_of_duty_enabled,
47
+ criteria: {
48
+ scheduleTypes: (0, exports.toJEScheduleTypes)(payload.schedule_types),
49
+ monthlyAmountMin: payload.monthly_amount_min,
50
+ },
51
+ steps: [(0, exports.toJEScheduleApprovalStepState)(payload.step)],
52
+ createdByUserId: payload.created_by_user_id ?? undefined,
53
+ updatedByUserId: payload.updated_by_user_id ?? undefined,
54
+ createTime: (0, zeniDayJS_1.date)(payload.create_time),
55
+ updateTime: (0, zeniDayJS_1.date)(payload.update_time),
56
+ });
57
+ exports.toJEScheduleApprovalRuleState = toJEScheduleApprovalRuleState;
58
+ const toJEScheduleApprovalStepPayload = (step) => ({
59
+ action: step.action,
60
+ actors: [
61
+ ...step.actorUserIds.map((userId) => ({
62
+ type: 'user',
63
+ id: userId,
64
+ })),
65
+ ...step.nonUserActors.map((actor) => ({
66
+ type: 'role',
67
+ sub_type: actor.subType,
68
+ })),
69
+ ],
70
+ });
71
+ /** Reverse mapper for create / update. The contract carries exactly one step. */
72
+ const toJEScheduleApprovalRulePayload = (formData) => ({
73
+ name: formData.name,
74
+ description: formData.description ?? null,
75
+ is_separation_of_duty_enabled: formData.separationOfDuties,
76
+ schedule_types: formData.criteria.scheduleTypes,
77
+ monthly_amount_min: formData.criteria.monthlyAmountMin,
78
+ step: toJEScheduleApprovalStepPayload(formData.steps[0] ?? {
79
+ action: 'require_approval',
80
+ actorUserIds: [],
81
+ nonUserActors: [],
82
+ }),
83
+ is_applicable_on_pending_approval_entity: formData.isApplicableOnPendingApprovalEntity,
84
+ });
85
+ exports.toJEScheduleApprovalRulePayload = toJEScheduleApprovalRulePayload;
86
+ const toJEScheduleApprover = (payload) => ({
87
+ userId: payload.user_id,
88
+ email: payload.email,
89
+ firstName: payload.first_name,
90
+ lastName: payload.last_name,
91
+ isZeni: payload.is_zeni,
92
+ jeLevel: payload.je_level ?? undefined,
93
+ jeLevelLabel: payload.je_level_label ?? undefined,
94
+ });
95
+ exports.toJEScheduleApprover = toJEScheduleApprover;
96
+ const toJEScheduleApproverRole = (payload) => ({
97
+ subType: (0, jeScheduleApprovalRuleTypes_1.toJEApprovalRoleSubType)(payload.sub_type),
98
+ level: payload.level,
99
+ label: payload.label,
100
+ });
101
+ exports.toJEScheduleApproverRole = toJEScheduleApproverRole;
102
+ const toJEScheduleApprovalInfo = (payload) => {
103
+ if (payload == null) {
104
+ return undefined;
105
+ }
106
+ return {
107
+ requiresApproval: payload.requires_approval,
108
+ canApprove: payload.can_approve,
109
+ approverLabels: payload.approver_labels,
110
+ approverRoles: payload.approver_roles,
111
+ approverUserIds: payload.approver_user_ids,
112
+ matchedRuleIds: payload.matched_rule_ids,
113
+ matchedRuleName: payload.matched_rule_name ?? undefined,
114
+ matchedRuleOwner: payload.matched_rule_owner != null
115
+ ? (0, jeScheduleApprovalRuleTypes_1.toJEApprovalOwner)(payload.matched_rule_owner)
116
+ : undefined,
117
+ monthlyAmount: payload.monthly_amount ?? undefined,
118
+ ruleMin: payload.rule_min ?? undefined,
119
+ separationOfDuties: payload.separation_of_duties,
120
+ preparerUserId: payload.preparer_user_id ?? undefined,
121
+ unevaluableReason: payload.unevaluable_reason ?? undefined,
122
+ message: payload.message,
123
+ };
124
+ };
125
+ exports.toJEScheduleApprovalInfo = toJEScheduleApprovalInfo;
126
+ const toJEApprovalErrorKind = (code) => {
127
+ switch (code) {
128
+ case 403:
129
+ return 'forbidden';
130
+ case 409:
131
+ return 'conflict';
132
+ case 400:
133
+ return 'validation';
134
+ case 404:
135
+ return 'not_found';
136
+ default:
137
+ return 'unknown';
138
+ }
139
+ };
140
+ const USER_FACING_MESSAGES = {
141
+ forbidden: 'You are not allowed to perform this action.',
142
+ conflict: 'This schedule was already approved by someone else.',
143
+ validation: undefined, // backend's status.message is already user-facing
144
+ not_found: 'JE schedule approval rules are not available for this account.',
145
+ unknown: undefined,
146
+ };
147
+ /** Wraps an API status with a typed `kind` and a user-facing message for 403 / 409. */
148
+ const toJEScheduleApprovalAPIStatus = (status) => {
149
+ const kind = toJEApprovalErrorKind(status.code);
150
+ return {
151
+ ...status,
152
+ kind,
153
+ message: USER_FACING_MESSAGES[kind] ?? status.message,
154
+ };
155
+ };
156
+ exports.toJEScheduleApprovalAPIStatus = toJEScheduleApprovalAPIStatus;
@@ -0,0 +1,87 @@
1
+ import { ID } from '../../commonStateTypes/common';
2
+ import { ZeniAPIStatus } from '../../responsePayload';
3
+ import { ZeniDate } from '../../zeniDayJS';
4
+ import { JEApprovalErrorKind, JEApprovalOwner, JEApprovalRoleSubType, JEApprovalStepAction, JEScheduleType } from './jeScheduleApprovalRuleTypes';
5
+ /** A user eligible to approve JE schedules, as `/je-schedules/approvers` reports them. */
6
+ export interface JEScheduleApprover {
7
+ email: string;
8
+ firstName: string;
9
+ isZeni: boolean;
10
+ lastName: string;
11
+ userId: ID;
12
+ jeLevel?: number;
13
+ jeLevelLabel?: string;
14
+ }
15
+ export interface JEScheduleApproverRole {
16
+ label: string;
17
+ level: number;
18
+ subType: JEApprovalRoleSubType;
19
+ }
20
+ export interface JEScheduleApprovalNonUserActor {
21
+ subType: JEApprovalRoleSubType;
22
+ }
23
+ export interface JEScheduleApprovalCriteria {
24
+ monthlyAmountMin: number;
25
+ scheduleTypes: JEScheduleType[];
26
+ }
27
+ /** Stored shape: actors are user ids; the view selector joins them against the approvers list. */
28
+ export interface JEScheduleApprovalStepState {
29
+ action: JEApprovalStepAction;
30
+ actorUserIds: ID[];
31
+ nonUserActors: JEScheduleApprovalNonUserActor[];
32
+ }
33
+ export interface JEScheduleApprovalRuleBase {
34
+ approvalRuleId: ID;
35
+ createTime: ZeniDate;
36
+ criteria: JEScheduleApprovalCriteria;
37
+ name: string;
38
+ owner: JEApprovalOwner;
39
+ priority: number;
40
+ separationOfDuties: boolean;
41
+ updateTime: ZeniDate;
42
+ createdByUserId?: ID;
43
+ description?: string;
44
+ updatedByUserId?: ID;
45
+ }
46
+ export interface JEScheduleApprovalRuleState extends JEScheduleApprovalRuleBase {
47
+ steps: JEScheduleApprovalStepState[];
48
+ }
49
+ /** Selector shape: actors resolved to approver records. */
50
+ export interface JEScheduleApprovalStep {
51
+ action: JEApprovalStepAction;
52
+ actors: JEScheduleApprover[];
53
+ nonUserActors: JEScheduleApprovalNonUserActor[];
54
+ }
55
+ export interface JEScheduleApprovalRule extends JEScheduleApprovalRuleBase {
56
+ steps: JEScheduleApprovalStep[];
57
+ }
58
+ /** Form-side shape for create / update; mapped to the wire by `toJEScheduleApprovalRulePayload`. */
59
+ export interface JEScheduleApprovalRuleFormData {
60
+ criteria: JEScheduleApprovalCriteria;
61
+ isApplicableOnPendingApprovalEntity: boolean;
62
+ name: string;
63
+ separationOfDuties: boolean;
64
+ steps: JEScheduleApprovalStepState[];
65
+ approvalRuleId?: ID;
66
+ description?: string;
67
+ }
68
+ /** Per-schedule approval evaluation carried on JE schedule rows (`approval_info`). */
69
+ export interface JEScheduleApprovalInfo {
70
+ approverLabels: string[];
71
+ approverRoles: string[];
72
+ approverUserIds: ID[];
73
+ canApprove: boolean;
74
+ matchedRuleIds: ID[];
75
+ message: string;
76
+ requiresApproval: boolean;
77
+ separationOfDuties: boolean;
78
+ matchedRuleName?: string;
79
+ matchedRuleOwner?: JEApprovalOwner;
80
+ monthlyAmount?: number;
81
+ preparerUserId?: ID;
82
+ ruleMin?: number;
83
+ unevaluableReason?: string;
84
+ }
85
+ export interface JEScheduleApprovalAPIStatus extends ZeniAPIStatus {
86
+ kind: JEApprovalErrorKind;
87
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,29 @@
1
+ export declare const JE_SCHEDULE_TYPES: readonly ["prepaid_expenses", "fixed_assets", "accrued_expenses"];
2
+ export declare const toJEScheduleType: (v: string) => "prepaid_expenses" | "fixed_assets" | "accrued_expenses";
3
+ export declare const toJEScheduleTypeStrict: (v: string) => "prepaid_expenses" | "fixed_assets" | "accrued_expenses" | undefined;
4
+ export type JEScheduleType = ReturnType<typeof toJEScheduleType>;
5
+ export declare const JE_APPROVAL_OWNERS: readonly ["zeni", "customer"];
6
+ export declare const toJEApprovalOwner: (v: string) => "customer" | "zeni";
7
+ export declare const toJEApprovalOwnerStrict: (v: string) => "customer" | "zeni" | undefined;
8
+ export type JEApprovalOwner = ReturnType<typeof toJEApprovalOwner>;
9
+ export declare const JE_APPROVAL_STEP_ACTIONS: readonly ["require_approval", "send_notification"];
10
+ export declare const toJEApprovalStepAction: (v: string) => "require_approval" | "send_notification";
11
+ export type JEApprovalStepAction = ReturnType<typeof toJEApprovalStepAction>;
12
+ export declare const JE_APPROVAL_ROLE_SUB_TYPES: readonly ["reviewer", "controller"];
13
+ export declare const toJEApprovalRoleSubType: (v: string) => "reviewer" | "controller";
14
+ export declare const toJEApprovalRoleSubTypeStrict: (v: string) => "reviewer" | "controller" | undefined;
15
+ export type JEApprovalRoleSubType = ReturnType<typeof toJEApprovalRoleSubType>;
16
+ export declare const JE_APPROVAL_ACTIONS: readonly ["approve", "reject", "save_draft"];
17
+ export type JEApprovalAction = (typeof JE_APPROVAL_ACTIONS)[number];
18
+ export declare const JE_LEVEL_PREPARER = 1;
19
+ export declare const JE_LEVEL_REVIEWER = 2;
20
+ export declare const JE_LEVEL_CONTROLLER = 3;
21
+ export declare const JE_LEVEL_LABELS: Record<number, string>;
22
+ export declare const JE_SCHEDULE_TYPE_LABELS: Record<JEScheduleType, string>;
23
+ /**
24
+ * Typed failure kinds for the approval-rule / approval-action endpoints.
25
+ * 403 = viewer may not edit (or touched the other owner's rule / is not an
26
+ * eligible approver / SoD); 409 = someone else already approved.
27
+ */
28
+ export declare const JE_APPROVAL_ERROR_KINDS: readonly ["forbidden", "conflict", "validation", "not_found", "unknown"];
29
+ export type JEApprovalErrorKind = (typeof JE_APPROVAL_ERROR_KINDS)[number];
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JE_APPROVAL_ERROR_KINDS = exports.JE_SCHEDULE_TYPE_LABELS = exports.JE_LEVEL_LABELS = exports.JE_LEVEL_CONTROLLER = exports.JE_LEVEL_REVIEWER = exports.JE_LEVEL_PREPARER = exports.JE_APPROVAL_ACTIONS = exports.toJEApprovalRoleSubTypeStrict = exports.toJEApprovalRoleSubType = exports.JE_APPROVAL_ROLE_SUB_TYPES = exports.toJEApprovalStepAction = exports.JE_APPROVAL_STEP_ACTIONS = exports.toJEApprovalOwnerStrict = exports.toJEApprovalOwner = exports.JE_APPROVAL_OWNERS = exports.toJEScheduleTypeStrict = exports.toJEScheduleType = exports.JE_SCHEDULE_TYPES = void 0;
4
+ const stringToUnion_1 = require("../../commonStateTypes/stringToUnion");
5
+ exports.JE_SCHEDULE_TYPES = [
6
+ 'prepaid_expenses',
7
+ 'fixed_assets',
8
+ 'accrued_expenses',
9
+ ];
10
+ const toJEScheduleType = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.JE_SCHEDULE_TYPES);
11
+ exports.toJEScheduleType = toJEScheduleType;
12
+ const toJEScheduleTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v, exports.JE_SCHEDULE_TYPES);
13
+ exports.toJEScheduleTypeStrict = toJEScheduleTypeStrict;
14
+ exports.JE_APPROVAL_OWNERS = ['zeni', 'customer'];
15
+ const toJEApprovalOwner = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.JE_APPROVAL_OWNERS);
16
+ exports.toJEApprovalOwner = toJEApprovalOwner;
17
+ const toJEApprovalOwnerStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v, exports.JE_APPROVAL_OWNERS);
18
+ exports.toJEApprovalOwnerStrict = toJEApprovalOwnerStrict;
19
+ exports.JE_APPROVAL_STEP_ACTIONS = [
20
+ 'require_approval',
21
+ 'send_notification',
22
+ ];
23
+ const toJEApprovalStepAction = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.JE_APPROVAL_STEP_ACTIONS);
24
+ exports.toJEApprovalStepAction = toJEApprovalStepAction;
25
+ exports.JE_APPROVAL_ROLE_SUB_TYPES = ['reviewer', 'controller'];
26
+ const toJEApprovalRoleSubType = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.JE_APPROVAL_ROLE_SUB_TYPES);
27
+ exports.toJEApprovalRoleSubType = toJEApprovalRoleSubType;
28
+ const toJEApprovalRoleSubTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v, exports.JE_APPROVAL_ROLE_SUB_TYPES);
29
+ exports.toJEApprovalRoleSubTypeStrict = toJEApprovalRoleSubTypeStrict;
30
+ exports.JE_APPROVAL_ACTIONS = ['approve', 'reject', 'save_draft'];
31
+ exports.JE_LEVEL_PREPARER = 1;
32
+ exports.JE_LEVEL_REVIEWER = 2;
33
+ exports.JE_LEVEL_CONTROLLER = 3;
34
+ exports.JE_LEVEL_LABELS = {
35
+ [exports.JE_LEVEL_PREPARER]: 'Preparer',
36
+ [exports.JE_LEVEL_REVIEWER]: 'Reviewer',
37
+ [exports.JE_LEVEL_CONTROLLER]: 'Controller',
38
+ };
39
+ exports.JE_SCHEDULE_TYPE_LABELS = {
40
+ prepaid_expenses: 'Prepaid Expenses',
41
+ fixed_assets: 'Fixed Assets',
42
+ accrued_expenses: 'Accrued Expenses',
43
+ };
44
+ /**
45
+ * Typed failure kinds for the approval-rule / approval-action endpoints.
46
+ * 403 = viewer may not edit (or touched the other owner's rule / is not an
47
+ * eligible approver / SoD); 409 = someone else already approved.
48
+ */
49
+ exports.JE_APPROVAL_ERROR_KINDS = [
50
+ 'forbidden',
51
+ 'conflict',
52
+ 'validation',
53
+ 'not_found',
54
+ 'unknown',
55
+ ];
@@ -2,6 +2,7 @@ import { StatusCodeWithLabelPayload } from '../../commonPayloadTypes/statusPaylo
2
2
  import { ID } from '../../commonStateTypes/common';
3
3
  import { AccountPayload } from '../account/accountPayload';
4
4
  import { ClassBasePayload } from '../class/classPayload';
5
+ import { JEScheduleApprovalInfoPayload } from '../jeScheduleApprovalRule/jeScheduleApprovalRulePayload';
5
6
  import { ScheduleTransactionPayload } from '../transaction/payloadTypes/scheduleTransactionPayload';
6
7
  import { TransactionIDPayload } from '../transaction/payloadTypes/transactionIDPayload';
7
8
  import { TransactionCategory } from '../transaction/stateTypes/transactionType';
@@ -83,6 +84,7 @@ export interface JEScheduledTransactionPayload {
83
84
  updated_by: UserPayload;
84
85
  vendor: VendorPayload;
85
86
  ai_summaries?: JEScheduleAISummariesPayload;
87
+ approval_info?: JEScheduleApprovalInfoPayload | null;
86
88
  confidence_score?: number | null;
87
89
  create_time?: string | null;
88
90
  created_by?: UserPayload;
@@ -13,6 +13,7 @@ const amount_1 = require("../../commonStateTypes/amount");
13
13
  const timePeriod_1 = require("../../commonStateTypes/timePeriod");
14
14
  const zeniDayJS_1 = require("../../zeniDayJS");
15
15
  const zeniUrl_1 = require("../../zeniUrl");
16
+ const jeScheduleApprovalRulePayload_1 = require("../jeScheduleApprovalRule/jeScheduleApprovalRulePayload");
16
17
  const transactionIDPayload_1 = require("../transaction/payloadTypes/transactionIDPayload");
17
18
  const jeScheduleHelper_1 = require("./jeScheduleHelper");
18
19
  const jeSchedulesTypes_1 = require("./jeSchedulesTypes");
@@ -334,6 +335,7 @@ function toJEScheduledTransaction(payload) {
334
335
  : {},
335
336
  scheduledJournalEntry: [],
336
337
  aiSummaries: toJEScheduleAISummaries(payload.ai_summaries),
338
+ approvalInfo: (0, jeScheduleApprovalRulePayload_1.toJEScheduleApprovalInfo)(payload.approval_info),
337
339
  confidenceScore: payload.confidence_score ?? undefined,
338
340
  createdByUserID: payload.created_by?.user_id ?? undefined,
339
341
  recommendations: toJEScheduleRecommendations(payload.recommendations),
@@ -384,6 +386,7 @@ function toJEAccruedScheduledTransaction(payload) {
384
386
  },
385
387
  currencyCode: payload.currency_code,
386
388
  currencySymbol: payload.currency_symbol,
389
+ approvalInfo: (0, jeScheduleApprovalRulePayload_1.toJEScheduleApprovalInfo)(payload.approval_info),
387
390
  dayOfPostingDate: payload.posting_date != null &&
388
391
  payload.posting_date >= timePeriod_1.MIN_SCHEDULE_DAY_OF_MONTH &&
389
392
  payload.posting_date <= timePeriod_1.MAX_SCHEDULE_DAY_OF_MONTH
@@ -5,6 +5,7 @@ import { RootState } from '../../rootStateTypes';
5
5
  import { ZeniDate } from '../../zeniDayJS';
6
6
  import { AccountBase } from '../account/accountState';
7
7
  import { Class } from '../class/classState';
8
+ import { JEScheduleApprovalInfo } from '../jeScheduleApprovalRule/jeScheduleApprovalRuleState';
8
9
  import { ScheduleTransaction } from '../transaction/stateTypes/scheduleTransaction';
9
10
  import { TransactionID } from '../transaction/stateTypes/transactionID';
10
11
  import { User } from '../user/userState';
@@ -84,3 +85,8 @@ export interface JEOneTimeAccrual extends JEOneTimeAccrualState {
84
85
  export declare const getJEOneTimeAccrualByKey: (jeOneTimeAccrualKey: JEOneTimeAccrualKey, jeSchedulesState: JESchedulesState) => JEOneTimeAccrual | undefined;
85
86
  export declare const getJEAccruedScheduleByJEScheduleKey: (JEScheduleKey: JEScheduleKey, state: RootState) => JEAccruedSchedule | undefined;
86
87
  export declare const getJEScheduledTransactionByJEScheduleTransactionKey: (jeScheduleTransactionKey: JEScheduleTransactionKey, state: RootState) => JEScheduledTransaction;
88
+ /**
89
+ * Schedules are keyed by transaction / accrued key, not schedule id, so this
90
+ * scans both maps. ponytail: O(n) scan; index by schedule id if lists grow.
91
+ */
92
+ export declare const getScheduleApprovalInfo: (jeSchedulesState: JESchedulesState, jeScheduleId: ID) => JEScheduleApprovalInfo | 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.getJEScheduledTransactionByJEScheduleTransactionKey = exports.getJEAccruedScheduleByJEScheduleKey = exports.getJEOneTimeAccrualByKey = void 0;
6
+ exports.getScheduleApprovalInfo = exports.getJEScheduledTransactionByJEScheduleTransactionKey = exports.getJEAccruedScheduleByJEScheduleKey = exports.getJEOneTimeAccrualByKey = void 0;
7
7
  const get_1 = __importDefault(require("lodash/get"));
8
8
  const amount_1 = require("../../commonStateTypes/amount");
9
9
  const accountSelector_1 = require("../account/accountSelector");
@@ -176,3 +176,16 @@ const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTransacti
176
176
  };
177
177
  };
178
178
  exports.getJEScheduledTransactionByJEScheduleTransactionKey = getJEScheduledTransactionByJEScheduleTransactionKey;
179
+ /**
180
+ * Schedules are keyed by transaction / accrued key, not schedule id, so this
181
+ * scans both maps. ponytail: O(n) scan; index by schedule id if lists grow.
182
+ */
183
+ const getScheduleApprovalInfo = (jeSchedulesState, jeScheduleId) => {
184
+ const schedules = [
185
+ ...Object.values(jeSchedulesState.schedulesByTransactionKey),
186
+ ...Object.values(jeSchedulesState.schedulesByAccruedJEScheduleKey),
187
+ ];
188
+ return schedules.find((schedule) => schedule.jeScheduleId === jeScheduleId)
189
+ ?.approvalInfo;
190
+ };
191
+ exports.getScheduleApprovalInfo = getScheduleApprovalInfo;
@@ -3,6 +3,7 @@ import { ID } from '../../commonStateTypes/common';
3
3
  import { ScheduleDaysOfMonth } from '../../commonStateTypes/timePeriod';
4
4
  import { ZeniDate } from '../../zeniDayJS';
5
5
  import { ZeniUrl as Url } from '../../zeniUrl';
6
+ import { JEScheduleApprovalInfo } from '../jeScheduleApprovalRule/jeScheduleApprovalRuleState';
6
7
  import { TransactionID } from '../transaction/stateTypes/transactionID';
7
8
  import { JEOneTimeAccrualKey, JEScheduleKey, JEScheduleTransactionKey, JournalEntryErrorCodeType, OneTimeAccrualAutomationTierType, OneTimeAccrualOriginType, OneTimeAccrualReversalPolicyType, OneTimeAccrualReversalTriggerType, OneTimeAccrualStatusCodeType, ScheduleJournalEntryStatusCodeType, ScheduleStatusCodeType, ScheduleTypes } from './jeSchedulesTypes';
8
9
  export interface ScheduleStatus {
@@ -112,6 +113,7 @@ export interface JEScheduledTransactionState {
112
113
  status: ScheduleStatus;
113
114
  vendorId: ID;
114
115
  aiSummaries?: JEScheduleAISummaries;
116
+ approvalInfo?: JEScheduleApprovalInfo;
115
117
  balanceAsOfToday?: number;
116
118
  confidenceScore?: number;
117
119
  createdByUserID?: ID;
@@ -1,4 +1,4 @@
1
- export declare const toSnackbarMessageSection: (v: string) => "common" | "recommendation_feedback" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "actual_matching_match_and_reverse" | "actual_matching_undo_reversal" | "actual_matching_ignore_suggestion" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_approval_reorder" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_approval_reorder" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "card_policy_created" | "card_policy_updated" | "card_policy_deleted" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "revert_schedule" | "ignore_accrual" | "revert_accrual" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "snooze_task" | "unsnooze_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "receipts_bulk_match" | "billing_address_view" | "express_pay_submit" | "exclude_transaction" | "reconcile" | "save_reconcile_for_later" | "recon_transaction_categorize" | "recon_transaction_match" | "update_debit_card_pin_attempt" | "set_debit_card_pin" | "ai_cfo_create_session_and_submit" | "ai_cfo_chat_session_deleted" | "charge_card_auto_pay_enable" | "charge_card_auto_pay_disable" | "treasury_setup" | "treasury_accept_term" | "treasury_transfer_money" | "treasury_transfer_money_failed" | "auto_transfer_rule_create" | "auto_transfer_rule_update" | "auto_transfer_rule_delete" | "auto_transfer_rule_pause" | "auto_transfer_rule_resume" | "treasury_update_portfolio_allocation" | "send_email_magic_link_to_user" | "complete_profile_done" | "create_transfer_entry" | "create_transaction" | "reports_resync" | "invalid_phone_number" | "transactions_categorized_updated_failed" | "transaction_categorized_updated_failed" | "transactionsCategorized_transactionsUpdated" | "transactionsCategorized_transactionUpdated" | "transactionCategorized_transactionsUpdated" | "transactionCategorized_transactionUpdated" | "transactionsCategorized_transactionsFailed" | "transactionsCategorized_transactionFailed" | "transactionCategorized_transactionsFailed" | "transactionCategorized_transactionFailed" | "transactionsUpdated_transactionsFailed" | "transactionsUpdated_transactionFailed" | "transactionUpdated_transactionsFailed" | "transactionUpdated_transactionFailed" | "transactionsCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionsUpdated_transactionFailed" | "transactionsCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionUpdated_transactionFailed" | "transactionCategorized_transactionsUpdated_transactionFailed" | "transactionCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionUpdated_transactionFailed" | "accounting_classes_enabled_update" | "accounting_projects_enabled_update" | "auto_review_income_without_customer_update" | "accounting_projects_qbo_not_enabled" | "capitalization_threshold_update" | "account_excluded_from_reconciliation" | "account_included_in_reconciliation" | "confirm_statement_mapping" | "statement_parsing_in_progress" | "statement_parsing_complete" | "ai_accountant_trigger_job" | "oauth_consent_approve" | "oauth_consent_invalid_request" | "credit_agent_update_profile" | "credit_agent_save_macro" | "credit_agent_schedule_cron" | "create_sub_task" | "qbo_connection_already_linked" | "qbo_connection_failed" | "accounting_projects_qbo_reconnect_failed" | "product_services_update" | "qbo_realm_id_update" | "kyc_kyb_reset" | "invoicing_dunning_case_resolved" | "invoicing_dunning_retry" | "invoicing_dunning_cancel" | "invoicing_dunning_settings_save" | "invoicing_qbo_backfill" | "invoicing_qbo_sync_health_retry" | "invoicing_qbo_settings_save" | "invoicing_branding_save" | "invoicing_discount_archive" | "invoicing_discount_unarchive" | "invoicing_discount_delete" | "invoicing_invoice_reminder_sent" | "invoicing_invoice_regenerated" | "invoicing_invoice_voided" | "invoicing_catalog_item_saved" | "invoicing_customer_saved" | "invoicing_subscription_saved" | "invoicing_coupon_saved" | "invoicing_invoice_saved" | "invoicing_credit_note_saved" | "invoicing_payment_recorded" | "invoicing_subscription_activated" | "invoicing_subscription_cancellation_removed" | "invoicing_subscription_cancelled" | "invoicing_subscription_non_renewing" | "invoicing_subscription_paused" | "invoicing_subscription_reactivated" | "invoicing_subscription_resumed" | "invoicing_subscription_term_end_changed" | "invoicing_data_import_download";
1
+ export declare const toSnackbarMessageSection: (v: string) => "common" | "recommendation_feedback" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "actual_matching_match_and_reverse" | "actual_matching_undo_reversal" | "actual_matching_ignore_suggestion" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_approval_reorder" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_approval_reorder" | "je_schedule_approval_create" | "je_schedule_approval_update" | "je_schedule_approval_delete" | "je_schedule_approval_reorder" | "je_schedule_approval_action" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "card_policy_created" | "card_policy_updated" | "card_policy_deleted" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "revert_schedule" | "ignore_accrual" | "revert_accrual" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "snooze_task" | "unsnooze_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "receipts_bulk_match" | "billing_address_view" | "express_pay_submit" | "exclude_transaction" | "reconcile" | "save_reconcile_for_later" | "recon_transaction_categorize" | "recon_transaction_match" | "update_debit_card_pin_attempt" | "set_debit_card_pin" | "ai_cfo_create_session_and_submit" | "ai_cfo_chat_session_deleted" | "charge_card_auto_pay_enable" | "charge_card_auto_pay_disable" | "treasury_setup" | "treasury_accept_term" | "treasury_transfer_money" | "treasury_transfer_money_failed" | "auto_transfer_rule_create" | "auto_transfer_rule_update" | "auto_transfer_rule_delete" | "auto_transfer_rule_pause" | "auto_transfer_rule_resume" | "treasury_update_portfolio_allocation" | "send_email_magic_link_to_user" | "complete_profile_done" | "create_transfer_entry" | "create_transaction" | "reports_resync" | "invalid_phone_number" | "transactions_categorized_updated_failed" | "transaction_categorized_updated_failed" | "transactionsCategorized_transactionsUpdated" | "transactionsCategorized_transactionUpdated" | "transactionCategorized_transactionsUpdated" | "transactionCategorized_transactionUpdated" | "transactionsCategorized_transactionsFailed" | "transactionsCategorized_transactionFailed" | "transactionCategorized_transactionsFailed" | "transactionCategorized_transactionFailed" | "transactionsUpdated_transactionsFailed" | "transactionsUpdated_transactionFailed" | "transactionUpdated_transactionsFailed" | "transactionUpdated_transactionFailed" | "transactionsCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionsUpdated_transactionFailed" | "transactionsCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionUpdated_transactionFailed" | "transactionCategorized_transactionsUpdated_transactionFailed" | "transactionCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionUpdated_transactionFailed" | "accounting_classes_enabled_update" | "accounting_projects_enabled_update" | "auto_review_income_without_customer_update" | "accounting_projects_qbo_not_enabled" | "capitalization_threshold_update" | "account_excluded_from_reconciliation" | "account_included_in_reconciliation" | "confirm_statement_mapping" | "statement_parsing_in_progress" | "statement_parsing_complete" | "ai_accountant_trigger_job" | "oauth_consent_approve" | "oauth_consent_invalid_request" | "credit_agent_update_profile" | "credit_agent_save_macro" | "credit_agent_schedule_cron" | "create_sub_task" | "qbo_connection_already_linked" | "qbo_connection_failed" | "accounting_projects_qbo_reconnect_failed" | "product_services_update" | "qbo_realm_id_update" | "kyc_kyb_reset" | "invoicing_dunning_case_resolved" | "invoicing_dunning_retry" | "invoicing_dunning_cancel" | "invoicing_dunning_settings_save" | "invoicing_qbo_backfill" | "invoicing_qbo_sync_health_retry" | "invoicing_qbo_settings_save" | "invoicing_branding_save" | "invoicing_discount_archive" | "invoicing_discount_unarchive" | "invoicing_discount_delete" | "invoicing_invoice_reminder_sent" | "invoicing_invoice_regenerated" | "invoicing_invoice_voided" | "invoicing_catalog_item_saved" | "invoicing_customer_saved" | "invoicing_subscription_saved" | "invoicing_coupon_saved" | "invoicing_invoice_saved" | "invoicing_credit_note_saved" | "invoicing_payment_recorded" | "invoicing_subscription_activated" | "invoicing_subscription_cancellation_removed" | "invoicing_subscription_cancelled" | "invoicing_subscription_non_renewing" | "invoicing_subscription_paused" | "invoicing_subscription_reactivated" | "invoicing_subscription_resumed" | "invoicing_subscription_term_end_changed" | "invoicing_data_import_download";
2
2
  export type SnackbarMessageSections = ReturnType<typeof toSnackbarMessageSection>;
3
3
  export declare const toSnackbarMessageSectionTexts: (v: string) => "notification" | "failed" | "success";
4
4
  export type SnackbarMessageSectionTexts = ReturnType<typeof toSnackbarMessageSectionTexts>;
@@ -54,6 +54,11 @@ const ALL_SNACKBAR_MESSAGE_SECTIONS = [
54
54
  'bill_pay_duplicate_approval_update',
55
55
  'bill_pay_approval_delete',
56
56
  'bill_pay_approval_reorder',
57
+ 'je_schedule_approval_create',
58
+ 'je_schedule_approval_update',
59
+ 'je_schedule_approval_delete',
60
+ 'je_schedule_approval_reorder',
61
+ 'je_schedule_approval_action',
57
62
  'bill_pay_updated',
58
63
  'bill_pay_deleted',
59
64
  'bill_pay_cancelled_deleted',
@@ -10,3 +10,12 @@ export declare const hasReimbursementAccessible: (currentTenant: CurrentTenant |
10
10
  export declare const hasChargeCardAccessible: (currentTenant: CurrentTenant | undefined, userRoleMap?: RoleMap) => boolean;
11
11
  export declare const hasZeniAccountsAccessible: (currentTenant: CurrentTenant | undefined, userRoleMap?: RoleMap) => boolean;
12
12
  export declare const hasTreasuryAccessible: (currentTenant: CurrentTenant | undefined, userRoleMap?: RoleMap) => boolean;
13
+ /**
14
+ * JE schedule screens are gated by the Statsig expense-automation gate in the
15
+ * app, which CES cannot read; the CES-level signal is "this tenant buys
16
+ * accounting services" (bookkeeping / CFO / tax / payroll). Screens AND the
17
+ * Statsig gate on top of this.
18
+ */
19
+ export declare const hasJEScheduleApprovalAccessible: (currentTenant: CurrentTenant | undefined) => boolean;
20
+ /** Zeni: reviewer or controller. Customer: admin or bookkeeping_admin. */
21
+ export declare const canEditJEScheduleApprovalRules: (userRoleMap: RoleMap | undefined, isZeni: boolean) => boolean;