Browse Source

implemented dashboard for vph and added script for downloading scripts for total

master
AJITHKUMAR12 9 months ago
parent
commit
545a63caae
  1. 22
      src/main/java/com/gcc/commissionerreview/controller/MainController.java
  2. 45
      src/main/java/com/gcc/commissionerreview/controller/VphApiController.java
  3. 162
      src/main/java/com/gcc/commissionerreview/service/VphService.java
  4. 4
      src/main/resources/templates/modules/pet/petreport.html
  5. 509
      src/main/resources/templates/modules/vphreport.html

22
src/main/java/com/gcc/commissionerreview/controller/MainController.java

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -17,6 +18,7 @@ import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.gcc.commissionerreview.service.VphService;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
@ -26,6 +28,8 @@ import jakarta.servlet.http.HttpSession;
public class MainController { public class MainController {
private static final String LOGIN_URL = "http://3.26.245.178:3000/login"; private static final String LOGIN_URL = "http://3.26.245.178:3000/login";
@Autowired
private VphService vphservice;
@GetMapping("/uphcreport") @GetMapping("/uphcreport")
public String uphcreport(Model model) { public String uphcreport(Model model) {
@ -205,4 +209,22 @@ public class MainController {
return "modules/pet/petreport"; return "modules/pet/petreport";
} }
@GetMapping("/vphreport")
public String vphreport(Model model) {
Map<String, Integer> categoryTotals = vphservice.getCategoryTotalsTillToday();
int hallBookingCount = vphservice.getHallBookingCountTillToday();
Map<String, Integer> visitorTotals = vphservice.getVisitorTotalsTillToday();
int visitorBookingCount = vphservice.getVisitorBookingCountTillToday();
model.addAttribute("categoryTotals", categoryTotals);
model.addAttribute("hallBookingCount", hallBookingCount);
model.addAttribute("visitorTotals", visitorTotals);
model.addAttribute("visitorBookingCount", visitorBookingCount);
return "modules/vphreport";
}
} }

45
src/main/java/com/gcc/commissionerreview/controller/VphApiController.java

@ -0,0 +1,45 @@
package com.gcc.commissionerreview.controller;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.gcc.commissionerreview.service.VphService;
@RestController
@RequestMapping("/commissionerreview/api")
public class VphApiController {
@Autowired
private VphService vphservice;
// ak
@GetMapping("/visitor-category")
public List<Map<String, Object>> visitorCategory(
@RequestParam String fromDate,
@RequestParam String toDate) {
return vphservice.getVisitorCategory(fromDate, toDate);
}
@GetMapping("/total-visitors")
public List<Map<String, Object>> totalVisitors(
@RequestParam String fromDate,
@RequestParam String toDate) {
return vphservice.getTotalVisitors(fromDate, toDate);
}
@GetMapping("/hall-bookings")
public List<Map<String, Object>> hallBookings(
@RequestParam String fromDate,
@RequestParam String toDate) {
return vphservice.getHallBookings(fromDate, toDate);
}
}

162
src/main/java/com/gcc/commissionerreview/service/VphService.java

@ -0,0 +1,162 @@
package com.gcc.commissionerreview.service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.imageio.ImageIO;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
@Service
public class VphService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
public void setFeedbackDataSource(@Qualifier("mysqlVphDataSource") DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<Map<String, Object>> getVisitorCategory(String fromDate, String toDate) {
String sql = """
SELECT DATE_FORMAT(rd.visit_date,'%d-%m-%Y') AS visitDate,
COALESCE(SUM(CASE WHEN vac.user_type='Adult ' THEN vcd.no_of_people END),0) Adult,
COALESCE(SUM(CASE WHEN vac.user_type='Children [ below 10 year]' THEN vcd.no_of_people END),0) Children,
COALESCE(SUM(CASE WHEN vac.user_type='Senior Citizen [above 60+]' THEN vcd.no_of_people END),0) SeniorCitizen,
COALESCE(SUM(CASE WHEN vac.user_type='Students' THEN vcd.no_of_people END),0) Students,
COALESCE(SUM(CASE WHEN vac.user_type='Foreigner' THEN vcd.no_of_people END),0) Foreigner,
COALESCE(SUM(CASE WHEN vac.user_type='Physically challeged' THEN vcd.no_of_people END),0) PhysicallyChallenged,
COALESCE(SUM(vcd.no_of_people),0) TotalCount
FROM reg_details rd
LEFT JOIN visitor_count_details vcd ON rd.ref_id=vcd.ref_id
LEFT JOIN visit_amount_config vac ON vcd.user_type_id=vac.id
WHERE rd.booking_flag='B'
AND DATE(rd.visit_date) BETWEEN ? AND ?
GROUP BY rd.visit_date
ORDER BY rd.visit_date
""";
return jdbcTemplate.queryForList(sql, fromDate, toDate);
}
public List<Map<String, Object>> getTotalVisitors(String fromDate, String toDate) {
String sql = """
SELECT DATE_FORMAT(visit_date,'%d-%m-%Y') visitDate,
SUM(no_of_people) RegisteredCount
FROM reg_details
WHERE booking_flag='B'
AND DATE(visit_date) BETWEEN ? AND ?
GROUP BY visit_date
ORDER BY visit_date
""";
return jdbcTemplate.queryForList(sql, fromDate, toDate);
}
public List<Map<String, Object>> getHallBookings(String fromDate, String toDate) {
String sql = """
SELECT hd.hall_name,
us.name userName,
DATE_FORMAT(bd.booking_date,'%d-%m-%Y') bookingDate,
DATE_FORMAT(bd.end_date,'%d-%m-%Y') eventDate
FROM booking_details bd
LEFT JOIN hall_details hd ON bd.hall_details_hall_id=hd.hall_id
LEFT JOIN users us ON bd.users_user_id=us.user_id
WHERE bd.booking_status IN ('WAITING_FOR_NOC','APPROVED')
AND DATE(bd.booking_date) BETWEEN ? AND ?
ORDER BY bd.booking_date
""";
return jdbcTemplate.queryForList(sql, fromDate, toDate);
}
// card
public Map<String, Integer> getCategoryTotalsTillToday() {
String sql = """
SELECT
IFNULL(vac.user_type, 'TOTAL') AS userCategory,
COALESCE(SUM(rd.no_of_people), 0) AS registeredCount
FROM reg_details rd
LEFT JOIN visitor_count_details vcd ON rd.ref_id = vcd.ref_id
LEFT JOIN visit_amount_config vac ON vcd.user_type_id = vac.id
WHERE rd.booking_flag = 'B'
AND date(rd.cdate) <= CURDATE()
GROUP BY vac.user_type WITH ROLLUP
""";
Map<String, Integer> result = new HashMap<>();
jdbcTemplate.query(sql, rs -> {
result.put(
rs.getString("userCategory"),
rs.getInt("registeredCount"));
});
return result;
}
/* ================= HALL BOOKING COUNT ================= */
public int getHallBookingCountTillToday() {
String sql = """
SELECT COUNT(*)
FROM booking_details
WHERE booking_status IN ('WAITING_FOR_NOC', 'APPROVED')
AND DATE(booking_date) <= CURDATE()
""";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
// visitor
public Map<String, Integer> getVisitorTotalsTillToday() {
String sql = """
SELECT
IFNULL(vac.user_type, 'TOTAL') AS userCategory,
COALESCE(SUM(rd.accepted_people), 0) AS registeredCount
FROM reg_details rd
LEFT JOIN visitor_count_details vcd ON rd.ref_id = vcd.ref_id
LEFT JOIN visit_amount_config vac ON vcd.user_type_id = vac.id
WHERE rd.booking_flag = 'B'
AND date(rd.visit_date) <= CURDATE()
GROUP BY vac.user_type WITH ROLLUP
""";
Map<String, Integer> result = new HashMap<>();
jdbcTemplate.query(sql, rs -> {
result.put(
rs.getString("userCategory"),
rs.getInt("registeredCount"));
});
return result;
}
/* ================= HALL BOOKING COUNT ================= */
public int getVisitorBookingCountTillToday() {
String sql = """
SELECT COUNT(*)
FROM booking_details
WHERE booking_status IN ('WAITING_FOR_NOC', 'APPROVED')
AND DATE(booking_date) <= CURDATE()
""";
return jdbcTemplate.queryForObject(sql, Integer.class);
}
}

4
src/main/resources/templates/modules/pet/petreport.html

@ -1073,12 +1073,14 @@
{ {
extend: 'excelHtml5', extend: 'excelHtml5',
title: 'Pet_License_MIS_Report', title: 'Pet_License_MIS_Report',
text: 'Download Excel'
text: 'Download Excel',
footer: true
}, },
{ {
extend: 'pdfHtml5', extend: 'pdfHtml5',
title: 'Pet_License_MIS_Report', title: 'Pet_License_MIS_Report',
text: 'Download PDF', text: 'Download PDF',
footer: true,
pageSize: 'A4' pageSize: 'A4'
} }

509
src/main/resources/templates/modules/vphreport.html

@ -0,0 +1,509 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Victoria MIS Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/buttons/2.3.6/css/buttons.dataTables.min.css" rel="stylesheet">
</head>
<style>
/* Override Bootstrap table-primary */
.table-primary {
background-color: #003366 !important;
color: #ffffff;
/* text color */
}
.table-primary th {
background-color: #003366 !important;
color: #ffffff !important;
border-color: #002244;
}
</style>
<body>
<div class="container-fluid mt-4">
<div class="card">
<div class="card-body">
<!--<h4 class="mb-3">Victoria Dashboard</h4>
<div class="row mb-3">
<div class="col-md-3"><input type="date" id="fromDate" class="form-control"></div>
<div class="col-md-3"><input type="date" id="toDate" class="form-control"></div>
<div class="col-md-2">
<button class="btn btn-primary" onclick="loadVictoriaMIS()">Load</button>
</div>
</div>-->
<!-- HEADER + DATE FILTER ROW -->
<!-- HEADER + DATE FILTER ROW -->
<div class="row align-items-center mb-3">
<!-- LEFT (empty spacer) -->
<div class="col-md-3"></div>
<!-- CENTER : TITLE -->
<div class="col-md-6 text-center">
<h4 class="mb-0 fw-bold">Victoria Public Hall</h4>
</div>
<!-- RIGHT : DATE FILTERS -->
<div class="col-md-3">
<div class="d-flex justify-content-end gap-2">
<input type="date" id="fromDate" class="form-control w-auto">
<input type="date" id="toDate" class="form-control w-auto">
<button class="btn btn-primary" onclick="loadVictoriaMIS()">Load</button>
</div>
</div>
</div>
<!--category wise visitor count-->
<div class="row row-cols-1 row-cols-md-4 row-cols-lg-8 g-3 mb-4">
<div class="col">
<div class="card text-center shadow-sm ">
<div class="card-body">
<h6><b>Total Visitors</b></h6>
<!--<h4 th:text="${categoryTotals['TOTAL']}">0</h4>-->
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['TOTAL']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3" th:text="${visitorTotals['TOTAL']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Senior Citizen</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Senior Citizen [above 60+]']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3"
th:text="${visitorTotals['Senior Citizen [above 60+]']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Adult</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Adult ']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3" th:text="${visitorTotals['Adult ']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Children</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Children [ below 10 year]']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3"
th:text="${visitorTotals['Children [ below 10 year]']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Students</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Students']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3" th:text="${visitorTotals['Students']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Foreigner</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Foreigner']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3" th:text="${visitorTotals['Foreigner']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Physically Challenged</h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Physically challeged']}">0</b>
</p>
<p class="mb-0">Visitor count :
<b class="text-twitter fw-700 mt-3"
th:text="${visitorTotals['Physically challeged']}">0</b>
</p>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6><b>Hall Bookings</b></h6>
<h4 th:text="${hallBookingCount}">0</h4>
</div>
</div>
</div>
</div>
<!--visitor wise count-->
<!-- <div class="row row-cols-1 row-cols-md-4 row-cols-lg-8 g-3 mb-4">
<div class="col">
<div class="card text-center shadow-sm ">
<div class="card-body">
<h6><b>Total Visitors</b></h6>
<h4 th:text="${visitorTotals['TOTAL']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Senior Citizen</h6>
<h4 th:text="${visitorTotals['Senior Citizen [above 60+]']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Adult</h6>
<h4 th:text="${visitorTotals['Adult ']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Children</h6>
<h4 th:text="${visitorTotals['Children [ below 10 year]']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Students</h6>
<h4 th:text="${visitorTotals['Students']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Foreigner</h6>
<h4 th:text="${visitorTotals['Foreigner']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Physically Challenged</h6>
<h4 th:text="${visitorTotals['Physically challeged']}">0</h4>
</div>
</div>
</div>
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6><b>Hall Bookings</b></h6>
<h4 th:text="${visitorBookingCount}">0</h4>
</div>
</div>
</div>
</div>-->
<!-- ================= TABLE 1 ================= -->
<h5>Visitor Booking Details – Category Wise</h5>
<div id="t1Export"></div>
<table class="table table-bordered" id="visitorTable">
<thead class="table-primary">
<tr>
<th>Date</th>
<th>Adult</th>
<th>Children</th>
<th>Senior Citizen</th>
<th>Students</th>
<th>Foreigner</th>
<th>Physically Challenged</th>
<th>Total</th>
</tr>
</thead>
<tbody></tbody>
</table>
<!-- ================= TABLE 2 ================= -->
<!--<h5 class="mt-4">Total Visitors Per Date</h5>
<div id="t2Export"></div>
<table class="table table-bordered" id="totalVisitorTable">
<thead class="table-secondary">
<tr>
<th>Date</th>
<th>Total Visitors</th>
</tr>
</thead>
<tbody></tbody>
</table>-->
<!-- ================= TABLE 3 ================= -->
<h5 class="mt-4">Hall Booking Details</h5>
<div id="t3Export"></div>
<table class="table table-bordered" id="hallTable">
<thead class="table-primary">
<tr>
<th>Hall Name</th>
<th>User Name</th>
<th>Booking Date</th>
<th>Event Date</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.6/js/buttons.print.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
<!-- SweetAlert -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).ready(function () {
// ✅ Set default date = today
const today = new Date().toISOString().split('T')[0];
$("#fromDate").val(today);
$("#toDate").val(today);
// ✅ Load data on page load
loadVictoriaMIS();
});
function loadVictoriaMIS() {
const fromDate = $("#fromDate").val();
const toDate = $("#toDate").val();
if (!fromDate || !toDate) {
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Select From & To date',
});
return;
}
if (fromDate > toDate) {
Swal.fire({
icon: 'error',
title: 'Error',
text: 'From date should be less than To date',
});
return;
}
loadVisitorCategory(fromDate, toDate);
loadTotalVisitors(fromDate, toDate);
loadHallBookings(fromDate, toDate);
}
/* ================= TABLE 1 ================= */
function loadVisitorCategory(fromDate, toDate) {
if ($.fn.DataTable.isDataTable('#visitorTable')) {
$('#visitorTable').DataTable().clear().destroy();
$("#t1Export").empty();
}
$("#visitorTable tbody").empty();
$.ajax({
url: "/commissionerreview/api/visitor-category",
method: "GET",
data: { fromDate, toDate },
success: function (data) {
$.each(data, function (i, r) {
$("#visitorTable tbody").append(`
<tr>
<td>${r.visitDate}</td>
<td>${r.Adult}</td>
<td>${r.Children}</td>
<td>${r.SeniorCitizen}</td>
<td>${r.Students}</td>
<td>${r.Foreigner}</td>
<td>${r.PhysicallyChallenged}</td>
<td><b>${r.TotalCount}</b></td>
</tr>
`);
});
$('#visitorTable').DataTable({
paging: true, // ✅ enable pagination
pageLength: 10, // default rows
lengthMenu: [10, 25, 50, 100],
searching: true,
ordering: true,
dom: 'Bfrtip',
buttons: [{
extend: 'excelHtml5',
text: 'Download Excel'
}, {
extend: 'pdfHtml5',
text: 'Download PDF'
}]
}).buttons().container().appendTo('#t1Export');
}
});
}
/* ================= TABLE 2 ================= */
function loadTotalVisitors(fromDate, toDate) {
if ($.fn.DataTable.isDataTable('#totalVisitorTable')) {
$('#totalVisitorTable').DataTable().clear().destroy();
$("#t2Export").empty();
}
$("#totalVisitorTable tbody").empty();
$.ajax({
url: "/commissionerreview/api/total-visitors",
method: "GET",
data: { fromDate, toDate },
success: function (data) {
$.each(data, function (i, r) {
$("#totalVisitorTable tbody").append(`
<tr>
<td>${r.visitDate}</td>
<td><b>${r.RegisteredCount}</b></td>
</tr>
`);
});
$('#totalVisitorTable').DataTable({
paging: false, searching: false, ordering: false,
dom: 'Bfrtip',
buttons: [{
extend: 'excelHtml5',
text: 'Download Excel'
}, {
extend: 'pdfHtml5',
text: 'Download PDF'
}]
}).buttons().container().appendTo('#t2Export');
}
});
}
/* ================= TABLE 3 ================= */
function loadHallBookings(fromDate, toDate) {
if ($.fn.DataTable.isDataTable('#hallTable')) {
$('#hallTable').DataTable().clear().destroy();
$("#t3Export").empty();
}
$("#hallTable tbody").empty();
$.ajax({
url: "/commissionerreview/api/hall-bookings",
method: "GET",
data: { fromDate, toDate },
success: function (data) {
$.each(data, function (i, r) {
$("#hallTable tbody").append(`
<tr>
<td>${r.hall_name}</td>
<td>${r.userName}</td>
<td>${r.bookingDate}</td>
<td>${r.eventDate}</td>
</tr>
`);
});
$('#hallTable').DataTable({
paging: false, searching: false, ordering: false,
dom: 'Bfrtip',
buttons: [{
extend: 'excelHtml5',
text: 'Download Excel'
}, {
extend: 'pdfHtml5',
text: 'Download PDF'
}]
}).buttons().container().appendTo('#t3Export');
}
});
}
</script>
</body>
</html>
Loading…
Cancel
Save