@oneuptime/common 7.0.4006 → 7.0.4019

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 (74) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +68 -1
  2. package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +0 -79
  3. package/Server/API/OnCallDutyPolicyAPI.ts +87 -0
  4. package/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.ts +35 -0
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.ts +23 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  7. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +243 -0
  8. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +46 -0
  9. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +237 -0
  10. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +210 -0
  11. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +61 -1
  12. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +63 -0
  13. package/Server/Services/OnCallDutyPolicyScheduleService.ts +597 -18
  14. package/Server/Services/OnCallDutyPolicyService.ts +129 -0
  15. package/Server/Services/TeamService.ts +36 -0
  16. package/Server/Services/UserNotificationSettingService.ts +114 -237
  17. package/Server/Services/UserService.ts +21 -0
  18. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +2 -2
  19. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +3 -3
  20. package/Types/Date.ts +23 -7
  21. package/Types/Email/EmailTemplateType.ts +6 -0
  22. package/Types/NotificationSetting/NotificationSettingEventType.ts +7 -0
  23. package/Types/OnCallDutyPolicy/Layer.ts +104 -20
  24. package/UI/Components/Alerts/Alert.tsx +6 -5
  25. package/UI/Components/HeaderAlert/HeaderAlert.tsx +2 -2
  26. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +70 -1
  27. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  28. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +0 -82
  29. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
  30. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +44 -0
  31. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -0
  32. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js +18 -0
  33. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js.map +1 -0
  34. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js +14 -0
  35. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js.map +1 -0
  36. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  37. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  38. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +170 -0
  39. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  40. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +40 -0
  41. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  42. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +170 -0
  43. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  44. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +152 -0
  45. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  46. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +39 -0
  47. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  48. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +42 -0
  49. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  50. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +387 -8
  51. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  52. package/build/dist/Server/Services/OnCallDutyPolicyService.js +101 -0
  53. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  54. package/build/dist/Server/Services/TeamService.js +27 -0
  55. package/build/dist/Server/Services/TeamService.js.map +1 -1
  56. package/build/dist/Server/Services/UserNotificationSettingService.js +35 -202
  57. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  58. package/build/dist/Server/Services/UserService.js +17 -0
  59. package/build/dist/Server/Services/UserService.js.map +1 -1
  60. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +2 -2
  61. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +3 -3
  62. package/build/dist/Types/Date.js +19 -7
  63. package/build/dist/Types/Date.js.map +1 -1
  64. package/build/dist/Types/Email/EmailTemplateType.js +5 -0
  65. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  66. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +6 -0
  67. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  68. package/build/dist/Types/OnCallDutyPolicy/Layer.js +66 -11
  69. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  70. package/build/dist/UI/Components/Alerts/Alert.js +4 -4
  71. package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
  72. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +2 -2
  73. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
  74. package/package.json +2 -2
@@ -517,6 +517,28 @@ export default class OnCallDutyPolicySchedule extends BaseModel {
517
517
  })
518
518
  public nextUserIdOnRoster?: ObjectID = undefined;
519
519
 
520
+ @ColumnAccessControl({
521
+ create: [],
522
+ read: [
523
+ Permission.ProjectOwner,
524
+ Permission.ProjectAdmin,
525
+ Permission.ProjectMember,
526
+ Permission.ReadProjectOnCallDutyPolicySchedule,
527
+ ],
528
+ update: [],
529
+ })
530
+ @TableColumn({
531
+ type: TableColumnType.Date,
532
+ title: "Roster Handoff At",
533
+ description:
534
+ "When does the roster handoff occur for this schedule for the current user?",
535
+ })
536
+ @Column({
537
+ type: ColumnType.Date,
538
+ nullable: true,
539
+ })
540
+ public rosterHandoffAt?: Date = undefined;
541
+
520
542
  @ColumnAccessControl({
521
543
  create: [],
522
544
  read: [
@@ -530,11 +552,56 @@ export default class OnCallDutyPolicySchedule extends BaseModel {
530
552
  @TableColumn({
531
553
  type: TableColumnType.Date,
532
554
  title: "Roster Next Handoff At",
533
- description: "When is the next roster handoff for this schedule?",
555
+ description:
556
+ "When does the next roster handoff occur for this schedule for the next user?",
534
557
  })
535
558
  @Column({
536
559
  type: ColumnType.Date,
537
560
  nullable: true,
538
561
  })
539
562
  public rosterNextHandoffAt?: Date = undefined;
563
+
564
+ @ColumnAccessControl({
565
+ create: [],
566
+ read: [
567
+ Permission.ProjectOwner,
568
+ Permission.ProjectAdmin,
569
+ Permission.ProjectMember,
570
+ Permission.ReadProjectOnCallDutyPolicySchedule,
571
+ ],
572
+ update: [],
573
+ })
574
+ @TableColumn({
575
+ type: TableColumnType.Date,
576
+ title: "Roster Next Event Start At",
577
+ description:
578
+ "When does the next event start for this schedule for the next user?",
579
+ })
580
+ @Column({
581
+ type: ColumnType.Date,
582
+ nullable: true,
583
+ })
584
+ public rosterNextStartAt?: Date = undefined;
585
+
586
+ @ColumnAccessControl({
587
+ create: [],
588
+ read: [
589
+ Permission.ProjectOwner,
590
+ Permission.ProjectAdmin,
591
+ Permission.ProjectMember,
592
+ Permission.ReadProjectOnCallDutyPolicySchedule,
593
+ ],
594
+ update: [],
595
+ })
596
+ @TableColumn({
597
+ type: TableColumnType.Date,
598
+ title: "Roster Event Start At",
599
+ description:
600
+ "When does the current event start for this schedule for the current user?",
601
+ })
602
+ @Column({
603
+ type: ColumnType.Date,
604
+ nullable: true,
605
+ })
606
+ public rosterStartAt?: Date = undefined;
540
607
  }
@@ -552,83 +552,4 @@ export default class OnCallDutyPolicyScheduleLayer extends BaseModel {
552
552
  transformer: RestrictionTimes.getDatabaseTransformer(),
553
553
  })
554
554
  public restrictionTimes?: RestrictionTimes = undefined;
555
-
556
- @ColumnAccessControl({
557
- create: [
558
- Permission.ProjectOwner,
559
- Permission.ProjectAdmin,
560
- Permission.ProjectMember,
561
- Permission.CreateProjectOnCallDutyPolicySchedule,
562
- ],
563
- read: [
564
- Permission.ProjectOwner,
565
- Permission.ProjectAdmin,
566
- Permission.ProjectMember,
567
- Permission.ReadProjectOnCallDutyPolicySchedule,
568
- ],
569
- update: [],
570
- })
571
- @TableColumn({
572
- manyToOneRelationColumn: "nextUserIdOnLayer",
573
- type: TableColumnType.Entity,
574
- modelType: User,
575
- title: "Next User On Layer",
576
- description: "Relation to User who is next on layer",
577
- })
578
- @ManyToOne(
579
- () => {
580
- return User;
581
- },
582
- {
583
- eager: false,
584
- nullable: true,
585
- onDelete: "SET NULL",
586
- orphanedRowAction: "nullify",
587
- },
588
- )
589
- @JoinColumn({ name: "nextUserIdOnLayer" })
590
- public nextUserOnLayer?: User = undefined;
591
-
592
- @ColumnAccessControl({
593
- create: [],
594
- read: [
595
- Permission.ProjectOwner,
596
- Permission.ProjectAdmin,
597
- Permission.ProjectMember,
598
- Permission.ReadProjectOnCallDutyPolicySchedule,
599
- ],
600
- update: [],
601
- })
602
- @TableColumn({
603
- type: TableColumnType.ObjectID,
604
- title: "Next User ID On Layer",
605
- description: "Next ID who is currently on layer",
606
- })
607
- @Column({
608
- type: ColumnType.ObjectID,
609
- nullable: true,
610
- transformer: ObjectID.getDatabaseTransformer(),
611
- })
612
- public nextUserIdOnLayer?: ObjectID = undefined;
613
-
614
- @ColumnAccessControl({
615
- create: [],
616
- read: [
617
- Permission.ProjectOwner,
618
- Permission.ProjectAdmin,
619
- Permission.ProjectMember,
620
- Permission.ReadProjectOnCallDutyPolicySchedule,
621
- ],
622
- update: [],
623
- })
624
- @TableColumn({
625
- type: TableColumnType.Date,
626
- title: "Layer Next Handoff At",
627
- description: "When is the next layer handoff for this schedule?",
628
- })
629
- @Column({
630
- type: ColumnType.Date,
631
- nullable: true,
632
- })
633
- public layerNextHandoffAt?: Date = undefined;
634
555
  }
@@ -0,0 +1,87 @@
1
+ import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import OnCallDutyPolicyService, {
3
+ Service as OnCallDutyPolicyServiceType,
4
+ } from "../Services/OnCallDutyPolicyService";
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 BadDataException from "Common/Types/Exception/BadDataException";
15
+ import ObjectID from "Common/Types/ObjectID";
16
+ import OnCallDutyPolicy from "Common/Models/DatabaseModels/OnCallDutyPolicy";
17
+ import OnCallDutyPolicyEscalationRuleUser from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
18
+ import OnCallDutyPolicyEscalationRuleTeam from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam";
19
+ import OnCallDutyPolicyEscalationRuleSchedule from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule";
20
+ import BaseModel from "Common/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
21
+
22
+ export default class OnCallDutyPolicyAPI extends BaseAPI<
23
+ OnCallDutyPolicy,
24
+ OnCallDutyPolicyServiceType
25
+ > {
26
+ public constructor() {
27
+ super(OnCallDutyPolicy, OnCallDutyPolicyService);
28
+
29
+ // CNAME verification api. THis API will be used from the dashboard to validate the CNAME MANUALLY.
30
+ this.router.get(
31
+ `${new this.entityType().getCrudApiPath()?.toString()}/current-on-duty-escalation-policies`,
32
+ UserMiddleware.getUserMiddleware,
33
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
34
+ try {
35
+ const databaseProps: DatabaseCommonInteractionProps =
36
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
37
+
38
+ const projectId: ObjectID = databaseProps.tenantId as ObjectID;
39
+
40
+ const userId: ObjectID = databaseProps.userId as ObjectID;
41
+
42
+ if (!projectId) {
43
+ return Response.sendErrorResponse(
44
+ req,
45
+ res,
46
+ new BadDataException("Invalid projectId."),
47
+ );
48
+ }
49
+
50
+ if (!userId) {
51
+ return Response.sendErrorResponse(
52
+ req,
53
+ res,
54
+ new BadDataException("Invalid userId."),
55
+ );
56
+ }
57
+
58
+ const result: {
59
+ escalationRulesByUser: Array<OnCallDutyPolicyEscalationRuleUser>;
60
+ escalationRulesByTeam: Array<OnCallDutyPolicyEscalationRuleTeam>;
61
+ escalationRulesBySchedule: Array<OnCallDutyPolicyEscalationRuleSchedule>;
62
+ } = await this.service.getOnCallPoliciesWhereUserIsOnCallDuty({
63
+ projectId: projectId,
64
+ userId: userId,
65
+ });
66
+
67
+ return Response.sendJsonObjectResponse(req, res, {
68
+ escalationRulesByUser: BaseModel.toJSONArray(
69
+ result.escalationRulesByUser,
70
+ OnCallDutyPolicyEscalationRuleUser,
71
+ ),
72
+ escalationRulesByTeam: BaseModel.toJSONArray(
73
+ result.escalationRulesByTeam,
74
+ OnCallDutyPolicyEscalationRuleTeam,
75
+ ),
76
+ escalationRulesBySchedule: BaseModel.toJSONArray(
77
+ result.escalationRulesBySchedule,
78
+ OnCallDutyPolicyEscalationRuleSchedule,
79
+ ),
80
+ });
81
+ } catch (e) {
82
+ next(e);
83
+ }
84
+ },
85
+ );
86
+ }
87
+ }
@@ -0,0 +1,35 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1743692467814 implements MigrationInterface {
4
+ public name = "MigrationName1743692467814";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP CONSTRAINT "FK_815023b155d367f28cc6855b843"`,
9
+ );
10
+ await queryRunner.query(
11
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP COLUMN "nextUserIdOnLayer"`,
12
+ );
13
+ await queryRunner.query(
14
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP COLUMN "layerNextHandoffAt"`,
15
+ );
16
+ await queryRunner.query(
17
+ `ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterHandoffAt" TIMESTAMP WITH TIME ZONE`,
18
+ );
19
+ }
20
+
21
+ public async down(queryRunner: QueryRunner): Promise<void> {
22
+ await queryRunner.query(
23
+ `ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterHandoffAt"`,
24
+ );
25
+ await queryRunner.query(
26
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD "layerNextHandoffAt" TIMESTAMP WITH TIME ZONE`,
27
+ );
28
+ await queryRunner.query(
29
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD "nextUserIdOnLayer" uuid`,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD CONSTRAINT "FK_815023b155d367f28cc6855b843" FOREIGN KEY ("nextUserIdOnLayer") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
33
+ );
34
+ }
35
+ }
@@ -0,0 +1,23 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1743714801105 implements MigrationInterface {
4
+ public name = "MigrationName1743714801105";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterNextStartAt" TIMESTAMP WITH TIME ZONE`,
9
+ );
10
+ await queryRunner.query(
11
+ `ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterStartAt" TIMESTAMP WITH TIME ZONE`,
12
+ );
13
+ }
14
+
15
+ public async down(queryRunner: QueryRunner): Promise<void> {
16
+ await queryRunner.query(
17
+ `ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterStartAt"`,
18
+ );
19
+ await queryRunner.query(
20
+ `ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterNextStartAt"`,
21
+ );
22
+ }
23
+ }
@@ -127,6 +127,8 @@ import { MigrationName1743518485566 } from "./1743518485566-MigrationName";
127
127
  import { MigrationName1743521461137 } from "./1743521461137-MigrationName";
128
128
  import { MigrationName1743530326936 } from "./1743530326936-MigrationName";
129
129
  import { MigrationName1743538648415 } from "./1743538648415-MigrationName";
130
+ import { MigrationName1743692467814 } from "./1743692467814-MigrationName";
131
+ import { MigrationName1743714801105 } from "./1743714801105-MigrationName";
130
132
 
131
133
  export default [
132
134
  InitialMigration,
@@ -258,4 +260,6 @@ export default [
258
260
  MigrationName1743521461137,
259
261
  MigrationName1743530326936,
260
262
  MigrationName1743538648415,
263
+ MigrationName1743692467814,
264
+ MigrationName1743714801105,
261
265
  ];
@@ -1,10 +1,253 @@
1
+ import BadDataException from "../../Types/Exception/BadDataException";
2
+ import ObjectID from "../../Types/ObjectID";
3
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
1
4
  import DatabaseService from "./DatabaseService";
2
5
  import Model from "Common/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule";
6
+ import Dictionary from "../../Types/Dictionary";
7
+ import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
8
+ import EmailTemplateType from "../../Types/Email/EmailTemplateType";
9
+ import { EmailEnvelope } from "../../Types/Email/EmailMessage";
10
+ import { SMSMessage } from "../../Types/SMS/SMS";
11
+ import UserNotificationSettingService from "./UserNotificationSettingService";
12
+ import NotificationSettingEventType from "../../Types/NotificationSetting/NotificationSettingEventType";
13
+ import { CallRequestMessage } from "../../Types/Call/CallRequest";
14
+ import DeleteBy from "../Types/Database/DeleteBy";
15
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
16
+ import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
3
17
 
4
18
  export class Service extends DatabaseService<Model> {
5
19
  public constructor() {
6
20
  super(Model);
7
21
  }
22
+
23
+ protected override async onCreateSuccess(
24
+ _onCreate: OnCreate<Model>,
25
+ createdItem: Model,
26
+ ): Promise<Model> {
27
+ const createdItemId: ObjectID = createdItem.id!;
28
+
29
+ if (!createdItemId) {
30
+ throw new BadDataException("Created item does not have an ID");
31
+ }
32
+
33
+ const createdModel: Model | null = await this.findOneById({
34
+ id: createdItemId,
35
+ select: {
36
+ projectId: true,
37
+ onCallDutyPolicyScheduleId: true,
38
+ onCallDutyPolicySchedule: {
39
+ name: true,
40
+ },
41
+ onCallDutyPolicyEscalationRule: {
42
+ name: true,
43
+ _id: true,
44
+ order: true,
45
+ },
46
+ onCallDutyPolicy: {
47
+ name: true,
48
+ _id: true,
49
+ },
50
+ },
51
+ props: {
52
+ isRoot: true,
53
+ },
54
+ });
55
+
56
+ if (!createdModel) {
57
+ throw new BadDataException("Created item does not have an ID");
58
+ }
59
+
60
+ if (!createdModel.onCallDutyPolicyScheduleId) {
61
+ throw new BadDataException(
62
+ "Created item does not have a onCallDutyPolicyScheduleId",
63
+ );
64
+ }
65
+
66
+ // send notification to the new current user.
67
+
68
+ const userOnSchedule: ObjectID | null =
69
+ await OnCallDutyPolicyScheduleService.getCurrentUserIdInSchedule(
70
+ createdModel.onCallDutyPolicyScheduleId,
71
+ );
72
+
73
+ if (!userOnSchedule) {
74
+ return createdItem;
75
+ }
76
+
77
+ const scheduleName: string =
78
+ createdModel.onCallDutyPolicySchedule?.name || "No name provided";
79
+
80
+ const sendEmailToUserId: ObjectID | undefined | null = userOnSchedule;
81
+
82
+ if (!sendEmailToUserId) {
83
+ return createdItem;
84
+ }
85
+
86
+ if (!createdModel) {
87
+ return createdItem;
88
+ }
89
+
90
+ const vars: Dictionary<string> = {
91
+ onCallPolicyName:
92
+ createdModel.onCallDutyPolicy?.name || "No name provided",
93
+ escalationRuleName:
94
+ createdModel.onCallDutyPolicyEscalationRule?.name || "No name provided",
95
+ escalationRuleOrder:
96
+ createdModel.onCallDutyPolicyEscalationRule?.order?.toString() ||
97
+ "No order provided",
98
+ reason: "You are currently on roster for schedule " + scheduleName,
99
+ onCallPolicyViewLink: (
100
+ await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
101
+ createdModel!.projectId!,
102
+ createdModel.onCallDutyPolicy!.id!,
103
+ )
104
+ ).toString(),
105
+ };
106
+
107
+ // Notify the current user about being added to the schedule.
108
+ const emailMessage: EmailEnvelope = {
109
+ templateType: EmailTemplateType.UserAddedToOnCallPolicy,
110
+ vars: vars,
111
+ subject: `You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName}`,
112
+ };
113
+
114
+ const sms: SMSMessage = {
115
+ message: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification, go to User Settings in the OneUptime Dashboard.`,
116
+ };
117
+
118
+ const callMessage: CallRequestMessage = {
119
+ data: [
120
+ {
121
+ sayMessage: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification, go to User Settings in the OneUptime Dashboard. Goodbye.`,
122
+ },
123
+ ],
124
+ };
125
+
126
+ await UserNotificationSettingService.sendUserNotification({
127
+ userId: sendEmailToUserId,
128
+ projectId: createdModel!.projectId!,
129
+ emailEnvelope: emailMessage,
130
+ smsMessage: sms,
131
+ callRequestMessage: callMessage,
132
+ eventType:
133
+ NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY,
134
+ });
135
+
136
+ return createdItem;
137
+ }
138
+
139
+ protected override async onBeforeDelete(
140
+ deleteBy: DeleteBy<Model>,
141
+ ): Promise<OnDelete<Model>> {
142
+ const itemsToFetchBeforeDelete: Array<Model> = await this.findBy({
143
+ query: deleteBy.query,
144
+ props: {
145
+ isRoot: true,
146
+ },
147
+ select: {
148
+ projectId: true,
149
+ onCallDutyPolicyScheduleId: true,
150
+ onCallDutyPolicySchedule: {
151
+ name: true,
152
+ _id: true,
153
+ },
154
+ onCallDutyPolicyEscalationRule: {
155
+ name: true,
156
+ _id: true,
157
+ order: true,
158
+ },
159
+ onCallDutyPolicy: {
160
+ name: true,
161
+ _id: true,
162
+ },
163
+ },
164
+ limit: LIMIT_PER_PROJECT,
165
+ skip: 0,
166
+ });
167
+
168
+ return {
169
+ deleteBy,
170
+ carryForward: {
171
+ deletedItems: itemsToFetchBeforeDelete,
172
+ },
173
+ };
174
+ }
175
+
176
+ protected override async onDeleteSuccess(
177
+ onDelete: OnDelete<Model>,
178
+ _itemIdsBeforeDelete: Array<ObjectID>,
179
+ ): Promise<OnDelete<Model>> {
180
+ const deletedItems: Array<Model> = onDelete.carryForward.deletedItems;
181
+
182
+ for (const deletedItem of deletedItems) {
183
+ const userOnSchedule: ObjectID | null =
184
+ await OnCallDutyPolicyScheduleService.getCurrentUserIdInSchedule(
185
+ deletedItem.onCallDutyPolicyScheduleId!,
186
+ );
187
+
188
+ if (!userOnSchedule) {
189
+ continue;
190
+ }
191
+
192
+ const sendEmailToUserId: ObjectID | undefined | null = userOnSchedule;
193
+
194
+ if (!sendEmailToUserId) {
195
+ return onDelete;
196
+ }
197
+
198
+ const scheduleName: string =
199
+ deletedItem.onCallDutyPolicySchedule?.name || "No name provided";
200
+
201
+ const vars: Dictionary<string> = {
202
+ onCallPolicyName:
203
+ deletedItem.onCallDutyPolicy?.name || "No name provided",
204
+ escalationRuleName:
205
+ deletedItem.onCallDutyPolicyEscalationRule?.name ||
206
+ "No name provided",
207
+ escalationRuleOrder:
208
+ deletedItem.onCallDutyPolicyEscalationRule?.order?.toString() ||
209
+ "No order provided",
210
+ reason: `You have been removed from the on-call duty policy escalation rule for schedule ${scheduleName}.`,
211
+ onCallPolicyViewLink: (
212
+ await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
213
+ deletedItem!.projectId!,
214
+ deletedItem.onCallDutyPolicy!.id!,
215
+ )
216
+ ).toString(),
217
+ };
218
+
219
+ // Notify the current user about being removed from the schedule.
220
+ const emailMessage: EmailEnvelope = {
221
+ templateType: EmailTemplateType.UserRemovedFromOnCallPolicy,
222
+ vars: vars,
223
+ subject: `You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName}`,
224
+ };
225
+
226
+ const sms: SMSMessage = {
227
+ message: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
228
+ };
229
+
230
+ const callMessage: CallRequestMessage = {
231
+ data: [
232
+ {
233
+ sayMessage: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
234
+ },
235
+ ],
236
+ };
237
+
238
+ await UserNotificationSettingService.sendUserNotification({
239
+ userId: sendEmailToUserId,
240
+ projectId: deletedItem!.projectId!,
241
+ emailEnvelope: emailMessage,
242
+ smsMessage: sms,
243
+ callRequestMessage: callMessage,
244
+ eventType:
245
+ NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY,
246
+ });
247
+ }
248
+
249
+ return onDelete;
250
+ }
8
251
  }
9
252
 
10
253
  export default new Service();
@@ -671,6 +671,52 @@ export class Service extends DatabaseService<Model> {
671
671
  select: {
672
672
  order: true,
673
673
  onCallDutyPolicyId: true,
674
+ projectId: true,
675
+ },
676
+ });
677
+
678
+ if (!resource) {
679
+ throw new BadDataException(
680
+ "OnCallDutyPolicyEscalationRule with this id not found",
681
+ );
682
+ }
683
+
684
+ // delete users in escalation rule, teams in escalation rule and schedules in escalation rule.
685
+ await OnCallDutyPolicyEscalationRuleScheduleService.deleteBy({
686
+ query: {
687
+ onCallDutyPolicyEscalationRuleId: resource.id!,
688
+ projectId: resource.projectId!,
689
+ },
690
+ limit: LIMIT_PER_PROJECT,
691
+ skip: 0,
692
+ props: {
693
+ isRoot: true,
694
+ },
695
+ });
696
+
697
+ // delete users in escalation rule.
698
+ await OnCallDutyPolicyEscalationRuleUserService.deleteBy({
699
+ query: {
700
+ onCallDutyPolicyEscalationRuleId: resource.id!,
701
+ projectId: resource.projectId!,
702
+ },
703
+ limit: LIMIT_PER_PROJECT,
704
+ skip: 0,
705
+ props: {
706
+ isRoot: true,
707
+ },
708
+ });
709
+
710
+ // delete teams in escalation rule.
711
+ await OnCallDutyPolicyEscalationRuleTeamService.deleteBy({
712
+ query: {
713
+ onCallDutyPolicyEscalationRuleId: resource.id!,
714
+ projectId: resource.projectId!,
715
+ },
716
+ limit: LIMIT_PER_PROJECT,
717
+ skip: 0,
718
+ props: {
719
+ isRoot: true,
674
720
  },
675
721
  });
676
722
  }