Skip to content

Prevent reviewing courses for semesters that haven't started yet - #1261

Open
IshanA2007 wants to merge 1 commit into
devfrom
1252-bug-reviewing-future-courses
Open

Prevent reviewing courses for semesters that haven't started yet#1261
IshanA2007 wants to merge 1 commit into
devfrom
1252-bug-reviewing-future-courses

Conversation

@IshanA2007

@IshanA2007 IshanA2007 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

GitHub Issues addressed

What I did

Reviews could be placed for a course in a future semester (e.g. Fall 2026). Root cause: the review semester choices (recent_semesters()semesters_for_course()) only had a lower year bound, and ReviewForm.clean() only validated that a matching Section existed. Production loads future-term sections for course registration, so those not-yet-started terms showed up as selectable and savable review options. (It didn't reproduce on older local data because that data simply lacked the future terms.)

The fix gates reviewable terms by the calendar date rather than by whatever is loaded in the DB (Semester.latest()):

  • Semester.has_started() (models.py) — new SEASON_START_MONTH map + method; a term is "started" once its start month is reached in the current/prior year (Fall→Aug, Summer→May, Spring/January→Jan).
  • utils.reviewable_semesters() — started-only subset of recent_semesters() (DB-level Case/When filter); semesters_for_course() now routes through it. recent_semesters() is intentionally left unchanged so the schedule builder still sees upcoming terms.
  • ReviewForm.clean() — the real backend gate: rejects a not-yet-started term for both course and club reviews.
  • UI filtering — the club dropdown (club_semester_choices_payload) and the empty-state / error-render semester lists in new_review.py now only offer started terms, so users never see an invalid option.

Screenshots

  • Before — "Fall 2026" selectable as a review term; the review saves successfully.
image
  • After — future terms no longer appear in the term dropdown, and are rejected server-side ("You can only review a semester that has already started.") even if forced.
image

Testing

Verified against a fresh prod dump (contains Fall 2026 = 9,038 sections). As of 2026-07-08: Fall 2026 has_started=False → excluded from reviewable_semesters() but still present in recent_semesters(); Summer 2026 / Spring 2026 remain reviewable.

Automated (full suite green — 265 tests):

  • test_semester.HasStartedTestCase — unit tests for the date gate (past/future year, Fall-before-August, Summer-by-July, start-month boundary).
  • test_review.ReviewFormSectionValidationTests — form rejects a future term (even with a matching section) and accepts a started term.
  • test_review.ReviewCascadeJsonEndpointsTests — future terms excluded from semesters_for_course() and the review_semester_options XHR.

To test manually: pick a course with a Fall 2026 section under My Reviews → New Review; Fall 2026 should not be offered as a term.

Questions/Discussions/Notes

  • Product call: a term becomes reviewable the moment it starts (so a summer term in progress is allowed). If we'd rather only allow reviewing a term once it has ended, that's a one-line change to the comparison in has_started().
  • Season start months are approximate first-of-month values, which is sufficient for a future/past gate; they intentionally don't track exact UVA add/drop dates.

Summary by CodeRabbit

  • New Features

    • Semester choices now only include terms that have already started.
    • Review forms now prevent creating reviews for future semesters.
  • Bug Fixes

    • Improved semester start-date handling, including season-based start months and boundary-day behavior.
    • Review creation and semester selection now stay consistent across course and club review flows.
  • Tests

    • Added coverage for semester start checks and future-semester review rejection.

Reviews could be placed for future terms (e.g. Fall 2026) because the review
semester choices only had a lower year bound and ReviewForm.clean() only checked
that a matching Section existed. Prod loads future-term sections for course
registration, so those terms showed up as selectable, savable review options.

Gate reviewable terms by calendar date instead of by whatever is loaded in the
DB (Semester.latest()):
- Add Semester.SEASON_START_MONTH + has_started() (started iff its start month
  has been reached in the current/prior year).
- Add utils.reviewable_semesters(); route semesters_for_course() through it.
  recent_semesters() is left untouched so the schedule builder still sees
  upcoming terms.
- ReviewForm.clean() now rejects a not-yet-started term (course and club).
- Filter the club dropdown and empty-state semester lists to started terms.

Tests: has_started() unit tests, form rejection of a future term, and XHR /
semesters_for_course exclusion.
@IshanA2007 IshanA2007 linked an issue Jul 8, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df6a8714-d8f0-4ef2-9ddb-1997c24d9ec2

📥 Commits

Reviewing files that changed from the base of the PR and between ed955fb and c6c4a49.

📒 Files selected for processing (7)
  • tcf_website/models/models.py
  • tcf_website/review/forms.py
  • tcf_website/review/services.py
  • tcf_website/tests/test_review.py
  • tcf_website/tests/test_semester.py
  • tcf_website/utils.py
  • tcf_website/views/review/new_review.py

📝 Walkthrough

Walkthrough

This PR adds a has_started() check to the Semester model based on a new season-to-start-month mapping, enforces it in ReviewForm validation to block reviews for future semesters, and introduces reviewable_semesters() used in services, views, and course semester lookups, with corresponding tests.

Changes

Restrict reviews and semester lists to started terms

Layer / File(s) Summary
Semester start-month logic
tcf_website/models/models.py, tcf_website/tests/test_semester.py
Adds SEASON_START_MONTH mapping and start_month()/has_started(as_of=None) methods to Semester; tests cover past/future years and inclusive boundary cases.
Form validation for future semesters
tcf_website/review/forms.py, tcf_website/tests/test_review.py
ReviewForm.clean() raises ValidationError when the selected semester has not started; tests add a future-semester helper and verify rejection/acceptance behavior.
reviewable_semesters() filtering
tcf_website/utils.py, tcf_website/tests/test_review.py
New reviewable_semesters() annotates semesters with a start month via Case/When and filters to already-started terms; semesters_for_course() now uses it; tests confirm future semesters are excluded from course/XHR results.
Service and view wiring
tcf_website/review/services.py, tcf_website/views/review/new_review.py
club_semester_choices_payload() and review view context builders switch from recent_semesters() to reviewable_semesters().

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ReviewForm
  participant Semester
  participant NewReviewView

  User->>NewReviewView: Submit review with semester
  NewReviewView->>ReviewForm: clean()
  ReviewForm->>Semester: has_started()
  Semester-->>ReviewForm: True/False
  alt semester not started
    ReviewForm-->>NewReviewView: ValidationError
    NewReviewView-->>User: Re-render form with error
  else semester started
    ReviewForm-->>NewReviewView: Valid
    NewReviewView-->>User: Review saved
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: blocking reviews for semesters that have not started yet.
Description check ✅ Passed The description covers the issue, implementation, screenshots, testing, and follow-up notes in the required template sections.
Linked Issues check ✅ Passed The PR addresses #1252 by preventing reviews for future semesters through model, form, and UI filtering changes.
Out of Scope Changes check ✅ Passed The added changes and tests are all directly related to the future-semester review restriction.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 1252-bug-reviewing-future-courses

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@IshanA2007
IshanA2007 marked this pull request as ready for review July 8, 2026 17:44
@IshanA2007 IshanA2007 self-assigned this Jul 8, 2026
@IshanA2007
IshanA2007 requested review from gyoge0 and jackrhoa July 8, 2026 17:45
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.

Bug: Reviewing future courses

1 participant