law-common 13.0.3-beta.7 → 13.0.3-beta.8

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.
@@ -0,0 +1,8 @@
1
+ export declare enum ProjectActionEnum {
2
+ CREATE = "CREATE",
3
+ UPDATE = "UPDATE",
4
+ DELETE = "DELETE",
5
+ DEACTIVATE = "DEACTIVATE",
6
+ ACTIVATE = "ACTIVATE",
7
+ RESTORE = "RESTORE"
8
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProjectActionEnum = void 0;
4
+ var ProjectActionEnum;
5
+ (function (ProjectActionEnum) {
6
+ ProjectActionEnum["CREATE"] = "CREATE";
7
+ ProjectActionEnum["UPDATE"] = "UPDATE";
8
+ ProjectActionEnum["DELETE"] = "DELETE";
9
+ ProjectActionEnum["DEACTIVATE"] = "DEACTIVATE";
10
+ ProjectActionEnum["ACTIVATE"] = "ACTIVATE";
11
+ ProjectActionEnum["RESTORE"] = "RESTORE";
12
+ // APPROVE = "APPROVE",
13
+ // REJECT = "REJECT",
14
+ // RECALL = "RECALL",
15
+ // REQUEST_CHANGES = "REQUEST_CHANGES",
16
+ // CHANGES_DONE = "CHANGES_DONE",
17
+ })(ProjectActionEnum || (exports.ProjectActionEnum = ProjectActionEnum = {}));
@@ -0,0 +1,12 @@
1
+ import { FlowConfig } from "./flow-config.type";
2
+ import { ProjectActionEnum } from "../enums/project_action_enum";
3
+ import { ProjectStatusEnum } from "../enums/project_status_enum";
4
+ export interface IProjectFlowConfigContextData {
5
+ }
6
+ /**
7
+ * COMPLETED, ON_HOLD, SUSPENDED, CANCELLED and ARCHIVED have no block. Nothing transitions into them
8
+ * and nothing transitions out - they are declared on the enum but inert in this flow. Giving them
9
+ * transitions means designing the project lifecycle, which is out of scope for LW-827's
10
+ * auto-approval template and needs its own ticket.
11
+ */
12
+ export declare const projectFlowConfig: FlowConfig<ProjectStatusEnum, ProjectActionEnum, IProjectFlowConfigContextData>;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.projectFlowConfig = void 0;
4
+ const base_flow_config_factory_1 = require("./base-flow-config.factory");
5
+ const project_action_enum_1 = require("../enums/project_action_enum");
6
+ const project_status_enum_1 = require("../enums/project_status_enum");
7
+ /**
8
+ * project is the one Tier 2 entity whose flow is MAPPED onto the existing status vocabulary rather
9
+ * than realigned to APPROVED / DEACTIVATED / DELETED. Every other Tier 2 entity was realigned; this
10
+ * one deliberately is not, for three reasons:
11
+ *
12
+ * 1. It already has all three canonical states, under two different names. ACTIVE is the live state
13
+ * (the APPROVED role), INACTIVE is the deactivated state, and DELETED exists verbatim. The presence
14
+ * of a separate DELETED is what disambiguates INACTIVE here - on the master tables that shared an
15
+ * ACTIVE / DEACTIVE / INACTIVE triple, INACTIVE was the tombstone and mapped to DELETED. That
16
+ * mapping does not transfer to project.
17
+ *
18
+ * 2. The other five members are domain vocabulary, not generator boilerplate. COMPLETED, ON_HOLD,
19
+ * SUSPENDED, CANCELLED and ARCHIVED describe real project lifecycle states somebody chose to
20
+ * declare. They are unwritten today, but discarding them to fit a six-action template would throw
21
+ * away design intent rather than dead code.
22
+ *
23
+ * 3. `project.status` is a public API field. It is required on ProjectCreateDto and optional on
24
+ * ProjectUpdateDto, both validated with @IsEnum, so renaming a member is an API contract change
25
+ * for every client, not just a data migration.
26
+ *
27
+ * So the transitions below are the ticket's auto-approval shape with ACTIVE standing in for APPROVED
28
+ * and INACTIVE for DEACTIVATED. The five domain statuses are reachable targets of nothing and carry no
29
+ * block of their own - a project in any of them has no action available through this flow, which is
30
+ * honest about the fact that nothing transitions into or out of them today.
31
+ */
32
+ const PROJECT_CREATE_PERMISSION = ["PROJECT_CREATE"];
33
+ const PROJECT_UPDATE_PERMISSION = ["PROJECT_UPDATE"];
34
+ const PROJECT_DELETE_PERMISSION = ["PROJECT_DELETE"];
35
+ const PROJECT_DEACTIVATE_PERMISSION = ["PROJECT_DEACTIVATE"];
36
+ const PROJECT_ACTIVATE_PERMISSION = ["PROJECT_ACTIVATE"];
37
+ const PROJECT_RESTORE_PERMISSION = ["PROJECT_RESTORE"];
38
+ const ACTION_MAP = {
39
+ [project_action_enum_1.ProjectActionEnum.CREATE]: {
40
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.ACTIVE],
41
+ permissions: PROJECT_CREATE_PERMISSION,
42
+ },
43
+ [project_action_enum_1.ProjectActionEnum.UPDATE]: {
44
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.ACTIVE],
45
+ permissions: PROJECT_UPDATE_PERMISSION,
46
+ },
47
+ [project_action_enum_1.ProjectActionEnum.DELETE]: {
48
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.DELETED],
49
+ permissions: PROJECT_DELETE_PERMISSION,
50
+ },
51
+ [project_action_enum_1.ProjectActionEnum.DEACTIVATE]: {
52
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.INACTIVE],
53
+ permissions: PROJECT_DEACTIVATE_PERMISSION,
54
+ },
55
+ [project_action_enum_1.ProjectActionEnum.ACTIVATE]: {
56
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.ACTIVE],
57
+ permissions: PROJECT_ACTIVATE_PERMISSION,
58
+ },
59
+ [project_action_enum_1.ProjectActionEnum.RESTORE]: {
60
+ reachableStatues: [project_status_enum_1.ProjectStatusEnum.ACTIVE],
61
+ permissions: PROJECT_RESTORE_PERMISSION,
62
+ },
63
+ };
64
+ const { createActionConfig } = (0, base_flow_config_factory_1.createFlowConfigFactory)()(ACTION_MAP);
65
+ // ACTIVE status transitions - the APPROVED role
66
+ const transitionActiveStatusUpdateAction = createActionConfig(project_action_enum_1.ProjectActionEnum.UPDATE, project_status_enum_1.ProjectStatusEnum.ACTIVE);
67
+ const transitionActiveStatusDeleteAction = createActionConfig(project_action_enum_1.ProjectActionEnum.DELETE, project_status_enum_1.ProjectStatusEnum.DELETED);
68
+ const transitionActiveStatusDeactivateAction = createActionConfig(project_action_enum_1.ProjectActionEnum.DEACTIVATE, project_status_enum_1.ProjectStatusEnum.INACTIVE);
69
+ // INACTIVE status transitions - the DEACTIVATED role
70
+ const transitionInactiveStatusDeleteAction = createActionConfig(project_action_enum_1.ProjectActionEnum.DELETE, project_status_enum_1.ProjectStatusEnum.DELETED);
71
+ const transitionInactiveStatusActivateAction = createActionConfig(project_action_enum_1.ProjectActionEnum.ACTIVATE, project_status_enum_1.ProjectStatusEnum.ACTIVE);
72
+ // DELETED status transitions
73
+ const transitionDeletedStatusUpdateAction = createActionConfig(project_action_enum_1.ProjectActionEnum.UPDATE, project_status_enum_1.ProjectStatusEnum.ACTIVE);
74
+ const transitionDeletedStatusRestoreAction = createActionConfig(project_action_enum_1.ProjectActionEnum.RESTORE, project_status_enum_1.ProjectStatusEnum.ACTIVE);
75
+ /**
76
+ * COMPLETED, ON_HOLD, SUSPENDED, CANCELLED and ARCHIVED have no block. Nothing transitions into them
77
+ * and nothing transitions out - they are declared on the enum but inert in this flow. Giving them
78
+ * transitions means designing the project lifecycle, which is out of scope for LW-827's
79
+ * auto-approval template and needs its own ticket.
80
+ */
81
+ exports.projectFlowConfig = {
82
+ [project_status_enum_1.ProjectStatusEnum.ACTIVE]: {
83
+ actions: {
84
+ [project_action_enum_1.ProjectActionEnum.UPDATE]: transitionActiveStatusUpdateAction,
85
+ [project_action_enum_1.ProjectActionEnum.DELETE]: transitionActiveStatusDeleteAction,
86
+ [project_action_enum_1.ProjectActionEnum.DEACTIVATE]: transitionActiveStatusDeactivateAction,
87
+ },
88
+ },
89
+ [project_status_enum_1.ProjectStatusEnum.INACTIVE]: {
90
+ actions: {
91
+ [project_action_enum_1.ProjectActionEnum.DELETE]: transitionInactiveStatusDeleteAction,
92
+ [project_action_enum_1.ProjectActionEnum.ACTIVATE]: transitionInactiveStatusActivateAction,
93
+ },
94
+ },
95
+ [project_status_enum_1.ProjectStatusEnum.DELETED]: {
96
+ actions: {
97
+ [project_action_enum_1.ProjectActionEnum.UPDATE]: transitionDeletedStatusUpdateAction,
98
+ [project_action_enum_1.ProjectActionEnum.RESTORE]: transitionDeletedStatusRestoreAction,
99
+ },
100
+ },
101
+ };
@@ -305,7 +305,9 @@ export * from "./model/billing_profile.entity.model";
305
305
  export * from "./enums/project_billing_type_enum";
306
306
  export * from "./enums/project_revenue_split_enum";
307
307
  export * from "./enums/project_revenue_split_mapping_status_enum";
308
+ export * from "./enums/project_action_enum";
308
309
  export * from "./enums/project_status_enum";
310
+ export * from "./flow-configs/project_flow.config";
309
311
  export * from "./enums/project_usage_notification_threshold_enum";
310
312
  export * from "./interface/project_revenue_split_mapping.entity.interface";
311
313
  export * from "./interface/field-constraint/project_revenue_split_mapping_field_constraints.interface";
@@ -321,7 +321,9 @@ __exportStar(require("./model/billing_profile.entity.model"), exports);
321
321
  __exportStar(require("./enums/project_billing_type_enum"), exports);
322
322
  __exportStar(require("./enums/project_revenue_split_enum"), exports);
323
323
  __exportStar(require("./enums/project_revenue_split_mapping_status_enum"), exports);
324
+ __exportStar(require("./enums/project_action_enum"), exports);
324
325
  __exportStar(require("./enums/project_status_enum"), exports);
326
+ __exportStar(require("./flow-configs/project_flow.config"), exports);
325
327
  __exportStar(require("./enums/project_usage_notification_threshold_enum"), exports);
326
328
  __exportStar(require("./interface/project_revenue_split_mapping.entity.interface"), exports);
327
329
  __exportStar(require("./interface/field-constraint/project_revenue_split_mapping_field_constraints.interface"), exports);
@@ -1,3 +1,7 @@
1
+ import { ProjectActionEnum } from "../enums/project_action_enum";
2
+ import { IProjectFlowConfigContextData } from "../flow-configs/project_flow.config";
3
+ import { IUserEntity } from "../interface/user.entity.interface";
4
+ import { IRowActions } from "./interface/row-actions.interface";
1
5
  import { IProjectUserDto } from "../../api";
2
6
  import { CurrencyEnum } from "../../enums";
3
7
  import { ProjectBillingTypeEnum } from "../enums/project_billing_type_enum";
@@ -66,4 +70,15 @@ export declare class ProjectEntityModel extends BaseEntityModel<EntityEnum.PROJE
66
70
  timesheets: TimesheetEntityModel[];
67
71
  }[];
68
72
  }>;
73
+ getNextStatus(currentUser: IUserEntity, action: ProjectActionEnum, projectFlowConfigContextData: IProjectFlowConfigContextData): ProjectStatusEnum;
74
+ getAvailableActions(currentUser: UserEntityModel, config?: {
75
+ combinedActions?: Record<string, {
76
+ combineActions: ProjectActionEnum[];
77
+ label: string;
78
+ }>;
79
+ customLabels?: Partial<Record<ProjectActionEnum, string>>;
80
+ }): IRowActions<EntityEnum.PROJECT>[];
81
+ getUpdateActionVisibility(currentUser: UserEntityModel): {
82
+ [key: string]: () => boolean;
83
+ };
69
84
  }
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ProjectEntityModel = void 0;
4
+ const error_key_enum_1 = require("../../enums/error.key.enum");
5
+ const exceptions_1 = require("../../exceptions");
6
+ const utils_1 = require("../../utils");
7
+ const project_flow_config_1 = require("../flow-configs/project_flow.config");
4
8
  const enums_1 = require("../../enums");
5
9
  const helper_fn_util_1 = require("../../utils/helper.fn.util");
6
10
  const project_billing_type_enum_1 = require("../enums/project_billing_type_enum");
@@ -155,6 +159,64 @@ class ProjectEntityModel extends base_entity_model_1.BaseEntityModel {
155
159
  }
156
160
  return result;
157
161
  }
162
+ getNextStatus(currentUser, action, projectFlowConfigContextData) {
163
+ if (!this.status) {
164
+ throw new exceptions_1.AppBadRequestException({
165
+ key: error_key_enum_1.ErrorKeyEnum.STATUS,
166
+ message: [`Status not found: ${this.status}`],
167
+ });
168
+ }
169
+ const flowForStatus = project_flow_config_1.projectFlowConfig[this.status];
170
+ if (!flowForStatus) {
171
+ throw new exceptions_1.AppBadRequestException({
172
+ key: error_key_enum_1.ErrorKeyEnum.STATUS,
173
+ message: [`No flow configuration found for status: ${this.status}`],
174
+ });
175
+ }
176
+ if (!action) {
177
+ throw new exceptions_1.AppBadRequestException({
178
+ key: error_key_enum_1.ErrorKeyEnum.ACTION_DATA,
179
+ message: ["actionData is required"],
180
+ });
181
+ }
182
+ const matchingPermissionConfig = flowForStatus.actions[action];
183
+ if (!matchingPermissionConfig) {
184
+ throw new exceptions_1.AppBadRequestException({
185
+ key: error_key_enum_1.ErrorKeyEnum.ACTION,
186
+ message: [`Action '${action}' is not valid for the current status.`],
187
+ });
188
+ }
189
+ if (!currentUser.permissions || currentUser.permissions.length === 0) {
190
+ throw new exceptions_1.AppBadRequestException({
191
+ key: error_key_enum_1.ErrorKeyEnum.PERMISSIONS,
192
+ message: ["Permission not available for currentUser"],
193
+ });
194
+ }
195
+ const hasPermission = matchingPermissionConfig.permissions.some((permission) => currentUser.permissions.includes(permission));
196
+ if (!hasPermission) {
197
+ throw new exceptions_1.AppBadRequestException({
198
+ key: error_key_enum_1.ErrorKeyEnum.PERMISSION,
199
+ message: [`Current user does not have permission to ${action} project`],
200
+ });
201
+ }
202
+ const nextStatus = matchingPermissionConfig.next(projectFlowConfigContextData);
203
+ return nextStatus;
204
+ }
205
+ getAvailableActions(currentUser, config) {
206
+ var _a;
207
+ const params = {
208
+ flowConfig: project_flow_config_1.projectFlowConfig,
209
+ currentStatus: this.status,
210
+ userPermissions: (_a = currentUser.permissions) !== null && _a !== void 0 ? _a : [],
211
+ visibilityData: this.getUpdateActionVisibility.bind(this, currentUser),
212
+ combinedActions: config === null || config === void 0 ? void 0 : config.combinedActions,
213
+ customLabels: config === null || config === void 0 ? void 0 : config.customLabels,
214
+ };
215
+ return utils_1.EntityActionFlowResolverV2.getAvailableActionsData(params);
216
+ }
217
+ getUpdateActionVisibility(currentUser) {
218
+ return {};
219
+ }
158
220
  }
159
221
  exports.ProjectEntityModel = ProjectEntityModel;
160
222
  ProjectEntityModel.relationConfigs = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "law-common",
3
- "version": "13.0.3-beta.7",
3
+ "version": "13.0.3-beta.8",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "files": [