2025-01-23 17:10:32 +00:00
|
|
|
module api_modules.classroom_compliance.api_class;
|
|
|
|
|
|
|
|
import handy_httpd;
|
|
|
|
import ddbc;
|
|
|
|
|
|
|
|
import api_modules.classroom_compliance.model;
|
|
|
|
import api_modules.classroom_compliance.util;
|
|
|
|
import api_modules.auth : User, getUserOrThrow;
|
|
|
|
import db;
|
|
|
|
import data_utils;
|
|
|
|
|
|
|
|
void createClass(ref HttpRequestContext ctx) {
|
|
|
|
Connection conn = getDb();
|
|
|
|
scope(exit) conn.close();
|
|
|
|
User user = getUserOrThrow(ctx, conn);
|
|
|
|
struct ClassPayload {
|
|
|
|
ushort number;
|
|
|
|
string schoolYear;
|
|
|
|
}
|
|
|
|
auto payload = readJsonPayload!(ClassPayload)(ctx);
|
|
|
|
const bool classNumberExists = recordExists(
|
|
|
|
conn,
|
|
|
|
"SELECT id FROM classroom_compliance_class WHERE number = ? AND school_year = ? AND user_id = ?",
|
|
|
|
payload.number, payload.schoolYear, user.id
|
|
|
|
);
|
|
|
|
if (classNumberExists) {
|
|
|
|
ctx.response.status = HttpStatus.BAD_REQUEST;
|
|
|
|
ctx.response.writeBodyString("There is already a class with this number, for the same school year.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ulong classId = insertOne(
|
|
|
|
conn,
|
|
|
|
"INSERT INTO classroom_compliance_class (number, school_year, user_id) VALUES (?, ?, ?) RETURNING id",
|
|
|
|
payload.number, payload.schoolYear, user.id
|
|
|
|
);
|
|
|
|
auto newClass = findOne(
|
|
|
|
conn,
|
|
|
|
"SELECT * FROM classroom_compliance_class WHERE id = ? AND user_id = ?",
|
|
|
|
&ClassroomComplianceClass.parse,
|
|
|
|
classId, user.id
|
|
|
|
).orElseThrow();
|
|
|
|
writeJsonBody(ctx, newClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
void getClasses(ref HttpRequestContext ctx) {
|
|
|
|
Connection conn = getDb();
|
|
|
|
scope(exit) conn.close();
|
|
|
|
User user = getUserOrThrow(ctx, conn);
|
2025-01-29 02:12:41 +00:00
|
|
|
const query = "
|
|
|
|
SELECT
|
|
|
|
c.id, c.number, c.school_year,
|
|
|
|
COUNT(DISTINCT s.id) AS student_count,
|
|
|
|
COUNT(DISTINCT e.id) AS entry_count,
|
|
|
|
MAX(e.date) AS last_entry_date
|
|
|
|
FROM classroom_compliance_class c
|
|
|
|
LEFT JOIN classroom_compliance_student s ON c.id = s.class_id
|
|
|
|
LEFT JOIN classroom_compliance_entry e ON c.id = e.class_id
|
|
|
|
WHERE c.user_id = ?
|
|
|
|
GROUP BY c.id
|
|
|
|
ORDER BY school_year DESC, number ASC
|
|
|
|
";
|
|
|
|
struct ClassResponse {
|
|
|
|
ulong id;
|
|
|
|
ushort number;
|
|
|
|
string schoolYear;
|
|
|
|
uint studentCount;
|
|
|
|
uint entryCount;
|
|
|
|
string lastEntryDate;
|
|
|
|
}
|
|
|
|
ClassResponse[] classes = findAll(
|
2025-01-23 17:10:32 +00:00
|
|
|
conn,
|
2025-01-29 02:12:41 +00:00
|
|
|
query,
|
|
|
|
r => ClassResponse(
|
|
|
|
r.getUlong(1),
|
|
|
|
r.getUshort(2),
|
|
|
|
r.getString(3),
|
|
|
|
r.getUint(4),
|
|
|
|
r.getUint(5),
|
|
|
|
r.getDate(6).toISOExtString()
|
|
|
|
),
|
2025-01-23 17:10:32 +00:00
|
|
|
user.id
|
|
|
|
);
|
|
|
|
writeJsonBody(ctx, classes);
|
|
|
|
}
|
|
|
|
|
|
|
|
void getClass(ref HttpRequestContext ctx) {
|
|
|
|
Connection conn = getDb();
|
|
|
|
scope(exit) conn.close();
|
|
|
|
User user = getUserOrThrow(ctx, conn);
|
|
|
|
auto cls = getClassOrThrow(ctx, conn, user);
|
|
|
|
writeJsonBody(ctx, cls);
|
|
|
|
}
|
|
|
|
|
|
|
|
void deleteClass(ref HttpRequestContext ctx) {
|
|
|
|
Connection conn = getDb();
|
|
|
|
scope(exit) conn.close();
|
|
|
|
User user = getUserOrThrow(ctx, conn);
|
|
|
|
auto cls = getClassOrThrow(ctx, conn, user);
|
|
|
|
const query = "DELETE FROM classroom_compliance_class WHERE id = ? AND user_id = ?";
|
|
|
|
PreparedStatement ps = conn.prepareStatement(query);
|
|
|
|
scope(exit) ps.close();
|
|
|
|
ps.setUlong(1, cls.id);
|
|
|
|
ps.setUlong(2, user.id);
|
|
|
|
ps.executeUpdate();
|
|
|
|
}
|