Backend: Assessment forms
Last modified with commit e90a924 on
by Aljaž.
Backend task for the shared form endpoint (GET/POST /assessments/{assessmentId}/forms/{activity}) – check the API spec and DB structure, access rules, the replace-on-save behaviour, implement, and verify against the spec.
Docs: Assessment forms
Spec: GET / POST /assessments/{assessmentId}/forms/{activity} (getAssessmentForm, saveAssessmentForm), AssessmentForm, AssessmentFormSaveRequest, AssessmentFormGrade, AssessmentFormNote in api-docs/openapi.yaml
DB: AssessmentGrades, AssessmentNotes in api/database/create_schema.sql
The one endpoint pair that every form uses. Each form’s own rules (keys, status) are in the Backend: Form – … tasks.
1. Double check API spec and DB structure
- Data visibility: GET returns only the caller’s grades and notes. Check against “Data visibility” in the docs.
- Shared forms (group-discussion, first-contact, argumentation) cover all candidates and
take no
candidateId. Individual forms (presentation, interview-notes, interview-grades) requirecandidateId. Check theAssessmentCandidateIdQuerydescription. - Save means replace: the submitted body is the full state, and anything left out is cleared. This works for “Spremi” and “Spremi i zatvori”. For interview-notes, all 6 pages are sent together as one state.
- Forms can be saved whatever the assessment’s status is (docs open question: upcoming / past). Confirm.
- The criterion key format
"<categoryKey>.<n>"is described, but the keys aren’t listed anywhere. Each form task defines them. Decide whether they go into the spec (an enum or a description per activity) or are only agreed with the frontend. Fix the inconsistent examples (zadatak.2vspojava-ponasanje.1). - Field key format:
notes,q1–q5,p<page>.<n>. Check against the Grupna diskusija, Predstavljanje kandidata and Strukturirani intervju – bilješke tasks. - Error cases: not an active board member → 403; interview-notes without notes-access →
403; argumentation disabled → 409
activity_disabled; missingcandidateId→ 400; acandidateId(query or body) that isn’t a candidate of this assessment → 404 (AssessmentNotFound), the same rule as every other assessment / BTC endpoint. - Roles and permissions: only active board members can open or save forms (a Trainer
outside the komisija can’t).
interview-notesalso needsassessments.notes-access. Check against the docs permission table on Assessment detail. - DB: the
Activitycheck constraints match the spec. AssessmentGrades allows group-discussion, first-contact, argumentation and interview-grades. AssessmentNotes allows group-discussion, presentation and interview-notes.Grade DECIMAL(2,1)0–3 matchesAssessmentGrade(multipleOf: 0.1).UQ_AssessmentGrades/UQ_AssessmentNoteskeep one row per field even when the same form is saved twice at once. AssessmentGrades hasAssessmentId(filled from the route) andArgumentationFlag(1 on argumentation rows, otherwise NULL; see Backend: Form – Igranje uloga – argumentacija).
2. Implementation
- Roles and permissions: active board member check → 403;
assessments.notes-accessfor interview-notes → 403. - DB / catalog: a catalog of activities in code (shared vs individual, graded vs notes). Each form task adds its keys to it. Calculation helpers: category = the average of the entered sub-criteria; POGODNOST = the average of the categories that have a value (empty categories ignored; confirm the open question in the docs); unrounded values.
- Function + repository for GET and POST, driven by the catalog.
- POST without a transaction: one
MERGEper table (AssessmentGrades, AssessmentNotes), with the target limited to the caller’s rows for (activity, these candidates) and the submitted rows as source: update matches, insert new ones, delete the target rows not in the source. Group discussion has both grades and notes; there the twoMERGEs run in one transaction. Empty strings count as “not filled in” and aren’t stored. - Errors from the write: unique violation (2601 / 2627, the same form saved twice at once) →
retry once; FK error 547 → the candidate was just removed (404) or argumentation was just
disabled (409
activity_disabled). - Validation: keys exist in the catalog for that activity; grades only on graded forms,
notes only on notes forms (group-discussion has both); grade 0–3 with at most one decimal;
every
candidateIdbelongs to this assessment (else 404). - The response contains the saved form and its recalculated
isCompleted.
3. Verify implementation against spec
- Request and response shapes and status codes match both operations.
- Two board members save the same form, and neither sees the other’s input.
- Clearing a field in the body deletes the stored value.
Done when
Any form can be loaded and saved through this endpoint pair. Each form’s own rules are added through the form tasks.