From 7eeb989b9e46339b597066baafee06ea26024c37 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 3 Nov 2025 09:31:55 +0000 Subject: [PATCH] Enhance supervisor email handling and input format options in bulk user creation --- rad/views.py | 68 ++++++++++++++++----- templates/accounts_bulk_create.html | 91 ++++++++++++++++++++++------- 2 files changed, 123 insertions(+), 36 deletions(-) diff --git a/rad/views.py b/rad/views.py index 44ea3eae..3004fe8c 100644 --- a/rad/views.py +++ b/rad/views.py @@ -815,8 +815,20 @@ def accounts_bulk_create_check(request): if not UserGrades.objects.filter(name=user["grade"]): errors.append("Invalid grade") - if user["supervisor_email"] == "undefined": - errors.append("No supervisor email provided") + # Treat empty, missing or the string 'undefined' as no supervisor email provided + if not user.get("supervisor_email") or user["supervisor_email"] == "undefined": + # Supervisor email not provided; try to match by name + if not user.get("supervisor_name"): + errors.append("No supervisor provided") + else: + supervisor = Supervisor.objects.filter(name__iexact=user["supervisor_name"]) + if not supervisor.exists(): + info.append("Supervisor does not exist (will be created)") + else: + info.append("Supervisor exists (matched by name)") + if supervisor.count() > 1: + errors.append("More than one supervisor with that name") + # no further name check needed since matched by name else: supervisor = Supervisor.objects.filter(email=user["supervisor_email"]) @@ -828,8 +840,14 @@ def accounts_bulk_create_check(request): if supervisor.count() > 1: errors.append("More than one supervisor with that email") - if supervisor.first().name != user["supervisor_name"]: - errors.append("Supervisor name does not match") + # Compare names case-insensitively and trimmed to avoid false mismatches + try: + sup_name = (supervisor.first().name or '').strip().lower() + posted_name = (user.get("supervisor_name") or '').strip().lower() + if posted_name and sup_name != posted_name: + errors.append("Supervisor name does not match") + except Exception: + pass if errors: return HttpResponse( @@ -869,11 +887,22 @@ def accounts_bulk_create(request): grade = UserGrades.objects.get(name=user["grade"]) user_profile.grade = grade - if "supervisor_email" in user and "supervisor_name" in user: - s, created = Supervisor.objects.get_or_create( - email=user["supervisor_email"], - name=user["supervisor_name"], - ) + if "supervisor_name" in user and user.get("supervisor_name"): + sup_email = user.get("supervisor_email") + # If supervisor email provided, prefer that. Otherwise try to match by name or create placeholder + if sup_email and sup_email != 'undefined': + s, created = Supervisor.objects.get_or_create(email=sup_email, defaults={"name": user.get("supervisor_name")}) + else: + # try match by name + s_qs = Supervisor.objects.filter(name__iexact=user.get("supervisor_name")) + if s_qs.exists(): + s = s_qs.first() + created = False + else: + import uuid + placeholder = f"no-email-{uuid.uuid4().hex}@local.invalid" + s = Supervisor.objects.create(email=placeholder, name=user.get("supervisor_name")) + created = True if created: s.save() @@ -913,11 +942,20 @@ def accounts_bulk_create(request): user_profile = UserProfile.objects.get(user=new_user) user_profile.peninsula_trainee = True # TODO: check supervisor details are correct - if "supervisor_email" in user and "supervisor_name" in user: - s, created = Supervisor.objects.get_or_create( - email=user["supervisor_email"], - name=user["supervisor_name"], - ) + if "supervisor_name" in user and user.get("supervisor_name"): + sup_email = user.get("supervisor_email") + if sup_email and sup_email != 'undefined': + s, created = Supervisor.objects.get_or_create(email=sup_email, defaults={"name": user.get("supervisor_name")}) + else: + s_qs = Supervisor.objects.filter(name__iexact=user.get("supervisor_name")) + if s_qs.exists(): + s = s_qs.first() + created = False + else: + import uuid + placeholder = f"no-email-{uuid.uuid4().hex}@local.invalid" + s = Supervisor.objects.create(email=placeholder, name=user.get("supervisor_name")) + created = True if created: s.save() @@ -962,7 +1000,7 @@ def request_cid_details(request): email = request.POST.get("email") try: validate_email(email) - except ValidationError as e: + except ValidationError: return HttpResponse("Invalid email.") cid_users = CidUser.objects.filter(email=email) diff --git a/templates/accounts_bulk_create.html b/templates/accounts_bulk_create.html index 6fb4e040..34c55699 100644 --- a/templates/accounts_bulk_create.html +++ b/templates/accounts_bulk_create.html @@ -36,12 +36,20 @@

Please note users created this way bypass some of the validations so check details such as email addresses are correct

+
+ + +
+
@@ -67,6 +75,23 @@ // split into rows excelRow = excelData.split(String.fromCharCode(10)); + // If the first row looks like a header (contains words like 'user', 'email', 'grade', 'supervisor'), drop it + if (excelRow.length) { + var firstRowCols = excelRow[0].split(String.fromCharCode(9)).map(function(c){return c.trim().toLowerCase();}); + var headerKeywords = ['user','first name','last name','email','grade','educational supervisor','supervisor','first','last']; + var isHeader = firstRowCols.some(function(c){ + if (!c) return false; + if (headerKeywords.indexOf(c) !== -1) return true; + if (c.indexOf('email') !== -1) return true; + if (c.indexOf('supervisor') !== -1) return true; + return false; + }); + if (isHeader) { + // remove header row + excelRow.shift(); + } + } + // split rows into columns for (i=0; i -1) { + var parts = full.split(/\s+/); + user.first_name = parts[0]; + user.last_name = parts.slice(1).join(' '); + } else { + user.first_name = full; + user.last_name = ''; + } + // supervisor email not provided in this format + user.supervisor_email = ''; + } myTbody.appendChild(myRow); users.push(user) emails.push(user.email) @@ -129,8 +178,8 @@ $.post("{% url 'accounts_check_users' %}", { csrfmiddlewaretoken: "{{ csrf_token }}", user_list: JSON.stringify(emails) }, function(data) { - console.log("Existing users", data) - }) + console.log("Existing users", data) + }) $("#users-list").append(`${users.length} users to create/update.`) @@ -154,23 +203,23 @@ @@ -207,6 +256,6 @@ #users-list li:has(.error) { border: 1px solid red; } - + {% endblock content %} \ No newline at end of file