-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcourseModuleService.ts
198 lines (174 loc) · 5.66 KB
/
courseModuleService.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/* eslint-disable class-methods-use-this */
import { startSession } from "mongoose";
import {
CourseModuleDTO,
CreateCourseModuleDTO,
UpdateCourseModuleDTO,
} from "../../types/courseTypes";
import logger from "../../utilities/logger";
import MgCourseUnit, { CourseUnit } from "../../models/courseunit.mgmodel";
import { getErrorMessage } from "../../utilities/errorUtils";
import MgCourseModule, {
CourseModule,
} from "../../models/coursemodule.mgmodel";
import ICourseModuleService from "../interfaces/courseModuleService";
const Logger = logger(__filename);
class CourseModuleService implements ICourseModuleService {
async getCourseModules(
courseUnitId: string,
): Promise<Array<CourseModuleDTO>> {
try {
const courseUnit: CourseUnit | null = await MgCourseUnit.findById(
courseUnitId,
);
if (!courseUnit) {
throw new Error(`Course unit with id ${courseUnitId} not found.`);
}
const courseModules: Array<CourseModule> = await MgCourseModule.find({
_id: { $in: courseUnit.modules },
});
return courseModules.map((courseModule) => courseModule.toObject());
} catch (error) {
Logger.error(
`Failed to get course modules for course unit with id: ${courseUnitId}. Reason = ${getErrorMessage(
error,
)}`,
);
throw error;
}
}
async getCourseModule(courseModuleId: string): Promise<CourseModuleDTO> {
try {
const courseModule: CourseModule | null = await MgCourseModule.findById(
courseModuleId,
);
if (!courseModule) {
throw new Error(`id ${courseModuleId} not found.`);
}
return courseModule.toObject();
} catch (error) {
Logger.error(
`Failed to get course module with id: ${courseModuleId}. Reason = ${getErrorMessage(
error,
)}`,
);
throw error;
}
}
async createCourseModule(
courseUnitId: string,
courseModuleDTO: CreateCourseModuleDTO,
): Promise<CourseModuleDTO> {
let newCourseModule: CourseModule | undefined;
const session = await startSession(); // start a transaction
session.startTransaction();
try {
const courseUnit: CourseUnit | null = await MgCourseUnit.findById(
courseUnitId,
).session(session);
if (!courseUnit) {
throw new Error(`Course unit with id ${courseUnitId} not found.`);
}
const numCourseModules = courseUnit.modules.length;
newCourseModule = await MgCourseModule.create({
...courseModuleDTO,
displayIndex: numCourseModules + 1,
session,
});
if (!newCourseModule) {
throw new Error(
`Error with creating course module with DTO: ${courseModuleDTO}`,
);
}
await MgCourseUnit.findByIdAndUpdate(courseUnitId, {
$push: { modules: newCourseModule.id }, // newModule is the object/value you want to push into the array
}).session(session);
await session.commitTransaction();
} catch (error) {
Logger.error(
`Failed to create course module under course unit with id: ${courseUnitId}. Reason = ${getErrorMessage(
error,
)}`,
);
throw error;
} finally {
session.endSession();
}
return {
id: newCourseModule.id,
displayIndex: newCourseModule.displayIndex,
title: newCourseModule.title,
} as CourseModuleDTO;
}
async updateCourseModule(
courseModuleId: string,
courseModuleDTO: UpdateCourseModuleDTO,
): Promise<CourseModuleDTO> {
let updatedModule: CourseModule | null;
try {
updatedModule = await MgCourseModule.findByIdAndUpdate(
courseModuleId,
{
title: courseModuleDTO.title,
},
{ new: true, runValidators: true },
);
if (!updatedModule) {
throw new Error(`Course module with id ${courseModuleId} not found.`);
}
} catch (error) {
Logger.error(
`Failed to update course module. Reason = ${getErrorMessage(error)}`,
);
throw error;
}
return {
id: updatedModule.id,
title: updatedModule.title,
displayIndex: updatedModule.displayIndex,
} as CourseModuleDTO;
}
async deleteCourseModule(
courseUnitId: string,
courseModuleId: string,
): Promise<string> {
let deletedCourseModuleId: string;
const session = await startSession();
session.startTransaction();
try {
// first update the course units module reference
const courseUnit = await MgCourseUnit.findByIdAndUpdate(
courseUnitId,
{
$pull: { modules: courseModuleId },
},
{ new: true, runValidators: true },
).session(session);
if (!courseUnit) {
throw new Error(`Course unit with id ${courseUnitId} not found`);
}
// then find ID of course module and delete
const deletedCourseModule: CourseModule | null =
await MgCourseModule.findByIdAndDelete(courseModuleId).session(session);
if (!deletedCourseModule) {
throw new Error(`Course module with id ${courseModuleId} not found`);
}
deletedCourseModuleId = deletedCourseModule.id;
// get the index and update the ones behind it
await MgCourseModule.updateMany(
{ displayIndex: { $gt: deletedCourseModule.displayIndex } },
{ $inc: { displayIndex: -1 } },
).session(session);
await session.commitTransaction();
} catch (error: unknown) {
Logger.error(
`Failed to delete course module. Reason = ${getErrorMessage(error)}`,
);
throw error;
} finally {
await session.endSession();
}
return deletedCourseModuleId;
}
}
export default CourseModuleService;