diff --git a/.husky/pre-commit b/.husky/pre-commit index a69ae89..96f642e 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -4,10 +4,10 @@ # npm test npx lint-staged -if [ "$(uname)" == "Darwin" ]; then +if [ "$(uname)" = "Darwin" ]; then npm run test -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then +elif [ "$(expr substr $(uname -s) 1 5)" = "Linux" ]; then npm run test -elif [ "$(expr substr $(uname -s) 1 5)" == "MINGW" ]; then +elif [ "$(expr substr $(uname -s) 1 5)" = "MINGW" ]; then npm run testWin fi diff --git a/controller/attendance.js b/controller/attendance.js index b98d726..b7473e9 100644 --- a/controller/attendance.js +++ b/controller/attendance.js @@ -6,7 +6,7 @@ import { } from "#services/attendance"; import { logger } from "#util"; import { isEntityIdValid } from "#middleware/entityIdValidation"; -import Student from "#models/attendance"; +import Student from "#models/student"; import Course from "#models/course"; async function addAttendance(req, res) { @@ -26,6 +26,7 @@ async function addAttendance(req, res) { res.status(400).json({ error: "Invalid Id", }); + return; } const attendance = await addNewAttendance( student, diff --git a/controller/faculty.js b/controller/faculty.js index 38a01dd..1a1dc49 100644 --- a/controller/faculty.js +++ b/controller/faculty.js @@ -1,4 +1,5 @@ import mongoose from "mongoose"; +import { commitWithRetry } from "#constant"; import { createFaculty, facultyList, @@ -63,7 +64,6 @@ async function addFaculty(req, res) { const session = await mongoose.startSession(); session.startTransaction(); try { - if (!isDepartmentValid || !isPreferredSubjectsValid) { res.status(400).json({ error: `Invalid IDs: Department: ${isDepartmentValid}, PreferredSubjects: ${isPreferredSubjectsValid}}`, @@ -78,7 +78,6 @@ async function addFaculty(req, res) { } const ERPID = `F${randomLetter}${randomNumber}`; - const newFaculty = await createFaculty( ERPID, dateOfJoining, @@ -103,18 +102,14 @@ async function addFaculty(req, res) { addNewEmployeeCurrent(employeeCurrentDetails, session), createEmployeeBank(employeeBankDetails, session), ]); + await commitWithRetry(session); res.json({ res: `added faculty ${newFaculty.ERPID}`, id: newFaculty.ERPID, }); - await session.commitTransaction(); - session.endSession(); } - - } catch (error) { await session.abortTransaction(); - session.endSession(); logger.error("Error while inserting", error); res.status(500); res.json({ err: "Error while inserting in DB" }); diff --git a/controller/organization.js b/controller/organization.js index 7e3793f..708154c 100644 --- a/controller/organization.js +++ b/controller/organization.js @@ -10,20 +10,26 @@ import Accreditation from "#models/accreditation"; import Parent from "#models/organization"; async function addOrganization(req, res) { - const { parent, startDate, name, accreditation } = req.body; - const isAccreditationValid = await isEntityIdValid(accreditation, Accreditation); + const { parent, startDate, name, accreditations } = req.body; + const isAccreditationsValid = await isEntityIdValid( + accreditations, + Accreditation, + ); const isParentValid = await isEntityIdValid(parent, Parent); try { - if (!isAccreditationValid || !isParentValid) { + if (!isAccreditationsValid || !isParentValid) { + console.log(isAccreditationsValid); + console.log(isParentValid); res.status(400).json({ error: "Invalid Id", }); + return; } const organization = await addNewOrganization( parent, startDate, name, - accreditation, + accreditations, ); res.json({ res: `added organization${organization.name}`, diff --git a/controller/student.js b/controller/student.js index 510ff28..d4026d8 100644 --- a/controller/student.js +++ b/controller/student.js @@ -14,7 +14,7 @@ import { logger } from "#util"; import { isEntityIdValid } from "#middleware/entityIdValidation"; import Department from "#models/department"; import Course from "#models/course"; -import { departmentAbbrev, departmentNames } from "#constant"; +import { departmentAbbrev, departmentNames , commitWithRetry } from "#constant"; async function addStudent(req, res) { const { @@ -198,9 +198,9 @@ async function addStudent(req, res) { const year = joiningYear.toString().slice(-2); let randomNumber = Math.floor(Math.random() * 1000).toString(); if (randomNumber.length === 2) { - randomNumber = `0${ randomNumber}`; + randomNumber = `0${randomNumber}`; } - const ERPID = `S${ abbrev }${year }${randomNumber}`; + const ERPID = `S${abbrev}${year}${randomNumber}`; const session = await mongoose.startSession(); session.startTransaction(); @@ -392,16 +392,13 @@ async function addStudent(req, res) { }, session, ); - await session.commitTransaction(); - res.json({ + await commitWithRetry(session); + res.status(200).json({ res: `added user ${newStudent.id} ${newStdBank.bankAccount} ,${newstdCollege.enrollmentNo}, ${newStdEduHistory.uid},${newStdMedHistory.uid},${newStdPersonal.uid}`, id: newStudent.id, }); } catch (err) { await session.abortTransaction(); - console.log(`aborted by catch + ${err}`); - } finally { - session.endSession(); } } else { let error = ""; // eslint-disable-line prefer-const diff --git a/misc/constant.js b/misc/constant.js index 3cc1d6d..b255bb1 100644 --- a/misc/constant.js +++ b/misc/constant.js @@ -38,3 +38,16 @@ export const departmentAbbrev = [ "AGD", "DA", ]; + +export async function commitWithRetry(session) { + let i = 0; + while (i < 3) { + try { + session.commitTransaction(); // Uses write concern set at transaction start. + break; + } catch (error) { + console.log(error); + i += 1; + } + } +} diff --git a/services/organization.js b/services/organization.js index 03eedbd..fdb556c 100644 --- a/services/organization.js +++ b/services/organization.js @@ -5,13 +5,13 @@ export async function addNewOrganization( parent, startDate, name, - accreditation, + accreditations, ) { const newOrganization = await Organization.create({ parent, startDate, name, - accreditation, + accreditations, }); if (newOrganization.name === name) { return newOrganization; diff --git a/test/routes/attendance.test.js b/test/routes/attendance.test.js index 08bffc8..f49ac8f 100644 --- a/test/routes/attendance.test.js +++ b/test/routes/attendance.test.js @@ -1,12 +1,29 @@ import { jest } from "@jest/globals"; // eslint-disable-line import/no-extraneous-dependencies import attendanceModel from "#models/attendance"; import connector from "#models/databaseUtil"; +import courseModel from "#models/course"; +import studentModel from "#models/student"; jest.mock("#util"); const { agent } = global; +let courseId; +let studentId; + +/* eslint-disable no-underscore-dangle */ +async function getIds(callback) { + courseId = await courseModel.read({}, 1); + courseId = courseId.data[0]._id; + studentId = await studentModel.read({}, 1); + studentId = studentId.data[0]._id; + callback(); +} + +beforeAll((done) => { + getIds(done); +}); function cleanUp(callback) { - attendanceModel.remove({ student: "64fc3c8bde9fa947ea1f412f" }).then(() => { + attendanceModel.remove({ monthlyAttended: 123456 }).then(() => { connector.disconnect((DBerr) => { if (DBerr) console.log("Database dissconnnect error: ", DBerr); callback(); @@ -21,9 +38,9 @@ afterAll((done) => { describe("checking attendance functions", () => { it("create attendance", async () => { const response = await agent.post("/attendance/add").send({ - student: "64fc3c8bde9fa947ea1f412f", - course: "64fc3c8bde9fa947ea1f412f", - monthlyAttended: 123, + student: studentId, + course: courseId, + monthlyAttended: 123456, monthlyOccured: 123, cumulativeAttended: 123, cumulativeOccured: 123, @@ -35,9 +52,9 @@ describe("checking attendance functions", () => { let id; beforeEach(async () => { id = await agent.post("/attendance/add").send({ - student: "64fc3c8bde9fa947ea1f412f", - course: "64fc3c8bde9fa947ea1f412f", - monthlyAttended: 123, + student: studentId, + course: courseId, + monthlyAttended: 123456, monthlyOccured: 123, cumulativeAttended: 123, cumulativeOccured: 123, @@ -46,13 +63,13 @@ describe("checking attendance functions", () => { }); afterEach(async () => { - await attendanceModel.remove({ student: "64fc3c8bde9fa947ea1f412f" }); + await attendanceModel.remove({ student: studentId }); }); it("read attendance", async () => { const response = await agent .get("/attendance/list") - .send({ student: "64fc3c8bde9fa947ea1f412f" }); + .send({ student: studentId }); expect(response.status).toBe(200); expect(response.body.res).toBeDefined(); }); @@ -60,7 +77,7 @@ describe("checking attendance functions", () => { it("update attendance", async () => { const response = await agent .post(`/attendance/update/${id}`) - .send({ student: "64fc3c8bde9fa947ea1f412f" }); + .send({ student: studentId }); expect(response.headers["content-type"]).toMatch(/json/); expect(response.status).toBe(200); expect(response.body.res).toMatch(/attendance updated/); diff --git a/test/routes/organization.test.js b/test/routes/organization.test.js index e6f3923..0ec115f 100644 --- a/test/routes/organization.test.js +++ b/test/routes/organization.test.js @@ -1,9 +1,12 @@ import { jest } from "@jest/globals"; // eslint-disable-line import/no-extraneous-dependencies import organizationModel from "#models/organization"; import connector from "#models/databaseUtil"; +import accreditationModel from "#models/accreditation"; jest.mock("#util"); const { agent } = global; +let accreditationIds; +let parentId; function cleanUp(callback) { organizationModel.remove({ startDate: "2023-06-18T14:11:30Z" }).then(() => { @@ -15,60 +18,72 @@ function cleanUp(callback) { }); }); } +/* eslint-disable no-underscore-dangle */ +async function getIds(callback) { + accreditationIds = await accreditationModel.read({}, 1); + accreditationIds = accreditationIds.data[0]._id; + parentId = await organizationModel.read({}, 1); + parentId = parentId.data[0]._id; + callback(); +} + +beforeAll((done) => { + getIds(done); +}); afterAll((done) => { cleanUp(done); }); describe("Organization API", () => { - it("should create organization", async () => { - const response = await agent.post("/organization/add").send({ - parent: "60a0e7e9a09c3f001c834e06", - startDate:"2023-06-18T14:11:30Z", - name:"my org", - accreditations: "60a0e7e9a09c3f001c834e06", - }); - - expect(response.status).toBe(200); - expect(response.body.res).toMatch(/added organization/); + it("should create organization", async () => { + const response = await agent.post("/organization/add").send({ + parent: parentId, + startDate: "2023-06-18T14:11:30Z", + name: "my org", + accreditations: accreditationIds, }); - - describe("after adding organization", () => { - let id; - beforeEach(async () => { - id = await agent.post("/organization/add").send({ - parent: "60a0e7e9a09c3f001c834e06", - startDate:"2023-06-18T14:11:30Z", - name:"my org", - accreditations: "60a0e7e9a09c3f001c834e06", - }); - id = JSON.parse(id.res.text).id; - }); - - afterEach(async () => { - await organizationModel.remove({ - parent: "60a0e7e9a09c3f001c834e06", - startDate:"2023-06-18T14:11:30Z", - name:"my org", - accreditations: "60a0e7e9a09c3f001c834e06", - }); - }); - - it("should read organization", async () => { - const response = await agent - .get("/organization/list") - .send({ name:"my org" }); - expect(response.status).toBe(200); - expect(response.body.res).toBeDefined(); + + expect(response.status).toBe(200); + expect(response.body.res).toMatch(/added organization/); + }); + + describe("after adding organization", () => { + let id; + beforeEach(async () => { + id = await agent.post("/organization/add").send({ + parent: parentId, + startDate: "2023-06-18T14:11:30Z", + name: "my org", + accreditations: accreditationIds, }); - - it("should update organization", async () => { - const response = await agent - .post(`/organization/update/${id}`) - .send({ name: "your org" }); - - expect(response.status).toBe(200); - expect(response.body.res).toMatch(/organization updated/); + id = JSON.parse(id.res.text).id; + }); + + afterEach(async () => { + await organizationModel.remove({ + parent: parentId, + startDate: "2023-06-18T14:11:30Z", + name: "my org", + accreditations: accreditationIds, }); }); - }); \ No newline at end of file + + it("should read organization", async () => { + const response = await agent + .get("/organization/list") + .send({ name: "my org" }); + expect(response.status).toBe(200); + expect(response.body.res).toBeDefined(); + }); + + it("should update organization", async () => { + const response = await agent + .post(`/organization/update/${id}`) + .send({ name: "your org" }); + + expect(response.status).toBe(200); + expect(response.body.res).toMatch(/organization updated/); + }); + }); +});