Enhance supervisor email handling and input format options in bulk user creation

This commit is contained in:
Ross
2025-11-03 09:31:55 +00:00
parent 206f0afd32
commit 7eeb989b9e
2 changed files with 123 additions and 36 deletions
+52 -14
View File
@@ -815,8 +815,20 @@ def accounts_bulk_create_check(request):
if not UserGrades.objects.filter(name=user["grade"]): if not UserGrades.objects.filter(name=user["grade"]):
errors.append("Invalid grade") errors.append("Invalid grade")
if user["supervisor_email"] == "undefined": # Treat empty, missing or the string 'undefined' as no supervisor email provided
errors.append("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: else:
supervisor = Supervisor.objects.filter(email=user["supervisor_email"]) supervisor = Supervisor.objects.filter(email=user["supervisor_email"])
@@ -828,8 +840,14 @@ def accounts_bulk_create_check(request):
if supervisor.count() > 1: if supervisor.count() > 1:
errors.append("More than one supervisor with that email") errors.append("More than one supervisor with that email")
if supervisor.first().name != user["supervisor_name"]: # 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") errors.append("Supervisor name does not match")
except Exception:
pass
if errors: if errors:
return HttpResponse( return HttpResponse(
@@ -869,11 +887,22 @@ def accounts_bulk_create(request):
grade = UserGrades.objects.get(name=user["grade"]) grade = UserGrades.objects.get(name=user["grade"])
user_profile.grade = grade user_profile.grade = grade
if "supervisor_email" in user and "supervisor_name" in user: if "supervisor_name" in user and user.get("supervisor_name"):
s, created = Supervisor.objects.get_or_create( sup_email = user.get("supervisor_email")
email=user["supervisor_email"], # If supervisor email provided, prefer that. Otherwise try to match by name or create placeholder
name=user["supervisor_name"], 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: if created:
s.save() s.save()
@@ -913,11 +942,20 @@ def accounts_bulk_create(request):
user_profile = UserProfile.objects.get(user=new_user) user_profile = UserProfile.objects.get(user=new_user)
user_profile.peninsula_trainee = True user_profile.peninsula_trainee = True
# TODO: check supervisor details are correct # TODO: check supervisor details are correct
if "supervisor_email" in user and "supervisor_name" in user: if "supervisor_name" in user and user.get("supervisor_name"):
s, created = Supervisor.objects.get_or_create( sup_email = user.get("supervisor_email")
email=user["supervisor_email"], if sup_email and sup_email != 'undefined':
name=user["supervisor_name"], 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: if created:
s.save() s.save()
@@ -962,7 +1000,7 @@ def request_cid_details(request):
email = request.POST.get("email") email = request.POST.get("email")
try: try:
validate_email(email) validate_email(email)
except ValidationError as e: except ValidationError:
return HttpResponse("Invalid email.") return HttpResponse("Invalid email.")
cid_users = CidUser.objects.filter(email=email) cid_users = CidUser.objects.filter(email=email)
+52 -3
View File
@@ -36,6 +36,14 @@
</p> </p>
<p>Please note users created this way bypass some of the validations so check details such as email addresses are correct</p> <p>Please note users created this way bypass some of the validations so check details such as email addresses are correct</p>
<div class="mb-2">
<label for="input-format" class="form-label">Input format</label>
<select id="input-format" class="form-select" style="width:300px">
<option value="spreadsheet">First,Last,Email,Grade,Supervisor,SupervisorEmail (spreadsheet)</option>
<option value="name-supervisor-email-grade">User \t Educational Supervisor \t Email \t Grade</option>
</select>
</div>
<textarea id="csv" placeholder="Paste users content here" style="width: 300px; height: 100px;"></textarea><br/> <textarea id="csv" placeholder="Paste users content here" style="width: 300px; height: 100px;"></textarea><br/>
<input type="button" value="Load Data" _="on click createTable()" > <input type="button" value="Load Data" _="on click createTable()" >
@@ -67,6 +75,23 @@
// split into rows // split into rows
excelRow = excelData.split(String.fromCharCode(10)); 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 // split rows into columns
for (i=0; i<excelRow.length; i++) { for (i=0; i<excelRow.length; i++) {
excelRow[i] = excelRow[i].split(String.fromCharCode(9)); excelRow[i] = excelRow[i].split(String.fromCharCode(9));
@@ -79,7 +104,14 @@
// Loop over the rows // Loop over the rows
var format = document.getElementById('input-format').value;
var elements = ["first_name", "last_name", "email", "grade", "supervisor_name", "supervisor_email"]; var elements = ["first_name", "last_name", "email", "grade", "supervisor_name", "supervisor_email"];
// For alternate format: User\tEducational Supervisor\tEmail\tGrade
// columns: full name, supervisor name, email, grade
if (format === 'name-supervisor-email-grade') {
elements = ['full_name', 'supervisor_name', 'email', 'grade'];
}
var users = []; var users = [];
$("#users-list").empty(); $("#users-list").empty();
@@ -95,15 +127,32 @@
// Loop over the columns and add TD to the TR // Loop over the columns and add TD to the TR
for (j=0; j<excelRow[i].length; j++) { for (j=0; j<excelRow[i].length; j++) {
// Loop over the row columns
if (excelRow[i][j].length != 0) { if (excelRow[i][j].length != 0) {
var myCell = document.createElement("td"); var myCell = document.createElement("td");
myCell.innerHTML = excelRow[i][j].trim(); myCell.innerHTML = excelRow[i][j].trim();
//users[i][elements[j]] = excelRow[i][j]; var key = elements[j] || null;
user[elements[j]] = excelRow[i][j].trim(); if (key) {
user[key] = excelRow[i][j].trim();
}
} }
myRow.appendChild(myCell); myRow.appendChild(myCell);
} }
// If alternate format, split full_name into first_name/last_name and ensure supervisor_email empty
if (format === 'name-supervisor-email-grade') {
var full = user.full_name || '';
full = full.trim();
if (full.indexOf(' ') > -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); myTbody.appendChild(myRow);
users.push(user) users.push(user)
emails.push(user.email) emails.push(user.email)