Skip to content

Commit 46c1366

Browse files
committed
feat(tatakforms): add get attendance count
- fix(tatakforms): incorrect attendance table name
1 parent 5bee7e8 commit 46c1366

File tree

9 files changed

+102
-29
lines changed

9 files changed

+102
-29
lines changed

bun.lockb

0 Bytes
Binary file not shown.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"elysia": "^1.0.13",
1313
"elysia-helmet": "^1.0.2",
1414
"elysia-ip": "^1.0.3",
15-
"jose": "^5.2.3",
15+
"jose": "^5.2.4",
1616
"juice": "^10.0.0",
1717
"mariadb": "^3.3.0",
1818
"nodemailer": "^6.9.13",

src/api/tatakforms/admin.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export function login(context: ElysiaContext): Promise<ResponseBody | undefined>
2323
return status501(context);
2424
}
2525

26-
2726
/**
2827
* POST /tatakforms/admin/login
2928
* @param context Elysia context

src/api/tatakforms/attendance.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
import type { ElysiaContext, ResponseBody } from "../../types";
22
import { ErrorTypes } from "../../types/enums";
33
import { status501 } from "../../routes";
4+
import { setHeader } from "../../utils/security";
45

5-
import TatakFormStudent from "../../db/models/tatakform/student";
66
import response from "../../utils/response";
77
import Strings from "../../config/strings";
88
import TatakFormAttendance from "../../db/models/tatakform/attendance";
99
import Tatakform from "../../db/models/tatakform/tatakform";
10-
import { setHeader } from "../../utils/security";
11-
import Log from "../../utils/log";
1210

1311
/**
1412
* Tatakform Attendance API
1513
* @author TotalElderBerry (Unknown af)
1614
* @param context
1715
*/
18-
export function attendance(context: ElysiaContext): Promise<ResponseBody | undefined> | ResponseBody {
16+
export function attendance(context: ElysiaContext): Promise<ResponseBody | undefined | File> | ResponseBody {
1917
switch (context.request.method) {
2018
case "GET":
2119
if (context.params?.eventId) {
@@ -41,7 +39,6 @@ async function postAttendance(context: ElysiaContext) {
4139
const slug = context.params?.slug;
4240
if (slug) {
4341
const tatak_event = await Tatakform.getBySlug(slug);
44-
const student = await TatakFormStudent.getByStudentId(context.body.student_id);
4542

4643
if (tatak_event) {
4744
await TatakFormAttendance.attendStudent(context.body.student_id, tatak_event);
@@ -73,16 +70,30 @@ async function postAttendance(context: ElysiaContext) {
7370
* GET /tatakforms/attendance/:slug
7471
* Fetches the attedance history of a student in an event
7572
*
73+
* GET /tatakforms/attendance/count/:eventId/:collegeId
74+
* Fetch attendance count by event and college
75+
*
7676
* GET /tatakforms/attendance/:slug/download
7777
* Download tatakform attendance
7878
*/
7979
async function getAttendance(context: ElysiaContext) {
8080
try {
81+
8182
// Get slug
8283
const slug = context.params?.slug;
83-
84+
8485
// If slug is specified
8586
if (slug) {
87+
// If path contains with count
88+
if (context.path.includes("count")) {
89+
// Get college id
90+
const collegeId = context.params?.collegeId;
91+
// Get attendance count
92+
const count = await TatakFormAttendance.getStudentCountAttendedBySlugAndCollege(slug, Number(collegeId));
93+
// Return response
94+
return response.success("Fetch Successful", count);
95+
}
96+
8697
// If path ends with "download"
8798
if (context.path.endsWith("download")) {
8899
// Generate PDF
@@ -99,13 +110,13 @@ async function getAttendance(context: ElysiaContext) {
99110
const tatakform = await Tatakform.getBySlug(slug);
100111
// Get attendance history by event
101112
const attendance = await TatakFormAttendance.getAttendanceByEvent(context.user?.student_id, tatakform.id);
102-
103113
// Return response
104114
return response.success("Fetch Successful", attendance);
105115
}
106116

107117
// Otherwise, get all attendance history
108118
const history = await TatakFormAttendance.getAttendance(context.user?.student_id);
119+
// Return response
109120
return response.success("Fetch Successful", history);
110121
}
111122

@@ -138,7 +149,7 @@ async function getAllStudentsAttended(context: ElysiaContext) {
138149
// If event id is specified
139150
if (eventId) {
140151
// Get all students attended by event and college
141-
const attendance = await TatakFormAttendance.getStudentsAttendedByEventAndCollege(eventId, context.user.college_id);
152+
const attendance = await TatakFormAttendance.getStudentsAttendedByEventAndCollege(Number(eventId), context.user.college_id);
142153
return response.success("Success", attendance)
143154
}
144155
}

src/api/tatakforms/students.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import Log from "../../utils/log";
1010
/**
1111
* Students API
1212
* @author TotalElderBerry (Unknown af)
13+
* @author mavyfaby (Maverick Fabroa)
1314
* @param context
1415
*/
1516
export function students(context: ElysiaContext): Promise<ResponseBody | undefined> | ResponseBody {
1617
switch (context.request.method) {
18+
case "GET":
19+
return getStudents(context);
1720
case "POST":
1821
return postStudents(context);
1922
case "OPTIONS":
@@ -23,6 +26,28 @@ export function students(context: ElysiaContext): Promise<ResponseBody | undefin
2326
return status501(context);
2427
}
2528

29+
/**
30+
* GET /tatakforms/students/(:studentId)
31+
*/
32+
async function getStudents(context: ElysiaContext) {
33+
// Get studentId from context
34+
const { studentId } = context.params || {};
35+
36+
try {
37+
// If studentId is not provided, return empty data
38+
if (!studentId) return response.error("No student found.", {});
39+
// If studentId is provided, return student by studentId
40+
const student = await TatakFormStudent.getByStudentId(studentId);
41+
// Return student
42+
return response.success(student);
43+
}
44+
45+
catch (error) {
46+
context.set.status = 500;
47+
return response.error(error);
48+
}
49+
}
50+
2651
/**
2752
* POST /tatakforms/register
2853
*/

src/db/models/tatakform/admin.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Database from "../..";
22
import Log from "../../../utils/log";
33

4-
type AdminData = {
4+
type TatakformAdminType = {
55
id: number;
66
college_id: number;
77
student_id: string;
@@ -19,14 +19,14 @@ class TatakFormAdmin {
1919
/**
2020
* Get by username and password
2121
*/
22-
public static getByUsernameAndPassword(username: string, password: string): Promise<AdminData> {
22+
public static getByUsernameAndPassword(username: string, password: string): Promise<TatakformAdminType> {
2323
return new Promise(async (resolve, reject) => {
2424
// Get database instance
2525
const db = Database.getInstance();
2626

2727
try {
2828
// Get admin by username and password
29-
const result = await db.query<AdminData[]>(
29+
const result = await db.query<TatakformAdminType[]>(
3030
`SELECT
3131
s.id, s.student_id, s.last_name, s.first_name, s.year_level, s.email_address, s.password, s.date_stamp, s.course_id, c.college_id, co.acronym, co.name
3232
FROM
@@ -36,14 +36,14 @@ class TatakFormAdmin {
3636
INNER JOIN
3737
colleges_courses c ON c.id = s.course_id
3838
INNER JOIN
39-
colleges co on co.id = c.college_id
39+
colleges co ON co.id = c.college_id
4040
WHERE
4141
s.student_id = ?
4242
`, [username]
4343
);
4444

4545
// If no result or password is incorrect
46-
if (result.length === 0 || !(await Bun.password.verify(password, result[0].password || ""))) {
46+
if (result.length === 0 || !(await Bun.password.verify(password, result[0].password))) {
4747
return reject("Username or password is incorrect");
4848
}
4949

@@ -61,14 +61,14 @@ class TatakFormAdmin {
6161
/**
6262
* Get by username
6363
*/
64-
public static getByUsername(username: string): Promise<AdminData> {
64+
public static getByUsername(username: string): Promise<TatakformAdminType> {
6565
return new Promise(async (resolve, reject) => {
6666
// Get database instance
6767
const db = Database.getInstance();
6868

6969
try {
7070
// Get admin by username
71-
const result = await db.query<AdminData[]>(
71+
const result = await db.query<TatakformAdminType[]>(
7272
`SELECT
7373
s.id, s.student_id, s.last_name, s.first_name, s.year_level, s.email_address, s.password, s.date_stamp, s.course_id, co.acronym, co.name
7474
FROM
@@ -78,7 +78,7 @@ class TatakFormAdmin {
7878
INNER JOIN
7979
colleges_courses c ON c.id = s.course_id
8080
INNER JOIN
81-
colleges co on co.id = c.college_id
81+
colleges co ON co.id = c.college_id
8282
WHERE
8383
s.student_id = ?
8484
`, [username]

src/db/models/tatakform/attendance.ts

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ class TatakFormAttendance {
5252
// Check if student has not yet registered time
5353
await TatakFormAttendance.isStudentAttended(studentId, event.id, columnName);
5454

55-
query = `UPDATE attendance SET ${columnName} = NOW() WHERE student_id = ? and event_id = ?`
55+
query = `UPDATE tatakforms_attendance SET ${columnName} = NOW() WHERE student_id = ? and event_id = ?`
5656
const updateResult = await db.query<MariaUpdateResult>(
5757
query, [studentId, event.id]
5858
);
5959
if (updateResult.affectedRows > 0) {
6060
resolve("Updated Attendance")
6161
}
6262
} else {
63-
query = `INSERT INTO attendance (student_id, event_id, ${columnName}) VALUES (?,?,NOW())`
63+
query = `INSERT INTO tatakforms_attendance (student_id, event_id, ${columnName}) VALUES (?,?,NOW())`
6464
const updateResult = await db.query<MariaUpdateResult>(
6565
query, [studentId, event.id]
6666
);
@@ -154,23 +154,23 @@ class TatakFormAttendance {
154154
/**
155155
* Get all attendance of students by event and college
156156
*/
157-
public static getStudentsAttendedByEventAndCollege(eventId: any, collegeId: any) {
157+
public static getStudentsAttendedByEventAndCollege(eventId: number, collegeId: number) {
158158
return new Promise(async (resolve, reject) => {
159159
// Get database instance
160160
const db = Database.getInstance();
161161

162162
try {
163163
const result = await db.query<AttendanceModel[]>(
164164
`SELECT
165-
attendance.*, s.first_name, s.last_name, s.course_id, c.acronym
165+
a.*, s.first_name, s.last_name, s.course_id, c.acronym
166166
FROM
167-
attendance
167+
tatakforms_attendance a
168168
INNER JOIN
169169
tatakforms_students s
170170
INNER JOIN
171171
colleges_courses c ON c.id = s.course_id
172172
WHERE
173-
attendance.student_id = s.student_id AND event_id = ? and c.college_id = ?
173+
a.student_id = s.student_id AND event_id = ? and c.college_id = ?
174174
`, [eventId, collegeId]
175175
);
176176

@@ -189,6 +189,42 @@ class TatakFormAttendance {
189189
});
190190
}
191191

192+
/**
193+
* Get all attendance count by event and college
194+
*/
195+
public static getStudentCountAttendedBySlugAndCollege(eventSlug: string, collegeId: number) {
196+
return new Promise(async (resolve, reject) => {
197+
// Get database instance
198+
const db = Database.getInstance();
199+
200+
try {
201+
const result = await db.query<{ count: bigint }[]>(
202+
`SELECT
203+
COUNT(*) AS count
204+
FROM
205+
tatakforms_attendance a
206+
INNER JOIN
207+
tatakforms_students s ON a.student_id = s.student_id
208+
INNER JOIN
209+
tatakforms t ON a.event_id = t.id
210+
INNER JOIN
211+
colleges_courses c ON c.id = s.course_id
212+
WHERE
213+
a.student_id = s.student_id AND t.slug = ? and c.college_id = ?
214+
`, [eventSlug, collegeId]
215+
);
216+
217+
resolve(Number(result[0].count));
218+
}
219+
220+
// Log error and reject promise
221+
catch (e) {
222+
Log.e(e);
223+
reject(e);
224+
}
225+
});
226+
}
227+
192228
/**
193229
* Check if student has not yet attendance
194230
*/

src/db/models/tatakform/student.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ class TatakFormStudent {
100100
const result = await db.query<UnivStudentModel[]>(query, [student_id]);
101101
// If no results
102102
if (result.length === 0) {
103-
Log.e(`${fromAdmin ? 'Admin' : 'Student'} not found (id = ${student_id})`);
104-
return reject(ErrorTypes.DB_EMPTY_RESULT);
103+
Log.e(`[TATAKFORM] [getByStudentId] ${fromAdmin ? 'Admin' : 'Student'} not found (id = ${student_id})`);
104+
return reject(`Student ID (${student_id}) not found`);
105105
}
106106

107107
// Resolve promise
@@ -111,7 +111,7 @@ class TatakFormStudent {
111111
// Log error and reject promise
112112
catch (e) {
113113
Log.e(e);
114-
reject(ErrorTypes.DB_ERROR);
114+
reject(e);
115115
}
116116
});
117117
}

src/routes/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ const routes: AppRoutes[] = [
3838
{ path: "/tatakforms/register", methods: ["POST", "OPTIONS"], handler: tatakformStudents },
3939
{ path: "/tatakforms/admin/login", methods: ["POST", "OPTIONS"], handler: tatakformAdminLogin },
4040
{ path: "/tatakforms/:slug", methods: ["GET"], handler: tatakforms },
41-
{ path: "/tatakforms/attendance/" , methods: ['GET'], handler: tatakformAttendance, auth: {GET: AuthType.TATAKFORM_ACCOUNT} },
41+
{ path: "/tatakforms/attendance/" , methods: ['GET'], handler: tatakformAttendance, auth: { GET: AuthType.TATAKFORM_ACCOUNT }},
4242
{ path: "/tatakforms/attendance/event/:eventId" , methods: ['GET'], handler: tatakformAttendance, auth: {GET: AuthType.TATAKFORM_ACCOUNT_ADMIN}},
43-
{ path: "/tatakforms/attendance/:slug" , methods: ['POST','GET'], handler: tatakformAttendance, auth: {POST: AuthType.TATAKFORM_ACCOUNT_ADMIN} },
43+
{ path: "/tatakforms/attendance/:slug" , methods: ['POST','GET'], handler: tatakformAttendance, auth: { POST: AuthType.TATAKFORM_ACCOUNT_ADMIN }},
4444
{ path: "/tatakforms/attendance/:slug/download" , methods: ['GET'], handler: tatakformAttendance, auth: {GET: AuthType.TATAKFORM_ACCOUNT} },
45+
{ path: "/tatakforms/attendance/:slug/count/:collegeId", methods: ['GET'], handler: tatakformAttendance, auth: { GET: AuthType.TATAKFORM_ACCOUNT_ADMIN}},
46+
{ path: "/tatakforms/student/:studentId" , methods: ['GET'], handler: tatakformStudents, auth: { GET: AuthType.TATAKFORM_ACCOUNT }},
4547
{ path: "/tatakforms/config", methods: ["GET"], handler: tatakforms },
4648
{ path: "/tatakforms", methods: ["GET"], handler: tatakforms },
4749

0 commit comments

Comments
 (0)