You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

928 lines
28 KiB

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/modules/base/head :: head}">
<style>
</style>
</head>
<body>
<div class="wrapper">
<!-- header top menu Start -->
<header th:replace="~{fragments/modules/base/header :: header}"></header>
<!-- header top menu end -->
<div class="page-wrap">
<!--=============== Left Menu side Start ================-->
<div th:replace="~{fragments/modules/base/menu :: menu}"></div>
<!--=============== Left side End ================-->
<div class="main-content">
<div class="container-fluid">
<div class="page-header mb-2">
<div class="row align-items-end">
<div class="col-lg-8">
<div class="page-header-title">
<!-- <i class="far fa-calendar-plus bg-blue"></i> -->
<div class="d-inline">
<h5>Reports</h5>
<span>Reports for training sessions </span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-4 col-sm-12">
<label class="form-label" for="selectReports">Select Reports</label>
<select class="form-control" id="selectReports" required>
<option value="">-- Select Report --</option>
</select>
</div>
<div class="col-md-4 col-sm-12" id="attendanceDropdown" style="display:none;">
<label class="form-label">Select Constituency</label>
<select class="form-control" id="attendanceConstituency">
<option value="">-- Select Constituency --</option>
</select>
</div>
<div class="col-md-4 col-sm-12" id="departmentDropdown" style="display:none;">
<label class="form-label">Select Constituency</label>
<select class="form-control" id="departmentConstituency">
<option value="">-- Select Constituency --</option>
</select>
</div>
<!--ak-->
<div class="col-md-4 col-sm-12" id="attendancenoticeDropdown"
style="display:none;">
<label class="form-label">Select Training</label>
<select class="form-control" id="attendancenoticeConstituency">
<option value="">-- Select Training --</option>
</select>
</div>
<div class="col-md-4 col-sm-12" id="batchDropdown" style="display:none;">
<label class="form-label">Select Batch</label>
<select class="form-control" id="batchSelect">
<option value="">-- Select Batch --</option>
</select>
</div>
</div>
<div class="row mt-3">
<div class="col-12 d-flex justify-content-center">
<!-- Replaced Search button with Print button -->
<button type="button" id="printBtn" class="btn btn-primary mx-2">
Print
</button>
<button class="btn btn-danger mx-2" id="resetBtn" name="reset">
Reset
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="pageLoader"
style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.8); z-index: 9999; text-align: center;">
<div style="position: relative; top: 50%; transform: translateY(-50%);">
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
<span class="sr-only">Loading...</span>
</div>
<!-- Add the 'Please wait' text below the spinner -->
<p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
</div>
</div>
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
</div>
</div>
<script th:replace="~{fragments/modules/base/script :: script}"></script>
<script>
$(document).ready(function () {
let selected = $(this).val().toLowerCase();
$.ajax({
url: "/election/api/dataentryadmin/report/dropdown/dropdownlist",
method: "GET",
success: function (data) {
let dropdown = $("#selectReports");
dropdown.empty();
dropdown.append('<option value="">-- Select Report --</option>');
data.forEach(function (row) {
// convert name -> key
let valueKey = row.dropdown_name
.toLowerCase()
.replace(/\s+/g, "") // remove spaces
dropdown.append(
`<option value="${valueKey}">
${row.dropdown_name}
</option>`
);
});
}
});
});
$("#selectReports").on("change", function () {
let selected = $(this).val();
// Hide both by default
$("#attendanceDropdown").hide();
$("#departmentDropdown").hide();
//ak
$("#attendancenoticeDropdown").hide();
$("#batchDropdown").hide();
// Reset dropdowns
$("#attendanceConstituency")
.empty()
.append('<option value="">-- Select Constituency --</option>');
$("#departmentConstituency")
.empty()
.append('<option value="">-- Select Constituency --</option>');
//ak
$("#attendancenoticeConstituency")
.empty()
.append('<option value="">-- Select Training --</option>');
$('#batchSelect').empty().append('<option value="">-- Select Batch --</option>');
/* ================= ATTENDANCE ================= */
if (
(selected.includes("order") && !selected.includes("mobfinalordercopy")) ||
selected.includes("voucher") ||
//selected.includes("attendance") ||
selected.includes("scnotice") ||
selected.includes("form12") ||
selected.includes("microobserverfirstorder") ||
selected.includes("microobserverscnotice") ||
selected.includes("pollpersonexcess") ||
selected.includes("form12") ||
selected.includes("countingfirstorder") ||
selected.includes("countingfinalattendance") ||
selected.includes("countingvoucher")
) {
$("#attendanceDropdown").show();
$.ajax({
url: "/election/api/dataentryadmin/report/Attendance/constituencies",
method: "GET",
success: function (data) {
let dropdown = $("#attendanceConstituency");
dropdown.empty();
dropdown.append('<option value="">-- Select Constituency --</option>');
data.forEach(function (row) {
dropdown.append(
`<option value="${row.ac_no}">${row.Constituency_Name}</option>`
);
});
},
error: function () {
alert("Failed to load attendance constituencies");
}
});
}
else if (selected === "microobservernoticesheet" || selected === "microobserverattendance") {
$("#batchDropdown").show();
$.ajax({
url: "/election/api/dataentryadmin/report/NoticeSheet/batch-list",
method: "GET",
success: function (data) {
let dropdown = $("#batchSelect");
dropdown.empty();
dropdown.append('<option value="">-- Select Batch --</option>');
data.forEach(function (batch) {
dropdown.append(
`<option value="${batch}">${batch}</option>`
);
});
},
error: function () {
alert("Failed to load batch list");
}
});
}
/* ================= Attendance and Notice ================= */
else if (
//selected.includes("attendance") ||
(selected.includes("attendance") &&
selected !== "countingattendance" && selected !== "countingfinalattendance") ||
selected.includes("noticesheetfirst") ||
selected.includes("noticesheetsecond") ||
selected.includes("noticesheetthird") ||
selected.includes("tnale") ||
selected.includes("zonalparty") ||
selected.includes("secondtrainingattendancecopy") ||
selected.includes("noticesecondrepeat") ||
selected.includes("mobattendance") ||
selected.includes("mobfinalordercopy")
) {
$("#attendancenoticeDropdown").show();
$.ajax({
url: "/election/api/dataentryadmin/report/Attendance/trainingconstituencies",
method: "GET",
success: function (data) {
let dropdown = $("#attendancenoticeConstituency");
dropdown.empty();
dropdown.append('<option value="">-- Select Training --</option>');
data.forEach(function (row) {
dropdown.append(
`<option value="${row.c_code}">${row.display_name}</option>`
);
});
},
error: function () {
alert("Failed to load training constituencies");
}
});
}
/* ================= DEPARTMENT ================= */
else if (selected.includes("department") || selected.includes("microobserverdepartment")) {
$("#departmentDropdown").show();
$.ajax({
url: "/election/api/dataentryadmin/report/Department/constituencies",
method: "GET",
success: function (data) {
let dropdown = $("#departmentConstituency");
dropdown.empty();
dropdown.append('<option value="">-- Select Constituency --</option>');
data.forEach(function (row) {
dropdown.append(
`<option value="${row.ac_no}">${row.Constituency_Name}</option>`
);
});
},
error: function () {
alert("Failed to load department constituencies");
}
});
}
});
$("#resetBtn").on("click", function () {
//console.log("resetBtn clicked");
$('#pageLoader').hide();
$("#selectReports").val("");
$("#attendanceDropdown").hide();
$("#departmentDropdown").hide();
$("#batchDropdown").hide();
$("#batchSelect").empty().append('<option value="">-- Select Batch --</option>');
$("#attendanceConstituency").empty().append('<option value="">-- Select Constituency --</option>');
$("#departmentConstituency").empty().append('<option value="">-- Select Constituency --</option>');
$("#attendancenoticeDropdown").hide();
$("#attendancenoticeConstituency").empty().append('<option value="">-- Select Training --</option>');
});
$("#printBtn").on("click", function () {
$('#pageLoader').show();
let selected = $("#selectReports").val();
if (!selected) {
Swal.fire("Warning", "Please select a report before printing.", "warning");
$('#pageLoader').hide();
return;
}
let apiURL = "";
if (selected === "firstorder") {
console.log("firstorder")
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/FirstOrder/first-order?workAcNo=" + workAcNo;
}
else if (selected === "scnoticefirst") {
//console.log("secondorder")
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/SCNotice/sc-notice?workAcNo=" + workAcNo;
}
else if (selected === "scnoticesecond") {
let workAcNo = $("#attendanceConstituency").val();
//console.log("scnotice")
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/SCNoticesecond/sc-notice-second" + "?workAcNo=" + workAcNo;
}
else if (selected === "secondorder") {
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
// ✅ Use async generate → poll → download flow (avoids blob buffering)
startAsyncReportGeneration(
"/election/api/dataentryadmin/report/SecondOrder/second-order",
workAcNo
);
return; // Don't fall through to the blob AJAX below
}
else if (selected === "secondorderack") {
//console.log("secondorderack");
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/SecondOrderAck/second-order-ack?workAcNo=" + workAcNo;
}
//ak
else if (selected === "noticesheetfirst") {
//console.log("noticesheet")
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
console.log("Ccode", Ccode)
apiURL = "/election/api/dataentryadmin/report/NoticeSheet/notice-sheet?Ccode=" + Ccode;
}
else if (selected === "noticesheetsecond") {
//console.log("noticesheetsecond")
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("Ccode", Ccode)
apiURL = "/election/api/dataentryadmin/report/NoticeSheetSecond/notice-sheet-second?Ccode=" + Ccode;
}
else if (selected === "noticesheetsecondrepeat") {
//console.log("noticesheetsecond")
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("Ccode", Ccode)
apiURL = "/election/api/dataentryadmin/report/NoticeSheetSecond/notice-sheet-second-repeat?Ccode=" + Ccode;
}
//ak
else if (selected === "attendancefirstday") {
let Ccode = $("#attendancenoticeConstituency").val();
console.log("attendancefirstday", Ccode)
if (!Ccode) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/Attendance/attendance-order?Ccode=" + Ccode;
}
else if (selected === "attendancesecondday") {
//let acNo = $("#attendanceConstituency").val();
let ccode = $("#attendancenoticeConstituency").val();
if (!ccode) {
Swal.fire("Warning", "Please select Training Center", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day?Ccode=" + ccode;
}
else if (selected === "attendanceseconddayrepeat") {
let ccode = $("#attendancenoticeConstituency").val();
if (!ccode) {
Swal.fire("Warning", "Please select Training Center", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day-repeat?Ccode=" + ccode;
}
else if (selected === "departmentsummary") {
let acNo = $("#departmentConstituency").val();
if (!acNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/Department/department-summary?acNo=" + acNo;
}
else if (selected === "countingdepartmentsummary") {
let acNo = $("#departmentConstituency").val();
if (!acNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/Department/counting-department-summary?acNo=" + acNo;
}
else if (selected === "countingfinaldepartmentsummary") {
let acNo = $("#departmentConstituency").val();
if (!acNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/Department/counting-final-department-summary?acNo=" + acNo;
}
else if (selected === "countingattendance") {
apiURL = "/election/api/dataentryadmin/report/Attendance/counting-attendance";
}
else if (selected === "countingfinalattendance") {
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
// Cookie-based download detection
let token = new Date().getTime().toString();
window.location.href = "/election/api/dataentryadmin/report/Attendance/counting-final-attendance?workAcNo=" + workAcNo + "&downloadToken=" + token;
// Poll for the cookie the server sets after PDF is written
let downloadCheck = setInterval(function () {
if (document.cookie.indexOf("downloadToken=" + token) !== -1) {
clearInterval(downloadCheck);
// Clear the cookie
document.cookie = "downloadToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
$('#pageLoader').hide();
}
}, 500);
// Failsafe: hide loader after 5 minutes max
setTimeout(function () {
clearInterval(downloadCheck);
$('#pageLoader').hide();
}, 300000);
return;
}
else if (selected === "thirdorder") {
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
// ✅ Use async generate → poll → download flow (avoids blob buffering)
startAsyncReportGeneration(
"/election/api/dataentryadmin/report/ThirdOrder/third-order",
workAcNo
);
return;
}
else if (selected === "attendancethirdday") {
console.log("attendancethirdday");
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select Training", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ThirdAttendance/attendance-third-day?Ccode=" + Ccode;
}
else if (selected === "noticesheetthird") {
console.log("noticesheetthird")
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select Training", "warning");
$('#pageLoader').hide();
return;
}
console.log("Ccode", Ccode)
apiURL = "/election/api/dataentryadmin/report/ThirdNoticeSheet/third-notice-sheet?Ccode=" + Ccode;
}
else if (selected === "tnale") {
console.log("tnale");
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select Training", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ThirdTNALE/third-TNLAE?Ccode=" + Ccode;
}
else if (selected === "zonalparty") {
console.log("zonalparty");
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select Training", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ZonalParty/zonal_party-details?Ccode=" + Ccode;
}
else if (selected === "voucher" || selected === "voucherthird") {
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) { // ✅ FIXED
Swal.fire("Warning", "Please select Constituency Center", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ThirdVoucher/voucher-third?workAcNo=" + workAcNo;
}
else if (selected === "form12report") {
//console.log("form12report")
let AcNo = $("#attendanceConstituency").val();
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/Form12/form12?AcNo=" + AcNo;
}
else if (selected === "microobserverfirstorder") {
//console.log("microobserver")
let AcNo = $("#attendanceConstituency").val();
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/FirstOrder/micro-observer?workAcNo=" + AcNo;
}
else if (selected === "microobserverdepartment") {
//console.log("microobserver")
let AcNo = $("#departmentConstituency").val();
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/Department/micro-observer?acNo=" + AcNo;
}
else if (selected === "microobserverattendance") {
//console.log("microobserver")
let batch = $("#batchSelect").val();
if (!batch) {
Swal.fire("Warning", "Please select batch", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/Attendance/micro-observer?batch=" + batch;
}
else if (selected === "microobservernoticesheet") {
//console.log("microobservernoticesheet")
let batch = $("#batchSelect").val();
if (!batch) {
Swal.fire("Warning", "Please select batch", "warning");
$('#pageLoader').hide();
return;
}
//console.log("batch", batch)
apiURL = "/election/api/dataentryadmin/report/NoticeSheet/micro-observer-notice-sheet?batch=" + batch;
}
else if (selected === "secondtrainingattendancecopy") {
//let acNo = $("#attendanceConstituency").val();
let ccode = $("#attendancenoticeConstituency").val();
if (!ccode) {
Swal.fire("Warning", "Please select Training Center", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day-copy?Ccode=" + ccode;
}
else if (selected === "microobserverscnotice") {
//console.log("secondorder")
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/SCNotice/micro-observer-notice?workAcNo=" + workAcNo;
}
else if (selected === "pollpersonexcess") {
console.log("Poll person excess")
let workAcNo = $("#attendanceConstituency").val();
if (!workAcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/FirstOrder/PollPersonExcess?workAcNo=" + workAcNo;
}
else if (selected === "form12excess") {
//console.log("form12report")
let AcNo = $("#attendanceConstituency").val();
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/Form12/form12excess?AcNo=" + AcNo;
}
else if (selected === "mobfinalordercopy") {
//console.log("microobserver")
//let AcNo = $("#attendanceConstituency").val();
let ccode = $("#attendancenoticeConstituency").val();
if (!ccode) {
Swal.fire("Warning", "Please select Training Center", "warning");
$('#pageLoader').hide();
return;
}
//console.log("workAcNo", workAcNo)
apiURL = "/election/api/dataentryadmin/report/FirstOrder/mobfinalordercopy?ccode=" + ccode;
}
//countingfirstorder
else if (selected === "countingfirstorder") {
//console.log("countingfirstorder")
let AcNo = $("#attendanceConstituency").val();
//console.log("AcNo="+AcNo );
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/FirstOrder/countingfirstorder?workAcNo=" + AcNo;
}
else if (selected === "countingfinalorder") {
//console.log("countingfirstorder")
let AcNo = $("#attendanceConstituency").val();
//console.log("AcNo="+AcNo );
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/FirstOrder/countingfinalorder?workAcNo=" + AcNo;
}
else if (selected === "countingvoucher") {
//console.log("countingfirstorder")
let AcNo = $("#attendanceConstituency").val();
//console.log("AcNo="+AcNo );
if (!AcNo) {
Swal.fire("Warning", "Please select constituency", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ThirdVoucher/counting-voucher?AcNo=" + AcNo;
}
else if (selected === "mobattendance") {
console.log("microobserverattendance");
let Ccode = $("#attendancenoticeConstituency").val();
if (!Ccode) {
Swal.fire("Warning", "Please select Training", "warning");
$('#pageLoader').hide();
return;
}
apiURL = "/election/api/dataentryadmin/report/ThirdAttendance/mob-attendance?Ccode=" + Ccode;
}
else {
Swal.fire("Info", "Report option not implemented yet.", "info");
return;
}
$.ajax({
url: apiURL,
method: "GET",
timeout: 300000, // 5 minutes — prevents premature abort for large reports
xhrFields: {
responseType: "blob"
},
success: function (data, status, xhr) {
$('#pageLoader').hide();
const blob = new Blob([data], { type: "application/pdf" });
// 🔹 Get filename from response header
let disposition = xhr.getResponseHeader("Content-Disposition");
let filename = "report.pdf";
if (disposition && disposition.indexOf("filename=") !== -1) {
filename = disposition.split("filename=")[1].replace(/"/g, "");
}
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
},
error: function (xhr) {
if (xhr.status === 404) {
$('#pageLoader').hide();
Swal.fire(
"No Data Found",
"NO Polling persons data available for the selected constituency.",
"info"
);
} else {
$('#pageLoader').hide();
Swal.fire(
"Error",
"Failed to generate PDF. Please check server logs.",
"error"
);
}
}
});
});
// ============================================================
// ✅ ASYNC REPORT GENERATION (for Second Order only)
// Generates PDF on server → polls status → triggers direct download
// This avoids blob buffering and eliminates the 6+ minute frontend wait.
// ============================================================
function startAsyncReportGeneration(baseUrl, workAcNo) {
$('#pageLoader').show();
$('#pageLoader .spinner-border').next('p').text('Generating report... Please wait.');
$.ajax({
url: baseUrl + "/generate?workAcNo=" + workAcNo,
method: "GET",
success: function (data) {
if (data && data.taskId) {
pollReportStatus(baseUrl, data.taskId);
} else {
$('#pageLoader').hide();
Swal.fire("Error", "Failed to start report generation.", "error");
}
},
error: function () {
$('#pageLoader').hide();
Swal.fire("Error", "Failed to start report generation. Please try again.", "error");
}
});
}
function pollReportStatus(baseUrl, taskId) {
let pollInterval = setInterval(function () {
$.ajax({
url: baseUrl + "/status/" + taskId,
method: "GET",
success: function (data) {
if (data.status === "COMPLETED") {
clearInterval(pollInterval);
$('#pageLoader .spinner-border').next('p').text('Downloading...');
// Direct file download — no blob buffering!
window.location.href = data.downloadUrl;
// Hide loader after a short delay (download starts in background)
setTimeout(function () {
$('#pageLoader').hide();
$('#pageLoader .spinner-border').next('p').text('Please wait...');
}, 3000);
} else if (data.status === "FAILED") {
clearInterval(pollInterval);
$('#pageLoader').hide();
Swal.fire("Error", "Report generation failed: " + (data.error || "Unknown error"), "error");
}
// If IN_PROGRESS, keep polling
},
error: function () {
clearInterval(pollInterval);
$('#pageLoader').hide();
Swal.fire("Error", "Lost connection while waiting for report. Please try again.", "error");
}
});
}, 3000); // Poll every 3 seconds
}
</script>
</body>
</html>