@zeniai/client-epic-state 5.3.15 → 5.3.17-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 (87) hide show
  1. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.d.ts +101 -0
  2. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.js +158 -0
  3. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.d.ts +91 -0
  4. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.js +2 -0
  5. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.d.ts +34 -0
  6. package/lib/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.js +68 -0
  7. package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +3 -0
  8. package/lib/entity/jeSchedules/jeSchedulesPayload.js +4 -0
  9. package/lib/entity/jeSchedules/jeSchedulesSelector.d.ts +6 -0
  10. package/lib/entity/jeSchedules/jeSchedulesSelector.js +21 -1
  11. package/lib/entity/jeSchedules/jeSchedulesState.d.ts +4 -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 +8 -1
  18. package/lib/epic.js +15 -0
  19. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRulePayload.js +147 -0
  20. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleState.js +1 -0
  21. package/lib/esm/entity/jeScheduleApprovalRule/jeScheduleApprovalRuleTypes.js +58 -0
  22. package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +4 -0
  23. package/lib/esm/entity/jeSchedules/jeSchedulesSelector.js +18 -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 +16 -1
  27. package/lib/esm/index.js +11 -4
  28. package/lib/esm/reducer.js +3 -0
  29. package/lib/esm/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.js +62 -10
  30. package/lib/esm/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +16 -1
  31. package/lib/esm/view/scheduleView/scheduleDetailView/epics/fetchScheduleDetailsEpic.js +2 -0
  32. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.js +56 -0
  33. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.js +31 -0
  34. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.js +25 -0
  35. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.js +66 -0
  36. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.js +46 -0
  37. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalDraftEpic.js +50 -0
  38. package/lib/esm/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.js +62 -0
  39. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.js +31 -0
  40. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.js +275 -0
  41. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.js +61 -0
  42. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.js +1 -0
  43. package/lib/esm/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.js +1 -0
  44. package/lib/esm/view/settingsView/settingsViewHelpers.js +7 -3
  45. package/lib/index.d.ts +14 -5
  46. package/lib/index.js +96 -47
  47. package/lib/reducer.d.ts +1 -0
  48. package/lib/reducer.js +3 -0
  49. package/lib/rootStateTypes.d.ts +2 -0
  50. package/lib/view/companyView/types/cockpitTypes.d.ts +1 -1
  51. package/lib/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.d.ts +3 -2
  52. package/lib/view/expenseAutomationView/epics/jeSchedule/oneTimeAccrualActionsEpic.js +62 -9
  53. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  54. package/lib/view/expenseAutomationView/payload/jeSchedulesPayload.d.ts +2 -0
  55. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.d.ts +4 -1
  56. package/lib/view/expenseAutomationView/reducers/jeSchedulesViewReducer.js +18 -3
  57. package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +1 -1
  58. package/lib/view/scheduleView/scheduleDetailView/epics/fetchScheduleDetailsEpic.js +2 -0
  59. package/lib/view/scheduleView/scheduleDetailView/scheduleDetailPayload.d.ts +1 -1
  60. package/lib/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.d.ts +9 -0
  61. package/lib/view/settings/jeScheduleApprovalRules/epic/deleteJEScheduleApprovalRuleEpic.js +60 -0
  62. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.d.ts +9 -0
  63. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApprovalRulesEpic.js +35 -0
  64. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.d.ts +9 -0
  65. package/lib/view/settings/jeScheduleApprovalRules/epic/fetchJEScheduleApproversEpic.js +29 -0
  66. package/lib/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.d.ts +13 -0
  67. package/lib/view/settings/jeScheduleApprovalRules/epic/jeScheduleApprovalActionEpic.js +70 -0
  68. package/lib/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.d.ts +13 -0
  69. package/lib/view/settings/jeScheduleApprovalRules/epic/reorderJEScheduleApprovalRulesEpic.js +50 -0
  70. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalDraftEpic.d.ts +11 -0
  71. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalDraftEpic.js +54 -0
  72. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.d.ts +9 -0
  73. package/lib/view/settings/jeScheduleApprovalRules/epic/saveJEScheduleApprovalRuleEpic.js +66 -0
  74. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.d.ts +51 -0
  75. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewPayload.js +37 -0
  76. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.d.ts +51 -0
  77. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewReducer.js +280 -0
  78. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.d.ts +8 -0
  79. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelector.js +65 -0
  80. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.d.ts +23 -0
  81. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewSelectorTypes.js +2 -0
  82. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.d.ts +28 -0
  83. package/lib/view/settings/jeScheduleApprovalRules/jeScheduleSetupApproverViewState.js +2 -0
  84. package/lib/view/settingsView/settingsViewHelpers.d.ts +1 -1
  85. package/lib/view/settingsView/settingsViewHelpers.js +6 -2
  86. package/lib/view/taskManager/taskListView/taskListReducer.d.ts +1 -1
  87. package/package.json +1 -1
@@ -0,0 +1,101 @@
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 { JEApprovalEntriesSource, 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>]`; a type alias so it satisfies the `Record<string, unknown>` body param. */
43
+ export type 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
+ };
52
+ export interface JEScheduleApproverPayload {
53
+ email: string;
54
+ first_name: string;
55
+ is_zeni: boolean;
56
+ je_level: number | null;
57
+ je_level_label: string | null;
58
+ last_name: string;
59
+ user_id: ID;
60
+ }
61
+ export interface JEScheduleApproverRolePayload {
62
+ label: string;
63
+ level: number | null;
64
+ sub_type: string;
65
+ }
66
+ export interface JEScheduleApproversPayload {
67
+ roles: JEScheduleApproverRolePayload[];
68
+ users: JEScheduleApproverPayload[];
69
+ viewer_owner: string;
70
+ }
71
+ export interface JEScheduleApprovalInfoPayload {
72
+ approver_labels: string[];
73
+ approver_roles: string[];
74
+ approver_user_ids: ID[];
75
+ can_approve: boolean;
76
+ entries_source: JEApprovalEntriesSource;
77
+ entries_version: number;
78
+ matched_rule_ids: ID[];
79
+ matched_rule_name: string | null;
80
+ matched_rule_owner: string | null;
81
+ message: string;
82
+ monthly_amount: number | null;
83
+ preparer_user_id: ID | null;
84
+ requires_approval: boolean;
85
+ rule_min: number | null;
86
+ separation_of_duties: boolean;
87
+ unevaluable_reason: string | null;
88
+ }
89
+ export type JEScheduleApprovalRulesListResponse = ZeniAPIResponse<JEScheduleApprovalRulesListPayload>;
90
+ export type JEScheduleApprovalRuleSaveResponse = ZeniAPIResponse<JEScheduleApprovalRuleSavePayload>;
91
+ export type JEScheduleApproversResponse = ZeniAPIResponse<JEScheduleApproversPayload>;
92
+ export declare const toJEScheduleApprovalStepState: (payload: JEScheduleApprovalStepPayload) => JEScheduleApprovalStepState;
93
+ export declare const toJEScheduleTypes: (scheduleTypes: string[]) => JEScheduleType[];
94
+ export declare const toJEScheduleApprovalRuleState: (payload: JEScheduleApprovalRulePayload) => JEScheduleApprovalRuleState;
95
+ /** Reverse mapper for create / update. The contract carries exactly one step. */
96
+ export declare const toJEScheduleApprovalRulePayload: (formData: JEScheduleApprovalRuleFormData) => JEScheduleApprovalRuleRequestBody;
97
+ export declare const toJEScheduleApprover: (payload: JEScheduleApproverPayload) => JEScheduleApprover;
98
+ export declare const toJEScheduleApproverRole: (payload: JEScheduleApproverRolePayload) => JEScheduleApproverRole;
99
+ export declare const toJEScheduleApprovalInfo: (payload: JEScheduleApprovalInfoPayload | null | undefined) => JEScheduleApprovalInfo | undefined;
100
+ /** Wraps an API status with a typed `kind` and a user-facing message for 403 / 404; a 404 on the action endpoint means the schedule, not the rules, is gone. */
101
+ export declare const toJEScheduleApprovalAPIStatus: (status: ZeniAPIStatus, context?: "rules" | "action") => JEScheduleApprovalAPIStatus;
@@ -0,0 +1,158 @@
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 ?? undefined,
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
+ entriesSource: payload.entries_source,
110
+ entriesVersion: payload.entries_version,
111
+ approverLabels: payload.approver_labels,
112
+ approverRoles: payload.approver_roles,
113
+ approverUserIds: payload.approver_user_ids,
114
+ matchedRuleIds: payload.matched_rule_ids,
115
+ matchedRuleName: payload.matched_rule_name ?? undefined,
116
+ matchedRuleOwner: payload.matched_rule_owner != null
117
+ ? (0, jeScheduleApprovalRuleTypes_1.toJEApprovalOwner)(payload.matched_rule_owner)
118
+ : undefined,
119
+ monthlyAmount: payload.monthly_amount ?? undefined,
120
+ ruleMin: payload.rule_min ?? undefined,
121
+ separationOfDuties: payload.separation_of_duties,
122
+ preparerUserId: payload.preparer_user_id ?? undefined,
123
+ unevaluableReason: payload.unevaluable_reason ?? undefined,
124
+ message: payload.message,
125
+ };
126
+ };
127
+ exports.toJEScheduleApprovalInfo = toJEScheduleApprovalInfo;
128
+ const toJEApprovalErrorKind = (code) => {
129
+ switch (code) {
130
+ case 403:
131
+ return 'forbidden';
132
+ case 409:
133
+ return 'conflict';
134
+ case 400:
135
+ return 'validation';
136
+ case 404:
137
+ return 'not_found';
138
+ default:
139
+ return 'unknown';
140
+ }
141
+ };
142
+ const USER_FACING_MESSAGES = {
143
+ forbidden: 'You are not allowed to perform this action.',
144
+ conflict: undefined, // already-claimed and stale-draft both arrive with a user-facing message
145
+ validation: undefined, // backend's status.message is already user-facing
146
+ not_found: 'JE schedule approval rules are not available for this account.',
147
+ unknown: undefined,
148
+ };
149
+ const SCHEDULE_NOT_FOUND_MESSAGE = 'This schedule no longer exists.';
150
+ /** Wraps an API status with a typed `kind` and a user-facing message for 403 / 404; a 404 on the action endpoint means the schedule, not the rules, is gone. */
151
+ const toJEScheduleApprovalAPIStatus = (status, context = 'rules') => {
152
+ const kind = toJEApprovalErrorKind(status.code);
153
+ const message = kind === 'not_found' && context === 'action'
154
+ ? status.message || SCHEDULE_NOT_FOUND_MESSAGE
155
+ : (USER_FACING_MESSAGES[kind] ?? status.message);
156
+ return { ...status, kind, message };
157
+ };
158
+ exports.toJEScheduleApprovalAPIStatus = toJEScheduleApprovalAPIStatus;
@@ -0,0 +1,91 @@
1
+ import { ID } from '../../commonStateTypes/common';
2
+ import { ZeniAPIStatus } from '../../responsePayload';
3
+ import { ZeniDate } from '../../zeniDayJS';
4
+ import { JEApprovalEntriesSource, 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
+ subType: JEApprovalRoleSubType;
18
+ level?: number;
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
+ /** 'parked' when the detail read served the rows saved while held; 'live' otherwise. */
75
+ entriesSource: JEApprovalEntriesSource;
76
+ /** Echoed back on approve; the server answers 409 when the draft was re-parked since. */
77
+ entriesVersion: number;
78
+ matchedRuleIds: ID[];
79
+ message: string;
80
+ requiresApproval: boolean;
81
+ separationOfDuties: boolean;
82
+ matchedRuleName?: string;
83
+ matchedRuleOwner?: JEApprovalOwner;
84
+ monthlyAmount?: number;
85
+ preparerUserId?: ID;
86
+ ruleMin?: number;
87
+ unevaluableReason?: string;
88
+ }
89
+ export interface JEScheduleApprovalAPIStatus extends ZeniAPIStatus {
90
+ kind: JEApprovalErrorKind;
91
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,34 @@
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_ZENI_ROLE_SUB_TYPES: readonly ["reviewer", "controller"];
13
+ /** Role actors valid only on customer-owned rules. */
14
+ export declare const JE_APPROVAL_CUSTOMER_ROLE_SUB_TYPES: readonly ["customer_super_admin", "customer_finance_admin"];
15
+ export declare const JE_APPROVAL_ROLE_SUB_TYPES: readonly ["reviewer", "controller", "customer_super_admin", "customer_finance_admin"];
16
+ export declare const toJEApprovalRoleSubType: (v: string) => "reviewer" | "controller" | "customer_super_admin" | "customer_finance_admin";
17
+ export declare const toJEApprovalRoleSubTypeStrict: (v: string) => "reviewer" | "controller" | "customer_super_admin" | "customer_finance_admin" | undefined;
18
+ export type JEApprovalRoleSubType = ReturnType<typeof toJEApprovalRoleSubType>;
19
+ export declare const JE_APPROVAL_ACTIONS: readonly ["approve", "reject", "save_draft"];
20
+ export type JEApprovalAction = (typeof JE_APPROVAL_ACTIONS)[number];
21
+ export declare const JE_LEVEL_PREPARER = 1;
22
+ export declare const JE_LEVEL_REVIEWER = 2;
23
+ export declare const JE_LEVEL_CONTROLLER = 3;
24
+ export declare const JE_LEVEL_LABELS: Record<number, string>;
25
+ export declare const JE_SCHEDULE_TYPE_LABELS: Record<JEScheduleType, string>;
26
+ /**
27
+ * Typed failure kinds for the approval-rule / approval-action endpoints.
28
+ * 403 = viewer may not edit (or touched the other owner's rule / is not an
29
+ * eligible approver / SoD); 409 = someone else already approved.
30
+ */
31
+ export declare const JE_APPROVAL_ENTRIES_SOURCES: readonly ["parked", "live"];
32
+ export type JEApprovalEntriesSource = (typeof JE_APPROVAL_ENTRIES_SOURCES)[number];
33
+ export declare const JE_APPROVAL_ERROR_KINDS: readonly ["forbidden", "conflict", "validation", "not_found", "unknown"];
34
+ export type JEApprovalErrorKind = (typeof JE_APPROVAL_ERROR_KINDS)[number];
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JE_APPROVAL_ERROR_KINDS = exports.JE_APPROVAL_ENTRIES_SOURCES = 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.JE_APPROVAL_CUSTOMER_ROLE_SUB_TYPES = exports.JE_APPROVAL_ZENI_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_ZENI_ROLE_SUB_TYPES = [
26
+ 'reviewer',
27
+ 'controller',
28
+ ];
29
+ /** Role actors valid only on customer-owned rules. */
30
+ exports.JE_APPROVAL_CUSTOMER_ROLE_SUB_TYPES = [
31
+ 'customer_super_admin',
32
+ 'customer_finance_admin',
33
+ ];
34
+ exports.JE_APPROVAL_ROLE_SUB_TYPES = [
35
+ ...exports.JE_APPROVAL_ZENI_ROLE_SUB_TYPES,
36
+ ...exports.JE_APPROVAL_CUSTOMER_ROLE_SUB_TYPES,
37
+ ];
38
+ const toJEApprovalRoleSubType = (v) => (0, stringToUnion_1.stringToUnion)(v, exports.JE_APPROVAL_ROLE_SUB_TYPES);
39
+ exports.toJEApprovalRoleSubType = toJEApprovalRoleSubType;
40
+ const toJEApprovalRoleSubTypeStrict = (v) => (0, stringToUnion_1.stringToUnionStrict)(v, exports.JE_APPROVAL_ROLE_SUB_TYPES);
41
+ exports.toJEApprovalRoleSubTypeStrict = toJEApprovalRoleSubTypeStrict;
42
+ exports.JE_APPROVAL_ACTIONS = ['approve', 'reject', 'save_draft'];
43
+ exports.JE_LEVEL_PREPARER = 1;
44
+ exports.JE_LEVEL_REVIEWER = 2;
45
+ exports.JE_LEVEL_CONTROLLER = 3;
46
+ exports.JE_LEVEL_LABELS = {
47
+ [exports.JE_LEVEL_PREPARER]: 'Preparer',
48
+ [exports.JE_LEVEL_REVIEWER]: 'Reviewer',
49
+ [exports.JE_LEVEL_CONTROLLER]: 'Controller',
50
+ };
51
+ exports.JE_SCHEDULE_TYPE_LABELS = {
52
+ prepaid_expenses: 'Prepaid Expenses',
53
+ fixed_assets: 'Fixed Assets',
54
+ accrued_expenses: 'Accrued Expenses',
55
+ };
56
+ /**
57
+ * Typed failure kinds for the approval-rule / approval-action endpoints.
58
+ * 403 = viewer may not edit (or touched the other owner's rule / is not an
59
+ * eligible approver / SoD); 409 = someone else already approved.
60
+ */
61
+ exports.JE_APPROVAL_ENTRIES_SOURCES = ['parked', 'live'];
62
+ exports.JE_APPROVAL_ERROR_KINDS = [
63
+ 'forbidden',
64
+ 'conflict',
65
+ 'validation',
66
+ 'not_found',
67
+ 'unknown',
68
+ ];
@@ -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;
@@ -166,6 +168,7 @@ export interface JEOneTimeAccrualPayload {
166
168
  actual_post_date?: string | null;
167
169
  actual_reversal_post_date?: string | null;
168
170
  ai_suggestion?: JEOneTimeAccrualAiSuggestionPayload | null;
171
+ approval_info?: JEScheduleApprovalInfoPayload | null;
169
172
  automation_tier?: string | null;
170
173
  cleared?: JEOneTimeAccrualClearedPayload | null;
171
174
  created_by_user?: UserPayload | null;
@@ -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
@@ -514,6 +517,7 @@ function toJEOneTimeAccrual(payload) {
514
517
  automationTier: payload.automation_tier != null
515
518
  ? (0, jeSchedulesTypes_1.toOneTimeAccrualAutomationTierType)(payload.automation_tier)
516
519
  : undefined,
520
+ approvalInfo: (0, jeScheduleApprovalRulePayload_1.toJEScheduleApprovalInfo)(payload.approval_info),
517
521
  estimatedAmount: toOneTimeAccrualAmount(payload.estimated_amount, payload.currency),
518
522
  memo: payload.memo ?? '',
519
523
  profileSnapshot: toJEOneTimeAccrualProfileSnapshot(payload.profile_snapshot, payload.currency),
@@ -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
+ /** Schedules are keyed by transaction / accrued key, not schedule id, so this re-indexes both maps by schedule id. */
89
+ export declare const getApprovalInfoByScheduleId: (jeSchedulesState: JESchedulesState) => Record<ID, JEScheduleApprovalInfo>;
90
+ export declare const getScheduleApprovalInfo: (jeSchedulesState: JESchedulesState, jeScheduleId: ID) => JEScheduleApprovalInfo | undefined;
91
+ /** One-time accruals are keyed by accrual id, so this is a direct lookup, unlike the schedule scan. */
92
+ export declare const getOneTimeAccrualApprovalInfo: (jeSchedulesState: JESchedulesState, accrualId: ID) => JEScheduleApprovalInfo | undefined;
@@ -3,7 +3,8 @@ 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.getOneTimeAccrualApprovalInfo = exports.getScheduleApprovalInfo = exports.getApprovalInfoByScheduleId = exports.getJEScheduledTransactionByJEScheduleTransactionKey = exports.getJEAccruedScheduleByJEScheduleKey = exports.getJEOneTimeAccrualByKey = void 0;
7
+ const toolkit_1 = require("@reduxjs/toolkit");
7
8
  const get_1 = __importDefault(require("lodash/get"));
8
9
  const amount_1 = require("../../commonStateTypes/amount");
9
10
  const accountSelector_1 = require("../account/accountSelector");
@@ -11,6 +12,7 @@ const classSelector_1 = require("../class/classSelector");
11
12
  const transactionSelector_1 = require("../transaction/transactionSelector");
12
13
  const userSelector_1 = require("../user/userSelector");
13
14
  const vendorSelector_1 = require("../vendor/vendorSelector");
15
+ const jeScheduleHelper_1 = require("./jeScheduleHelper");
14
16
  // Takes the slice, not RootState: an accrual denormalizes its vendor, account and class names, so
15
17
  // unlike getJEAccruedScheduleByJEScheduleKey this joins nothing.
16
18
  //
@@ -176,3 +178,21 @@ const getJEScheduledTransactionByJEScheduleTransactionKey = (jeScheduleTransacti
176
178
  };
177
179
  };
178
180
  exports.getJEScheduledTransactionByJEScheduleTransactionKey = getJEScheduledTransactionByJEScheduleTransactionKey;
181
+ /** Schedules are keyed by transaction / accrued key, not schedule id, so this re-indexes both maps by schedule id. */
182
+ exports.getApprovalInfoByScheduleId = (0, toolkit_1.createSelector)((jeSchedulesState) => jeSchedulesState.schedulesByTransactionKey, (jeSchedulesState) => jeSchedulesState.schedulesByAccruedJEScheduleKey, (schedulesByTransactionKey, schedulesByAccruedJEScheduleKey) => {
183
+ const byScheduleId = {};
184
+ [
185
+ ...Object.values(schedulesByTransactionKey),
186
+ ...Object.values(schedulesByAccruedJEScheduleKey),
187
+ ].forEach((schedule) => {
188
+ if (schedule.jeScheduleId != null && schedule.approvalInfo != null) {
189
+ byScheduleId[schedule.jeScheduleId] = schedule.approvalInfo;
190
+ }
191
+ });
192
+ return byScheduleId;
193
+ });
194
+ const getScheduleApprovalInfo = (jeSchedulesState, jeScheduleId) => (0, get_1.default)((0, exports.getApprovalInfoByScheduleId)(jeSchedulesState), jeScheduleId, undefined);
195
+ exports.getScheduleApprovalInfo = getScheduleApprovalInfo;
196
+ /** One-time accruals are keyed by accrual id, so this is a direct lookup, unlike the schedule scan. */
197
+ const getOneTimeAccrualApprovalInfo = (jeSchedulesState, accrualId) => (0, get_1.default)(jeSchedulesState.oneTimeAccrualsByKey, (0, jeScheduleHelper_1.generateJEOneTimeAccrualKey)(accrualId), undefined)?.approvalInfo;
198
+ exports.getOneTimeAccrualApprovalInfo = getOneTimeAccrualApprovalInfo;
@@ -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;
@@ -252,6 +254,8 @@ export interface JEOneTimeAccrualState {
252
254
  actualPostDate?: ZeniDate;
253
255
  actualReversalPostDate?: ZeniDate;
254
256
  aiSuggestion?: JEOneTimeAccrualAiSuggestion;
257
+ /** Set only on a draft an approval rule holds; see JEScheduledTransactionState.approvalInfo. */
258
+ approvalInfo?: JEScheduleApprovalInfo;
255
259
  automationTier?: OneTimeAccrualAutomationTierType;
256
260
  cleared?: JEOneTimeAccrualCleared;
257
261
  createdBy?: JEOneTimeAccrualCreator;