Browse Source

Implemented datewise splitup of bookings

master
AJITHKUMAR12 9 months ago
parent
commit
a3cbb2daca
  1. 13
      src/main/java/com/gcc/commissionerreview/controller/VphApiController.java
  2. 47
      src/main/java/com/gcc/commissionerreview/service/VphService.java
  3. 287
      src/main/resources/templates/modules/vphreport.html

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

@ -1,5 +1,7 @@
package com.gcc.commissionerreview.controller;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
@ -42,4 +44,15 @@ public class VphApiController {
return vphservice.getHallBookings(fromDate, toDate);
}
@GetMapping("/visitor-details-by-date")
public List<Map<String, Object>> getVisitorDetailsByDate(
@RequestParam String visitDate) {
// visitDate comes as dd-MM-yyyy
DateTimeFormatter uiFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate localDate = LocalDate.parse(visitDate, uiFormatter);
return vphservice.getVisitorDetailsByDate(localDate);
}
}

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

@ -1,5 +1,6 @@
package com.gcc.commissionerreview.service;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -159,4 +160,50 @@ public class VphService {
return jdbcTemplate.queryForObject(sql, Integer.class);
}
// query for modal
public List<Map<String, Object>> getVisitorDetailsByDate(LocalDate visitDate) {
String sql = """
SELECT
rd.ref_id,
rd.mob_no,
rd.email,
DATE(rd.visit_date) AS visitDate,
rd.no_of_people,
rd.total_amount AS amountPaid,
rd.id_details AS IdCardNumber,
tm.timing AS time,
tsm.timing AS slot,
tm.time_id,
tsm.language
FROM reg_details rd
LEFT JOIN time_master tm
ON rd.time_id = tm.time_id
LEFT JOIN avslot_reg_det ard
ON rd.ref_id = ard.ref_id
LEFT JOIN time_slot_master tsm
ON ard.slot_id = tsm.slot_id
LEFT JOIN visitor_count_details vcd
ON rd.ref_id = vcd.ref_id
WHERE DATE(rd.visit_date) = ?
AND rd.booking_flag = 'B'
GROUP BY
rd.ref_id,
rd.mob_no,
rd.email,
DATE(rd.visit_date),
rd.no_of_people,
rd.total_amount,
rd.id_details,
tm.timing,
tm.time_id,
tsm.timing,
tsm.language
ORDER BY tm.time_id ASC,
tsm.timing ASC
""";
return jdbcTemplate.queryForList(sql, visitDate);
}
}

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

@ -23,8 +23,25 @@
color: #ffffff !important;
border-color: #002244;
}
/* Wrap long email text */
.email-wrap {
max-width: 170px;
white-space: nowrap;
word-break: break-word;
line-height: 1.3;
}
/* Keep date/time compact */
.nowrap {
white-space: nowrap;
}
</style>
<body>
<div class="container-fluid mt-4">
<div class="card">
@ -52,13 +69,13 @@
</div>
<!-- RIGHT : DATE FILTERS -->
<div class="col-md-3">
<!-- <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>-->
</div>
<!--category wise visitor count-->
@ -66,7 +83,7 @@
<div class="col">
<div class="card text-center shadow-sm ">
<div class="card-body">
<h6><b>Total Visitors</b></h6>
<h6><b>Total Visitors Booked</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>
@ -80,7 +97,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Senior Citizen</h6>
<h6><b>Senior Citizen</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Senior Citizen [above 60+]']}">0</b>
@ -96,7 +113,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Adult</h6>
<h6><b>Adult</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Adult ']}">0</b>
</p>
@ -110,7 +127,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Children</h6>
<h6><b>Children</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Children [ below 10 year]']}">0</b>
@ -128,7 +145,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Students</h6>
<h6><b>Students</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Students']}">0</b>
</p>
@ -142,7 +159,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Foreigner</h6>
<h6><b>Foreigner</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3" th:text="${categoryTotals['Foreigner']}">0</b>
</p>
@ -156,7 +173,7 @@
<div class="col">
<div class="card text-center shadow-sm">
<div class="card-body">
<h6>Physically Challenged</h6>
<h6><b>Physically Challenged</b></h6>
<p class="mb-1">Registered count :
<b class="text-twitter fw-700 mt-3"
th:text="${categoryTotals['Physically challeged']}">0</b>
@ -171,15 +188,27 @@
<div class="col">
<!--<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 class="card text-center shadow-sm">
<div class="card-body">
<h6><b>Hall Bookings</b></h6>
<p class="mb-1">Registered count :
<b class="fw-700">1</b>
</p>
<p class="mb-0">&nbsp;</p>
</div>
</div>
</div>
@ -266,7 +295,19 @@
<!-- ================= TABLE 1 ================= -->
<h5>Visitor Booking Details – Category Wise</h5>
<!--<h5>Visitor Booking Details – Category Wise</h5>-->
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="mb-0">Visitor Booking Details – Category Wise</h5>
<span class="text-danger fw-semibold">
<span class="text-danger">*</span> Note:Visitor bookings are not available on Tuesdays.
</span>
<div class="d-flex 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-sm btn-primary" onclick="loadVictoriaMIS()">Load</button>
</div>
</div>
<div id="t1Export"></div>
<table class="table table-bordered" id="visitorTable">
@ -282,6 +323,7 @@
<th>Total</th>
</tr>
</thead>
<tbody></tbody>
</table>
@ -318,6 +360,46 @@
</div>
</div>
</div>
<!-- VISITOR DETAILS MODAL -->
<div class="modal fade" id="visitorModal" tabindex="-1">
<div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
Visitor Details - <span id="modalVisitDate"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="visitorModalExport" class="mb-2"></div>
<table class="table table-bordered" id="visitorDetailTable">
<thead class="table-primary">
<tr>
<th>Ref ID</th>
<th>Mobile</th>
<th>Email</th>
<th>Visit Date</th>
<th>No. of People</th>
<th>Amount Paid</th>
<th>ID Card</th>
<th>Time</th>
<th>Slot</th>
<th>Language</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</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>
@ -373,7 +455,7 @@
}
/* ================= TABLE 1 ================= */
function loadVisitorCategory(fromDate, toDate) {
/*function loadVisitorCategory(fromDate, toDate) {
if ($.fn.DataTable.isDataTable('#visitorTable')) {
$('#visitorTable').DataTable().clear().destroy();
@ -420,8 +502,189 @@
}).buttons().container().appendTo('#t1Export');
}
});
}*/
function formatDate(dateStr) {
if (!dateStr) return '-';
const [y, m, d] = dateStr.split('-');
return `${d}-${m}-${y}`;
}
//modal for visitor details
function openVisitorModal(visitDate) {
console.log(visitDate);
$("#modalVisitDate").text(visitDate);
$("#visitorModal").modal("show");
if ($.fn.DataTable.isDataTable('#visitorDetailTable')) {
$('#visitorDetailTable').DataTable().clear().destroy();
$("#visitorModalExport").empty();
}
$("#visitorDetailTable tbody").empty();
$.ajax({
url: "/commissionerreview/api/visitor-details-by-date",
method: "GET",
data: { visitDate: visitDate },
success: function (data) {
$.each(data, function (i, r) {
const emailVal = r.email ? r.email : '-';
const mobileVal = r.mob_no ? r.mob_no : '-';
$("#visitorDetailTable tbody").append(`
<tr>
<td>${r.ref_id}</td>
<td>${mobileVal}</td>
<!-- <td>${r.email}</td>-->
<td>
<span class="email-single-line" title="${emailVal}">
${emailVal}
</span>
</td>
<td class="nowrap">${formatDate(r.visitDate)}</td>
<td>${r.no_of_people}</td>
<td>${r.amountPaid}</td>
<td>${r.IdCardNumber}</td>
<td class="nowrap">${r.time}</td>
<td class="nowrap">${r.slot}</td>
<td>${r.language}</td>
</tr>
`);
});
$('#visitorDetailTable').DataTable({
paging: true,
pageLength: 10,
lengthMenu: [10, 25, 50, 100],
searching: true,
ordering: true,
dom: 'Bfrtip',
info: false,
buttons: [
{ extend: 'excelHtml5', text: 'Download Excel' }
/*{
extend: 'pdfHtml5',
text: 'Download PDF',
orientation: 'landscape', // ✅ MUST
pageSize: 'A4',
exportOptions: {
columns: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // ✅ INCLUDE Time, Slot, Language
},
customize: function (doc) {
// Font sizes
doc.defaultStyle.fontSize = 8;
doc.styles.tableHeader.fontSize = 9;
// Margins
doc.pageMargins = [20, 20, 20, 20];
// Force equal column widths
const table = doc.content[1].table;
table.widths = Array(table.body[0].length).fill('*');
}
}*/
]
}).buttons().container().appendTo('#visitorModalExport');
}
});
}
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) {
// ✅ TOTAL VARIABLES
let totalAdult = 0;
let totalChildren = 0;
let totalSenior = 0;
let totalStudents = 0;
let totalForeigner = 0;
let totalPhysical = 0;
let grandTotal = 0;
// ✅ LOOP RESPONSE
$.each(data, function (i, r) {
totalAdult += Number(r.Adult) || 0;
totalChildren += Number(r.Children) || 0;
totalSenior += Number(r.SeniorCitizen) || 0;
totalStudents += Number(r.Students) || 0;
totalForeigner += Number(r.Foreigner) || 0;
totalPhysical += Number(r.PhysicallyChallenged) || 0;
grandTotal += Number(r.TotalCount) || 0;
$("#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>-->
<td>
<a href="javascript:void(0)"
class="fw-bold text-primary"
onclick="openVisitorModal('${r.visitDate}')">
${r.TotalCount}
</a>
</td>
</tr>
`);
});
// ✅ APPEND GRAND TOTAL ROW
$("#visitorTable tbody").append(`
<tr class="table-primary">
<td>Grand Total</td>
<td>${totalAdult}</td>
<td>${totalChildren}</td>
<td>${totalSenior}</td>
<td>${totalStudents}</td>
<td>${totalForeigner}</td>
<td>${totalPhysical}</td>
<td>${grandTotal}</td>
</tr>
`);
// ✅ INITIALIZE DATATABLE
$('#visitorTable').DataTable({
paging: true,
pageLength: 10,
lengthMenu: [10, 25, 50, 100],
searching: true,
ordering: true,
dom: 'Bfrtip',
buttons: [
{ extend: 'excelHtml5', footer: true, text: 'Download Excel' },
{ extend: 'pdfHtml5', footer: true, text: 'Download PDF' }
]
}).buttons().container().appendTo('#t1Export');
}
});
}
/* ================= TABLE 2 ================= */
function loadTotalVisitors(fromDate, toDate) {

Loading…
Cancel
Save