Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (32)
Showing
with 1553 additions and 177 deletions
This diff is collapsed.
# Course Class Meeting API
## Get Course Class Meeting by Course Class Meeting Id
- Endpoint: `/course-class-meeting/?courseClassMeetingId=<course_class_meeting_id>[&shouldIncludeAttendances="true"|"false"]`
- HTTP Method: `GET`
- Response Body (Success):
```json
{
"id": "8b3f8b6b-a65b-49ef-a3c0-f14fdf57316a",
"startTime": "2021-08-17T13:00:00.000Z",
"endTime": "2021-08-17T15:00:00.000Z",
"openAttendanceTime": "2021-08-17T13:00:00.000Z",
"closeAttendanceTime": "2021-08-17T15:00:00.000Z",
"link": null,
"topic": null,
"notes": null,
"createdAt": "2021-03-22T11:10:35.540Z",
"updatedAt": "2021-03-22T11:10:35.540Z",
"courseClassId": "b4a2d11c-a0fa-4752-8d38-51e484737e65",
"courseClassMeetingAttendances": [
{
"status": "ABSENT",
"Student": {
"id": "070d0c07-f741-4358-b90a-8bfe134e0198",
"userName": null,
"fullName": null,
"gender": null,
"nim": null,
"nik": null,
"phone": null,
"year": null,
"createdAt": "2021-03-22T11:10:35.287Z",
"updatedAt": "2021-03-22T11:10:35.287Z",
"advisorId": "a6d2b6b1-7c03-4d9a-a12f-f32809d01639",
"majorId": "476cfe20-e7b2-4537-bdbc-3b76aa226ae3",
"userId": "052b3a5a-d51f-4cb5-ad8e-41ad94803cc5"
}
}
]
}
```
- Response Body (Failure):
```json
{
"name": "Error",
"message": "Undefined one of these parameters: courseClassMeetingId, or studentId, or lecturerId"
}
```
```json
{
"name": "Error",
"message": "Object doesn't exist."
}
```
## Get Course Class Meeting by Student Id
- Endpoint: `/course-class-meeting/?studentId=<student_id>&semester=<semester>&startYear=<year>`
- HTTP Method: `GET`
- Response Body (Success):
```json
[
{
"id": "f599df29-6ac9-4e63-b77b-83a27c15bbb3",
"startTime": "2021-12-08T13:00:00.000Z",
"endTime": "2021-12-08T15:00:00.000Z",
"openAttendanceTime": "2021-12-08T13:00:00.000Z",
"closeAttendanceTime": "2021-12-08T15:00:00.000Z",
"CourseClass": {
"courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00",
"Course": {
"code": "IF5122",
"name": "Pembangunan Perangkat Lunak"
}
}
},
{
"id": "f8e192cf-b384-42a1-a187-22a08104350d",
"startTime": "2021-12-01T13:00:00.000Z",
"endTime": "2021-12-01T15:00:00.000Z",
"openAttendanceTime": "2021-12-01T13:00:00.000Z",
"closeAttendanceTime": "2021-12-01T15:00:00.000Z",
"CourseClass": {
"courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00",
"Course": {
"code": "IF5122",
"name": "Pembangunan Perangkat Lunak"
}
}
},
{
"id": "dbe564c4-c647-466c-9d3e-bbeabc9180d1",
"startTime": "2021-12-14T09:30:00.000Z",
"endTime": "2021-12-14T11:30:00.000Z",
"openAttendanceTime": "2021-12-14T09:30:00.000Z",
"closeAttendanceTime": "2021-12-14T11:30:00.000Z",
"CourseClass": {
"courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed",
"Course": {
"code": "IF6012",
"name": "Arsitektur Komputer Lanjut"
}
}
},
{
"id": "ae5a783d-f89c-4616-a976-cd01e249972f",
"startTime": "2021-12-07T09:30:00.000Z",
"endTime": "2021-12-07T11:30:00.000Z",
"openAttendanceTime": "2021-12-07T09:30:00.000Z",
"closeAttendanceTime": "2021-12-07T11:30:00.000Z",
"CourseClass": {
"courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed",
"Course": {
"code": "IF6012",
"name": "Arsitektur Komputer Lanjut"
}
}
}
]
```
- Response Body (Failure):
```json
{
"name": "Error",
"message": "Undefined semester,startYear"
}
```
```json
{
"name": "Error",
"message": "Object doesn't exist."
}
```
## Get Course Class Meeting by Lecturer Id
- Endpoint: `/course-class-meeting/?lecturerId=<lecturer_id>&semester=<semester>&startYear=<year>`
- HTTP Method: `GET`
- Response Body (Success):
```json
[
{
"id": "33b797f8-6d41-4ad4-b3de-a00dacfb692f",
"startTime": "2021-08-18T13:00:00.000Z",
"endTime": "2021-08-18T15:00:00.000Z",
"openAttendanceTime": "2021-08-18T13:00:00.000Z",
"closeAttendanceTime": "2021-08-18T15:00:00.000Z",
"CourseClass": {
"courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00",
"Course": {
"code": "IF5122",
"name": "Pembangunan Perangkat Lunak"
}
}
},
{
"id": "8b3f8b6b-a65b-49ef-a3c0-f14fdf57316a",
"startTime": "2021-08-17T13:00:00.000Z",
"endTime": "2021-08-17T15:00:00.000Z",
"openAttendanceTime": "2021-08-17T13:00:00.000Z",
"closeAttendanceTime": "2021-08-17T15:00:00.000Z",
"CourseClass": {
"courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00",
"Course": {
"code": "IF5122",
"name": "Pembangunan Perangkat Lunak"
}
}
},
{
"id": "aa9e275b-67a1-426c-a24f-547dea0aeb8a",
"startTime": "2021-08-19T13:00:00.000Z",
"endTime": "2021-08-19T15:00:00.000Z",
"openAttendanceTime": "2021-08-19T13:00:00.000Z",
"closeAttendanceTime": "2021-08-19T15:00:00.000Z",
"CourseClass": {
"courseId": "b0686ddc-81e9-4779-9b51-35fe831f916c",
"Course": {
"code": "IF6099",
"name": "Tesis"
}
}
},
{
"id": "99df0561-6962-4335-bff9-fb70369d076c",
"startTime": "2021-08-18T13:00:00.000Z",
"endTime": "2021-08-18T15:00:00.000Z",
"openAttendanceTime": "2021-08-18T13:00:00.000Z",
"closeAttendanceTime": "2021-08-18T15:00:00.000Z",
"CourseClass": {
"courseId": "b0686ddc-81e9-4779-9b51-35fe831f916c",
"Course": {
"code": "IF6099",
"name": "Tesis"
}
}
},
{
"id": "dbe564c4-c647-466c-9d3e-bbeabc9180d1",
"startTime": "2021-12-14T09:30:00.000Z",
"endTime": "2021-12-14T11:30:00.000Z",
"openAttendanceTime": "2021-12-14T09:30:00.000Z",
"closeAttendanceTime": "2021-12-14T11:30:00.000Z",
"CourseClass": {
"courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed",
"Course": {
"code": "IF6012",
"name": "Arsitektur Komputer Lanjut"
}
}
},
{
"id": "ae5a783d-f89c-4616-a976-cd01e249972f",
"startTime": "2021-12-07T09:30:00.000Z",
"endTime": "2021-12-07T11:30:00.000Z",
"openAttendanceTime": "2021-12-07T09:30:00.000Z",
"closeAttendanceTime": "2021-12-07T11:30:00.000Z",
"CourseClass": {
"courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed",
"Course": {
"code": "IF6012",
"name": "Arsitektur Komputer Lanjut"
}
}
}
]
```
- Response Body (Failure):
```json
{
"name": "Error",
"message": "Undefined semester,startYear"
}
```
```json
{
"name": "Error",
"message": "Object doesn't exist."
}
```
## Update Course Class Meeting
- Endpoint: `/course-class-meeting/<id>`
- HTTP Method: `PUT`
- Request Body:
```json
{
"link": "https://www.steamcommunity.com/id/icancan",
"topic": "Code Review",
"notes": "LGTM",
"startClass": "2021-08-17T13:15:00.000Z",
"endClass": "2021-08-17T13:16:00.000Z",
"startAttendance": "2021-08-17T13:14:59.000Z",
"endAttendance": "2021-08-17T13:16:01.000Z",
"attendances": [
{
"studentId": "aab0fa6a-b521-4a19-9106-d50cc01e4bf3",
"status": "PRESENT"
}
]
}
```
- Response Body (Success):
```json
{
"id": "05351502-c9f4-4dfa-9b39-bd922d28f857",
"startTime": "2021-08-17T13:15:00.000Z",
"endTime": "2021-08-17T13:16:00.000Z",
"openAttendanceTime": "2021-08-17T13:14:59.000Z",
"closeAttendanceTime": "2021-08-17T13:16:01.000Z",
"link": "https://www.steamcommunity.com/id/icancan",
"topic": "Code Review",
"notes": "LGTM",
"createdAt": "2021-03-24T19:54:29.567Z",
"updatedAt": "2021-03-26T07:59:48.401Z",
"courseClassId": "b973d0d6-ee5a-455d-84f5-1feb35de5df1",
"courseClassMeetingAttendances": [
{
"id": "e84270ff-2332-445c-aa81-7a5662262e9e",
"status": "PRESENT",
"Student": {
"id": "aab0fa6a-b521-4a19-9106-d50cc01e4bf3",
"userName": null,
"fullName": null,
"gender": null,
"nim": null,
"nik": null,
"phone": null,
"year": null,
"createdAt": "2021-03-24T19:54:29.472Z",
"updatedAt": "2021-03-24T19:54:29.472Z",
"advisorId": "d24cd8e0-fe26-45eb-a8c7-f63d23d8eaf1",
"majorId": "3013df19-a67d-43d7-a055-09fe3f09fda9",
"userId": "8cbb6503-1573-4e64-ae1c-f92a3cee5b62"
}
}
]
}
```
# Student API
## Get Student Data by User Id
- Endpoint: `/student/{id}`
- Endpoint: `/student/{id}[?includeTranscript="true"|"false"&includeScore="true"|"false"&includeCredits="true"|"false"]`
- HTTP Method: `GET`
- Response Body (Success):
......@@ -16,11 +16,137 @@
"nik": "12345677777",
"phone": "0812347890",
"year": 2020,
"createdAt": "2021-02-17T03:35:10.494Z",
"updatedAt": "2021-02-17T03:35:10.494Z",
"advisorId": "57e19842-d712-45fd-9068-04cde6bf41f3",
"majorId": "d7123456-45fd-9068-0123-04cde6bf41f3",
"userId": "626a872a-7dbf-403a-bca3-83cb9946a9fe"
"createdAt": "2021-03-22T11:10:35.287Z",
"updatedAt": "2021-03-22T11:10:35.287Z",
"advisorId": "a6d2b6b1-7c03-4d9a-a12f-f32809d01639",
"majorId": "476cfe20-e7b2-4537-bdbc-3b76aa226ae3",
"userId": "052b3a5a-d51f-4cb5-ad8e-41ad94803cc5",
"Advisor": {
"id": "a6d2b6b1-7c03-4d9a-a12f-f32809d01639",
"userName": null,
"fullName": null,
"gender": null,
"nip": null,
"nik": null,
"phone": null,
"academicRole": "KAPRODI",
"createdAt": "2021-03-22T11:10:35.263Z",
"updatedAt": "2021-03-22T11:10:35.263Z",
"skillGroupId": "2d0e4681-d984-4ecb-b57f-b9b92fe6d996",
"userId": "052b3a5a-d51f-4cb5-ad8e-41ad94803cc5"
},
"Major": {
"id": "476cfe20-e7b2-4537-bdbc-3b76aa226ae3",
"numberCode": 235,
"name": "Magister Teknik Informatika",
"createdAt": "2021-03-22T11:10:34.922Z",
"updatedAt": "2021-03-22T11:10:34.922Z",
"facultyId": "f183c826-1b97-4b68-b448-53a0087c8c38",
"Faculty": {
"id": "f183c826-1b97-4b68-b448-53a0087c8c38",
"shortName": "STEI",
"fullName": "Sekolah Teknik Elektro dan Informatika",
"createdAt": "2021-03-22T11:10:34.807Z",
"updatedAt": "2021-03-22T11:10:34.807Z"
}
},
"studyPlans": [
{
"id": "94bb4598-d900-4f39-9e63-fd13bbb4c2aa",
"startYear": 2022,
"creditsTotal": 0,
"semester": "2",
"status": "DRAFT",
"notes": null,
"createdAt": "2021-03-22T11:30:01.305Z",
"updatedAt": "2021-03-22T11:30:01.305Z",
"studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
"studyPlanCourses": []
},
{
"id": "54dbfaa8-1af3-448f-b395-f6f873fdbb5d",
"startYear": 2022,
"creditsTotal": 0,
"semester": "1",
"status": "FINAL",
"notes": "LGTM",
"createdAt": "2021-03-22T11:13:28.237Z",
"updatedAt": "2021-03-22T11:18:29.776Z",
"studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
"studyPlanCourses": []
},
{
"id": "b5f12832-3ea8-4312-a077-ad26c1d1dc40",
"startYear": 2021,
"creditsTotal": 2,
"semester": "2",
"status": "FINAL",
"notes": "LGTM",
"createdAt": "2021-03-22T11:10:35.457Z",
"updatedAt": "2021-03-26T06:07:10.417Z",
"studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
"studyPlanCourses": [
{
"id": "de473be6-92bd-4f66-a51a-949d69546ef5",
"attendancePercentage": 0,
"score": "T",
"status": "APPROVED",
"createdAt": "2021-03-26T06:07:10.390Z",
"updatedAt": "2021-03-26T06:07:10.390Z",
"courseClassId": "f52290f5-da7d-4d2b-b230-dd335d6a2247",
"studyPlanId": "b5f12832-3ea8-4312-a077-ad26c1d1dc40",
"CourseClass": {
"courseId": "0e3ceed1-d054-4cb4-8396-05ddd58bade8"
}
}
]
},
{
"id": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
"startYear": 2021,
"creditsTotal": 5,
"semester": "1",
"status": "FINAL",
"notes": "LGTM",
"createdAt": "2021-03-22T11:10:35.444Z",
"updatedAt": "2021-03-22T11:10:35.444Z",
"studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
"studyPlanCourses": [
{
"id": "b5f4b392-3a76-4a87-b733-d3730b65f7c9",
"attendancePercentage": 0,
"score": "A",
"status": "APPROVED",
"createdAt": "2021-04-06T12:57:16.089Z",
"updatedAt": "2021-04-06T12:57:16.089Z",
"courseClassId": "5ed2ff48-21ab-4152-a857-70faa5d8cfc4",
"studyPlanId": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
"CourseClass": {
"courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed"
}
},
{
"id": "130b3fba-b1d9-4363-88ea-ba68f91914b0",
"attendancePercentage": 0,
"score": "B",
"status": "APPROVED",
"createdAt": "2021-04-06T12:57:16.108Z",
"updatedAt": "2021-04-06T12:57:16.108Z",
"courseClassId": "b4a2d11c-a0fa-4752-8d38-51e484737e65",
"studyPlanId": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
"CourseClass": {
"courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00"
}
}
]
}
],
"score": {
"nr": 0,
"ip": 3.5,
"ipk": 3.5
},
"creditsTotal": 7
}
```
......
# Study Plan API
## Get Study Plan
- Endpoint: `/study-plan/?studentId=<student_id>[&shouldIncludeCourses="true"|"false"]`
- Endpoint: `/study-plan/?studyPlanId=<study_plan_id>&semester=<semester>&startYear=<year>[&shouldIncludeCourses="true"|"false"]`
- Endpoint: `/study-plan/?studyPlanId=<study_plan_id>[&shouldIncludeCourses="true"|"false"]`
- Endpoint: `/study-plan/?studentId=<student_id>&semester=<semester>&startYear=<year>[&shouldIncludeCourses="true"|"false"]`
- HTTP Method: `GET`
- Response Body (Success):
......@@ -13,6 +13,7 @@
"creditsTotal": 2,
"semester": "2",
"status": "DRAFT",
"notes": "LGTM",
"createdAt": "2021-03-14T10:59:28.652Z",
"updatedAt": "2021-03-14T10:59:28.652Z",
"studentId": "32657182-8849-4783-a141-51f29c008fc5",
......@@ -36,6 +37,7 @@
"creditsTotal": 0,
"semester": "1",
"status": "DRAFT",
"notes": "LGTM",
"createdAt": "2021-03-13T13:24:37.317Z",
"updatedAt": "2021-03-13T13:24:37.317Z",
"studentId": "7d9d0f64-ee6a-44d6-b56c-e9d9fd75de0d"
......@@ -66,6 +68,7 @@
"startYear": 2021,
"semester": 1,
"status": "DRAFT", // Optional
"notes": "LGTM", // Optional
"studyPlanCourses" : [ //Optional
{
"courseClassId": "c2353c52-9543-4135-9d1d-b9a0f96e64e2",
......@@ -88,6 +91,7 @@
"creditsTotal": 8,
"semester": "1",
"status": "DRAFT",
"notes": "LGTM",
"studyPlanCourses": [
{
"id": "d74d549b-250d-49ba-a90f-42fb16de2ae1",
......@@ -160,10 +164,20 @@
```json
{
"status": "FINAL",
"notes": "LGTM",
"studyPlanCourses": [
{ "courseClassId": "fe9d83cb-26c3-42a9-838a-20d66266e073" },
{ "courseClassId": "9c643f0b-7cdd-4d02-aacd-d33347fdfc0b" },
{ "courseClassId": "606ac4ce-c61e-449c-8728-5953966a787b" }
{
"courseClassId": "22c6c19f-7dab-45c0-8cfc-2d9aa59c1775",
"status": "APPROVED"
},
{
"courseClassId": "f5b9f49f-be34-4fca-b0da-116990eb515a",
"status": "UNAPPROVED"
},
{
"courseClassId": "33552c74-bef4-4219-8555-e1de8bc33452",
"status": "UNAPPROVED"
}
]
}
```
......@@ -172,41 +186,45 @@
```json
{
"id": "ea02c570-811a-4321-bca1-e94088356517",
"id": "10da0a53-6453-4207-9818-3f61d5cd206d",
"startYear": 2021,
"creditsTotal": 11,
"semester": "1",
"status": "FINAL",
"createdAt": "2021-03-15T08:28:35.937Z",
"updatedAt": "2021-03-15T08:28:54.642Z",
"studentId": "694588c4-237b-491e-baa6-0058660381a1",
"notes": "LGTM",
"createdAt": "2021-03-23T11:24:10.891Z",
"updatedAt": "2021-03-23T11:24:10.891Z",
"studentId": "5f956664-194a-431f-b313-fc7062812f76",
"studyPlanCourses": [
{
"id": "cd5ce03d-20e0-4c77-b648-d04cc119b2de",
"id": "10ec462a-201f-4615-879e-fc325ab0e35d",
"attendancePercentage": 0,
"score": "T",
"createdAt": "2021-03-15T08:39:57.443Z",
"updatedAt": "2021-03-15T08:39:57.443Z",
"courseClassId": "fe9d83cb-26c3-42a9-838a-20d66266e073",
"studyPlanId": "ea02c570-811a-4321-bca1-e94088356517"
"status": "APPROVED",
"createdAt": "2021-03-23T11:32:48.787Z",
"updatedAt": "2021-03-23T11:32:48.787Z",
"courseClassId": "22c6c19f-7dab-45c0-8cfc-2d9aa59c1775",
"studyPlanId": "10da0a53-6453-4207-9818-3f61d5cd206d"
},
{
"id": "562e324d-1130-4262-957b-0e89de4fd6c0",
"id": "117d3e69-3ed1-4dbf-9abc-849226e93270",
"attendancePercentage": 0,
"score": "T",
"createdAt": "2021-03-15T08:39:57.444Z",
"updatedAt": "2021-03-15T08:39:57.444Z",
"courseClassId": "9c643f0b-7cdd-4d02-aacd-d33347fdfc0b",
"studyPlanId": "ea02c570-811a-4321-bca1-e94088356517"
"status": "UNAPPROVED",
"createdAt": "2021-03-23T11:32:48.788Z",
"updatedAt": "2021-03-23T11:32:48.788Z",
"courseClassId": "f5b9f49f-be34-4fca-b0da-116990eb515a",
"studyPlanId": "10da0a53-6453-4207-9818-3f61d5cd206d"
},
{
"id": "2113f0f1-bbc8-4378-b53a-383c524a9e07",
"id": "436650d4-d85c-42d4-bf07-134bcf5a9b1b",
"attendancePercentage": 0,
"score": "T",
"createdAt": "2021-03-15T08:39:57.444Z",
"updatedAt": "2021-03-15T08:39:57.444Z",
"courseClassId": "606ac4ce-c61e-449c-8728-5953966a787b",
"studyPlanId": "ea02c570-811a-4321-bca1-e94088356517"
"status": "UNAPPROVED",
"createdAt": "2021-03-23T11:32:48.788Z",
"updatedAt": "2021-03-23T11:32:48.788Z",
"courseClassId": "33552c74-bef4-4219-8555-e1de8bc33452",
"studyPlanId": "10da0a53-6453-4207-9818-3f61d5cd206d"
}
]
}
......
......@@ -4,8 +4,9 @@
"description": "Backend service for SIX",
"main": "index.js",
"scripts": {
"test": "NODE_ENV=test && ./node_modules/mocha/bin/mocha src/test",
"start": "NODE_ENV=development && node src/index.js"
"linux-test": "NODE_ENV=test && ./node_modules/mocha/bin/mocha src/test",
"linux-start": "NODE_ENV=development && node src/index.js",
"windows-start": "set NODE_ENV=development && node src/index.js"
},
"author": "Group B",
"license": "MIT",
......
'use strict';
const {
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound,
} = require('../util/common');
const {
getCourseClassMeetingById,
getCourseClassMeetingByStudentId,
getCourseClassMeetingByLecturerId,
updateCourseClassMeeting
} = require('../util/db/course-class-meeting');
const {
NotExistError,
} = require('../util/error');
exports.getCourseClassMeeting = async (req, res) => {
const {
opts,
} = req.body;
const {
courseClassMeetingId,
studentId,
lecturerId
} = req.query;
try {
let response;
if (courseClassMeetingId) {
response = await getCourseClassMeetingById(opts);
} else if (studentId) {
response = await getCourseClassMeetingByStudentId(opts);
} else if (lecturerId) {
response = await getCourseClassMeetingByLecturerId(opts);
}
res.json(response);
} catch (error) {
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
} else {
handleRequestWithInternalServerError(res, error);
}
}
};
exports.updateCourseClassMeeting = async (req, res) => {
try {
const {
courseClassMeeting,
changeset
} = req.body;
const updatedCourseClassMeeting = await updateCourseClassMeeting(courseClassMeeting, changeset);
res.json(updatedCourseClassMeeting);
} catch (error) {
handleRequestWithInternalServerError(res, error);
}
};
'use strict';
const { handleRequestWithInvalidRequestBody } = require('../util/common');
const {
getCourseClass,
createCourseClass
const {
handleRequestWithInvalidRequestBody,
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound,
} = require("../util/common");
const {
getCourseClass,
createCourseClass,
updateCourseClass
} = require('../util/db/course-class');
const {
NotExistError,
} = require("../util/error");
exports.getCourseClassData = async(req, res) => {
let getMany = true;
if (req.params.id) {
let include;
if (req.body['include']) {
include = req.body['include'];
}
req.body = {};
req.body['id'] = req.params.id;
if (include){
req.body['include'] = include;
}
getMany = false;
}
......@@ -31,11 +29,11 @@ exports.getCourseClassData = async(req, res) => {
} catch (error){
console.error(error);
res.status(400)
.json({
status: 400,
message: error.message,
});
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
} else {
handleRequestWithInternalServerError(res, error);
}
}
};
......@@ -48,6 +46,7 @@ exports.createCourseClassData = async(req, res) => {
participantCount,
semester,
status,
courseClassDefaultSchedules
} = req.body;
const newCourseClass = {
......@@ -57,7 +56,8 @@ exports.createCourseClassData = async(req, res) => {
capacity,
participantCount,
semester,
status
status,
courseClassDefaultSchedules
};
try {
......@@ -68,3 +68,17 @@ exports.createCourseClassData = async(req, res) => {
handleRequestWithInvalidRequestBody(res, error);
}
};
exports.updateCourseClass = async (req, res) => {
try {
const {
courseClass,
changeset
} = req.body;
const updatedStudyPlan = await updateCourseClass(courseClass, changeset);
res.json(updatedStudyPlan);
} catch (error) {
handleRequestWithInternalServerError(res, error);
}
};
\ No newline at end of file
'use strict';
const {
Student,
Lecturer,
Major,
Faculty,
} = require('../models/index');
const {
NotExistError
} = require('../util/error');
const {
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound
} = require('../util/common');
const {
getStudent,
getCreditsTotal,
getHistoricalTranscript,
getStudentIP,
getStudentIPK,
getStudentNR
} = require('../util/db/student');
exports.getStudentData = async(req, res) => {
const foundStudent = await Student.findOne({
where: {
userId: req.params.id,
},
include: [
{
model: Lecturer,
as: 'Advisor',
},
{
model: Major,
include: Faculty,
},
],
}).catch(err => {
res.status(400)
.json({
status: 400,
message: 'Invalid uuid input.'
});
});
const { opts } = req;
if (foundStudent){
res.json(foundStudent);
} else {
res.status(400)
.json({
status: 400,
message: 'Student doesn\'t exist.',
});
try {
const student = await getStudent(opts);
if (req.includeTranscript.toLowerCase() === "true"){
student.dataValues.studyPlans = await getHistoricalTranscript(student.id);
}
if (req.includeScore.toLowerCase() === "true"){
const nr = await getStudentNR(student);
const ip = await getStudentIP(student);
const ipk = await getStudentIPK(student);
student.dataValues.score = {
nr,
ip,
ipk
};
}
if (req.includeCredits.toLowerCase() === "true"){
student.dataValues.creditsTotal = await getCreditsTotal(student);
}
res.json(student);
} catch (error) {
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
} else {
handleRequestWithInternalServerError(res, error);
}
}
};
......
......@@ -27,9 +27,9 @@ exports.getStudyPlan = async (req, res) => {
try {
const studyPlan = await getStudyPlan(opts);
res.json(studyPlan);
res.json(studyPlan);
} catch (error) {
if (error instanceof NotExistError) {
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
} else {
handleRequestWithInternalServerError(res, error);
......@@ -46,6 +46,7 @@ exports.createStudyPlanData = async(req, res) => {
startYear,
semester,
status,
notes,
studyPlanCourses
} = req.body;
......@@ -56,6 +57,7 @@ exports.createStudyPlanData = async(req, res) => {
startYear,
semester,
status,
notes
};
let creditsTotal = 0;
......@@ -86,7 +88,7 @@ exports.createStudyPlanData = async(req, res) => {
exports.updateStudyPlan = async (req, res) => {
try {
const {
const {
studyPlan,
changeset
} = req.body;
......
......@@ -10,7 +10,8 @@ const EndpointEnum = Object.freeze({
COURSE_CLASS: '/course-class',
COURSE: '/course',
STUDY_PLAN: '/study-plan',
COURSE_CLASS_MEETING: '/course-class-meeting',
}
})
module.exports = EndpointEnum;
\ No newline at end of file
module.exports = EndpointEnum;
const {
CourseClass,
} = require('../models/index');
const {
deleteCurrentMeetings
} = require('../util/hook');
const { generateCourseClassMeetings } = require('../util/common');
CourseClass.afterCreate(async courseClass => {
await generateCourseClassMeetings(courseClass);
});
CourseClass.afterUpdate(async courseClass => {
await deleteCurrentMeetings(courseClass);
await generateCourseClassMeetings(courseClass);
});
const {
StudyPlan,
} = require('../models/index');
const { calculateTotalCredits } = require('../util/hook');
const {
StudyPlanStatusEnum,
} = require('../enums/index');
const {
calculateTotalCredits,
deleteCurrentMeetingAttendances
} = require('../util/hook');
const { generateCourseClassMeetingAttendances } = require('../util/common');
StudyPlan.beforeCreate(async studyPlan => {
studyPlan.creditsTotal = await calculateTotalCredits(studyPlan.studyPlanCourses);
......@@ -9,4 +18,17 @@ StudyPlan.beforeCreate(async studyPlan => {
StudyPlan.beforeUpdate(async studyPlan => {
studyPlan.creditsTotal = await calculateTotalCredits(studyPlan.studyPlanCourses);
});
\ No newline at end of file
});
StudyPlan.afterCreate(async studyPlan => {
if (studyPlan.status === StudyPlanStatusEnum.FINAL){
await generateCourseClassMeetingAttendances(studyPlan);
}
});
StudyPlan.afterUpdate(async studyPlan => {
if (studyPlan.status === StudyPlanStatusEnum.FINAL) {
await deleteCurrentMeetingAttendances(studyPlan);
await generateCourseClassMeetingAttendances(studyPlan);
}
});
......@@ -16,9 +16,10 @@ const skillGroupRouter = require('./routes/skillgroup');
const courseClassRouter = require('./routes/courseclass');
const courseRouter = require('./routes/course');
const studyPlanRouter = require('./routes/study-plan');
const courseClassMeetingRouter = require('./routes/course-class-meeting');
require('./hooks/study-plan');
require('./hooks/course-class');
app.use(cors());
app.use(express.json());
......@@ -32,6 +33,7 @@ app.use(EndpointEnum.SKILL_GROUP, skillGroupRouter);
app.use(EndpointEnum.COURSE_CLASS, courseClassRouter);
app.use(EndpointEnum.COURSE, courseRouter);
app.use(EndpointEnum.STUDY_PLAN, studyPlanRouter);
app.use(EndpointEnum.COURSE_CLASS_MEETING, courseClassMeetingRouter);
let appServer = app.listen(port, host, () => console.log(`SIX backend service listening at http://${host}:${port}`));
......
'use strict';
const {
handleRequestWithInvalidRequestBody,
checkRequiredParameter,
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound,
} = require("../util/common");
const {
CourseClassMeetingAttendance,
Student
} = require("../models/index");
const {
RequiredParameterUndefinedError,
NotExistError,
} = require("../util/error");
const { getCourseClassMeetingById } = require("../util/db/course-class-meeting");
const getCourseClassMeetingMiddleware = async(req, res, next) => {
const {
courseClassMeetingId,
studentId,
lecturerId,
startYear,
semester,
shouldIncludeAttendances = "false",
} = req.query;
try {
const opts = {
where: {}
};
checkRequiredParameter({
oneOf: {
courseClassMeetingId,
studentId,
lecturerId
}
});
if (courseClassMeetingId) {
opts.where.id = courseClassMeetingId;
if (shouldIncludeAttendances.toLowerCase() === "true") {
opts.include = [
{
model: CourseClassMeetingAttendance,
as: "courseClassMeetingAttendances",
attributes: ["status"],
include: Student
}
]
}
} else if (studentId) {
checkRequiredParameter({
semester,
startYear,
});
opts.where = {
studentId,
semester,
startYear,
};
opts.include = "studyPlanCourses"
} else if (lecturerId) {
checkRequiredParameter({
semester,
startYear,
});
opts.where = {
lecturerId,
semester,
startYear,
};
}
req.body.opts = opts;
next();
} catch (error) {
if (error instanceof RequiredParameterUndefinedError) handleRequestWithInvalidRequestBody(res, error);
else handleRequestWithInternalServerError(res, error);
}
};
const updateCourseClassMeetingBodyCheckerMiddleware = async (req, res, next) => {
try {
const {
startClass,
endClass,
startAttendance,
endAttendance,
link,
topic,
notes,
attendances,
} = req.body;
checkRequiredParameter({
oneOf: {
startClass,
endClass,
startAttendance,
endAttendance,
link,
topic,
notes,
attendances,
},
});
next();
} catch (error) {
if (error instanceof RequiredParameterUndefinedError) {
handleRequestWithInvalidRequestBody(res, error);
} else {
handleRequestWithInternalServerError(res, error);
}
}
};
const updateCourseClassMeetingMiddleware = async (req, res, next) => {
const { id } = req.params;
try {
const courseClassMeeting = await getCourseClassMeetingById({
where: {
id,
},
shouldIncludeAttendances: true,
});
const {
startClass,
endClass,
startAttendance,
endAttendance,
link,
topic,
notes,
attendances,
} = req.body;
const changeset = {
startTime: startClass,
endTime: endClass,
openAttendanceTime: startAttendance,
closeAttendanceTime: endAttendance,
link,
topic,
notes,
courseClassMeetingAttendances: attendances,
};
req.body.courseClassMeeting = courseClassMeeting;
req.body.changeset = changeset;
next();
} catch (error) {
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
} else {
handleRequestWithInternalServerError(res, error);
}
}
};
module.exports = {
getCourseClassMeetingMiddleware,
updateCourseClassMeetingBodyCheckerMiddleware,
updateCourseClassMeetingMiddleware,
};
'use strict';
const {
Course,
Major,
Faculty,
Lecturer,
CourseClassDefaultSchedule
} = require("../models/index");
const {
handleRequestWithInvalidRequestBody,
checkRequiredParameter,
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound
} = require("../util/common");
const { getCourseClass } = require("../util/db/course-class");
const {
RequiredParameterUndefinedError,
NotExistError
} = require("../util/error");
const getCourseClassMiddleware = async(req, res, next) => {
const {
status,
semester,
startYear,
include
} = req.query;
const {
id
} = req.params;
let opts = {};
if (id) {
opts.where = {id};
} else {
opts.where = {};
if (status) {
opts.where.status = status;
}
if (semester) {
opts.where.semester = semester;
}
if (startYear) {
opts.where.startYear = startYear;
}
}
opts.include = [{
model: CourseClassDefaultSchedule,
as: "courseClassDefaultSchedules"
}];
if (include){
if (include.includes('Course')){
opts.include.push({
model: Course,
include: [
{
model: Major,
include: Faculty
}
]
});
}
if (include.includes('Lecturer')){
opts.include.push({
model: Lecturer,
});
}
if (include.includes('Students')){
req.body.includeStudent = true;
}
}
req.body.opts = opts;
next();
};
const updateCourseClassMiddleware = async (req, res, next) => {
const { id } = req.params;
try {
const {
status,
startYear,
semester,
capacity,
lecturerId,
courseClassDefaultSchedules
} = req.body;
checkRequiredParameter({
oneOf: {
status,
startYear,
semester,
capacity,
lecturerId,
courseClassDefaultSchedules
}
});
const courseClass = await getCourseClass({
body: {
opts: {
where: {
id
},
include: [{
model: CourseClassDefaultSchedule,
as: "courseClassDefaultSchedules"
}]
}
}
});
const changeset = {};
if (status) {
changeset.status = status;
}
if (lecturerId) {
changeset.lecturerId = lecturerId;
}
if (startYear) {
changeset.startYear = startYear;
}
if (semester) {
changeset.semester = semester;
}
if (capacity) {
changeset.capacity = capacity;
}
if (courseClassDefaultSchedules) {
changeset.courseClassDefaultSchedules = courseClassDefaultSchedules;
}
req.body.courseClass = courseClass;
req.body.changeset = changeset;
next();
} catch (error) {
if (error instanceof NotExistError) {
handleRequestWithResourceItemNotFound(res, error);
}
else if (error instanceof RequiredParameterUndefinedError) {
handleRequestWithInvalidRequestBody(res, error);
}
else {
handleRequestWithInternalServerError(res, error);
}
}
};
module.exports = {
getCourseClassMiddleware,
updateCourseClassMiddleware
}
\ No newline at end of file
const {
Lecturer,
Major,
Faculty
} = require('../models/index');
const getStudentMiddleware = async(req, res, next) => {
const {
includeTranscript = "false",
includeScore = "false",
includeCredits = "false"
} = req.query;
const {
id
} = req.params;
req.opts = {
where: {
userId: id
}
};
req.opts.include = [
{
model: Lecturer,
as: 'Advisor',
},
{
model: Major,
include: Faculty,
},
];
req.includeTranscript = includeTranscript;
req.includeScore = includeScore;
req.includeCredits = includeCredits;
next();
};
module.exports = {
getStudentMiddleware
};
\ No newline at end of file
'use strict';
const {
handleRequestWithInvalidRequestBody,
checkRequiredParameter,
const {
handleRequestWithInvalidRequestBody,
checkRequiredParameter,
handleRequestWithInternalServerError,
handleRequestWithResourceItemNotFound
} = require("../util/common");
const { getStudyPlan } = require("../util/db/study-plan");
const {
RequiredParameterUndefinedError,
NotExistError
RequiredParameterUndefinedError,
NotExistError
} = require("../util/error");
const getStudyPlanMiddleware = async(req, res, next) => {
const {
studyPlanId,
studentId,
semester,
studentId,
semester,
startYear,
shouldIncludeCourses = "true",
} = req.query;
......@@ -51,7 +51,7 @@ const getStudyPlanMiddleware = async(req, res, next) => {
if (shouldIncludeCourses.toLowerCase() === "true") {
opts.include = "studyPlanCourses"
}
req.body.opts = opts;
next();
......@@ -67,12 +67,14 @@ const updateStudyPlanMiddleware = async (req, res, next) => {
try {
const {
status,
notes,
studyPlanCourses
} = req.body;
checkRequiredParameter({
oneOf: {
status,
notes,
studyPlanCourses
}
});
......@@ -90,6 +92,10 @@ const updateStudyPlanMiddleware = async (req, res, next) => {
changeset.status = status;
}
if (notes) {
changeset.notes = notes;
}
if (studyPlanCourses) {
changeset.studyPlanCourses = studyPlanCourses;
}
......
......@@ -5,7 +5,7 @@ const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const config = require(__dirname + '/../config/config.json')[env.trim()];
const db = {};
let sequelize;
......
const express = require('express');
const router = express.Router();
const courseClassMeeting = require('../controllers/course-class-meeting');
const {
getCourseClassMeetingMiddleware,
updateCourseClassMeetingBodyCheckerMiddleware,
updateCourseClassMeetingMiddleware
} = require('../middleware/course-class-meeting');
router.get('/', getCourseClassMeetingMiddleware);
router.get('/', courseClassMeeting.getCourseClassMeeting);
router.put('/:id', updateCourseClassMeetingBodyCheckerMiddleware);
router.put('/:id', updateCourseClassMeetingMiddleware);
router.put('/:id', courseClassMeeting.updateCourseClassMeeting);
module.exports = router;
var express = require('express');
var router = express.Router();
const express = require('express');
const router = express.Router();
var courseclass = require('../controllers/courseclass');
const courseclass = require('../controllers/courseclass');
const {
getCourseClassMiddleware,
updateCourseClassMiddleware
} = require('../middleware/course-class');
router.post('/', courseclass.createCourseClassData);
// GET request to get all course class data (can use filter)
router.get('/', getCourseClassMiddleware);
router.get('/', courseclass.getCourseClassData);
// GET request to get course class data by id (can use filter)
router.get('/:id', getCourseClassMiddleware);
router.get('/:id', courseclass.getCourseClassData);
router.post('/', courseclass.createCourseClassData);
// PUT request to update course class data
router.put('/:id', updateCourseClassMiddleware);
router.put('/:id', courseclass.updateCourseClass);
module.exports = router;