Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

09 — User Behaviour (Bulk Module)

Observed/expected user behaviour patterns that shape the bulk UX, derived from the workflow reality (admission-time onboarding, spreadsheet-driven data) and the backend's hard constraints. Analytics (proposed).


1. Behavioural personas

PatternWhoImpact on design
Batch-onboardingAdmissions Admin at admission seasonwizard must be repeatable in < 2 min; report must be actionable (03 J1-J3)
Spreadsheet-firstRegistrar hands over XLSXclient only accepts .csv; convert-in-app (forward-looking); clear guidance
Fix-and-reuploadAdmin after partial failureerror CSV download + row-highlight re-upload (06 §4.1c)
Copy-paste adminAdmin who pastes from Excel into a text editorBOM/CRLF/quote quirks — client sanitizes + warns (14 §2)

2. Behavioural rules (derived from constraints)

  1. Expect duplicate rows on re-upload. Server rejects existing emails/admissionNumbers per row (students-import.adapter.ts:49-56); users habitually re-upload the same file. UI must label duplicates "already imported" instead of alarming (03 J3).
  2. Expect "not found" reference rows on first try. New tenants import students before grades/sections/years are fully configured; the adapter refuses to create refs (08 §1.2). UI must link "Academic year not found" rows to the Academics setup screen and allow correcting the file, not the data.
  3. No one reads a 400-row error list linearly. Group errors (duplicates / references / format — 04 §7), page at 50, and offer error CSV download.
  4. Impatience with long uploads. The import is synchronous (bulk-import.service.ts:22-65); users will navigate away. The in-flight panel must (a) warn, (b) explain partial-upload safety (06 §4.1a), (c) auto-recover on return via a (forward-looking) resume/report check.
  5. Template-first behaviour. Users want a template, not a spec. Provide client-generated template download (08 §1.4) and treat GET /bulk/export as a roster snapshot, never as the template (04 §6).
  6. Trust in counts. Users sum the report; the invariant imported + failed === totalRows (04 §5) keeps the summary trustworthy — surface it verbatim.
  7. Phone = review, desktop = do. File picking and error review happen on desktop; on phone the app should allow viewing reports and re-downloading error CSVs.

3. Frequency & timing

  • Import: bursty (admission season, term start); export: weekly cadence.
  • Sessions: < 5 min per batch; the whole wizard must fit in one sitting including one fix-reupload cycle.

4. Failure-response patterns (exact)

User actionSystem response (server)Expected user reactionDesigned response
Upload malformed file400 Malformed CSV: could not parse file. (bulk-import.service.ts:32)frustration; checks fileclient parse catches pre-upload; exact copy on SS4
Upload header-only400 CSV must include a header row and data. (:35)confusionSS2 blocks with same string
Wrong entity404 No import adapter for entity "X". (:19)surpriseclient hard-codes entity list; entity picker (planned) discovery
Partial failurereport with row errorsfix-and-reuploaderror CSV + row-highlight flow (03 J3)
Timeout/networkdropped request; rows may existre-upload fearidempotency copy + duplicate labelling (06 §4.1a)
Rate limited429 (api tier 100/min)waitcountdown copy, no auto-retry (00-shared/07 §4)

5. Habits the design must not fight

  • Users keep the source spreadsheet open while reviewing errors → row numbers must match physical file lines (bulk-import.service.ts:46).
  • Users rename/duplicate files → client keys the wizard state on the file hash + row count, not filename.
  • Users paste email lists with stray commas → quoted-field parsing is server-side (csv-parse handles it); client must use the same parser library in the isolate so preview == server (15 §4).

6. Metrics (proposed)

bulk.upload.sessions, bulk.upload.success_rate (imported/totalRows), bulk.upload.first_pass_rate, bulk.result.time_to_reupload, bulk.result.duplicate_share — the last two directly measure the fix-and-reupload loop from 03 J3.