Browse Source

Park Attendance Dashboard updated

master
kanimozhi 7 months ago
parent
commit
a6d2374058
  1. 28
      src/main/java/com/gcc/commissionerreview/service/AttendanceService.java
  2. 101
      src/main/resources/templates/modules/attendance-dashboard.html

28
src/main/java/com/gcc/commissionerreview/service/AttendanceService.java

@ -298,6 +298,34 @@ public class AttendanceService {
+ toDateTime + ", Zone: " + zone); + toDateTime + ", Zone: " + zone);
return jdbcTemplate.queryForList(sql, params.toArray()); return jdbcTemplate.queryForList(sql, params.toArray());
} else if (category != null && category.equalsIgnoreCase("total")) {
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, "
+ "et.incharge_name, et.incharge_phoneno, et.phone_number as emp_mobile, "
+ "COALESCE(pd.park_name, '') AS park_name, et.park_id, "
+ "COALESCE(pd.supervisor_name, '') AS supervisor_name, COALESCE(pd.supervisor_mobile, '') AS supervisor_mobile "
+ "FROM enrollment_table et "
+ "LEFT JOIN park_details pd ON et.park_id = pd.park_id AND pd.is_active = 1 AND pd.is_delete = 0 "
+ "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone != 0 ";
java.util.List<Object> params = new java.util.ArrayList<>();
params.add(empType);
if (zone != null) {
sql += " AND et.zone = ? ";
params.add(zone);
}
if (parkName != null && !parkName.isEmpty() && !parkName.equals("-")) {
sql += " AND et.park_id = ? ";
params.add(parkName);
}
sql += " ORDER BY pd.park_name, et.name ";
System.out.println("Total - EmpType: " + empType + ", From: " + fromDateTime + ", To: "
+ toDateTime + ", Zone: " + zone + ", ParkName: " + parkName);
return jdbcTemplate.queryForList(sql, params.toArray());
} else { } else {
switch (category == null ? "present" : category.toLowerCase()) { switch (category == null ? "present" : category.toLowerCase()) {

101
src/main/resources/templates/modules/attendance-dashboard.html

@ -289,7 +289,9 @@
// const supervisor = Number(r.SupervisorCount) || 0; // const supervisor = Number(r.SupervisorCount) || 0;
html += `<tr><td>${zone || '-'}</td>`; html += `<tr><td>${zone || '-'}</td>`;
html += `<td class="text-center">${total}</td>`;
html += `<td class="text-center">` + (total > 0
? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="total">${total}</a>`
: `<span class="disabled-count">${total}</span>`) + `</td>`;
html += `<td class="text-center">${facialRegistered}</td>`; html += `<td class="text-center">${facialRegistered}</td>`;
html += `<td class="text-center">` + (facialNotRegistered > 0 html += `<td class="text-center">` + (facialNotRegistered > 0
? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="notregistered">${facialNotRegistered}</a>` ? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="notregistered">${facialNotRegistered}</a>`
@ -437,10 +439,38 @@
if (!Array.isArray(data)) { modalBody.innerText = JSON.stringify(data); return; } if (!Array.isArray(data)) { modalBody.innerText = JSON.stringify(data); return; }
if (data.length === 0) { modalBody.innerHTML = '<div class="alert alert-info">No park-wise records</div>'; return; } if (data.length === 0) { modalBody.innerHTML = '<div class="alert alert-info">No park-wise records</div>'; return; }
// Filter parks: when a category is selected, only show parks with count > 0 for that category
const catLower = (category || '').toLowerCase();
const displayData = !catLower ? data : data.filter(r => {
const total = Number(r.TotalCount) || 0;
const present = Number(r.AttendanceMarked) || 0;
const od = Number(r.ODCount) || 0;
const leave = Number(r.LeaveCount) || 0;
const facialNotRegistered = Number(r.facialNotRegistered) || 0;
const notMarked = Math.max(0, total - present - od - leave - facialNotRegistered);
if (catLower === 'total') return total > 0;
if (catLower === 'present') return present > 0;
if (catLower === 'od') return od > 0;
if (catLower === 'leave') return leave > 0;
if (catLower === 'notmarked') return notMarked > 0;
if (catLower === 'notregistered') return facialNotRegistered > 0;
return true;
});
if (displayData.length === 0) { modalBody.innerHTML = '<div class="alert alert-info">No parks with ' + (category || '').toUpperCase() + ' count</div>'; return; }
const showAll = !catLower;
let html = '<div class="table-responsive"><table class="table table-sm table-striped"><thead><tr>'; let html = '<div class="table-responsive"><table class="table table-sm table-striped"><thead><tr>';
html += '<th style="display:none;">Park ID</th><th>Park Name</th><th>Supervisor Name</th><th>Supervisor Mobile</th><th class="text-center">Total</th><th class="text-center">Facial Registered</th><th class="text-center">Facial Not Registered</th><th class="text-center">Present</th><th class="text-center">OD</th><th class="text-center">Leave</th><th class="text-center">Not Marked</th>';
html += '<th style="display:none;">Park ID</th><th>Park Name</th><th>Supervisor Name</th><th>Supervisor Mobile</th>';
if (showAll) {
html += '<th class="text-center">Total</th><th class="text-center">Facial Registered</th><th class="text-center">Facial Not Registered</th><th class="text-center">Present</th><th class="text-center">OD</th><th class="text-center">Leave</th><th class="text-center">Not Marked</th>';
} else {
const categoryLabel = { present: 'Present', od: 'OD', leave: 'Leave', notmarked: 'Not Marked', notregistered: 'Facial Not Registered' };
html += `<th class="text-center">${categoryLabel[catLower] || category}</th>`;
}
html += '</tr></thead><tbody>'; html += '</tr></thead><tbody>';
data.forEach(r => {
displayData.forEach(r => {
const parkId = r.park_id || ''; const parkId = r.park_id || '';
const park = r.park_name || ''; const park = r.park_name || '';
const parkDisplay = park === '' ? (parkId || 'Unknown') : park; const parkDisplay = park === '' ? (parkId || 'Unknown') : park;
@ -458,19 +488,29 @@
html += `<td>${parkDisplay}</td>`; html += `<td>${parkDisplay}</td>`;
html += `<td>${supervisorName}</td>`; html += `<td>${supervisorName}</td>`;
html += `<td>${supervisorMobile}</td>`; html += `<td>${supervisorMobile}</td>`;
html += `<td class="text-center">${total}</td>`;
html += `<td class="text-center">${facialRegistered}</td>`;
// html += `<td class="text-center">${facialNotRegistered}</td>`;
html += `<td class="text-center">` + (facialNotRegistered > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="notregistered">${facialNotRegistered}</a>` : `<span class="disabled-count">${facialNotRegistered}</span>`) + `</td>`;
html += `<td class="text-center">` + (present > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="present">${present}</a>` : `<span class="disabled-count">${present}</span>`) + `</td>`;
html += `<td class="text-center">` + (od > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="od">${od}</a>` : `<span class="disabled-count">${od}</span>`) + `</td>`;
html += `<td class="text-center">` + (leave > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="leave">${leave}</a>` : `<span class="disabled-count">${leave}</span>`) + `</td>`;
html += `<td class="text-center">` + (notMarked > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="notmarked">${notMarked}</a>` : `<span class="disabled-count">${notMarked}</span>`) + `</td>`;
if (showAll) {
html += `<td class="text-center">${total}</td>`;
html += `<td class="text-center">${facialRegistered}</td>`;
html += `<td class="text-center">` + (facialNotRegistered > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="notregistered">${facialNotRegistered}</a>` : `<span class="disabled-count">${facialNotRegistered}</span>`) + `</td>`;
html += `<td class="text-center">` + (present > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="present">${present}</a>` : `<span class="disabled-count">${present}</span>`) + `</td>`;
html += `<td class="text-center">` + (od > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="od">${od}</a>` : `<span class="disabled-count">${od}</span>`) + `</td>`;
html += `<td class="text-center">` + (leave > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="leave">${leave}</a>` : `<span class="disabled-count">${leave}</span>`) + `</td>`;
html += `<td class="text-center">` + (notMarked > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="notmarked">${notMarked}</a>` : `<span class="disabled-count">${notMarked}</span>`) + `</td>`;
} else {
// Show only the selected category column
let catValue = 0;
if (catLower === 'present') catValue = present;
else if (catLower === 'od') catValue = od;
else if (catLower === 'leave') catValue = leave;
else if (catLower === 'notmarked') catValue = notMarked;
else if (catLower === 'notregistered') catValue = facialNotRegistered;
html += `<td class="text-center">` + (catValue > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" data-parkname="${parkDisplay}" data-category="${catLower}">${catValue}</a>` : `<span class="disabled-count">${catValue}</span>`) + `</td>`;
}
html += '</tr>'; html += '</tr>';
}); });
// Compute grand totals for park-wise summary
let grandTotal = 0, grandSupervisor = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
// Compute grand totals from ALL data to match zone summary (no count mismatch)
let grandTotal = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
data.forEach(r => { data.forEach(r => {
const total = Number(r.TotalCount) || 0; const total = Number(r.TotalCount) || 0;
const facialRegistered = Number(r.facialRegistered) || 0; const facialRegistered = Number(r.facialRegistered) || 0;
@ -490,13 +530,23 @@
html += '<td>Total</td>'; html += '<td>Total</td>';
html += '<td></td>'; html += '<td></td>';
html += '<td></td>'; html += '<td></td>';
html += `<td class="text-center">${grandTotal}</td>`;
html += `<td class="text-center">${grandFacialReg}</td>`;
html += `<td class="text-center">${grandFacialNotReg}</td>`;
html += `<td class="text-center">${grandPresent}</td>`;
html += `<td class="text-center">${grandOd}</td>`;
html += `<td class="text-center">${grandLeave}</td>`;
html += `<td class="text-center">${grandNotMarked}</td>`;
if (showAll) {
html += `<td class="text-center">${grandTotal}</td>`;
html += `<td class="text-center">${grandFacialReg}</td>`;
html += `<td class="text-center">${grandFacialNotReg}</td>`;
html += `<td class="text-center">${grandPresent}</td>`;
html += `<td class="text-center">${grandOd}</td>`;
html += `<td class="text-center">${grandLeave}</td>`;
html += `<td class="text-center">${grandNotMarked}</td>`;
} else {
let grandCatValue = 0;
if (catLower === 'present') grandCatValue = grandPresent;
else if (catLower === 'od') grandCatValue = grandOd;
else if (catLower === 'leave') grandCatValue = grandLeave;
else if (catLower === 'notmarked') grandCatValue = grandNotMarked;
else if (catLower === 'notregistered') grandCatValue = grandFacialNotReg;
html += `<td class="text-center">${grandCatValue}</td>`;
}
html += '</tr></tfoot></table></div>'; html += '</tr></tfoot></table></div>';
modalBody.innerHTML = html; modalBody.innerHTML = html;
} catch (e) { } catch (e) {
@ -583,7 +633,9 @@
let displayColumns = []; let displayColumns = [];
const catLower = (category || 'present').toLowerCase(); const catLower = (category || 'present').toLowerCase();
if (catLower === 'present') {
if (catLower === 'total') {
displayColumns = ['park_name', 'supervisor_name', 'supervisor_mobile', 'enrollment_id', 'name', 'emp_mobile'];
} else if (catLower === 'present') {
displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno', 'App Version', 'App Type', 'Location']; displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno', 'App Version', 'App Type', 'Location'];
if (empType === 'Park') displayColumns.push('park_name'); if (empType === 'Park') displayColumns.push('park_name');
displayColumns.push('intime', 'inphoto', 'outtime', 'outphoto'); displayColumns.push('intime', 'inphoto', 'outtime', 'outphoto');
@ -642,6 +694,9 @@
location: 'Location', location: 'Location',
image: 'Image', image: 'Image',
supervisor_id: 'Supervisor ID', supervisor_id: 'Supervisor ID',
supervisor_name: 'Supervisor Name',
supervisor_mobile: 'Supervisor Mobile',
emp_mobile: 'Employee Mobile',
}; };
if (map[key]) return map[key]; if (map[key]) return map[key];
return key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); return key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
@ -715,8 +770,8 @@
const zone = zoneAnchor.getAttribute('data-zone'); const zone = zoneAnchor.getAttribute('data-zone');
const empType = zoneAnchor.getAttribute('data-emptype'); const empType = zoneAnchor.getAttribute('data-emptype');
const category = zoneAnchor.getAttribute('data-category'); const category = zoneAnchor.getAttribute('data-category');
// Supervisor: show employee details directly (no park-wise drill-down)
if (category === 'supervisor') {
// Supervisor & Total: show employee details directly (no park-wise drill-down)
if (category === 'supervisor' || category === 'total') {
loadDetailed(empType, category, zone); loadDetailed(empType, category, zone);
} else if (empType === 'Park') { } else if (empType === 'Park') {
loadParkWiseSummary(zone, category); loadParkWiseSummary(zone, category);

Loading…
Cancel
Save