Mar 06 2026: fixed attendance report page, searchable ID only

This commit is contained in:
2026-03-06 17:37:18 -05:00
parent e04935772b
commit a15c835f9a
2 changed files with 57 additions and 12 deletions
+38 -3
View File
@@ -5384,8 +5384,10 @@ def save_manual_attendance():
@login_required @login_required
def search_employees_api(): def search_employees_api():
""" """
API endpoint to search employees by name or ID API endpoint to search employees by name or ID.
Returns JSON with employee list Returns matches from the Employee table first, then appends any IDs found
in attendance_data that have no Employee record so unregistered IDs
that have attendance records can still be filtered on the attendance page.
""" """
try: try:
search_query = request.args.get('q', '').strip() search_query = request.args.get('q', '').strip()
@@ -5393,9 +5395,9 @@ def search_employees_api():
if not search_query or len(search_query) < 2: if not search_query or len(search_query) < 2:
return jsonify({'employees': []}) return jsonify({'employees': []})
# Search by ID or name
search_pattern = f"%{search_query}%" search_pattern = f"%{search_query}%"
# 1. Registered employees — search by ID or name
employees = Employee.query.filter( employees = Employee.query.filter(
db.or_( db.or_(
Employee.id.like(search_pattern), Employee.id.like(search_pattern),
@@ -5412,6 +5414,39 @@ def search_employees_api():
'full_name': f"{emp.firstName} {emp.lastName}" 'full_name': f"{emp.firstName} {emp.lastName}"
} for emp in employees] } for emp in employees]
registered_ids = {str(emp.id) for emp in employees}
# 2. Unregistered IDs — present in attendance_data but not in Employee table.
# Only add when the search term looks like (part of) a numeric ID and we
# still have room in the result list.
if len(employee_list) < 10:
remaining_slots = 10 - len(employee_list)
try:
unregistered_rows = db.session.execute(
text("""
SELECT DISTINCT ad.employee_id
FROM attendance_data ad
LEFT JOIN employee e ON CAST(ad.employee_id AS UNSIGNED) = e.id
WHERE e.id IS NULL
AND ad.employee_id LIKE :pattern
ORDER BY ad.employee_id
LIMIT :lim
"""),
{'pattern': search_pattern, 'lim': remaining_slots}
).fetchall()
for row in unregistered_rows:
emp_id = str(row[0])
if emp_id not in registered_ids:
employee_list.append({
'id': emp_id,
'firstName': f'ID: {emp_id}',
'lastName': '(no record)',
'full_name': f'ID: {emp_id} (no record)'
})
except Exception as unreg_err:
logger_handler.logger.warning(f"Could not search unregistered employee IDs: {unreg_err}")
return jsonify({'employees': employee_list}) return jsonify({'employees': employee_list})
except Exception as e: except Exception as e:
+10
View File
@@ -773,6 +773,16 @@ document.addEventListener('DOMContentLoaded', function() {
return; return;
} }
// If the visible input is a plain numeric ID, keep the hidden field
// in sync immediately so the user can just type an ID and submit
// without having to pick from the dropdown (handles IDs not in Employee table).
if (/^\d+$/.test(searchTerm)) {
employeeHiddenFilter.value = searchTerm;
} else {
// Non-numeric input — clear hidden field until a suggestion is picked
employeeHiddenFilter.value = '';
}
if (searchTerm.length < 2) { if (searchTerm.length < 2) {
autocompleteResultsFilter.classList.remove('show'); autocompleteResultsFilter.classList.remove('show');
return; return;