diff --git a/generic/templates/generic/trainees_bulk_update.html b/generic/templates/generic/trainees_bulk_update.html index b43fdf36..109a97d0 100644 --- a/generic/templates/generic/trainees_bulk_update.html +++ b/generic/templates/generic/trainees_bulk_update.html @@ -1,50 +1,50 @@ {% extends 'generic/base.html' %} {% block content %} -
Paste the spreadsheet rows below. Headings like "Year 1 - Group 1" are used to set the grade (Year N -> STN). Rows should contain "Name
Paste the spreadsheet rows below. Headings like "Year 1 - Group 1" are used to set the grade (Year N -> STN). Rows should contain "Name
| Raw | -Name | -Grade | -Matched user | -Supervisor text | -Matched supervisor | -
|---|---|---|---|---|---|
{{ r.raw }} |
- {{ r.norm_name }} | -{{ r.grade }} | -{% if r.matched_user %}{{ r.matched_user.first_name }} {{ r.matched_user.last_name }}{% else %}No match{% endif %} | -{{ r.supervisor_text }} | -{% if r.matched_supervisor %}{{ r.matched_supervisor.name }}{% else %}No match{% endif %} | -
| Raw | +Name | +Grade | +Matched user | +Supervisor text | +Matched supervisor | +
|---|---|---|---|---|---|
{{ r.raw }} |
+ {{ r.norm_name }} | +{{ r.grade }} | +{% if r.matched_user %}{{ r.matched_user.first_name }} {{ r.matched_user.last_name }}{% else %}No match{% endif %} | +{{ r.supervisor_text }} | +{% if r.matched_supervisor %}{{ r.matched_supervisor.name }}{% else %}No match{% endif %} | +
Updated: {{ report.updated }}; Skipped (no user matched): {{ report.skipped }}
-{% endif %} + {% if report %} +Updated: {{ report.updated }}; Skipped (no user matched): {{ report.skipped }}
+ {% endif %} {% endblock %} diff --git a/generic/views.py b/generic/views.py index 389b8974..edba078d 100644 --- a/generic/views.py +++ b/generic/views.py @@ -4262,7 +4262,6 @@ def trainees_bulk_update_from_spreadsheet(request): - Preview: parse the pasted text and show rows with any matched user / supervisor - Apply: apply grade and supervisor updates for matched users """ - logger.debug("Trainees bulk update called") import re @@ -4309,11 +4308,27 @@ def trainees_bulk_update_from_spreadsheet(request): matched_user = None if first and last: + # Prefer an exact first+last match qs = User.objects.filter(first_name__iexact=first, last_name__iexact=last) - if not qs.exists(): - qs = User.objects.filter(last_name__iexact=last) if qs.exists(): matched_user = qs.first() + else: + # Fallback: only match by last name when the last-name query returns + # a single candidate AND the candidate's first name reasonably + # matches the provided first token. This avoids ambiguous matches + # (e.g. Maria vs Stephanie both 'Bailey'). We accept a match when + # the candidate first name startswith the first 3 chars of the + # provided first token, or contains it as a substring (case-ins). + candidates = User.objects.filter(last_name__iexact=last) + if candidates.count() == 1: + candidate = candidates.first() + cand_first = (candidate.first_name or "").strip() + if cand_first: + # take at most 3 chars for prefix comparison + prefix = first[:3].lower() + cand_first_low = cand_first.lower() + if cand_first_low.startswith(prefix) or first.lower() in cand_first_low: + matched_user = candidate matched_supervisor = None if supervisor_part: