fix(api): close M5 frontend contract gaps

This commit is contained in:
zouantchaw
2026-03-19 10:28:13 +01:00
parent 3399dfdac7
commit 4b2ef9d843
9 changed files with 293 additions and 21 deletions

View File

@@ -1287,18 +1287,43 @@ async function createAttendanceEvent(actor, payload, eventType) {
});
}
async function loadExistingAttendanceSession() {
const existing = await client.query(
`
SELECT id, status, check_in_at AS "clockInAt"
FROM attendance_sessions
WHERE assignment_id = $1
ORDER BY updated_at DESC
LIMIT 1
`,
[assignment.id]
);
return existing.rows[0] || null;
}
const sessionResult = await client.query(
`
SELECT id, status
SELECT id, status, check_in_at AS "clockInAt"
FROM attendance_sessions
WHERE assignment_id = $1
`,
[assignment.id]
);
if (eventType === 'CLOCK_IN' && sessionResult.rowCount > 0 && sessionResult.rows[0].status === 'OPEN') {
throw new AppError('ATTENDANCE_ALREADY_OPEN', 'Assignment already has an open attendance session', 409, {
if (eventType === 'CLOCK_IN' && sessionResult.rowCount > 0) {
const existingSession = sessionResult.rows[0];
if (existingSession.status === 'OPEN') {
throw new AppError('ALREADY_CLOCKED_IN', 'An active attendance session already exists for this assignment', 409, {
assignmentId: assignment.id,
sessionId: existingSession.id,
clockInAt: existingSession.clockInAt || null,
});
}
throw new AppError('ATTENDANCE_SESSION_EXISTS', 'Attendance session already exists for this assignment', 409, {
assignmentId: assignment.id,
sessionId: existingSession.id,
clockInAt: existingSession.clockInAt || null,
});
}
@@ -1414,21 +1439,43 @@ async function createAttendanceEvent(actor, payload, eventType) {
let sessionId;
if (eventType === 'CLOCK_IN') {
const insertedSession = await client.query(
`
INSERT INTO attendance_sessions (
tenant_id,
assignment_id,
staff_id,
clock_in_event_id,
status,
check_in_at
)
VALUES ($1, $2, $3, $4, 'OPEN', $5)
RETURNING id
`,
[assignment.tenant_id, assignment.id, assignment.staff_id, eventResult.rows[0].id, capturedAt]
);
let insertedSession;
try {
insertedSession = await client.query(
`
INSERT INTO attendance_sessions (
tenant_id,
assignment_id,
staff_id,
clock_in_event_id,
status,
check_in_at
)
VALUES ($1, $2, $3, $4, 'OPEN', $5)
RETURNING id
`,
[assignment.tenant_id, assignment.id, assignment.staff_id, eventResult.rows[0].id, capturedAt]
);
} catch (error) {
if (error?.code !== '23505') {
throw error;
}
const existingSession = await loadExistingAttendanceSession();
if (existingSession?.status === 'OPEN') {
throw new AppError('ALREADY_CLOCKED_IN', 'An active attendance session already exists for this assignment', 409, {
assignmentId: assignment.id,
sessionId: existingSession.id,
clockInAt: existingSession.clockInAt || null,
});
}
throw new AppError('ATTENDANCE_SESSION_EXISTS', 'Attendance session already exists for this assignment', 409, {
assignmentId: assignment.id,
sessionId: existingSession?.id || null,
clockInAt: existingSession?.clockInAt || null,
});
}
sessionId = insertedSession.rows[0].id;
await client.query(
`