Conversation
There was a problem hiding this comment.
Pull request overview
This pull request implements a labor attendance report feature that tracks labor student participation in labor-only meetings across terms within an academic year. The implementation adds a new sheet to the downloadable reports spreadsheet showing each labor student's meeting attendance count per term.
Changes:
- Added
laborAttendanceByTerm()function to query and aggregate labor meeting attendance by student and term - Integrated the new "Labor Attendance By Term" sheet into the spreadsheet generation workflow
- Added comprehensive integration test coverage for the new functionality
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| app/logic/volunteerSpreadsheet.py | Implements laborAttendanceByTerm function (lines 228-249) to query labor students and count their meeting attendance, and integrates it into createSpreadsheet (line 298) |
| tests/code/test_spreadsheet.py | Adds test_laborAttendanceByTerm integration test (lines 686-724) covering empty results and attendance counting scenarios |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…Team/celts into Labor_Attendance_report_1626
…ftwareDevTeam/celts into Labor_Attendance_report_1626
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ank term/duplicate row bugs
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn.CONCAT(User.firstName, ' ', User.lastName).alias('fullName'), | ||
| User.bnumber, | ||
| fn.CONCAT(User.username, '@berea.edu').alias('email'), | ||
| fn.COUNT(EventParticipant.event_id).alias('meetingsAttended') |
There was a problem hiding this comment.
nonLaborQuery counts EventParticipant.event_id without DISTINCT, while laborQuery counts distinct Event.id. Since EventParticipant has no uniqueness constraint on (user,event), duplicate participant rows would inflate the meeting count for non-labor attendees. Use a distinct count here as well (e.g., count distinct event id) so "Meetings Attended" consistently reflects unique meetings.
| fn.COUNT(EventParticipant.event_id).alias('meetingsAttended') | |
| fn.COUNT(fn.DISTINCT(EventParticipant.event_id)).alias('meetingsAttended') |
| .where( | ||
| (CeltsLabor.term == term) | ||
| ) | ||
| .group_by(CeltsLabor.user) | ||
| ) |
There was a problem hiding this comment.
This query selects non-aggregated columns (full name, bnumber, email) but only groups by CeltsLabor.user. This relies on MySQL's non-standard GROUP BY behavior and will break if ONLY_FULL_GROUP_BY is enabled, and it also reduces portability/clarity. Include the non-aggregated selected columns (or the underlying User fields) in the GROUP BY to make the aggregation deterministic and SQL-standard.
| (CeltsLabor.term == term) | ||
| ) | ||
| .where(CeltsLabor.user.is_null()) | ||
| .group_by(EventParticipant.user) |
There was a problem hiding this comment.
This query selects non-aggregated columns (full name, bnumber, email) but only groups by EventParticipant.user. As written, it depends on MySQL's permissive GROUP BY behavior and can fail under ONLY_FULL_GROUP_BY. Group by the non-aggregated selected columns (or the underlying User fields) so the aggregation is deterministic and compatible with stricter SQL modes.
| .group_by(EventParticipant.user) | |
| .group_by( | |
| User.firstName, | |
| User.lastName, | |
| User.bnumber, | |
| User.username, | |
| ) |
Issue Description
Fixes #1626
Changes
laborAttendanceByTerm(term)function to query labor students and count their meeting attendance by termcreateSpreadsheet(), there are two sheets: one for Fall term and one for Spring termtest_laborAttendanceByTermintest_spreadsheet.pyThis is how the spreadsheet looks like:

Testing
database/reset_database.sh testand thentests/run_tests.shor if you want to test the laborAttendanceByTerm function specifically, you can runpytest tests/code/test_spreadsheet.py::test_laborAttendanceByTerm -vdatabase/reset_database.sh from-backupand thenflask run-And then do the same for Spring 2025.