Skip to content

Collect an APAAR ID at first login, and fix three student-upload faults - #1959

Merged
vikrantwiz02 merged 1 commit into
FusionIIIT:prod/acad-reactfrom
vikrantwiz02:acad-apaar-and-upload-fixes
Aug 19, 2026
Merged

vikrantwiz02 merged 1 commit into
FusionIIIT:prod/acad-reactfrom
vikrantwiz02:acad-apaar-and-upload-fixes

Conversation

@vikrantwiz02

@vikrantwiz02 vikrantwiz02 commented Aug 19, 2026 •

Copy link
Copy Markdown
Member

Frontend counterpart: FusionIIIT/Fusion-client#294.

APAAR ID at first login

apaar_id joins the first-login profile popup as a required, 12-digit field. profile_completed only flips on a successful submit and the popup blocks the app until then, so no student reaches Fusion without supplying one.

Verified end to end against a real record (a roll number), rolled back afterwards:

GET exposes apaar_id: True
no APAAR ID          -> 400  APAAR ID is required
APAAR ID too short   -> 400  APAAR ID must be exactly 12 digits
valid APAAR ID       -> 200  Profile completed successfully
saved: apaar_id='a 12-digit id'  profile_completed=True

The column is on both admission models. The popup resolves a record from either table and then serializes and saves through shared attribute names, so a UG/PG-only column would have raised AttributeError for a PhD student. It is also threaded through the admin paths so it is not write-only: the spreadsheet parser accepts an APAAR heading, both bulk creates persist it via the shared _common dict, the manual add and update_student carry it, and get_student and the batch-student list return it. The download template is deliberately unchanged — the value comes from the student, not the office.

Three tests added: required, 12-digit format, and the happy path asserting the stored value.

Three faults found while uploading this year's intake files

An extended heading stopped a column being read. The parser matches lowercased headings against exact spellings; this year's template says JEE App. No. / CCMT Roll No. / AICTE App. No. where the list has jee app. no. / ccmt roll no.. Every row of a 554-student upload therefore had an empty jee_app_no — which also silenced duplicate detection, since that check keys on the application number. A field left unmatched now falls back to a heading that contains one of its spellings (aliases under 8 characters excluded, no column claimed twice). Re-parsed: jee_app_no: 'a 12-digit id'.

A repeat upload reported a raw unique-index violation. The duplicate check read camelCase keys while a parsed payload carries the spreadsheet's headings, so it compared nothing; and it only ran when skip_duplicates was set, leaving the insert to fail on the index. Duplicates are now always detected, with skip_duplicates deciding only whether they are passed over or reported:

before after
default duplicate key value violates unique constraint "…roll_number_key" Roll Number a roll number already exists for a student
skip_duplicates: true same Postgres error 2 duplicates skipped

An M.Tech Design intake could not be saved at all. A specialization-to-discipline table overrode the discipline the sheet states:

elif specialization == 'Design':
    discipline_obj = get_or_create_discipline('Design')

so the lookup searched for M.Tech Design under discipline Design, while that batch is run by Mechanical Engineering — and the failure message concatenated batch name and guessed discipline into Create batch for M.Tech Design Design, naming a batch that cannot exist. When the strict lookup misses, the sheet's own discipline is now preferred, then a batch of that name if it is the only one for that year, and the message names a real batch and lists the disciplines that run it. Only reached when the current lookup already failed, so no upload that works today changes behaviour.

With the real file: save -> 200 '1 students uploaded successfully.', stored branch='Mechanical Engineering' spec='Design' programme=pg year=2026. The same table also pins Mechatronics, CAD/CAM, Manufacturing and Automation, Data Science, AI & ML and the ECE specializations; they agree with the current batches, but the fallback now covers them if a department ever changes.

Checks

Every path exercised against a copy of production data with all writes rolled back; manage.py check clean, no missing migrations. Needs python manage.py migrate on deploy (0052_student_apaar_id) before the frontend ships, or the profile submit will 500 on the missing column.

APAAR ID joins the first-login profile popup as a required, 12-digit field. It
is stored on both admission models -- the popup resolves a record from either,
so a UG/PG-only column would have broken a PhD student's submit -- and it is
threaded through the admin paths as well: the spreadsheet parser accepts an
APAAR heading, both bulk creates persist it, the manual add and the admin edit
carry it, and the student reads return it. profile_completed only flips on a
successful submit, so no student reaches the app without supplying one. The
download template is deliberately unchanged, since the value comes from the
student rather than the office.

Three faults found while uploading real intake files:

An extended heading stopped a column being read at all. The parser matches
lowercased headings against a list of exact spellings, and this year's template
says "JEE App. No. / CCMT Roll No. / AICTE App. No." where the list has "jee
app. no. / ccmt roll no.". Every uploaded row therefore had an empty
jee_app_no, which also silenced duplicate detection, since that check keys on
the application number. A field left unmatched now falls back to a heading that
contains one of its spellings.

A repeat upload reported a raw unique-index violation rather than saying the
students were already there. The duplicate check read camelCase keys while a
parsed payload carries the spreadsheet's headings, so it found nothing to
compare; and it only ran when skip_duplicates was set, leaving the insert to
fail. Duplicates are now always detected, and skip_duplicates only decides
whether they are passed over or reported: "Roll Number 26BCS002 already exists
for AARADHY SAHU" instead of a constraint name.

An M.Tech Design intake could not be saved at all. A specialization-to-
discipline table overrode the discipline the sheet states, so the batch lookup
searched for "M.Tech Design" under discipline Design while that batch is run by
Mechanical Engineering, and the failure message concatenated the two into
"Create batch for M.Tech Design Design", naming a batch that cannot exist. When
the strict lookup misses, the sheet's own discipline is now preferred, then a
batch of that name if it is the only one that year; the message names a real
batch and lists the disciplines that run it.
@vikrantwiz02
vikrantwiz02 merged commit 04c1e43 into FusionIIIT:prod/acad-react Aug 19, 2026
1 check passed
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