Browse Source

Attendance Dashboard controller and service updated

master
kanimozhi 8 months ago
parent
commit
7ca3f67f2c
  1. 23
      src/main/java/com/gcc/commissionerreview/controller/AttendanceController.java
  2. 125
      src/main/java/com/gcc/commissionerreview/service/AttendanceService.java
  3. 76
      src/main/resources/templates/modules/attendance-dashboard.html

23
src/main/java/com/gcc/commissionerreview/controller/AttendanceController.java

@ -16,8 +16,8 @@ import com.gcc.commissionerreview.service.AttendanceService;
public class AttendanceController { public class AttendanceController {
@Autowired @Autowired
AttendanceService attendanceService;
AttendanceService attendanceService;
@GetMapping("/abstractCounts") @GetMapping("/abstractCounts")
public List<Map<String, Object>> getAbstractCounts() { public List<Map<String, Object>> getAbstractCounts() {
return attendanceService.getAbstractCounts(); return attendanceService.getAbstractCounts();
@ -28,9 +28,9 @@ public class AttendanceController {
@RequestParam(name = "fromDate", required = false) String fromDate, @RequestParam(name = "fromDate", required = false) String fromDate,
@RequestParam(name = "toDate", required = false) String toDate) { @RequestParam(name = "toDate", required = false) String toDate) {
List<Map<String, Object>> result = attendanceService.getZoneSummary(empType, fromDate, toDate);
System.out.println("Zone Summary Result for "+empType+ ":"+ result);
return result;
List<Map<String, Object>> result = attendanceService.getZoneSummary(empType, fromDate, toDate);
System.out.println("Zone Summary Result for " + empType + ":" + result);
return result;
} }
@ -58,7 +58,7 @@ public class AttendanceController {
@RequestParam(name = "toDate", required = false) String toDate, @RequestParam(name = "toDate", required = false) String toDate,
@RequestParam(name = "zone", required = false) Integer zone) { @RequestParam(name = "zone", required = false) Integer zone) {
List<Map<String, Object>> result = attendanceService.getParkWiseSummary(fromDate, toDate, zone); List<Map<String, Object>> result = attendanceService.getParkWiseSummary(fromDate, toDate, zone);
System.out.println("Park Wise Summary Result: " + result);
System.out.println("Park Wise Summary Result: " + result);
return result; return result;
} }
@ -68,12 +68,13 @@ public class AttendanceController {
@RequestParam(name = "fromDate", required = false) String fromDate, @RequestParam(name = "fromDate", required = false) String fromDate,
@RequestParam(name = "toDate", required = false) String toDate, @RequestParam(name = "toDate", required = false) String toDate,
@RequestParam(name = "zone", required = false) Integer zone, @RequestParam(name = "zone", required = false) Integer zone,
@RequestParam(name = "parkName", required = false) String parkName) {
@RequestParam(name = "parkId", required = false) String parkId) {
List<Map<String, Object>> result = attendanceService.getDetailedList(empType, category, fromDate, toDate, zone, parkName);
System.out.println("Detailed Result: " + result);
List<Map<String, Object>> result = attendanceService.getDetailedList(empType, category, fromDate, toDate, zone,
parkId);
System.out.println("Detailed Result: " + result);
return result;
return result;
} }
} }

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

@ -73,10 +73,12 @@ public class AttendanceService {
+ "COALESCE(fd.facialNotRegistered, 0) AS facialNotRegistered, " + "COALESCE(fd.facialNotRegistered, 0) AS facialNotRegistered, "
+ "COUNT(DISTINCT CASE WHEN att.indatetime >= ? AND att.indatetime <= ? THEN att.enrollment_id END) AS AttendanceMarked, " + "COUNT(DISTINCT CASE WHEN att.indatetime >= ? AND att.indatetime <= ? THEN att.enrollment_id END) AS AttendanceMarked, "
+ "COUNT(DISTINCT CASE WHEN att.oddatetime >= ? AND att.oddatetime <= ? THEN att.enrollment_id END) AS ODCount, " + "COUNT(DISTINCT CASE WHEN att.oddatetime >= ? AND att.oddatetime <= ? THEN att.enrollment_id END) AS ODCount, "
+ "COUNT(DISTINCT CASE WHEN att.leavedatetime >= ? AND att.leavedatetime <= ? THEN att.enrollment_id END) AS LeaveCount "
+ "COUNT(DISTINCT CASE WHEN att.leavedatetime >= ? AND att.leavedatetime <= ? THEN att.enrollment_id END) AS LeaveCount, "
+ "COUNT(distinct et.incharge_id) AS SupervisorCount "
+ "FROM enrollment_table et " + "FROM enrollment_table et "
+ "LEFT JOIN attendance att ON et.enrollment_id = att.enrollment_id " + "LEFT JOIN attendance att ON et.enrollment_id = att.enrollment_id "
+ "LEFT JOIN facial_data fd ON et.zone = fd.zone " + "LEFT JOIN facial_data fd ON et.zone = fd.zone "
+ "LEFT JOIN park_details pd ON et.incharge_id = pd.supervisor_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 " + "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone != 0 "
+ "GROUP BY et.zone, fd.facialRegistered, fd.facialNotRegistered " + "GROUP BY et.zone, fd.facialRegistered, fd.facialNotRegistered "
+ "ORDER BY et.zone"; + "ORDER BY et.zone";
@ -112,30 +114,33 @@ public class AttendanceService {
dateColumn = "att.indatetime"; dateColumn = "att.indatetime";
filterDateColumn = "att.indatetime"; filterDateColumn = "att.indatetime";
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, et.park_name, emp.image as image "
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, "
+ "COALESCE(pd.park_name, '') AS park_name, et.park_id, emp.image as image "
+ " FROM enrollment_table et " + " FROM enrollment_table et "
+ " left join gccfacialdb.employees emp on et.enrollment_id = emp.employeeid "
+ " where et.isactive =1 and et.isdelete = 0 and et.emp_type = ? and et.zone !=0 "
+ " and et.enrollment_id not in (select enrollment_id from attendance where date(indatetime) between ? and ?) ";
+ " LEFT JOIN park_details pd ON et.park_id = pd.park_id AND pd.is_active = 1 AND pd.is_delete = 0 "
+ " LEFT JOIN gccfacialdb.employees emp ON et.enrollment_id = emp.employeeid "
+ " WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone != 0 AND et.facial_attendance != 1 "
+ " AND et.enrollment_id NOT IN (SELECT enrollment_id FROM attendance WHERE date(indatetime) BETWEEN ? AND ? "
+ " OR date(oddatetime) BETWEEN ? AND ? OR date(leavedatetime) BETWEEN ? AND ?)";
java.util.List<Object> params = new java.util.ArrayList<>(); java.util.List<Object> params = new java.util.ArrayList<>();
params.add(empType); params.add(empType);
params.add(fromDate); params.add(fromDate);
params.add(toDate); params.add(toDate);
params.add(fromDate);
params.add(toDate);
params.add(fromDate);
params.add(toDate);
if (zone != null) { if (zone != null) {
sql += " and et.zone = ? ";
sql += " AND et.zone = ? ";
params.add(zone); params.add(zone);
} }
if (parkName != null && !parkName.isEmpty() && !parkName.equals("-")) { if (parkName != null && !parkName.isEmpty() && !parkName.equals("-")) {
sql += " and et.park_name = ? ";
sql += " AND et.park_id = ? ";
params.add(parkName); params.add(parkName);
} }
if (parkName != null && !parkName.isEmpty() && parkName.equals("-")) {
sql += " and et.park_name = '' ";
}
// sql += " order by " + dateColumn + " desc "; // sql += " order by " + dateColumn + " desc ";
System.out.println("EmpType: " + empType + ", Category: " + category + ", From: " + fromDateTime + ", To: " System.out.println("EmpType: " + empType + ", Category: " + category + ", From: " + fromDateTime + ", To: "
@ -143,33 +148,69 @@ public class AttendanceService {
return jdbcTemplate.queryForList(sql, params.toArray()); return jdbcTemplate.queryForList(sql, params.toArray());
} else if (category != null && category.equals("notregistered")) { } else if (category != null && category.equals("notregistered")) {
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, et.park_name, emp.image as image "
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, "
+ "COALESCE(pd.park_name, '') AS park_name, et.park_id, emp.image as image "
+ " FROM enrollment_table et " + " FROM enrollment_table et "
+ " left join gccfacialdb.employees emp on et.enrollment_id = emp.employeeid "
+ " where et.isactive =1 and et.isdelete = 0 and et.emp_type = ? and et.zone !=0 and facial_attendance = 0 ";
+ " LEFT JOIN park_details pd ON et.park_id = pd.park_id AND pd.is_active = 1 AND pd.is_delete = 0 "
+ " LEFT JOIN gccfacialdb.employees emp ON et.enrollment_id = emp.employeeid "
+ " WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone != 0 AND facial_attendance = 0 ";
java.util.List<Object> params = new java.util.ArrayList<>(); java.util.List<Object> params = new java.util.ArrayList<>();
params.add(empType); params.add(empType);
if (zone != null) { if (zone != null) {
sql += " and et.zone = ? ";
sql += " AND et.zone = ? ";
params.add(zone); params.add(zone);
} }
if (parkName != null && !parkName.isEmpty() && !parkName.equals("-")) { if (parkName != null && !parkName.isEmpty() && !parkName.equals("-")) {
sql += " and et.park_name = ? ";
sql += " AND et.park_id = ? ";
params.add(parkName); params.add(parkName);
} }
if (parkName != null && !parkName.isEmpty() && parkName.equals("-")) {
sql += " and et.park_name = '' ";
}
// sql += " order by " + dateColumn + " desc "; // sql += " order by " + dateColumn + " desc ";
System.out.println("EmpType: " + empType + ", Category: " + category + ", From: " + fromDateTime + ", To: " System.out.println("EmpType: " + empType + ", Category: " + category + ", From: " + fromDateTime + ", To: "
+ toDateTime + ", Zone: " + zone + ", ParkName: " + parkName); + toDateTime + ", Zone: " + zone + ", ParkName: " + parkName);
return jdbcTemplate.queryForList(sql, params.toArray()); return jdbcTemplate.queryForList(sql, params.toArray());
} else if (category != null && category.equalsIgnoreCase("supervisor")) {
// String sql = "SELECT et.enrollment_id, et.name, et.designation,
// et.department, et.incharge_name, et.incharge_phoneno, emp.image as image "
// + "FROM enrollment_table et "
// + "LEFT JOIN gccfacialdb.employees emp ON et.enrollment_id = emp.employeeid "
// + "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone
// != 0 "
// + "AND et.enrollment_id IN (SELECT supervisor_id FROM park_details WHERE
// is_active = 1 AND is_delete = 0) ";
String sql = "SELECT pd.supervisor_id, pd.supervisor_name as name, pd.supervisor_designation AS designation, "
+
" et.department, et.incharge_name, et.incharge_phoneno " +
"FROM ( " +
" SELECT DISTINCT supervisor_id, supervisor_name, supervisor_designation " +
" FROM park_details " +
" WHERE is_active = 1 AND is_delete = 0 AND zone = ? " +
") pd " +
"LEFT JOIN ( " +
" SELECT DISTINCT incharge_id, department, incharge_name, incharge_phoneno " +
" FROM enrollment_table " +
" WHERE isactive = 1 AND isdelete = 0 and emp_type = ? " +
") et ON pd.supervisor_id = et.incharge_id";
java.util.List<Object> params = new java.util.ArrayList<>();
params.add(zone);
params.add(empType);
// if (zone != null) {
// sql += " AND et.zone = ? ";
// params.add(zone);
// }
// sql += " ORDER BY et.name ";
System.out.println("Supervisor - EmpType: " + empType + ", From: " + fromDateTime + ", To: "
+ toDateTime + ", Zone: " + zone);
return jdbcTemplate.queryForList(sql, params.toArray());
} else { } else {
switch (category == null ? "present" : category.toLowerCase()) { switch (category == null ? "present" : category.toLowerCase()) {
@ -186,17 +227,19 @@ public class AttendanceService {
filterDateColumn = "att.indatetime"; filterDateColumn = "att.indatetime";
} }
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, et.emp_id, et.park_name, "
+ "ifnull(att.appversion,'') as appversion, ifnull(att.apptype,'')as apptype, ifnull(att.location,'') as location, "
String sql = "SELECT et.enrollment_id, et.name, et.designation, et.department, et.incharge_name, et.incharge_phoneno, et.emp_id, "
+ "COALESCE(pd.park_name, '') AS park_name, et.park_id, "
+ "IFNULL(att.appversion,'') as appversion, IFNULL(att.apptype,'') as apptype, IFNULL(att.location,'') as location, "
+ "DATE_FORMAT(att.indatetime, '%d-%m-%Y %h:%i %p') as intime, att.inphoto as inphoto, att.inby, " + "DATE_FORMAT(att.indatetime, '%d-%m-%Y %h:%i %p') as intime, att.inphoto as inphoto, att.inby, "
+ "DATE_FORMAT(att.outdatetime, '%d-%m-%Y %h:%i %p') as outtime, att.outphoto as outphoto, att.outby, " + "DATE_FORMAT(att.outdatetime, '%d-%m-%Y %h:%i %p') as outtime, att.outphoto as outphoto, att.outby, "
+ "DATE_FORMAT(att.oddatetime, '%d-%m-%Y %h:%i %p') as odtime, att.odby, et.zone, " + "DATE_FORMAT(att.oddatetime, '%d-%m-%Y %h:%i %p') as odtime, att.odby, et.zone, "
+ "DATE_FORMAT(att.leavedatetime, '%d-%m-%Y %h:%i %p') as leavedatetime, att.leaveby " + "DATE_FORMAT(att.leavedatetime, '%d-%m-%Y %h:%i %p') as leavedatetime, att.leaveby "
+ "FROM enrollment_table et " + "FROM enrollment_table et "
+ "inner join attendance att on et.enrollment_id = att.enrollment_id "
+ " and " + filterDateColumn + " >= ? and " + filterDateColumn + " <= ? "
+ "where et.isactive =1 and et.isdelete = 0 and et.emp_type = ? and et.zone !=0 "
+ " and " + filterDateColumn + " is not null ";
+ "LEFT JOIN park_details pd ON et.park_id = pd.park_id AND pd.is_active = 1 AND pd.is_delete = 0 "
+ "INNER JOIN attendance att ON et.enrollment_id = att.enrollment_id "
+ " AND " + filterDateColumn + " >= ? AND " + filterDateColumn + " <= ? "
+ "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = ? AND et.zone != 0 "
+ " AND " + filterDateColumn + " IS NOT NULL ";
java.util.List<Object> params = new java.util.ArrayList<>(); java.util.List<Object> params = new java.util.ArrayList<>();
params.add(fromDateTime); params.add(fromDateTime);
@ -204,12 +247,12 @@ public class AttendanceService {
params.add(empType); params.add(empType);
if (zone != null) { if (zone != null) {
sql += " and et.zone = ? ";
sql += " AND et.zone = ? ";
params.add(zone); params.add(zone);
} }
if (parkName != null && !parkName.isEmpty()) { if (parkName != null && !parkName.isEmpty()) {
sql += " and et.park_name = ? ";
sql += " AND et.park_id = ? ";
params.add(parkName); params.add(parkName);
} }
@ -243,24 +286,28 @@ public class AttendanceService {
System.out.println("Zone: " + zone + ", From: " + fromDateTime + ", To: " + toDateTime); System.out.println("Zone: " + zone + ", From: " + fromDateTime + ", To: " + toDateTime);
String sql = "WITH facial_data AS ( " String sql = "WITH facial_data AS ( "
+ "SELECT park_name, "
+ "SUM(CASE WHEN facial_attendance = 1 THEN 1 ELSE 0 END) AS facialRegistered, "
+ "SUM(CASE WHEN facial_attendance = 0 THEN 1 ELSE 0 END) AS facialNotRegistered "
+ "FROM enrollment_table "
+ "WHERE isactive = 1 AND isdelete = 0 AND emp_type = 'Park' AND zone = ? "
+ "GROUP BY park_name "
+ "SELECT et2.park_id, "
+ "SUM(CASE WHEN et2.facial_attendance = 1 THEN 1 ELSE 0 END) AS facialRegistered, "
+ "SUM(CASE WHEN et2.facial_attendance = 0 THEN 1 ELSE 0 END) AS facialNotRegistered "
+ "FROM enrollment_table et2 "
+ "WHERE et2.isactive = 1 AND et2.isdelete = 0 AND et2.emp_type = 'Park' AND et2.zone = ? "
+ "GROUP BY et2.park_id "
+ ") " + ") "
+ "SELECT et.park_name, COUNT(DISTINCT et.enrollment_id) AS TotalCount, et.incharge_name, et.incharge_phoneno, "
+ "SELECT et.park_id, COALESCE(pd.park_name, '') AS park_name, "
+ "COUNT(DISTINCT et.enrollment_id) AS TotalCount, "
+ "COALESCE(pd.supervisor_name, '') AS supervisor_name, COALESCE(pd.supervisor_mobile, '') AS supervisor_mobile, "
+ "COALESCE(fd.facialRegistered, 0) AS facialRegistered, COALESCE(fd.facialNotRegistered, 0) AS facialNotRegistered, " + "COALESCE(fd.facialRegistered, 0) AS facialRegistered, COALESCE(fd.facialNotRegistered, 0) AS facialNotRegistered, "
+ "COUNT(DISTINCT CASE WHEN att.indatetime >= ? AND att.indatetime <= ? THEN att.enrollment_id END) AS AttendanceMarked, " + "COUNT(DISTINCT CASE WHEN att.indatetime >= ? AND att.indatetime <= ? THEN att.enrollment_id END) AS AttendanceMarked, "
+ "COUNT(DISTINCT CASE WHEN att.oddatetime >= ? AND att.oddatetime <= ? THEN att.enrollment_id END) AS ODCount, " + "COUNT(DISTINCT CASE WHEN att.oddatetime >= ? AND att.oddatetime <= ? THEN att.enrollment_id END) AS ODCount, "
+ "COUNT(DISTINCT CASE WHEN att.leavedatetime >= ? AND att.leavedatetime <= ? THEN att.enrollment_id END) AS LeaveCount "
+ "COUNT(DISTINCT CASE WHEN att.leavedatetime >= ? AND att.leavedatetime <= ? THEN att.enrollment_id END) AS LeaveCount, "
+ "COUNT(distinct et.incharge_id) AS SupervisorCount "
+ "FROM enrollment_table et " + "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 "
+ "LEFT JOIN attendance att ON et.enrollment_id = att.enrollment_id " + "LEFT JOIN attendance att ON et.enrollment_id = att.enrollment_id "
+ "LEFT JOIN facial_data fd ON et.park_name = fd.park_name "
+ "LEFT JOIN facial_data fd ON et.park_id = fd.park_id "
+ "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = 'Park' AND et.zone != 0 AND et.zone = ? " + "WHERE et.isactive = 1 AND et.isdelete = 0 AND et.emp_type = 'Park' AND et.zone != 0 AND et.zone = ? "
+ "GROUP BY et.park_name, fd.facialRegistered, fd.facialNotRegistered, et.incharge_name, et.incharge_phoneno "
+ "ORDER BY et.park_name";
+ "GROUP BY et.park_id, pd.park_name, pd.supervisor_name, pd.supervisor_mobile, fd.facialRegistered, fd.facialNotRegistered "
+ "ORDER BY pd.park_name";
return jdbcTemplate.queryForList(sql, new Object[] { zone, fromDateTime, toDateTime, fromDateTime, toDateTime, return jdbcTemplate.queryForList(sql, new Object[] { zone, fromDateTime, toDateTime, fromDateTime, toDateTime,
fromDateTime, toDateTime, zone }); fromDateTime, toDateTime, zone });

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

@ -186,6 +186,7 @@
<div class="small">Total: <strong>${item.totalCount}</strong></div> <div class="small">Total: <strong>${item.totalCount}</strong></div>
<div class="small">Facial Registered: <strong>${facialRegistered}</strong></div> <div class="small">Facial Registered: <strong>${facialRegistered}</strong></div>
<div class="small">Facial Not Registered: <strong>${facialNotRegistered}</strong></div> <div class="small">Facial Not Registered: <strong>${facialNotRegistered}</strong></div>
<div class="small">Present %: <strong><span id="presentPercent">—</span></strong></div>
</div> </div>
</div></div>`; </div></div>`;
}); });
@ -224,7 +225,8 @@
if (!Array.isArray(data)) { target.innerText = JSON.stringify(data); return; } if (!Array.isArray(data)) { target.innerText = JSON.stringify(data); return; }
if (data.length === 0) { target.innerHTML = '<div class="alert alert-info">No records</div>'; return; } if (data.length === 0) { target.innerHTML = '<div class="alert alert-info">No records</div>'; return; }
const rows = data.slice().sort((a, b) => String(a.zone || '').localeCompare(String(b.zone || ''), undefined, { numeric: true })); const rows = data.slice().sort((a, b) => String(a.zone || '').localeCompare(String(b.zone || ''), undefined, { numeric: true }));
let html = '<table class="table table-sm table-striped"><thead><tr><th>Zone</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></tr></thead><tbody>';
// let html = '<table class="table table-sm table-striped"><thead><tr><th>Zone</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">Supervisor</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></tr></thead><tbody>';
let html = '<table class="table table-sm table-striped"><thead><tr><th>Zone</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></tr></thead><tbody>';
rows.forEach(r => { rows.forEach(r => {
const zone = r.zone; const zone = r.zone;
const total = Number(r.TotalCount) || 0; const total = Number(r.TotalCount) || 0;
@ -233,7 +235,8 @@
const present = Number(r.AttendanceMarked) || 0; const present = Number(r.AttendanceMarked) || 0;
const od = Number(r.ODCount) || 0; const od = Number(r.ODCount) || 0;
const leave = Number(r.LeaveCount) || 0; const leave = Number(r.LeaveCount) || 0;
const notMarked = total - present - od - leave;
const notMarked = Math.max(0, total - present - od - leave - facialNotRegistered);
// 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}</td>`;
@ -241,6 +244,9 @@
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>`
: `<span class="disabled-count">${facialNotRegistered}</span>`) + `</td>`; : `<span class="disabled-count">${facialNotRegistered}</span>`) + `</td>`;
// html += `<td class="text-center">` + (supervisor > 0
// ? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="supervisor">${supervisor}</a>`
// : `<span class="disabled-count">${supervisor}</span>`) + `</td>`;
html += `<td class="text-center">` + (present > 0 html += `<td class="text-center">` + (present > 0
? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="present">${present}</a>` ? `<a href="#" class="zone-count" data-zone="${zone}" data-emptype="${empType}" data-category="present">${present}</a>`
: `<span class="disabled-count">${present}</span>`) + `</td>`; : `<span class="disabled-count">${present}</span>`) + `</td>`;
@ -257,7 +263,7 @@
}); });
// Compute grand totals // Compute grand totals
let grandTotal = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
let grandTotal = 0, grandSupervisor = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
rows.forEach(r => { rows.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;
@ -266,18 +272,20 @@
const od = Number(r.ODCount) || 0; const od = Number(r.ODCount) || 0;
const leave = Number(r.LeaveCount) || 0; const leave = Number(r.LeaveCount) || 0;
grandTotal += total; grandTotal += total;
// grandSupervisor += (Number(r.SupervisorCount) || 0);
grandFacialReg += facialRegistered; grandFacialReg += facialRegistered;
grandFacialNotReg += facialNotRegistered; grandFacialNotReg += facialNotRegistered;
grandPresent += present; grandPresent += present;
grandOd += od; grandOd += od;
grandLeave += leave; grandLeave += leave;
grandNotMarked += (total - present - od - leave);
grandNotMarked += Math.max(0, total - present - od - leave - facialNotRegistered);
}); });
html += '</tbody><tfoot><tr style="font-weight:bold; background-color:#e9ecef;">'; html += '</tbody><tfoot><tr style="font-weight:bold; background-color:#e9ecef;">';
html += '<td>Total</td>'; html += '<td>Total</td>';
html += `<td class="text-center">${grandTotal}</td>`; html += `<td class="text-center">${grandTotal}</td>`;
html += `<td class="text-center">${grandFacialReg}</td>`; html += `<td class="text-center">${grandFacialReg}</td>`;
html += `<td class="text-center">${grandFacialNotReg}</td>`; html += `<td class="text-center">${grandFacialNotReg}</td>`;
// html += `<td class="text-center">${grandSupervisor}</td>`;
html += `<td class="text-center">${grandPresent}</td>`; html += `<td class="text-center">${grandPresent}</td>`;
html += `<td class="text-center">${grandOd}</td>`; html += `<td class="text-center">${grandOd}</td>`;
html += `<td class="text-center">${grandLeave}</td>`; html += `<td class="text-center">${grandLeave}</td>`;
@ -312,6 +320,17 @@
.then(parkData => { .then(parkData => {
console.log('Park data loaded:', parkData); console.log('Park data loaded:', parkData);
renderTable(parkTarget, parkData, 'Park'); renderTable(parkTarget, parkData, 'Park');
// Compute Present % (Present + OD) / Total
if (Array.isArray(parkData) && parkData.length > 0) {
let totalAll = 0, presentOdAll = 0;
parkData.forEach(r => {
totalAll += (Number(r.TotalCount) || 0);
presentOdAll += (Number(r.AttendanceMarked) || 0) + (Number(r.ODCount) || 0);
});
const pct = totalAll > 0 ? ((presentOdAll / totalAll) * 100).toFixed(1) : '0.0';
const el = document.getElementById('presentPercent');
if (el) el.textContent = pct + '%';
}
}) })
.catch(e => { .catch(e => {
console.error('Park error:', e); console.error('Park error:', e);
@ -369,36 +388,38 @@
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; }
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>Park Name</th><th>Incharge Name</th><th>Mobile Number</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>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 += '</tr></thead><tbody>'; html += '</tr></thead><tbody>';
data.forEach(r => { data.forEach(r => {
const park = r.park_name || '-';
const inchargeName = r.incharge_name || '-';
const inchargePhone = r.incharge_phoneno || '-';
const parkId = r.park_id || '';
const park = r.park_name || '';
const parkDisplay = park === '' ? (parkId || 'Unknown') : park;
const supervisorName = r.supervisor_name || '-';
const supervisorMobile = r.supervisor_mobile || '-';
const total = Number(r.TotalCount) || 0; const total = Number(r.TotalCount) || 0;
const facialRegistered = Number(r.facialRegistered) || 0; const facialRegistered = Number(r.facialRegistered) || 0;
const facialNotRegistered = Number(r.facialNotRegistered) || 0; const facialNotRegistered = Number(r.facialNotRegistered) || 0;
const present = Number(r.AttendanceMarked) || 0; const present = Number(r.AttendanceMarked) || 0;
const od = Number(r.ODCount) || 0; const od = Number(r.ODCount) || 0;
const leave = Number(r.LeaveCount) || 0; const leave = Number(r.LeaveCount) || 0;
const notMarked = total - present - od - leave;
const notMarked = Math.max(0, total - present - od - leave - facialNotRegistered);
html += '<tr>'; html += '<tr>';
html += `<td>${park}</td>`;
html += `<td>${inchargeName}</td>`;
html += `<td>${inchargePhone}</td>`;
html += `<td>${parkDisplay}</td>`;
html += `<td>${supervisorName}</td>`;
html += `<td>${supervisorMobile}</td>`;
html += `<td class="text-center">${total}</td>`; html += `<td class="text-center">${total}</td>`;
html += `<td class="text-center">${facialRegistered}</td>`; html += `<td class="text-center">${facialRegistered}</td>`;
// html += `<td class="text-center">${facialNotRegistered}</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-park="${park}" 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-park="${park}" 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-park="${park}" 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-park="${park}" 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-park="${park}" data-category="notmarked">${notMarked}</a>` : `<span class="disabled-count">${notMarked}</span>`) + `</td>`;
html += `<td class="text-center">` + (facialNotRegistered > 0 ? `<a href="#" class="park-employee-count" data-zone="${zone}" data-parkid="${parkId}" 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-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-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-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-category="notmarked">${notMarked}</a>` : `<span class="disabled-count">${notMarked}</span>`) + `</td>`;
html += '</tr>'; html += '</tr>';
}); });
// Compute grand totals for park-wise summary // Compute grand totals for park-wise summary
let grandTotal = 0, grandFacialReg = 0, grandFacialNotReg = 0, grandPresent = 0, grandOd = 0, grandLeave = 0, grandNotMarked = 0;
let grandTotal = 0, grandSupervisor = 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;
@ -412,7 +433,7 @@
grandPresent += present; grandPresent += present;
grandOd += od; grandOd += od;
grandLeave += leave; grandLeave += leave;
grandNotMarked += (total - present - od - leave);
grandNotMarked += Math.max(0, total - present - od - leave - facialNotRegistered);
}); });
html += '</tbody><tfoot><tr style="font-weight:bold; background-color:#e9ecef;">'; html += '</tbody><tfoot><tr style="font-weight:bold; background-color:#e9ecef;">';
html += '<td>Total</td>'; html += '<td>Total</td>';
@ -495,7 +516,7 @@
let url = `${apiBase}/detailed?empType=${encodeURIComponent(empType)}&category=${encodeURIComponent(category)}&fromDate=${encodeURIComponent(fromDate)}&toDate=${encodeURIComponent(toDate)}`; let url = `${apiBase}/detailed?empType=${encodeURIComponent(empType)}&category=${encodeURIComponent(category)}&fromDate=${encodeURIComponent(fromDate)}&toDate=${encodeURIComponent(toDate)}`;
url += `&zone=${encodeURIComponent(zoneVal)}`; url += `&zone=${encodeURIComponent(zoneVal)}`;
if (parkName) { if (parkName) {
url += `&parkName=${encodeURIComponent(parkName)}`;
url += `&parkId=${encodeURIComponent(parkName)}`;
} }
const res = await fetch(url); const res = await fetch(url);
if (!res.ok) { if (!res.ok) {
@ -529,6 +550,8 @@
} else if (catLower === 'notregistered') { } else if (catLower === 'notregistered') {
displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno']; displayColumns = ['enrollment_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno'];
// if (empType === 'Park') displayColumns.push('park_name'); // if (empType === 'Park') displayColumns.push('park_name');
} else if (catLower === 'supervisor') {
displayColumns = ['supervisor_id', 'name', 'designation', 'department', 'incharge_name', 'incharge_phoneno'];
} else { } else {
displayColumns = Object.keys(data[0]); displayColumns = Object.keys(data[0]);
} }
@ -566,7 +589,8 @@
appversion: 'App Version', appversion: 'App Version',
apptype: 'App Type', apptype: 'App Type',
location: 'Location', location: 'Location',
image: 'Image'
image: 'Image',
supervisor_id: 'Supervisor ID',
}; };
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());
@ -640,8 +664,10 @@
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');
// For Park: show park-wise summary; For NULM: show employee details directly
if (empType === 'Park') {
// Supervisor: show employee details directly (no park-wise drill-down)
if (category === 'supervisor') {
loadDetailed(empType, category, zone);
} else if (empType === 'Park') {
loadParkWiseSummary(zone, category); loadParkWiseSummary(zone, category);
} }
// NULM branch commented out // NULM branch commented out
@ -664,9 +690,9 @@
if (parkEmployeeAnchor) { if (parkEmployeeAnchor) {
ev.preventDefault(); ev.preventDefault();
const zone = parkEmployeeAnchor.getAttribute('data-zone'); const zone = parkEmployeeAnchor.getAttribute('data-zone');
const park = parkEmployeeAnchor.getAttribute('data-park');
const parkId = parkEmployeeAnchor.getAttribute('data-parkid');
const category = parkEmployeeAnchor.getAttribute('data-category'); const category = parkEmployeeAnchor.getAttribute('data-category');
loadDetailed('Park', category, zone, park);
loadDetailed('Park', category, zone, parkId);
return; return;
} }
}); });

Loading…
Cancel
Save