Skip to content

feat: support previous special term when academic year changes#4402

Merged
leslieyip02 merged 10 commits into
masterfrom
feat/st-support
Jun 21, 2026
Merged

feat: support previous special term when academic year changes#4402
leslieyip02 merged 10 commits into
masterfrom
feat/st-support

Conversation

@jloh02

@jloh02 jloh02 commented May 20, 2026

Copy link
Copy Markdown
Member

Closes #4109

@vercel

vercel Bot commented May 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
nusmods-export Ignored Ignored Preview Jun 21, 2026 3:27pm
nusmods-website Ignored Ignored Preview Jun 21, 2026 3:27pm

Request Review

@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.51807% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.97%. Comparing base (988c6fd) to head (9dd1d49).
⚠️ Report is 241 commits behind head on master.

Files with missing lines Patch % Lines
website/src/actions/moduleBank.ts 60.86% 9 Missing ⚠️
website/src/utils/specialTerm.ts 88.13% 7 Missing ⚠️
website/src/views/modules/ModulePageContent.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4402      +/-   ##
==========================================
+ Coverage   54.52%   56.97%   +2.44%     
==========================================
  Files         274      317      +43     
  Lines        6076     7128    +1052     
  Branches     1455     1724     +269     
==========================================
+ Hits         3313     4061     +748     
- Misses       2763     3067     +304     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces automatic detection of the previous-AY Special Term I/II overlap window, so that when the academic year config rotates to the new AY before ST I/II complete, the website and scraper transparently source sem 3/4 data from the previous year without manual intervention.

  • A new shared nusmods-academic-calendar package exposes calendar-aware helpers (isPreviousAySpecialTermActive, getEffectiveSpecialTermAcadYear, shouldUsePreviousAyForSemester, etc.) consumed by both the scraper and website.
  • The scraper's DataPipeline detects the overlap window at runtime and fetches sem 3/4 data from the previous AY, writing venue files under both AYs; combineModules gains a preserveModuleInfoSemesters option that keeps current-AY module metadata while merging previous-AY timetable/exam data.
  • The website's fetchModule action is enriched with an async archive-fetch step that calls mergePreviousAySpecialTermData to replace unreliable new-AY ModReg R0 special-term data with authoritative archive data; the ST2 external-exam-link logic is updated to use the new helpers.

Confidence Score: 5/5

The change is safe to merge. The new code paths are well-tested, have safe fallbacks (archive fetch errors silently degrade to current-AY data), and are gated on an opt-in overlap window that does nothing outside the ST I/II period.

The overlap detection and merging logic is thoroughly tested in both the new shared package and the website utils. Scraper behaviour is exercised by the updated CollateModules tests. Error paths (archive fetch failure, missing calendar entries) all fall back gracefully. The only non-blocking concern is that moduleDataCheck logs spurious warnings for every module with previous-AY ST data, but this does not affect correctness.

scrapers/nus-v2/src/tasks/CollateModules.ts — the warn-before-guard ordering produces noisy logs during the overlap period

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant W as "Website (fetchModule)"
    participant S as "Redux Store"
    participant API as "NUSMods API"
    participant ARC as "Archive API"

    W->>API: "GET /module/{code} (current AY)"
    API-->>W: "Module (may lack ST1/ST2 timetable)"
    W->>S: "dispatch SUCCESS_KEY(FETCH_MODULE) via requestAction"
    Note over W,S: "Components render with current-AY data"

    W->>W: "enrichModuleWithPreviousAySpecialTerm()"
    alt "During overlap window (prevAY ST active)"
        W->>S: "check moduleArchive cache"
        alt "Not cached"
            W->>ARC: "GET /module/{code}?year=prevAY"
            ARC-->>W: "archiveModule"
        end
        W->>W: "mergePreviousAySpecialTermData()"
        alt "Archive data wins"
            W->>S: "dispatch SUCCESS_KEY(FETCH_MODULE) with merged module"
            Note over W,S: "Components re-render with archive ST1/ST2 data"
        end
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant W as "Website (fetchModule)"
    participant S as "Redux Store"
    participant API as "NUSMods API"
    participant ARC as "Archive API"

    W->>API: "GET /module/{code} (current AY)"
    API-->>W: "Module (may lack ST1/ST2 timetable)"
    W->>S: "dispatch SUCCESS_KEY(FETCH_MODULE) via requestAction"
    Note over W,S: "Components render with current-AY data"

    W->>W: "enrichModuleWithPreviousAySpecialTerm()"
    alt "During overlap window (prevAY ST active)"
        W->>S: "check moduleArchive cache"
        alt "Not cached"
            W->>ARC: "GET /module/{code}?year=prevAY"
            ARC-->>W: "archiveModule"
        end
        W->>W: "mergePreviousAySpecialTermData()"
        alt "Archive data wins"
            W->>S: "dispatch SUCCESS_KEY(FETCH_MODULE) with merged module"
            Note over W,S: "Components re-render with archive ST1/ST2 data"
        end
    end
Loading

Reviews (6): Last reviewed commit: "chore: add unit tests for boundary value..." | Re-trigger Greptile

Comment thread website/src/utils/specialTerm.ts
Comment thread scrapers/nus-v2/src/tasks/DataPipeline.ts Outdated
Comment thread website/src/actions/moduleBank.ts
jloh02 and others added 4 commits May 21, 2026 12:51
Clarify merge preference rules, the second CollateVenues call, and the intentional post-fetch enrichment dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reorder config fields and CollateModules inputs so the scraper lint step passes in CI.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ravern

ravern commented May 22, 2026

Copy link
Copy Markdown
Member

@greptileai review

@greptile-apps

greptile-apps Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@leslieyip02 leslieyip02 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM, just some minor nits.

Comment thread packages/nusmods-academic-calendar/index.test.js
Comment thread website/src/utils/specialTerm.test.ts
@leslieyip02 leslieyip02 merged commit 94fe511 into master Jun 21, 2026
8 checks passed
@leslieyip02 leslieyip02 deleted the feat/st-support branch June 21, 2026 15: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.

Do not override Special Term II courses when migrating academic year

3 participants