Skip to content

Course planner backend: transcript grades in parse response, plan + checklist tables - #197

Draft
jerryzhou196 wants to merge 2 commits into
mainfrom
feat/course-planner
Draft

Course planner backend: transcript grades in parse response, plan + checklist tables#197
jerryzhou196 wants to merge 2 commits into
mainfrom
feat/course-planner

Conversation

@jerryzhou196

@jerryzhou196 jerryzhou196 commented Jul 1, 2026

Copy link
Copy Markdown
Member

Backend half of the new course planner (/plan) feature — frontend PR: UWFlow/uwflow_frontend#281.

Changes

  • Transcript parser (flow/api/parse/transcript): extracts per-course units (attempted credits) and numeric grades from each course line, and /parse/transcript now returns a per-term breakdown (terms: [{term_id, level, courses: [{code, units, grade}]}]). Grades are returned for the client's local GPA calculator only and are never written to the database, consistent with the privacy policy ("We do not store your grades"). CR/NG/current-term courses have grade: null.
  • New migration 1782938317000_add_course_planner:
    • user_course_plan (user_id, course_id, term_id) — courses planned into future terms, modeled on user_shortlist, user-editable through Hasura.
    • checklist (id, name, requirements jsonb) — maintainer-seeded degree requirement checklists; each requirement is a list of "one of" alternative course codes. Seeded with Honours CS, Honours Math, and Software Engineering core checklists.
  • Transcript course inserts are batched into one unnest-join INSERT: user_course_taken has a per-statement trigger in prod refreshing materialized.course_recommendation, so per-course INSERTs turned one upload into ~40 sequential matview refreshes and blew the 10s request deadline. courses_imported now counts rows actually inserted.
  • Hasura metadata for both tables (checklist read-only for anonymous+user; plan rows scoped to X-Hasura-User-Id).

Testing

  • go test ./api/parse/... passes; transcript test expectations extended with units/grades derived independently from the test PDFs via pdftotext -layout.
  • go build ./... and go vet ./api/... clean.
  • Checklist seed JSON validated.
  • Not yet run against a live stack — needs hasura migrate apply + metadata apply on next make start.

🤖 Generated with Claude Code

…cklist tables

- Transcript parser now extracts per-course units and numeric grades and
  returns a per-term breakdown in the /parse/transcript response. Grades
  are returned for the client's local GPA calculator only and are never
  written to the database (per privacy policy).
- New migration: user_course_plan (courses planned into future terms,
  modeled on user_shortlist) and checklist (maintainer-seeded degree
  requirement checklists as JSONB, each requirement a list of "one of"
  alternatives), with Hasura metadata and user permissions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
user_course_taken has a per-statement trigger in prod that refreshes
materialized.course_recommendation. Inserting one course at a time turned
a transcript upload into ~40 sequential matview refreshes, easily
exceeding the 10s request deadline ("deleting old courses: timeout").
One unnest-join INSERT brings the whole save down to two statements.

courses_imported now reports rows actually inserted (unknown course
codes no longer count).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant