@oneuptime/common 7.0.3887 → 7.0.3899

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,48 @@
1
+ import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import WorkspaceNotificationRuleService, {
3
+ Service as WorkspaceNotificationRuleServiceType,
4
+ } from "../Services/WorkspaceNotificationRuleService";
5
+ import {
6
+ ExpressRequest,
7
+ ExpressResponse,
8
+ NextFunction,
9
+ } from "../Utils/Express";
10
+ import Response from "../Utils/Response";
11
+ import BaseAPI from "./BaseAPI";
12
+ import CommonAPI from "./CommonAPI";
13
+ import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
14
+ import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNotificationRule";
15
+ import ObjectID from "../../Types/ObjectID";
16
+
17
+ export default class WorkspaceNotificationRuleAPI extends BaseAPI<
18
+ WorkspaceNotificationRule,
19
+ WorkspaceNotificationRuleServiceType
20
+ > {
21
+ public constructor() {
22
+ super(WorkspaceNotificationRule, WorkspaceNotificationRuleService);
23
+
24
+ this.router.get(
25
+ `${new this.entityType().getCrudApiPath()?.toString()}/test/:workspaceNotifcationRuleId`,
26
+ UserMiddleware.getUserMiddleware,
27
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
28
+ try {
29
+ const databaseProps: DatabaseCommonInteractionProps =
30
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
31
+
32
+ await this.service.testRule({
33
+ ruleId: new ObjectID(
34
+ req.params["workspaceNotifcationRuleId"] as string,
35
+ ),
36
+ props: databaseProps,
37
+ projectId: databaseProps.tenantId!,
38
+ testByUserId: databaseProps.userId!,
39
+ });
40
+
41
+ return Response.sendEmptySuccessResponse(req, res);
42
+ } catch (e) {
43
+ next(e);
44
+ }
45
+ },
46
+ );
47
+ }
48
+ }
@@ -302,7 +302,9 @@ export class Service extends DatabaseService<Model> {
302
302
  return 0;
303
303
  }
304
304
 
305
- return lastIncident.incidentNumber || 0;
305
+ return lastIncident.incidentNumber
306
+ ? Number(lastIncident.incidentNumber)
307
+ : 0;
306
308
  }
307
309
 
308
310
  @CaptureSpan()
@@ -38,6 +38,8 @@ import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNot
38
38
  import UserService from "./UserService";
39
39
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
40
40
  import Monitor from "../../Models/DatabaseModels/Monitor";
41
+ import Text from "../../Types/Text";
42
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
41
43
 
42
44
  export interface MessageBlocksByWorkspaceType {
43
45
  workspaceType: WorkspaceType;
@@ -56,6 +58,209 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
56
58
  super(WorkspaceNotificationRule);
57
59
  }
58
60
 
61
+ @CaptureSpan()
62
+ public async testRule(data: {
63
+ ruleId: ObjectID;
64
+ projectId: ObjectID;
65
+ testByUserId: ObjectID; // this can be useful to invite user to channels if the channels was created.
66
+ props: DatabaseCommonInteractionProps;
67
+ }): Promise<void> {
68
+ const rule: WorkspaceNotificationRule | null = await this.findOneById({
69
+ id: data.ruleId,
70
+ select: {
71
+ notificationRule: true,
72
+ workspaceType: true,
73
+ eventType: true,
74
+ name: true,
75
+ },
76
+ props: {
77
+ isRoot: true,
78
+ },
79
+ });
80
+
81
+ if (!rule) {
82
+ throw new BadDataException("Rule not found");
83
+ }
84
+
85
+ // check fi the testUser account is connected to workspace or not.
86
+ const userWOrkspaceAuth: WorkspaceUserAuthToken | null =
87
+ await WorkspaceUserAuthTokenService.findOneBy({
88
+ query: {
89
+ projectId: data.projectId,
90
+ userId: data.testByUserId,
91
+ workspaceType: rule.workspaceType!,
92
+ },
93
+ select: {
94
+ workspaceUserId: true,
95
+ },
96
+ props: {
97
+ isRoot: true,
98
+ },
99
+ });
100
+
101
+ if (!userWOrkspaceAuth || !userWOrkspaceAuth.workspaceUserId) {
102
+ throw new BadDataException(
103
+ "This account is not connected to " +
104
+ rule.workspaceType +
105
+ ". Please go to User Settings and connect the account.",
106
+ );
107
+ }
108
+
109
+ const projectAuth: WorkspaceProjectAuthToken | null =
110
+ await WorkspaceProjectAuthTokenService.findOneBy({
111
+ query: {
112
+ projectId: data.projectId,
113
+ workspaceType: rule.workspaceType!,
114
+ },
115
+ select: {
116
+ workspaceType: true,
117
+ authToken: true,
118
+ },
119
+ props: {
120
+ isRoot: true,
121
+ },
122
+ });
123
+
124
+ if (!projectAuth) {
125
+ throw new BadDataException(
126
+ "This project is not connected to " +
127
+ rule.workspaceType +
128
+ ". Please go to Project Settings and connect the account.",
129
+ );
130
+ }
131
+
132
+ const projectAuthToken: string = projectAuth.authToken!;
133
+
134
+ const notificationRule: BaseNotificationRule =
135
+ rule.notificationRule as BaseNotificationRule;
136
+
137
+ // now send test message to these channels.
138
+ const messageBlocksByWorkspaceTypes: Array<MessageBlocksByWorkspaceType> =
139
+ [];
140
+
141
+ // use markdown to create blocks
142
+ messageBlocksByWorkspaceTypes.push({
143
+ workspaceType: rule.workspaceType!,
144
+ messageBlocks: [
145
+ {
146
+ _type: "WorkspacePayloadMarkdown",
147
+ text: `This is a test message for rule **${rule.name}**`,
148
+ } as WorkspacePayloadMarkdown,
149
+ ],
150
+ });
151
+
152
+ let existingChannelNames: Array<string> = [];
153
+
154
+ let createdChannels: NotificationRuleWorkspaceChannel[] = [];
155
+
156
+ if ((notificationRule as IncidentNotificationRule).shouldCreateNewChannel) {
157
+ const generateRandomString: string = Text.generateRandomText(5);
158
+
159
+ try {
160
+ // create channel
161
+ createdChannels = await this.createChannelsBasedOnRules({
162
+ projectOrUserAuthTokenForWorkspace: projectAuthToken,
163
+ workspaceType: rule.workspaceType!,
164
+ notificationRules: [rule],
165
+ channelNameSiffix: generateRandomString,
166
+ notificationEventType: rule.eventType!,
167
+ });
168
+ } catch (err) {
169
+ throw new BadDataException(
170
+ "Cannot create a new channel. " + (err as Error)?.message,
171
+ );
172
+ }
173
+
174
+ try {
175
+ await this.inviteUsersBasedOnRulesAndWorkspaceChannels({
176
+ workspaceChannels: createdChannels,
177
+ projectId: data.projectId,
178
+ notificationRules: [rule],
179
+ userIds: [data.testByUserId],
180
+ });
181
+ } catch (err) {
182
+ throw new BadDataException(
183
+ "Cannot invite users to the channel. " + (err as Error)?.message,
184
+ );
185
+ }
186
+ }
187
+
188
+ if (notificationRule.shouldPostToExistingChannel) {
189
+ existingChannelNames = this.getExistingChannelNamesFromNotificationRules({
190
+ notificationRules: [notificationRule],
191
+ });
192
+
193
+ for (const channelName of existingChannelNames) {
194
+ try {
195
+ // check if these channels exist.
196
+ const channelExists: boolean =
197
+ await WorkspaceUtil.getWorkspaceTypeUtil(
198
+ rule.workspaceType!,
199
+ ).doesChannelExist({
200
+ authToken: projectAuthToken,
201
+ channelName: channelName,
202
+ });
203
+
204
+ if (!channelExists) {
205
+ throw new BadDataException(
206
+ `Channel ${channelName} does not exist.`,
207
+ );
208
+ }
209
+ } catch (err) {
210
+ throw new BadDataException((err as Error)?.message);
211
+ }
212
+ }
213
+
214
+ // post message
215
+
216
+ for (const createdChannel of createdChannels) {
217
+ try {
218
+ await WorkspaceUtil.postMessageToAllWorkspaceChannelsAsBot({
219
+ projectId: data.projectId,
220
+ messagePayloadsByWorkspace: messageBlocksByWorkspaceTypes.map(
221
+ (messageBlocksByWorkspaceType: MessageBlocksByWorkspaceType) => {
222
+ return {
223
+ _type: "WorkspaceMessagePayload",
224
+ workspaceType: messageBlocksByWorkspaceType.workspaceType,
225
+ messageBlocks: messageBlocksByWorkspaceType.messageBlocks,
226
+ channelNames: [],
227
+ channelIds: [createdChannel.id],
228
+ };
229
+ },
230
+ ),
231
+ });
232
+ } catch (err) {
233
+ throw new BadDataException(
234
+ "Cannot post message to channel. " + (err as Error)?.message,
235
+ );
236
+ }
237
+ }
238
+
239
+ for (const existingChannelName of existingChannelNames) {
240
+ try {
241
+ await WorkspaceUtil.postMessageToAllWorkspaceChannelsAsBot({
242
+ projectId: data.projectId,
243
+ messagePayloadsByWorkspace: messageBlocksByWorkspaceTypes.map(
244
+ (messageBlocksByWorkspaceType: MessageBlocksByWorkspaceType) => {
245
+ return {
246
+ _type: "WorkspaceMessagePayload",
247
+ workspaceType: messageBlocksByWorkspaceType.workspaceType,
248
+ messageBlocks: messageBlocksByWorkspaceType.messageBlocks,
249
+ channelNames: [existingChannelName],
250
+ channelIds: [],
251
+ };
252
+ },
253
+ ),
254
+ });
255
+ } catch (err) {
256
+ throw new BadDataException(
257
+ "Cannot post message to channel. " + (err as Error)?.message,
258
+ );
259
+ }
260
+ }
261
+ }
262
+ }
263
+
59
264
  @CaptureSpan()
60
265
  public async sendWorkspaceMarkdownNotification(data: {
61
266
  projectId: ObjectID;
@@ -103,6 +308,7 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
103
308
  projectId: data.projectId,
104
309
  notificationRuleEventType: NotificationRuleEventType.Monitor,
105
310
  workspaceType: messageBlocksByWorkspaceType.workspaceType,
311
+ notificationFor: data.notificationFor,
106
312
  });
107
313
 
108
314
  let monitorChannels: Array<WorkspaceChannel> = [];
@@ -198,15 +404,17 @@ export class Service extends DatabaseService<WorkspaceNotificationRule> {
198
404
  projectId: ObjectID;
199
405
  workspaceType: WorkspaceType;
200
406
  notificationRuleEventType: NotificationRuleEventType;
407
+ notificationFor: NotificationFor;
201
408
  }): Promise<Array<string>> {
202
409
  logger.debug("getExistingChannelNamesBasedOnEventType called with data:");
203
410
  logger.debug(data);
204
411
 
205
412
  const notificationRules: Array<WorkspaceNotificationRule> =
206
- await this.getNotificationRules({
413
+ await this.getMatchingNotificationRules({
207
414
  projectId: data.projectId,
208
415
  workspaceType: data.workspaceType,
209
416
  notificationRuleEventType: data.notificationRuleEventType,
417
+ notificationFor: data.notificationFor,
210
418
  });
211
419
 
212
420
  logger.debug("Notification rules retrieved:");
@@ -30,6 +30,7 @@ import SlackifyMarkdown from "slackify-markdown";
30
30
  import { DropdownOption } from "../../../../UI/Components/Dropdown/Dropdown";
31
31
  import OneUptimeDate from "../../../../Types/Date";
32
32
  import CaptureSpan from "../../Telemetry/CaptureSpan";
33
+ import BadDataException from "../../../../Types/Exception/BadDataException";
33
34
 
34
35
  export default class SlackUtil extends WorkspaceBase {
35
36
  @CaptureSpan()
@@ -123,7 +124,10 @@ export default class SlackUtil extends WorkspaceBase {
123
124
  if ((result.jsonData as JSONObject)?.["ok"] !== true) {
124
125
  logger.error("Invalid response from Slack API:");
125
126
  logger.error(result.jsonData);
126
- throw new BadRequestException("Invalid response");
127
+ const messageFromSlack: string = (result.jsonData as JSONObject)?.[
128
+ "error"
129
+ ] as string;
130
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
127
131
  }
128
132
 
129
133
  logger.debug("Modal shown to user successfully.");
@@ -187,7 +191,10 @@ export default class SlackUtil extends WorkspaceBase {
187
191
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
188
192
  logger.error("Invalid response from Slack API:");
189
193
  logger.error(response.jsonData);
190
- throw new BadRequestException("Invalid response");
194
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
195
+ "error"
196
+ ] as string;
197
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
191
198
  }
192
199
 
193
200
  logger.debug("Channel joined successfully with data:");
@@ -240,7 +247,10 @@ export default class SlackUtil extends WorkspaceBase {
240
247
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
241
248
  logger.error("Invalid response from Slack API:");
242
249
  logger.error(response.jsonData);
243
- throw new BadRequestException("Invalid response");
250
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
251
+ "error"
252
+ ] as string;
253
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
244
254
  }
245
255
 
246
256
  logger.debug("User invited to channel successfully.");
@@ -344,7 +354,7 @@ export default class SlackUtil extends WorkspaceBase {
344
354
 
345
355
  if (!channels[data.channelName]) {
346
356
  logger.error("Channel not found.");
347
- throw new Error("Channel not found.");
357
+ throw new BadDataException("Channel not found.");
348
358
  }
349
359
 
350
360
  logger.debug("Workspace channel ID obtained:");
@@ -386,7 +396,10 @@ export default class SlackUtil extends WorkspaceBase {
386
396
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
387
397
  logger.error("Invalid response from Slack API:");
388
398
  logger.error(response.jsonData);
389
- throw new BadRequestException("Invalid response");
399
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
400
+ "error"
401
+ ] as string;
402
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
390
403
  }
391
404
 
392
405
  if (
@@ -440,7 +453,10 @@ export default class SlackUtil extends WorkspaceBase {
440
453
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
441
454
  logger.error("Invalid response from Slack API:");
442
455
  logger.error(response.jsonData);
443
- throw new BadRequestException("Invalid response");
456
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
457
+ "error"
458
+ ] as string;
459
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
444
460
  }
445
461
 
446
462
  const channels: Dictionary<WorkspaceChannel> = {};
@@ -527,6 +543,33 @@ export default class SlackUtil extends WorkspaceBase {
527
543
  return values;
528
544
  }
529
545
 
546
+ @CaptureSpan()
547
+ public static override async doesChannelExist(data: {
548
+ authToken: string;
549
+ channelName: string;
550
+ }): Promise<boolean> {
551
+ // if channel name starts with #, remove it
552
+ if (data.channelName && data.channelName.startsWith("#")) {
553
+ data.channelName = data.channelName.substring(1);
554
+ }
555
+
556
+ // convert channel name to lowercase
557
+ data.channelName = data.channelName.toLowerCase();
558
+
559
+ // get channel id from channel name
560
+ const channels: Dictionary<WorkspaceChannel> =
561
+ await this.getAllWorkspaceChannels({
562
+ authToken: data.authToken,
563
+ });
564
+
565
+ // if this channel exists
566
+ if (channels[data.channelName]) {
567
+ return true;
568
+ }
569
+
570
+ return false;
571
+ }
572
+
530
573
  @CaptureSpan()
531
574
  public static override async sendMessage(data: {
532
575
  workspaceMessagePayload: WorkspaceMessagePayload;
@@ -664,7 +707,10 @@ export default class SlackUtil extends WorkspaceBase {
664
707
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
665
708
  logger.error("Invalid response from Slack API:");
666
709
  logger.error(response.jsonData);
667
- throw new BadRequestException("Invalid response");
710
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
711
+ "error"
712
+ ] as string;
713
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
668
714
  }
669
715
 
670
716
  logger.debug("Payload blocks sent to channel successfully.");
@@ -736,7 +782,10 @@ export default class SlackUtil extends WorkspaceBase {
736
782
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
737
783
  logger.error("Invalid response from Slack API:");
738
784
  logger.error(response.jsonData);
739
- throw new BadRequestException("Invalid response");
785
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
786
+ "error"
787
+ ] as string;
788
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
740
789
  }
741
790
 
742
791
  if (
@@ -1111,7 +1160,10 @@ export default class SlackUtil extends WorkspaceBase {
1111
1160
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
1112
1161
  logger.error("Invalid response from Slack API:");
1113
1162
  logger.error(response.jsonData);
1114
- throw new BadRequestException("Invalid response");
1163
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
1164
+ "error"
1165
+ ] as string;
1166
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
1115
1167
  }
1116
1168
 
1117
1169
  // check if the user is in the channel
@@ -1175,7 +1227,10 @@ export default class SlackUtil extends WorkspaceBase {
1175
1227
  if ((response.jsonData as JSONObject)?.["ok"] !== true) {
1176
1228
  logger.error("Invalid response from Slack API:");
1177
1229
  logger.error(response.jsonData);
1178
- throw new BadRequestException("Invalid response");
1230
+ const messageFromSlack: string = (response.jsonData as JSONObject)?.[
1231
+ "error"
1232
+ ] as string;
1233
+ throw new BadRequestException("Error from Slack " + messageFromSlack);
1179
1234
  }
1180
1235
 
1181
1236
  // check if the user is in the channel
@@ -48,6 +48,15 @@ export default class WorkspaceBase {
48
48
  }): Promise<boolean> {
49
49
  throw new NotImplementedException();
50
50
  }
51
+
52
+ @CaptureSpan()
53
+ public static async doesChannelExist(_data: {
54
+ authToken: string;
55
+ channelName: string;
56
+ }): Promise<boolean> {
57
+ throw new NotImplementedException();
58
+ }
59
+
51
60
  @CaptureSpan()
52
61
  public static async getUsernameFromUserId(_data: {
53
62
  authToken: string;
@@ -0,0 +1,29 @@
1
+ import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import WorkspaceNotificationRuleService from "../Services/WorkspaceNotificationRuleService";
3
+ import Response from "../Utils/Response";
4
+ import BaseAPI from "./BaseAPI";
5
+ import CommonAPI from "./CommonAPI";
6
+ import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNotificationRule";
7
+ import ObjectID from "../../Types/ObjectID";
8
+ export default class WorkspaceNotificationRuleAPI extends BaseAPI {
9
+ constructor() {
10
+ var _a;
11
+ super(WorkspaceNotificationRule, WorkspaceNotificationRuleService);
12
+ this.router.get(`${(_a = new this.entityType().getCrudApiPath()) === null || _a === void 0 ? void 0 : _a.toString()}/test/:workspaceNotifcationRuleId`, UserMiddleware.getUserMiddleware, async (req, res, next) => {
13
+ try {
14
+ const databaseProps = await CommonAPI.getDatabaseCommonInteractionProps(req);
15
+ await this.service.testRule({
16
+ ruleId: new ObjectID(req.params["workspaceNotifcationRuleId"]),
17
+ props: databaseProps,
18
+ projectId: databaseProps.tenantId,
19
+ testByUserId: databaseProps.userId,
20
+ });
21
+ return Response.sendEmptySuccessResponse(req, res);
22
+ }
23
+ catch (e) {
24
+ next(e);
25
+ }
26
+ });
27
+ }
28
+ }
29
+ //# sourceMappingURL=WorkspaceNotificationRuleAPI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkspaceNotificationRuleAPI.js","sourceRoot":"","sources":["../../../../Server/API/WorkspaceNotificationRuleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,gCAEN,MAAM,8CAA8C,CAAC;AAMtD,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,OAAO,yBAAyB,MAAM,wDAAwD,CAAC;AAC/F,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAE5C,MAAM,CAAC,OAAO,OAAO,4BAA6B,SAAQ,OAGzD;IACC;;QACE,KAAK,CAAC,yBAAyB,EAAE,gCAAgC,CAAC,CAAC;QAEnE,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,GAAG,MAAA,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,cAAc,EAAE,0CAAE,QAAQ,EAAE,mCAAmC,EACxF,cAAc,CAAC,iBAAiB,EAChC,KAAK,EAAE,GAAmB,EAAE,GAAoB,EAAE,IAAkB,EAAE,EAAE;YACtE,IAAI,CAAC;gBACH,MAAM,aAAa,GACjB,MAAM,SAAS,CAAC,iCAAiC,CAAC,GAAG,CAAC,CAAC;gBAEzD,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;oBAC1B,MAAM,EAAE,IAAI,QAAQ,CAClB,GAAG,CAAC,MAAM,CAAC,4BAA4B,CAAW,CACnD;oBACD,KAAK,EAAE,aAAa;oBACpB,SAAS,EAAE,aAAa,CAAC,QAAS;oBAClC,YAAY,EAAE,aAAa,CAAC,MAAO;iBACpC,CAAC,CAAC;gBAEH,OAAO,QAAQ,CAAC,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,CAAC,CAAC,CAAC;YACV,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;CACF"}
@@ -228,7 +228,9 @@ export class Service extends DatabaseService {
228
228
  if (!lastIncident) {
229
229
  return 0;
230
230
  }
231
- return lastIncident.incidentNumber || 0;
231
+ return lastIncident.incidentNumber
232
+ ? Number(lastIncident.incidentNumber)
233
+ : 0;
232
234
  }
233
235
  async onBeforeCreate(createBy) {
234
236
  if (!createBy.props.tenantId && !createBy.props.isRoot) {