-
${esc(sem.label)}
+
+ ${esc(sem.label)}
+ ${esc(sem.academic_year || "")}
+
@@ -166,6 +188,16 @@ function buildValidationHTML(studentInfo, semesters) {
background: #dce7f3;
border: 1pt solid #000;
border-bottom: none;
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ }
+ .sem-year { font-weight: bold; }
+
+ .standing {
+ text-align: center;
+ font-weight: bold;
+ color: #c00000;
}
.course-table {
@@ -264,7 +296,7 @@ function buildValidationHTML(studentInfo, semesters) {
| ${esc(studentInfo.name)} |
Discipline |
${esc(studentInfo.discipline)} |
-
+ ${lastGradedRow}${completionRow}
${semesterBlocks}
diff --git a/src/lib/credits.js b/src/lib/credits.js
index 20bae2d02..9f1f1eb20 100644
--- a/src/lib/credits.js
+++ b/src/lib/credits.js
@@ -98,3 +98,7 @@ export const creditsTowardsDegree = (totals) =>
export function remainingCreditRequirement(totals) {
return DEGREE_CREDIT_REQUIREMENT - creditsTowardsDegree(totals);
}
+
+// Nothing left to earn, so a student carrying surplus credits counts as done.
+export const hasCompletedDegree = (totals) =>
+ remainingCreditRequirement(totals) <= 0;
diff --git a/src/lib/credits.test.js b/src/lib/credits.test.js
index 7209c44e4..beb09afd0 100644
--- a/src/lib/credits.test.js
+++ b/src/lib/credits.test.js
@@ -3,6 +3,7 @@ import { describe, expect, it } from "vitest";
import {
computeCreditSummary,
fmtCredits,
+ hasCompletedDegree,
remainingCreditRequirement,
} from "./credits";
@@ -251,3 +252,20 @@ describe("remainingCreditRequirement", () => {
expect(remainingCreditRequirement({ earned: 151, swayam: 5 })).toBe(-3);
});
});
+
+describe("hasCompletedDegree", () => {
+ it("is false while credits are still outstanding", () => {
+ expect(hasCompletedDegree({ earned: 122, swayam: 6 })).toBe(false);
+ expect(hasCompletedDegree({ earned: 147, swayam: 0 })).toBe(false);
+ });
+
+ it("is true on exactly the requirement, and on a surplus", () => {
+ expect(hasCompletedDegree({ earned: 148, swayam: 0 })).toBe(true);
+ expect(hasCompletedDegree({ earned: 151, swayam: 5 })).toBe(true);
+ });
+
+ it("does not count swayam credits above the cap towards completion", () => {
+ // 150 earned, but 4 of the 10 swayam credits do not count: 146 < 148.
+ expect(hasCompletedDegree({ earned: 150, swayam: 10 })).toBe(false);
+ });
+});