feat(leaves): add student leave request and approval workflow (fixes #253) - #258
Open
MOHITKOURAV01 wants to merge 2 commits into
Open
feat(leaves): add student leave request and approval workflow (fixes #253)#258MOHITKOURAV01 wants to merge 2 commits into
MOHITKOURAV01 wants to merge 2 commits into
Conversation
Attendance was one-directional: a teacher marked a student absent and that was the end of it. A planned absence was indistinguishable from truancy, and requests happened over the phone with no record. - Add LeaveRequest model with a derived inclusive day count, a back-dating grace window, and an ALLOWED_TRANSITIONS table driving a single canTransition guard so the lifecycle cannot be bypassed - Add leaveController with submission, own-requests listing plus a days summary, withdrawal, the reviewer queue, approve/reject with a mandatory rejection comment, admin cancellation, a per-student summary and a class leave calendar - Reject overlapping live requests for the same student with a 409 - Add /api/leaves routes with multer for supporting documents - Add /leaves page: date-range picker with a live day count, half-day handling, attachments, status badges and withdrawal - Add LeaveApprovalPanel dashboard tab with filters, an expandable detail view and the student's leave history alongside the decision Fixes Sitaram8472#253
Mongoose 9 no longer passes a `next` callback to document middleware, so
the callback-style pre('validate') hook resolved without running — the
derived day count was never written and reversed or back-dated ranges
were silently accepted.
Convert the hook to an async function that throws.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Closes #253.
Attendance in EduStream was one-directional: a teacher marked a student
PresentorAbsentand that was the end of it. A planned absence was indistinguishable from truancy, requests happened over the phone with no record, and teachers had no queue of what was waiting on them. This PR adds a proper leave request and approval workflow.Backend
backend/models/LeaveRequest.jstotalDays, half-day handling, a back-dating grace window, attachments, audit fields, and anALLOWED_TRANSITIONStable drivingcanTransition()/decide()backend/controllers/leaveController.jsbackend/routes/leaveRoutes.js/api/leaveswith multer for supporting documentsEndpoints
Frontend
pages/LeaveRequests.jsx—/leaves. Students apply with a date-range picker that shows a live day count, choose a leave type, attach a doctor's note, and see status badges, the reviewer's comment and a withdraw button on anything still pending. A summary strip shows requests filed, approved days, days awaiting approval and rejections.components/teacher/LeaveApprovalPanel.jsx— a new Leave Requests tab on the Teacher Dashboard: the pending queue with filters by status, type, class and student name; expand a request to read it in full, see its attachments, and — usefully — that student's leave history alongside the decision. Approve or reject with a comment.Design notes
ALLOWED_TRANSITIONSis a table, and every status change goes throughcanTransition(). The lifecycle rules are in one readable place instead of scatteredifstatements across the controller, so adding a state later cannot silently open a hole.totalDaysis derived server-side in a pre-validate hook and never accepted from the client, so a request cannot claim a three-day absence is half a day. A half-day request is forced to 0.5 and must sit inside a single date.409naming the existing request's status, so a student cannot double-book the same days.decide()on the model, so it holds no matter which endpoint calls it.reviewedByandreviewedAt, and deciding an already-decided request returns a409rather than quietly overwriting the first decision./leaves/metakes no id, andGET /leaves/:idchecks ownership before returning anything.userFacingflag so the controller returns400for those and keeps500for genuine bugs.Verification
The rules were exercised directly:
Plus
node --checkon every file, routers mounting on a real Express app, a cleanvite build, and no new eslint errors.Note on Mongoose 9
The project is on
mongoose@^9.4.1, which no longer passes anextcallback to document middleware — a callback-stylepre('validate')hook resolves without running its body, which would have lefttotalDaysunwritten and accepted reversed date ranges. The hook is anasyncfunction; the second commit fixes this after it was caught in testing. Worth knowing for any other PR adding a model to this repo.Compatibility
Purely additive — the existing
Attendancemodel is untouched.server.jsgains two lines,App.jsxone route,TeacherDashboard.jsxone tab.