From a1d8213a96d4aaeaf1d24776c34bcff5ae2a71a6 Mon Sep 17 00:00:00 2001 From: akram Date: Fri, 29 Dec 2023 01:10:29 +0200 Subject: [PATCH 1/5] =?UTF-8?q?=E2=9C=8D=EF=B8=8F=20Refactor:=20Change=20t?= =?UTF-8?q?he=20naming=20of=20attendance=20to=20scout=20attendance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ce.controller.js => scoutAttendance.controller.js} | 4 ++-- server/routes/api.route.js | 4 ++-- server/routes/attendance.route.js | 11 ----------- server/routes/scoutAttendance.route.js | 11 +++++++++++ 4 files changed, 15 insertions(+), 15 deletions(-) rename server/controllers/{attendance.controller.js => scoutAttendance.controller.js} (98%) delete mode 100644 server/routes/attendance.route.js create mode 100644 server/routes/scoutAttendance.route.js diff --git a/server/controllers/attendance.controller.js b/server/controllers/scoutAttendance.controller.js similarity index 98% rename from server/controllers/attendance.controller.js rename to server/controllers/scoutAttendance.controller.js index 2815addc..ad9aa86d 100644 --- a/server/controllers/attendance.controller.js +++ b/server/controllers/scoutAttendance.controller.js @@ -1,6 +1,6 @@ import db from "../database/db.js" -const attendanceController = { +const scoutAttendanceController = { // @desc Insert a new attendance record for a scout in a certain sector // @route POST /api/attendance/ // @access Private @@ -123,4 +123,4 @@ const attendanceController = { } } -export default attendanceController; \ No newline at end of file +export default scoutAttendanceController; \ No newline at end of file diff --git a/server/routes/api.route.js b/server/routes/api.route.js index 7287f599..c98f1859 100644 --- a/server/routes/api.route.js +++ b/server/routes/api.route.js @@ -9,7 +9,7 @@ import captainRouter from './captain.route.js' import alertRouter from './alert.route.js' import scoutRouter from './scout.route.js' import sectorRouter from './sector.route.js' -import attendanceRouter from './attendance.route.js' +import scoutAttendanceRouter from './scoutAttendance.route.js' const apiRouter = Router() apiRouter.use('/auth', authRouter) @@ -25,6 +25,6 @@ apiRouter.use('/captain', authMiddleware, captainRouter) apiRouter.use('/alert', authMiddleware, alertRouter) apiRouter.use('/scout', authMiddleware, scoutRouter) apiRouter.use('/sector', authMiddleware, sectorRouter) -apiRouter.use('/attendance', authMiddleware, attendanceRouter) +apiRouter.use('/attendance', authMiddleware, scoutAttendanceRouter) export default apiRouter diff --git a/server/routes/attendance.route.js b/server/routes/attendance.route.js deleted file mode 100644 index 24f0ff57..00000000 --- a/server/routes/attendance.route.js +++ /dev/null @@ -1,11 +0,0 @@ -import { Router } from "express" -import attendanceController from "../controllers/attendance.controller.js" - -const attendanceRouter = Router() - -// Insert a new attendance for a scout -attendanceRouter.post('/', attendanceController.upsertAttendance) -attendanceRouter.get('/sector/all', attendanceController.getSectorAttendance) -attendanceRouter.get('/:scoutId/:weekNumber/:termNumber', attendanceController.getScoutAttendance) - -export default attendanceRouter; \ No newline at end of file diff --git a/server/routes/scoutAttendance.route.js b/server/routes/scoutAttendance.route.js new file mode 100644 index 00000000..97b6c305 --- /dev/null +++ b/server/routes/scoutAttendance.route.js @@ -0,0 +1,11 @@ +import { Router } from "express" +import scoutAttendanceController from "../controllers/scoutAttendance.controller.js" + +const scoutAttendanceRouter = Router() + +// Insert a new attendance for a scout +scoutAttendanceRouter.post('/', scoutAttendanceController.upsertAttendance) +scoutAttendanceRouter.get('/sector/all', scoutAttendanceController.getSectorAttendance) +scoutAttendanceRouter.get('/:scoutId/:weekNumber/:termNumber', scoutAttendanceController.getScoutAttendance) + +export default scoutAttendanceRouter; \ No newline at end of file From 8fa12713d597e25d300b1a7a6cb71e32264826e7 Mon Sep 17 00:00:00 2001 From: akram Date: Fri, 29 Dec 2023 01:32:19 +0200 Subject: [PATCH 2/5] =?UTF-8?q?=E2=9C=A8=20feat:=20Implement=20getting=20t?= =?UTF-8?q?he=20attendance=20records=20of=20a=20sector's=20regular=20capta?= =?UTF-8?q?ins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../captainAttendance.controller.js | 38 +++++++++++++++++++ server/routes/api.route.js | 4 +- server/routes/captainAttendance.route.js | 11 ++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 server/controllers/captainAttendance.controller.js create mode 100644 server/routes/captainAttendance.route.js diff --git a/server/controllers/captainAttendance.controller.js b/server/controllers/captainAttendance.controller.js new file mode 100644 index 00000000..b30681b6 --- /dev/null +++ b/server/controllers/captainAttendance.controller.js @@ -0,0 +1,38 @@ +import db from "../database/db.js" + +const captainAttendanceController = { + getSectorAttendance: async (req, res) => { + try { + const { baseName, suffixName, weekNumber, termNumber } = req.query + + const result = await db.query(` + SELECT "Captain".*, "CaptainAttendance".* FROM "Captain" LEFT JOIN "CaptainAttendance" ON "Captain"."captainId" = "CaptainAttendance"."captainId" + AND "CaptainAttendance"."weekNumber" = $3 AND "CaptainAttendance"."termNumber" = $4 + INNER JOIN "Sector" ON "Sector"."baseName" = "Captain"."rSectorBaseName" AND "Sector"."suffixName" = "Captain"."rSectorSuffixName" + WHERE "Sector"."baseName" = $1 AND "Sector"."suffixName" = $2; + `, + [baseName, suffixName, weekNumber, termNumber]) + + if (result.rowCount === 0) { + return res.status(404).json({ + error: "No data exists for the provided info" + }) + } + + res.status(200).json({ + message: "Successful retrieval", + body: result.rows, + count: result.rowCount + }) + + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occured while retrieving captain Attendance', + body: error, + }) + } + } +} + +export default captainAttendanceController; \ No newline at end of file diff --git a/server/routes/api.route.js b/server/routes/api.route.js index c98f1859..550f2bab 100644 --- a/server/routes/api.route.js +++ b/server/routes/api.route.js @@ -10,6 +10,7 @@ import alertRouter from './alert.route.js' import scoutRouter from './scout.route.js' import sectorRouter from './sector.route.js' import scoutAttendanceRouter from './scoutAttendance.route.js' +import captainAttendanceRouter from './captainAttendance.route.js' const apiRouter = Router() apiRouter.use('/auth', authRouter) @@ -25,6 +26,7 @@ apiRouter.use('/captain', authMiddleware, captainRouter) apiRouter.use('/alert', authMiddleware, alertRouter) apiRouter.use('/scout', authMiddleware, scoutRouter) apiRouter.use('/sector', authMiddleware, sectorRouter) -apiRouter.use('/attendance', authMiddleware, scoutAttendanceRouter) +apiRouter.use('/scoutAttendance', authMiddleware, scoutAttendanceRouter) +apiRouter.use('/captainAttendance', authMiddleware, captainAttendanceRouter) export default apiRouter diff --git a/server/routes/captainAttendance.route.js b/server/routes/captainAttendance.route.js new file mode 100644 index 00000000..bc08ff4f --- /dev/null +++ b/server/routes/captainAttendance.route.js @@ -0,0 +1,11 @@ +import { Router } from "express" +import captainAttendanceController from "../controllers/captainAttendance.controller.js" + +const captainAttendanceRouter = Router() + +// Insert a new attendance for a captain +//captainAttendanceRouter.post('/', captainAttendanceController.upsertAttendance) +captainAttendanceRouter.get('/sector/all', captainAttendanceController.getSectorAttendance) +//captainAttendanceRouter.get('/:captainId/:weekNumber/:termNumber', captainAttendanceController.getCaptainAttendance) + +export default captainAttendanceRouter; \ No newline at end of file From b962e3425ae84d3cbd9e4434f357f1be26828b74 Mon Sep 17 00:00:00 2001 From: akram Date: Fri, 29 Dec 2023 03:28:09 +0200 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=9A=91=20=20fix:=20Make=20the=20upser?= =?UTF-8?q?tAttendance=20work=20&=20change=20the=20condition=20for=20check?= =?UTF-8?q?ing=20to=20inserting=20or=20updating?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/scoutAttendance.controller.js | 67 ++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/server/controllers/scoutAttendance.controller.js b/server/controllers/scoutAttendance.controller.js index ad9aa86d..4f385415 100644 --- a/server/controllers/scoutAttendance.controller.js +++ b/server/controllers/scoutAttendance.controller.js @@ -2,42 +2,61 @@ import db from "../database/db.js" const scoutAttendanceController = { // @desc Insert a new attendance record for a scout in a certain sector - // @route POST /api/attendance/ + // @route POST /api/sectorAttendance/ // @access Private upsertAttendance: async (req, res) => { try { - const { attendanceRecords } = req.body + const attendanceRecords = req.body.body if (attendanceRecords === 0) { return res.status(404).json({ error: "No records were found" }) } + + const weekNumber = attendanceRecords[0].weekNumber; + const termNumber = attendanceRecords[0].termNumber; + + const prevRecords = await db.query(` + SELECT * + FROM "ScoutAttendance" + WHERE "weekNumber" = $1 AND "termNumber" = $2; + `, + [weekNumber, termNumber]) + let result = []; - if (!attendanceRecords[0].attendanceStatus) //insert + + // If the attendance records already exists then update them, if not insert a new records + if (prevRecords.rowCount === 0) { - for (let i = 0; i < attendanceRecords.length; i++) { - result.push( - await db.query(` - INSERT INTO attendanceStatus VALUES ($1, $2, $3, $4) - RETURNING *; - `, - [attendanceRecords[i].scoutId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] - ) - ); + for (let i = 0; i < attendanceRecords.length; i++) { + + // Insert a new record from the attendance array into the databse + const queryResult = await db.query(` + INSERT INTO "ScoutAttendance" VALUES ($1, $2, $3, $4) + RETURNING *; + `, + [attendanceRecords[i].scoutId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] + ) + + // Add the newly inserted record to the result array to return back + result.push(queryResult.rows[0]); } } - else { //update + else { for (let i = 0; i < attendanceRecords.length; i++) { - result.push( - await db.query(` - UPDATE attendanceStatus SET "attendanceStatus" = $4 - WHERE "scoutId" = $1 AND "weekNumber" = $2 AND "termNumber" = $3 - RETURNING *; - `, - [attendanceRecords[i].scoutId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] - ) - ); + + // Update the current record from the array + const queryResult = await db.query(` + UPDATE "ScoutAttendance" SET "attendanceStatus" = $4 + WHERE "scoutId" = $1 AND "weekNumber" = $2 AND "termNumber" = $3 + RETURNING *; + `, + [attendanceRecords[i].scoutId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] + ) + + // Add the info about the updated record into the result array + result.push(queryResult.rows[0]); } } @@ -58,7 +77,7 @@ const scoutAttendanceController = { }, // @desc Get all attendance records for all the scouts in a certain sector in a certain week & term - // @route GET /api/attendance/sector/:baseName/:suffixName/:weekNumber/:termNumber + // @route GET /api/sectorAttendance/sector/all // @access Private getSectorAttendance: async (req, res) => { try { @@ -94,7 +113,7 @@ const scoutAttendanceController = { }, // @desc Get attendance records for a certain scout in a certain week & term - // @route GET /api/attendance/:scoutId/:weekNumber/:termNumber + // @route GET /api/sectorAttendance/:scoutId/:weekNumber/:termNumber // @access Private getScoutAttendance: async (req, res) => { try { From 4f9bcd859c4708275e918c1c59dc577cc1a3a11c Mon Sep 17 00:00:00 2001 From: akram Date: Fri, 29 Dec 2023 03:45:28 +0200 Subject: [PATCH 4/5] =?UTF-8?q?=E2=9C=A8feat:=20Implement=20upserting=20fo?= =?UTF-8?q?r=20captains=20attendance=20records=20&=20getting=20a=20certain?= =?UTF-8?q?=20captain=20attendance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../captainAttendance.controller.js | 96 +++++++++++++++++++ server/routes/captainAttendance.route.js | 4 +- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/server/controllers/captainAttendance.controller.js b/server/controllers/captainAttendance.controller.js index b30681b6..3e63f121 100644 --- a/server/controllers/captainAttendance.controller.js +++ b/server/controllers/captainAttendance.controller.js @@ -1,6 +1,77 @@ import db from "../database/db.js" const captainAttendanceController = { + upsertAttendance: async (req, res) => { + try { + const attendanceRecords = req.body.body + + if (attendanceRecords === 0) { + return res.status(404).json({ + error: "No records were found" + }) + } + + const weekNumber = attendanceRecords[0].weekNumber; + const termNumber = attendanceRecords[0].termNumber; + + const prevRecords = await db.query(` + SELECT * + FROM "CaptainAttendance" + WHERE "weekNumber" = $1 AND "termNumber" = $2; + `, + [weekNumber, termNumber]) + + let result = []; + + // If the attendance records already exists then update them, if not insert a new records + if (prevRecords.rowCount === 0) + { + for (let i = 0; i < attendanceRecords.length; i++) { + + // Insert a new record from the attendance array into the databse + const queryResult = await db.query(` + INSERT INTO "CaptainAttendance" VALUES ($1, $2, $3, $4) + RETURNING *; + `, + [attendanceRecords[i].captainId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] + ) + + // Add the newly inserted record to the result array to return back + result.push(queryResult.rows[0]); + } + } + else { + for (let i = 0; i < attendanceRecords.length; i++) { + + // Update the current record from the array + const queryResult = await db.query(` + UPDATE "CaptainAttendance" SET "attendanceStatus" = $4 + WHERE "captainId" = $1 AND "weekNumber" = $2 AND "termNumber" = $3 + RETURNING *; + `, + [attendanceRecords[i].captainId, attendanceRecords[i].weekNumber, attendanceRecords[i].termNumber, attendanceRecords[i].attendanceStatus] + ) + + // Add the info about the updated record into the result array + result.push(queryResult.rows[0]); + } + } + + // Return a success message + res.status(200).json({ + message: "Successful insertion/update", + body: result, + count: result.length, + }) + + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occured while inserting/updating captain Attendance', + body: error, + }) + } + }, getSectorAttendance: async (req, res) => { try { const { baseName, suffixName, weekNumber, termNumber } = req.query @@ -25,6 +96,31 @@ const captainAttendanceController = { count: result.rowCount }) + } catch (error) { + console.log(error) + res.status(500).json({ + error: 'An error occured while retrieving captain Attendance', + body: error, + }) + } + }, + getCaptainAttendance: async (req, res) => { + try { + const { captainId, weekNumber, termNumber } = req.params + + const result = await db.query(` + SELECT * + FROM "CaptainAttendance" + WHERE "captainId" = $1 AND "weekNumber" = $2 AND "termNumber" = $3 + `, + [captainId, weekNumber, termNumber]) + + res.status(200).json({ + message: "Successful retrieval", + body: result.rows, + count: result.rowCount, + }) + } catch (error) { console.log(error) res.status(500).json({ diff --git a/server/routes/captainAttendance.route.js b/server/routes/captainAttendance.route.js index bc08ff4f..e03cac43 100644 --- a/server/routes/captainAttendance.route.js +++ b/server/routes/captainAttendance.route.js @@ -4,8 +4,8 @@ import captainAttendanceController from "../controllers/captainAttendance.contro const captainAttendanceRouter = Router() // Insert a new attendance for a captain -//captainAttendanceRouter.post('/', captainAttendanceController.upsertAttendance) +captainAttendanceRouter.post('/', captainAttendanceController.upsertAttendance) captainAttendanceRouter.get('/sector/all', captainAttendanceController.getSectorAttendance) -//captainAttendanceRouter.get('/:captainId/:weekNumber/:termNumber', captainAttendanceController.getCaptainAttendance) +captainAttendanceRouter.get('/:captainId/:weekNumber/:termNumber', captainAttendanceController.getCaptainAttendance) export default captainAttendanceRouter; \ No newline at end of file From 3dfe2cfc08c9b80e7f7be07bc074db63963d6ffb Mon Sep 17 00:00:00 2001 From: akram Date: Fri, 29 Dec 2023 03:51:16 +0200 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=8E=A8=20chore:=20Make=20the=20attend?= =?UTF-8?q?anceRecords=20destructured=20from=20the=20request=20body=20&=20?= =?UTF-8?q?add=20some=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/controllers/captainAttendance.controller.js | 4 +++- server/controllers/scoutAttendance.controller.js | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/controllers/captainAttendance.controller.js b/server/controllers/captainAttendance.controller.js index 3e63f121..90ff095c 100644 --- a/server/controllers/captainAttendance.controller.js +++ b/server/controllers/captainAttendance.controller.js @@ -3,7 +3,8 @@ import db from "../database/db.js" const captainAttendanceController = { upsertAttendance: async (req, res) => { try { - const attendanceRecords = req.body.body + // NOTE: attendanceRecords must be sent as an array of objects in the request body + const { attendanceRecords } = req.body if (attendanceRecords === 0) { return res.status(404).json({ @@ -14,6 +15,7 @@ const captainAttendanceController = { const weekNumber = attendanceRecords[0].weekNumber; const termNumber = attendanceRecords[0].termNumber; + // Query to check if there are an exisiting records for this week & term or not const prevRecords = await db.query(` SELECT * FROM "CaptainAttendance" diff --git a/server/controllers/scoutAttendance.controller.js b/server/controllers/scoutAttendance.controller.js index 4f385415..25e35bcb 100644 --- a/server/controllers/scoutAttendance.controller.js +++ b/server/controllers/scoutAttendance.controller.js @@ -6,7 +6,8 @@ const scoutAttendanceController = { // @access Private upsertAttendance: async (req, res) => { try { - const attendanceRecords = req.body.body + // NOTE: attendanceRecords must be sent as an array of objects in the request body + const { attendanceRecords } = req.body if (attendanceRecords === 0) { return res.status(404).json({ @@ -16,7 +17,8 @@ const scoutAttendanceController = { const weekNumber = attendanceRecords[0].weekNumber; const termNumber = attendanceRecords[0].termNumber; - + + // Query to check if there are an exisiting records for this week & term or not const prevRecords = await db.query(` SELECT * FROM "ScoutAttendance"