Repository navigation
feat: timetable import (one-off, by hand), optional subjects and the timetable endpoints - #42
Merged
Merged
Conversation
ThorSPB
marked this pull request as ready for review
October 14, 2026 09:39
ThorSPB
force-pushed
the
feat/5-timetable
branch
from
October 14, 2026 10:35
c20ec4e to
ada39c6
Compare
…timetable endpoints The faculty's semester timetables (workbooks shared with UPT accounts only) are read by `CampusPulse.Api import-timetable`, run by hand with a private overrides file. Workbooks are recognised by their sheets, not their file names. Re-imports keep study groups, subjects and offers (retiring what disappears) and refuse, unless forced, when students would lose something. One-hour cells alternating in a two-hour block are two hours every other week (top row odd by default). Optional, facultative and pick-a-time subjects come with their offered slots, which students choose in their settings. Endpoints: the current semester, programmes and groups, a student's group and subjects, their timetable and a group's (expanded into dates), rooms and a room's day. Closes #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ThorSPB
force-pushed
the
feat/5-timetable
branch
from
October 14, 2026 10:36
ada39c6 to
cd60b6f
Compare
…nal column offers it A required course whose labs a faculty lists with the optional ones read as optional, so its classes showed only to students who chose it. A sheet's requiredSubjects reads those offers as times to pick (pickSlot); a name in both lists is refused, one that matches nothing is warned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks
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.
Closes #5
What
The import:
CampusPulse.Api import-timetable --overrides FILE [--parse-only | --dry-run] [--force] WORKBOOK.xlsx…, a CLI mode of the API, run by hand; on the Pi throughdeploy/pi/campuspulse-import-timetable(sandboxed, like the migrations; installed by hand, not run). Guide:docs/timetable-import.md.sources), never by file name: a re-downloaded "Timetable (1).xlsx" replaces what the first download brought. It refuses (exit 1) a workbook of no known source or of two, two workbooks of one source in a run, and a source whose sheets were already imported under another id.noLongerOffered.--force.--dry-runruns the same write in a transaction and rolls it back, so it validates exactly what a real run would.--parse-onlyneeds no database.SheetParser.Versionmatch its last import. A test pins the version to what the parser reads from the test workbook.The parser:
&, and2h/12sapt, stay whole when offers are split.kind.One-hour cells (his decision):
topRowWeeks: evenflips a sheet,alternate: falseturns it off, andcellschanges any one cell. Each such cell is warned.Abbreviations resolve to the sheet's courses, in this order:
- XY;Typos merge, but never when only a number or numeral differs.
Offers:
optionalsubjects; master labs givepickSlot.[X]tags pick the programmes.optionalSubjectsturns a subject's grid classes into offers for the whole year (his decision for the optional courses whose groups aren't the timetable's).requiredSubjectskeeps one required when an optional column offers it (a required course whose labs are listed with the optional ones): its offers there are times to pick, as withpickSlot.Overrides: a per-cell
textguard (on a mismatch: warn, ignore), pluskind. Unused cells, aliases and optional subjects are warned, and so are sheets no source lists. Unknown keys are refused.Model, migration
AddTimetable(generated on ThorSPB):sourceandretired_at), rooms;source, file name, sheets).Students'
student_settingsandstudent_subjectscascade fromusers; the cascade walk (EF andpg_constraint) asserts both.Endpoints (all signed in):
GET /semesters/current,GET /timetable/programmes(offered groups only);GET/PUT /me/settings(noLongerOffered,fromAnotherSemester);GET /timetable/groups/{id}/choices,GET /me/subjects(noLongerOffered),PUT/DELETE /me/subjects/{id};GET /me/timetable,GET /timetable/groups/{id},GET /rooms,GET /rooms/{code}/timetable.Retired groups and subjects can't be picked. Dates are bounded to 2000-2100. The time-zone database is required at startup, and today is Bucharest's date.
Testing
TimetableWorkbook). Unit tests cover the parser rules above, the overrides validation, the calendar, the CLI and the version pin.--forcere-importing; a dry run writing nothing;--force;--force, and offered again later;--parse-onlyon ThorSPB with the private overrides, copies deleted after. Counts are in Import this semester's AC timetable and exam schedule (one-off) #5; no real text is in this repo or this PR.Not done here
🤖 Generated with Claude Code