From dab6339ff662752eddd4150dcfd64f7f211a65f5 Mon Sep 17 00:00:00 2001 From: Rosa Date: Tue, 21 Mar 2023 21:32:02 -0400 Subject: [PATCH 1/5] feat: update prereqs for Intro Algo to be consistent with new requirements --- data/updatePrereq.js | 342 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 data/updatePrereq.js diff --git a/data/updatePrereq.js b/data/updatePrereq.js new file mode 100644 index 0000000..ef2caaa --- /dev/null +++ b/data/updatePrereq.js @@ -0,0 +1,342 @@ +import { connect } from "./db.js"; +import dotenv from "dotenv"; +import SISCourseV from '../model/SISCourseV.js'; + +dotenv.config(); + +async function updateIntroAlgo() { + connect(); + const number = "EN.601.433"; + const oldPrereq = [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ]; + + const newPrereq = [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ]; + + let data = await SISCourseV.find({number}); + let course = data[0]; + for (let version of course.versions) { + version.preReq = newPrereq; + } + await course.save(); + console.log("done!") +} + +// updateIntroAlgo(); + +async function checkUpdated() { + connect(); + const number = "EN.601.433"; + let data = await SISCourseV.find({number}); + let course = data[0]; + + for (let version of course.versions) { + console.log(version.preReq); + } +} + +checkUpdated(); + + + +/** Intro Algo + * { + "data": { + "_id": "635df458662f1ebee559601f", + "terms": [ + "Fall 2021", + "Spring 2023", + "Fall 2022", + "Spring 2022", + "Spring 2021", + "Fall 2020", + "Spring 2020", + "Fall 2019" + ], + "title": "Intro Algorithms", + "number": "EN.601.433", + "versions": [ + { + "department": "EN Computer Science", + "tags": [ + "BMED-BDS", + "COGS-COMPCG", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "637042cbbfb975c236485bf9", + "areas": "EQ", + "term": "Fall 2021", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "COGS-COMPCG", + "BMED-BDS", + "ARCH-ARCH", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [ + { + "RestrictionName": "Computer Science minors", + "Description": "" + }, + { + "RestrictionName": "UGrad Computer Engineering majors", + "Description": "" + }, + { + "RestrictionName": "UGrad Computer Science majors", + "Description": "" + } + ], + "_id": "635df5c8662f1ebee559ed3c", + "areas": "EQ", + "term": "Spring 2023", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "BMED-BDS", + "COGS-COMPCG", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df59b662f1ebee559da76", + "areas": "EQ", + "term": "Fall 2022", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "COGS-COMPCG", + "BMED-BDS", + "ARCH-ARCH", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df571662f1ebee559c810", + "areas": "EQ", + "term": "Spring 2022", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "COGS-COMPCG", + "BMED-BDS", + "ARCH-ARCH", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df501662f1ebee5599dcf", + "areas": "EQ", + "term": "Spring 2021", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "BMED-BDS", + "COGS-COMPCG", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df4c8662f1ebee559885b", + "areas": "EQ", + "term": "Fall 2020", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "COGS-COMPCG", + "BMED-BDS", + "ARCH-ARCH", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df489662f1ebee5596c56", + "areas": "EQ", + "term": "Spring 2020", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + }, + { + "department": "EN Computer Science", + "tags": [ + "COGS-COMPCG", + "BME-BDS", + "BMED-BDS", + "CSCI-THRY" + ], + "preReq": [ + { + "Description": "EN.600.226/EN.601.226 AND (EN.553.171/EN.550.171 OR EN.553.172/EN.550.170 OR EN.600.271/EN.601.231 OR EN.601.230", + "Expression": "EN.600.226[C]^AND^(^EN.553.171[C]^OR^EN.553.172[C]^OR^EN.600.271[C]^OR^EN.601.230[C]^)", + "IsNegative": "N" + }, + { + "Description": "Students may receive credit for only one of EN.600.363, EN.600.463, EN.601.433, EN.601.633.", + "Expression": "EN.600.363[C]^OR^EN.601.633[C]", + "IsNegative": "Y" + } + ], + "coReq": [], + "restrictions": [], + "_id": "635df458662f1ebee5596020", + "areas": "EQ", + "term": "Fall 2019", + "school": "Whiting School of Engineering", + "credits": 3, + "wi": false, + "level": "Upper Level Undergraduate", + "bio": "This course concentrates on the design of algorithms and the rigorous analysis of their efficiency. topics include the basic definitions of algorithmic complexity (worst case, average case); basic tools such as dynamic programming, sorting, searching, and selection; advanced data structures and their applications (such as union-find); graph algorithms and searching techniques such as minimum spanning trees, depth-first search, shortest paths, design of online algorithms and competitive analysis. [Analysis]" + } + ], + "__v": 9 + } +} + * + */ \ No newline at end of file From d1880997d490dcfba2fc7a7312d3f385c675c6f0 Mon Sep 17 00:00:00 2001 From: Rosa Date: Tue, 21 Mar 2023 23:31:22 -0400 Subject: [PATCH 2/5] feat: remove old majors and modify names of new majors --- data/replaceOldMajors.js | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 data/replaceOldMajors.js diff --git a/data/replaceOldMajors.js b/data/replaceOldMajors.js new file mode 100644 index 0000000..0b70167 --- /dev/null +++ b/data/replaceOldMajors.js @@ -0,0 +1,80 @@ +import { connect } from "./db.js"; +import User from '../model/User.js'; +import Plan from '../model/Plan.js'; + +async function replaceOldWithNew() { + connect(); + + const users = await User.find({}); + for (let user of users) { + for (let plan_id of user.plan_ids) { + let plan = await Plan.findById(plan_id).exec(); + if (plan !== null && plan.majors != null && plan.majors.length > 0) { + // console.log("before: " + plan.majors); + for (let ind in plan.majors) { + let major = plan.majors[ind]; + if (major.includes("B.A. Computer Science (NEW - 2021 & after)")) { + plan.majors[ind] = "B.A. Computer Science"; + } else if (major.includes("B.S. Computer Science (OLD - Pre-2021)") + || major.includes("B.S. Computer Science (NEW - 2021 & after)")) { + plan.majors[ind] = "B.S. Computer Science"; + } else if (major.includes("Minor Computer Science (OLD - Pre-2021)")) { + plan.majors[ind] = "Minor Computer Science"; + } else if (major.includes("Minor Computer Science (NEW - 2021 & after)")) { + plan.majors[ind] = "Minor Computer Science"; + } else if (major.includes("Minor Applied Mathematics & Statistics (OLD - Pre-2021)") + || major.includes("Minor Applied Mathematics & Statistics (NEW - 2021 & after)")) { + plan.majors[ind] = "Minor Applied Mathematics & Statistics"; + } + } + plan.majors = [...new Set(plan.majors)]; + // console.log("after: " + plan.majors + ""); + await plan.save(); + // console.log("done!\n"); + } + if (plan !== null && plan.major_ids != null && plan.major_ids.length > 0) { + console.log("before: " + plan.major_ids); + for (let ind in plan.major_ids) { + let major = plan.major_ids[ind]; + if (major.includes("B.A. Computer Science (NEW - 2021 & after)")) { + plan.major_ids[ind] = "B.A. Computer Science"; + } else if (major.includes("B.S. Computer Science (OLD - Pre-2021)") + || major.includes("B.S. Computer Science (NEW - 2021 & after)")) { + plan.major_ids[ind] = "B.S. Computer Science"; + } else if (major.includes("Minor Computer Science (OLD - Pre-2021)")) { + plan.major_ids[ind] = "Minor Computer Science"; + } else if (major.includes("Minor Computer Science (NEW - 2021 & after)")) { + plan.major_ids[ind] = "Minor Computer Science"; + } else if (major.includes("Minor Applied Mathematics & Statistics (OLD - Pre-2021)") + || major.includes("Minor Applied Mathematics & Statistics (NEW - 2021 & after)")) { + plan.major_ids[ind] = "Minor Applied Mathematics & Statistics"; + } + } + plan.major_ids = [...new Set(plan.major_ids)]; + console.log("after: " + plan.major_ids + ""); + await plan.save(); + console.log("done!\n"); + } + } + } + console.log("done") +} + +replaceOldWithNew(); + + +async function checkResult() { + connect(); + + const users = await User.find({}); + for (let user of users) { + for (let plan_id of user.plan_ids) { + let plan = await Plan.findById(plan_id).exec(); + if (plan !== null && plan.majors != null && plan.majors.length > 0) { + console.log(plan.majors); + } + } + } +} + +// checkResult(); \ No newline at end of file From fcf38c1e87fbca762ad81aa697e0300a2d5966ac Mon Sep 17 00:00:00 2001 From: mpark63 Date: Sun, 26 Mar 2023 22:55:54 -0400 Subject: [PATCH 3/5] DEV-142: remove parallel .save() --- data/replaceOldMajors.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data/replaceOldMajors.js b/data/replaceOldMajors.js index 0b70167..1061862 100644 --- a/data/replaceOldMajors.js +++ b/data/replaceOldMajors.js @@ -29,7 +29,6 @@ async function replaceOldWithNew() { } plan.majors = [...new Set(plan.majors)]; // console.log("after: " + plan.majors + ""); - await plan.save(); // console.log("done!\n"); } if (plan !== null && plan.major_ids != null && plan.major_ids.length > 0) { @@ -52,9 +51,9 @@ async function replaceOldWithNew() { } plan.major_ids = [...new Set(plan.major_ids)]; console.log("after: " + plan.major_ids + ""); - await plan.save(); console.log("done!\n"); } + await plan.save(); } } console.log("done") From b5281f78a01ea768f6d709aaa33f2a1abcac94df Mon Sep 17 00:00:00 2001 From: Rosa Date: Fri, 21 Apr 2023 22:34:12 -0400 Subject: [PATCH 4/5] feat: add path for patching oldCourse w newCourse --- routes/course.js | 79 +++++++++++++++++++++++++++++++++++++ tests/routes/course.spec.js | 60 ++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/routes/course.js b/routes/course.js index 40f58af..639a525 100644 --- a/routes/course.js +++ b/routes/course.js @@ -262,4 +262,83 @@ router.delete("/api/courses/:course_id", auth, async (req, res) => { } }); + + +// delete and create a new course +// need to provide new course as json object in request body +// distribution field is also updated +router.patch("/api/courses/:course_id", auth, async (req, res) => { + // delete the course + const c_id = req.params.course_id; + try { + // verify that course belongs to req user + const course = await Courses.findById(c_id).exec(); + if (!course) { + return errorHandler(res, 404, "Course not found."); + } else if (req.user._id !== course.user_id) { + return forbiddenHandler(res); + } + // delete course and update distributions + await Courses.findByIdAndDelete(c_id).exec(); + await Years + .findByIdAndUpdate( + course.year_id, + { $pull: { courses: course._id }}, + { runValidators: true } + ) + .exec(); + for (let id of course.distribution_ids) { + const distribution = await Distributions + .findByIdAndUpdate( + id, + { $pull: { courses: c_id } }, + { new: true, runValidators: true } + ) + .exec(); + await distributionCreditUpdate(distribution, course, false); + } + returnData(course, res); + } catch (err) { + errorHandler(res, 500, err); + } + + // insert a new course + const course = req.body.new_course; + if (!course || Object.keys(course).length == 0) { + return missingHandler(res, { course }); + } + if (course.user_id !== req.user._id) { + return forbiddenHandler(res); + } + try { + // check that course distributions belong to plan + const plan = await Plans.findById(course.plan_id).exec(); + course.distribution_ids.forEach((id) => { + if (!plan.distribution_ids.includes(id)) + errorHandler(res, 500, { + message: "Invalid combination of plan_id and distribution_ids.", + }); + }); + const retrievedCourses = await Courses.findByPlanId(course.plan_id); + for (const existingCourse of retrievedCourses) { + if(existingCourse.number === course.number && existingCourse.term === course.term && existingCourse.year === course.year && existingCourse.title === course.title){ + return errorHandler(res, 400, { + message: "Cannot take same course multiple times in the same semester", + }); + } + } + // create course and update distributiosn + const retrievedCourse = await Courses.create(course); + // update year with new course + await Years + .findByIdAndUpdate(retrievedCourse.year_id, { + $push: { courses: retrievedCourse._id }, + }) + .exec(); + returnData(retrievedCourse, res); + } catch (err) { + errorHandler(res, 500, err); + } +}); + export default router; diff --git a/tests/routes/course.spec.js b/tests/routes/course.spec.js index 1f57ec0..f071006 100644 --- a/tests/routes/course.spec.js +++ b/tests/routes/course.spec.js @@ -529,3 +529,63 @@ describe("Course Routes: PATCH /api/courses/dragged", () => { expect(res.status).toBe(500); }); }); + + + +describe("Course Routes: PATCH /api/courses/:course_id", () => { + it("Should return the new course added", async () => { + courses = await Courses.find({}); + let oldCourse = courses[0]; + const newCourse = SAMEPLE_COURSES[0]; + // change taken status to true + const res = await request + .patch(`/api/courses/${course._id}`) + .set("Authorization", `Bearer ${TEST_TOKEN_1}`) + .send(newCourse); + + expect(res.status).toBe(200); + // check course deleted + oldCourse = await Courses.findById(oldCourse._id); + expect(oldCourse).toBeNull(); + // check new course returned + const returnedCourse = res.body.data; + expect(returnedCourse.title).toBe(newCourse.title); + expect(returnedCourse.term).toBe(newCourse.term); + expect(returnedCourse.number).toBe(newCourse.number); + expect(returnedCourse.level).toBe(newCourse.level); + expect(returnedCourse.user_id).toBe(newCourse.user_id); + expect(returnedCourse.plan_id).toBe(newCourse.plan_id); + }); + + it("Should return status 403 for invalid user", async () => { + // course.taken is false by default + courses = await Courses.find({}); + let course = courses[0]; + // attempt to change taken status + const res = await request + .patch(`/api/courses/${course._id}`) + .set("Authorization", `Bearer ${TEST_TOKEN_2}`) + .send(SAMEPLE_COURSES[0]); + expect(res.status).toBe(403); + // check old course still there + const thatCourse = await Courses.findById(course._id); + expect(thatCourse.title).toBe(course.title); + }); + + it("Should return status 500 for invalid id", async () => { + const res = await request + .patch(`/api/courses/changeStatus/${INVALID_ID}`) + .set("Authorization", `Bearer ${TEST_TOKEN_1}`) + .send(SAMEPLE_COURSES[0]); + expect(res.status).toBe(500); + }); + + it("Should return status 400 for missing taken", async () => { + courses = await Courses.find({}); + let course = courses[0]; + const res = await request + .patch(`/api/courses/changeStatus/${course._id}`) + .set("Authorization", `Bearer ${TEST_TOKEN_1}`); + expect(res.status).toBe(400); + }); +}); From 4db82a697f43257816a8dc84fb7d6f8ab648add8 Mon Sep 17 00:00:00 2001 From: Rosa Date: Sun, 14 May 2023 16:34:05 -0400 Subject: [PATCH 5/5] feat: delete distribution and add inserting course --- data/patchCourses.js | 17 +++++++++++++++++ routes/course.js | 36 +++--------------------------------- 2 files changed, 20 insertions(+), 33 deletions(-) create mode 100644 data/patchCourses.js diff --git a/data/patchCourses.js b/data/patchCourses.js new file mode 100644 index 0000000..7d30a5d --- /dev/null +++ b/data/patchCourses.js @@ -0,0 +1,17 @@ +import { connect } from "./db.js"; +import dotenv from "dotenv"; +import SISCourseV from '../model/SISCourseV.js'; +// import mongoose from 'mongoose'; + +// dotenv.config(); +// mongoose.set('strictQuery', true); + +async function patchCourses() { + connect(); + + const courses = await SISCourseV.find(); + + console.log(courses); +} + +patchCourses() \ No newline at end of file diff --git a/routes/course.js b/routes/course.js index 639a525..e09f0b6 100644 --- a/routes/course.js +++ b/routes/course.js @@ -278,7 +278,6 @@ router.patch("/api/courses/:course_id", auth, async (req, res) => { } else if (req.user._id !== course.user_id) { return forbiddenHandler(res); } - // delete course and update distributions await Courses.findByIdAndDelete(c_id).exec(); await Years .findByIdAndUpdate( @@ -287,16 +286,6 @@ router.patch("/api/courses/:course_id", auth, async (req, res) => { { runValidators: true } ) .exec(); - for (let id of course.distribution_ids) { - const distribution = await Distributions - .findByIdAndUpdate( - id, - { $pull: { courses: c_id } }, - { new: true, runValidators: true } - ) - .exec(); - await distributionCreditUpdate(distribution, course, false); - } returnData(course, res); } catch (err) { errorHandler(res, 500, err); @@ -310,25 +299,8 @@ router.patch("/api/courses/:course_id", auth, async (req, res) => { if (course.user_id !== req.user._id) { return forbiddenHandler(res); } - try { - // check that course distributions belong to plan - const plan = await Plans.findById(course.plan_id).exec(); - course.distribution_ids.forEach((id) => { - if (!plan.distribution_ids.includes(id)) - errorHandler(res, 500, { - message: "Invalid combination of plan_id and distribution_ids.", - }); - }); - const retrievedCourses = await Courses.findByPlanId(course.plan_id); - for (const existingCourse of retrievedCourses) { - if(existingCourse.number === course.number && existingCourse.term === course.term && existingCourse.year === course.year && existingCourse.title === course.title){ - return errorHandler(res, 400, { - message: "Cannot take same course multiple times in the same semester", - }); - } - } - // create course and update distributiosn - const retrievedCourse = await Courses.create(course); + + const retrievedCourse = await Courses.create(course); // update year with new course await Years .findByIdAndUpdate(retrievedCourse.year_id, { @@ -336,9 +308,7 @@ router.patch("/api/courses/:course_id", auth, async (req, res) => { }) .exec(); returnData(retrievedCourse, res); - } catch (err) { - errorHandler(res, 500, err); - } + }); export default router;