Skip to content

Commit 0d5d171

Browse files
committed
Implement Exam Endpoints
1 parent 14fc01e commit 0d5d171

File tree

6 files changed

+332
-47
lines changed

6 files changed

+332
-47
lines changed

_apidoc.js

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@
211211
*
212212
* @apiError (Error 500) err Error message if there was an error during the deletion.
213213
*
214-
* */
214+
* */
215215

216216
/**
217217
* @api {post} /infrastructure/update Update infrastructure details
@@ -273,7 +273,7 @@
273273
*
274274
* @apiError (Error 500) err Error message if there was an error during the deletion.
275275
*
276-
* */
276+
* */
277277

278278
/**
279279
* @api {post} /accreditation/update update accreditation details
@@ -359,7 +359,7 @@
359359
*
360360
* @apiError (Error 500) err Error message if there was an error during the deletion.
361361
*
362-
* */
362+
* */
363363
/**
364364
* @api {post} /tutorial/update Update tutorial details
365365
* @apiName UpdateTutorial
@@ -470,7 +470,7 @@
470470
*
471471
* @apiError (Error 500) err Error while deleting from DB.
472472
*
473-
* */
473+
* */
474474

475475
/**
476476
* @api {post} /department/update Update department
@@ -665,3 +665,72 @@
665665
* @apiSuccess {String[]} module.cognitiveLevels Array of cognitive levels of
666666
* attainment as per Bloom's Taxanomy (L1-L6).
667667
*/
668+
669+
// ------------------------------------------------------------------------------------------
670+
// Exam.
671+
// ------------------------------------------------------------------------------------------
672+
673+
/**
674+
* @api {post} /exam/add Add Exam
675+
* @apiName AddExam
676+
* @apiExam Exam
677+
* @apiDescription Add a new exam.
678+
*
679+
* @apiBody {String} title Exam title.
680+
* @apiBody {ObjectId[]} students Array of student ObjectIDs.
681+
*
682+
* @apiSuccess {String} res Response message.
683+
* @apiError (Error 500) ExamAddError Error while adding the exam
684+
*
685+
* @apiSuccessExample Success-Response:
686+
* HTTP/1.1 200 OK
687+
* {
688+
* "res": "added exam Example Exam"
689+
* }
690+
*
691+
* @apiErrorExample Error-Response:
692+
* HTTP/1.1 500 Internal Server Error
693+
* {
694+
* "err": "Error while inserting in DB"
695+
* }
696+
*/
697+
698+
/**
699+
* @api {delete} /exam/delete/:id Delete Exam
700+
* @apiName DeleteExam
701+
* @apiExam Exam
702+
*
703+
* @apiParam {ObjectId} id The ObjectID of the exam to delete.
704+
*
705+
* @apiSuccess {String} res Success message indicating the deletion.
706+
* @apiError (Error 500) ExamDeleteError Error while deleting the exam
707+
*
708+
*/
709+
710+
/**
711+
* @api {post} /exam/update/:id Update Exam Details
712+
* @apiName UpdateExam
713+
* @apiExam Exam
714+
* @apiDescription Update existing exam details.
715+
*
716+
* @apiParam {ObjectId} id The ObjectID of the exam to update.
717+
* @apiBody {String} [title] Exam title.
718+
* @apiBody {ObjectId[]} [students] Array of student ObjectIDs.
719+
*
720+
* @apiSuccess {String} res Exam updated.
721+
* @apiError (Error 500) ExamUpdateError Error in updating database
722+
*
723+
*/
724+
725+
/**
726+
* @api {get} /exam/list Get Exam List
727+
* @apiName GetExamList
728+
* @apiExam Exam
729+
*
730+
* @apiQuery {String} [title] Title of the exam.
731+
*
732+
* @apiSuccess {Exam[]} res Array of filtered exam documents.
733+
* @apiSuccess {ObjectId} exam._id ObjectID of the exam document in the database.
734+
* @apiSuccess {String} exam.title Title of the exam.
735+
* @apiSuccess {ObjectId[]} exam.students Array of student ObjectIDs in the exam.
736+
*/

app.js

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,60 @@
1-
import path, { dirname } from "path";
2-
import { fileURLToPath } from "url";
3-
import express from "express";
4-
import morgan from "morgan";
5-
import cookieParser from "cookie-parser";
6-
import cors from "cors";
7-
import { logger } from "#util";
8-
import indexRouter from "#routes/index";
9-
import usersRouter from "#routes/users";
10-
import authRouter from "#routes/auth";
11-
import accreditationRouter from "#routes/accreditation";
12-
import infrastructureRouter from "#routes/infrastructure";
13-
import practicalRouter from "#routes/practical";
14-
import organizationRouter from "#routes/organization";
15-
import studentRouter from "#routes/student";
16-
import tutorialRouter from "#routes/tutorial";
17-
import assignmentRouter from "#routes/assignment";
18-
import timetableRouter from "#routes/timetable";
19-
import courseworkRouter from "#routes/coursework";
20-
import moduleRouter from "#routes/module";
21-
import { identifyUser } from "#middleware/identifyUser";
22-
import departmentRouter from "#routes/department";
1+
import path, { dirname } from 'path';
2+
import { fileURLToPath } from 'url';
3+
import express from 'express';
4+
import morgan from 'morgan';
5+
import cookieParser from 'cookie-parser';
6+
import cors from 'cors';
7+
import { logger } from '#util';
8+
import indexRouter from '#routes/index';
9+
import usersRouter from '#routes/users';
10+
import authRouter from '#routes/auth';
11+
import accreditationRouter from '#routes/accreditation';
12+
import infrastructureRouter from '#routes/infrastructure';
13+
import practicalRouter from '#routes/practical';
14+
import organizationRouter from '#routes/organization';
15+
import studentRouter from '#routes/student';
16+
import tutorialRouter from '#routes/tutorial';
17+
import assignmentRouter from '#routes/assignment';
18+
import timetableRouter from '#routes/timetable';
19+
import courseworkRouter from '#routes/coursework';
20+
import moduleRouter from '#routes/module';
21+
import { identifyUser } from '#middleware/identifyUser';
22+
import departmentRouter from '#routes/department';
23+
import examRouter from '#routes/exam';
2324

2425
const app = express();
2526
const currDirName = dirname(fileURLToPath(import.meta.url));
2627

27-
morgan.token("remote-user", (req) => req.user);
28+
morgan.token('remote-user', (req) => req.user);
2829
app.use(identifyUser);
2930
app.use(cors());
3031
app.use(express.json());
3132
app.use(express.urlencoded({ extended: false }));
3233
app.use(cookieParser());
33-
app.use(morgan(
34-
":remote-addr - :remote-user \":method :url HTTP/:http-version\" :status \":referrer\" \":user-agent\"",
35-
{ stream: logger.stream },
36-
));
34+
app.use(
35+
morgan(
36+
':remote-addr - :remote-user ":method :url HTTP/:http-version" :status ":referrer" ":user-agent"',
37+
{ stream: logger.stream }
38+
)
39+
);
3740

38-
app.use(express.static(path.join(currDirName, "public")));
41+
app.use(express.static(path.join(currDirName, 'public')));
42+
43+
app.use('/', indexRouter);
44+
app.use('/users', usersRouter);
45+
app.use('/auth', authRouter);
46+
app.use('/accreditation', accreditationRouter);
47+
app.use('/infrastructure', infrastructureRouter);
48+
app.use('/department', departmentRouter);
49+
app.use('/practical', practicalRouter);
50+
app.use('/organization', organizationRouter);
51+
app.use('/student', studentRouter);
52+
app.use('/tutorial', tutorialRouter);
53+
app.use('/assignment', assignmentRouter);
54+
app.use('/timetable', timetableRouter);
55+
app.use('/department', departmentRouter);
56+
app.use('/coursework', courseworkRouter);
57+
app.use('/module', moduleRouter);
58+
app.use('/exam', examRouter);
3959

40-
app.use("/", indexRouter);
41-
app.use("/users", usersRouter);
42-
app.use("/auth", authRouter);
43-
app.use("/accreditation", accreditationRouter);
44-
app.use("/infrastructure", infrastructureRouter);
45-
app.use("/department", departmentRouter);
46-
app.use("/practical", practicalRouter);
47-
app.use("/organization", organizationRouter);
48-
app.use("/student", studentRouter);
49-
app.use("/tutorial", tutorialRouter);
50-
app.use("/assignment", assignmentRouter);
51-
app.use("/timetable", timetableRouter);
52-
app.use("/department", departmentRouter);
53-
app.use("/coursework", courseworkRouter);
54-
app.use("/module", moduleRouter);
5560
export default app;

controller/exam.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {
2+
createExam,
3+
deleteExamById,
4+
examList,
5+
updateExamById,
6+
} from '#services/exam';
7+
import { logger } from '#util';
8+
9+
async function addExam(req, res) {
10+
const { date, startTime, duration, infrastructure, supervisor, course } =
11+
req.body;
12+
try {
13+
const exam = await createExam(
14+
date,
15+
startTime,
16+
duration,
17+
supervisor,
18+
infrastructure,
19+
course
20+
);
21+
res.json({ res: `added exam ${exam.id}`, id: exam.id });
22+
} catch (error) {
23+
logger.error('Error while inserting', error);
24+
res.status(500);
25+
res.json({ err: 'Error while inserting in DB' });
26+
}
27+
}
28+
29+
async function updateExam(req, res) {
30+
const { id } = req.params;
31+
const { ...data } = req.body;
32+
try {
33+
await updateExamById(id, data);
34+
res.json({ res: `updated exam with id ${id}` });
35+
} catch (error) {
36+
logger.error('Error while updating', error);
37+
res.status(500);
38+
res.json({ err: 'Error while updaing in DB' });
39+
}
40+
}
41+
42+
async function getExam(req, res) {
43+
const filter = req.query;
44+
const exam = await examList(filter);
45+
res.json({ res: exam });
46+
}
47+
48+
async function deleteExam(req, res) {
49+
const { id } = req.params;
50+
try {
51+
await deleteExamById(id);
52+
res.json({ res: `Deleted exam with ID ${id}` });
53+
} catch (error) {
54+
logger.error('Error while deleting', error);
55+
res.status(500).json({ error: 'Error while deleting from DB' });
56+
}
57+
}
58+
59+
export default {
60+
addExam,
61+
deleteExam,
62+
getExam,
63+
updateExam,
64+
};

routes/exam.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import express from 'express';
2+
import examController from '#controller/exam';
3+
4+
const router = express.Router();
5+
router.post('/add', examController.addExam);
6+
router.get('/list', examController.getExam);
7+
router.post('/update/:id', examController.updateExam);
8+
router.delete('/delete/:id', examController.deleteExam);
9+
10+
export default router;

services/exam.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import Exam from '#models/exam';
2+
import databaseError from '#error/database';
3+
4+
export async function createExam(
5+
date,
6+
startTime,
7+
duration,
8+
supervisor,
9+
infrastructure,
10+
course
11+
) {
12+
const newExam = await Exam.create({
13+
date,
14+
startTime,
15+
duration,
16+
supervisor,
17+
infrastructure,
18+
course,
19+
});
20+
if (newExam.date === date) {
21+
return newExam;
22+
}
23+
throw new databaseError.DataEntryError('exam');
24+
}
25+
26+
export async function updateExamById(id, data) {
27+
const updated = await Exam.update({ _id: id }, data);
28+
if (updated) {
29+
return updated;
30+
}
31+
throw new databaseError.DataEntryError('exam');
32+
}
33+
34+
export async function examList(filter) {
35+
const exams = await Exam.read(filter, 0);
36+
return exams;
37+
}
38+
39+
export async function deleteExamById(examId) {
40+
const deleted = await Exam.remove({ _id: examId });
41+
if (deleted) {
42+
return deleted;
43+
}
44+
throw new databaseError.DataDeleteError('exam');
45+
}

0 commit comments

Comments
 (0)