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.

927 lines
28 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head th:replace="~{fragments/modules/base/head :: head}">
  4. <style>
  5. </style>
  6. </head>
  7. <body>
  8. <div class="wrapper">
  9. <!-- header top menu Start -->
  10. <header th:replace="~{fragments/modules/base/header :: header}"></header>
  11. <!-- header top menu end -->
  12. <div class="page-wrap">
  13. <!--=============== Left Menu side Start ================-->
  14. <div th:replace="~{fragments/modules/base/menu :: menu}"></div>
  15. <!--=============== Left side End ================-->
  16. <div class="main-content">
  17. <div class="container-fluid">
  18. <div class="page-header mb-2">
  19. <div class="row align-items-end">
  20. <div class="col-lg-8">
  21. <div class="page-header-title">
  22. <!-- <i class="far fa-calendar-plus bg-blue"></i> -->
  23. <div class="d-inline">
  24. <h5>Reports</h5>
  25. <span>Reports for training sessions </span>
  26. </div>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. <div class="row">
  32. <div class="col-md-12">
  33. <div class="card">
  34. <div class="card-body">
  35. <div class="row">
  36. <div class="col-md-4 col-sm-12">
  37. <label class="form-label" for="selectReports">Select Reports</label>
  38. <select class="form-control" id="selectReports" required>
  39. <option value="">-- Select Report --</option>
  40. </select>
  41. </div>
  42. <div class="col-md-4 col-sm-12" id="attendanceDropdown" style="display:none;">
  43. <label class="form-label">Select Constituency</label>
  44. <select class="form-control" id="attendanceConstituency">
  45. <option value="">-- Select Constituency --</option>
  46. </select>
  47. </div>
  48. <div class="col-md-4 col-sm-12" id="departmentDropdown" style="display:none;">
  49. <label class="form-label">Select Constituency</label>
  50. <select class="form-control" id="departmentConstituency">
  51. <option value="">-- Select Constituency --</option>
  52. </select>
  53. </div>
  54. <!--ak-->
  55. <div class="col-md-4 col-sm-12" id="attendancenoticeDropdown"
  56. style="display:none;">
  57. <label class="form-label">Select Training</label>
  58. <select class="form-control" id="attendancenoticeConstituency">
  59. <option value="">-- Select Training --</option>
  60. </select>
  61. </div>
  62. <div class="col-md-4 col-sm-12" id="batchDropdown" style="display:none;">
  63. <label class="form-label">Select Batch</label>
  64. <select class="form-control" id="batchSelect">
  65. <option value="">-- Select Batch --</option>
  66. </select>
  67. </div>
  68. </div>
  69. <div class="row mt-3">
  70. <div class="col-12 d-flex justify-content-center">
  71. <!-- Replaced Search button with Print button -->
  72. <button type="button" id="printBtn" class="btn btn-primary mx-2">
  73. Print
  74. </button>
  75. <button class="btn btn-danger mx-2" id="resetBtn" name="reset">
  76. Reset
  77. </button>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. <div id="pageLoader"
  87. 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;">
  88. <div style="position: relative; top: 50%; transform: translateY(-50%);">
  89. <div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
  90. <span class="sr-only">Loading...</span>
  91. </div>
  92. <!-- Add the 'Please wait' text below the spinner -->
  93. <p style="margin-top: 1rem; font-size: 1.2rem; color: #007bff;">Please wait...</p>
  94. </div>
  95. </div>
  96. <footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
  97. </div>
  98. </div>
  99. <script th:replace="~{fragments/modules/base/script :: script}"></script>
  100. <script>
  101. $(document).ready(function () {
  102. let selected = $(this).val().toLowerCase();
  103. $.ajax({
  104. url: "/election/api/dataentryadmin/report/dropdown/dropdownlist",
  105. method: "GET",
  106. success: function (data) {
  107. let dropdown = $("#selectReports");
  108. dropdown.empty();
  109. dropdown.append('<option value="">-- Select Report --</option>');
  110. data.forEach(function (row) {
  111. // convert name -> key
  112. let valueKey = row.dropdown_name
  113. .toLowerCase()
  114. .replace(/\s+/g, "") // remove spaces
  115. dropdown.append(
  116. `<option value="${valueKey}">
  117. ${row.dropdown_name}
  118. </option>`
  119. );
  120. });
  121. }
  122. });
  123. });
  124. $("#selectReports").on("change", function () {
  125. let selected = $(this).val();
  126. // Hide both by default
  127. $("#attendanceDropdown").hide();
  128. $("#departmentDropdown").hide();
  129. //ak
  130. $("#attendancenoticeDropdown").hide();
  131. $("#batchDropdown").hide();
  132. // Reset dropdowns
  133. $("#attendanceConstituency")
  134. .empty()
  135. .append('<option value="">-- Select Constituency --</option>');
  136. $("#departmentConstituency")
  137. .empty()
  138. .append('<option value="">-- Select Constituency --</option>');
  139. //ak
  140. $("#attendancenoticeConstituency")
  141. .empty()
  142. .append('<option value="">-- Select Training --</option>');
  143. $('#batchSelect').empty().append('<option value="">-- Select Batch --</option>');
  144. /* ================= ATTENDANCE ================= */
  145. if (
  146. (selected.includes("order") && !selected.includes("mobfinalordercopy")) ||
  147. selected.includes("voucher") ||
  148. //selected.includes("attendance") ||
  149. selected.includes("scnotice") ||
  150. selected.includes("form12") ||
  151. selected.includes("microobserverfirstorder") ||
  152. selected.includes("microobserverscnotice") ||
  153. selected.includes("pollpersonexcess") ||
  154. selected.includes("form12") ||
  155. selected.includes("countingfirstorder") ||
  156. selected.includes("countingfinalattendance") ||
  157. selected.includes("countingvoucher")
  158. ) {
  159. $("#attendanceDropdown").show();
  160. $.ajax({
  161. url: "/election/api/dataentryadmin/report/Attendance/constituencies",
  162. method: "GET",
  163. success: function (data) {
  164. let dropdown = $("#attendanceConstituency");
  165. dropdown.empty();
  166. dropdown.append('<option value="">-- Select Constituency --</option>');
  167. data.forEach(function (row) {
  168. dropdown.append(
  169. `<option value="${row.ac_no}">${row.Constituency_Name}</option>`
  170. );
  171. });
  172. },
  173. error: function () {
  174. alert("Failed to load attendance constituencies");
  175. }
  176. });
  177. }
  178. else if (selected === "microobservernoticesheet" || selected === "microobserverattendance") {
  179. $("#batchDropdown").show();
  180. $.ajax({
  181. url: "/election/api/dataentryadmin/report/NoticeSheet/batch-list",
  182. method: "GET",
  183. success: function (data) {
  184. let dropdown = $("#batchSelect");
  185. dropdown.empty();
  186. dropdown.append('<option value="">-- Select Batch --</option>');
  187. data.forEach(function (batch) {
  188. dropdown.append(
  189. `<option value="${batch}">${batch}</option>`
  190. );
  191. });
  192. },
  193. error: function () {
  194. alert("Failed to load batch list");
  195. }
  196. });
  197. }
  198. /* ================= Attendance and Notice ================= */
  199. else if (
  200. //selected.includes("attendance") ||
  201. (selected.includes("attendance") &&
  202. selected !== "countingattendance" && selected !== "countingfinalattendance") ||
  203. selected.includes("noticesheetfirst") ||
  204. selected.includes("noticesheetsecond") ||
  205. selected.includes("noticesheetthird") ||
  206. selected.includes("tnale") ||
  207. selected.includes("zonalparty") ||
  208. selected.includes("secondtrainingattendancecopy") ||
  209. selected.includes("noticesecondrepeat") ||
  210. selected.includes("mobattendance") ||
  211. selected.includes("mobfinalordercopy")
  212. ) {
  213. $("#attendancenoticeDropdown").show();
  214. $.ajax({
  215. url: "/election/api/dataentryadmin/report/Attendance/trainingconstituencies",
  216. method: "GET",
  217. success: function (data) {
  218. let dropdown = $("#attendancenoticeConstituency");
  219. dropdown.empty();
  220. dropdown.append('<option value="">-- Select Training --</option>');
  221. data.forEach(function (row) {
  222. dropdown.append(
  223. `<option value="${row.c_code}">${row.display_name}</option>`
  224. );
  225. });
  226. },
  227. error: function () {
  228. alert("Failed to load training constituencies");
  229. }
  230. });
  231. }
  232. /* ================= DEPARTMENT ================= */
  233. else if (selected.includes("department") || selected.includes("microobserverdepartment")) {
  234. $("#departmentDropdown").show();
  235. $.ajax({
  236. url: "/election/api/dataentryadmin/report/Department/constituencies",
  237. method: "GET",
  238. success: function (data) {
  239. let dropdown = $("#departmentConstituency");
  240. dropdown.empty();
  241. dropdown.append('<option value="">-- Select Constituency --</option>');
  242. data.forEach(function (row) {
  243. dropdown.append(
  244. `<option value="${row.ac_no}">${row.Constituency_Name}</option>`
  245. );
  246. });
  247. },
  248. error: function () {
  249. alert("Failed to load department constituencies");
  250. }
  251. });
  252. }
  253. });
  254. $("#resetBtn").on("click", function () {
  255. //console.log("resetBtn clicked");
  256. $('#pageLoader').hide();
  257. $("#selectReports").val("");
  258. $("#attendanceDropdown").hide();
  259. $("#departmentDropdown").hide();
  260. $("#batchDropdown").hide();
  261. $("#batchSelect").empty().append('<option value="">-- Select Batch --</option>');
  262. $("#attendanceConstituency").empty().append('<option value="">-- Select Constituency --</option>');
  263. $("#departmentConstituency").empty().append('<option value="">-- Select Constituency --</option>');
  264. $("#attendancenoticeDropdown").hide();
  265. $("#attendancenoticeConstituency").empty().append('<option value="">-- Select Training --</option>');
  266. });
  267. $("#printBtn").on("click", function () {
  268. $('#pageLoader').show();
  269. let selected = $("#selectReports").val();
  270. if (!selected) {
  271. Swal.fire("Warning", "Please select a report before printing.", "warning");
  272. $('#pageLoader').hide();
  273. return;
  274. }
  275. let apiURL = "";
  276. if (selected === "firstorder") {
  277. console.log("firstorder")
  278. let workAcNo = $("#attendanceConstituency").val();
  279. if (!workAcNo) {
  280. Swal.fire("Warning", "Please select constituency", "warning");
  281. $('#pageLoader').hide();
  282. return;
  283. }
  284. console.log("workAcNo", workAcNo)
  285. apiURL = "/election/api/dataentryadmin/report/FirstOrder/first-order?workAcNo=" + workAcNo;
  286. }
  287. else if (selected === "scnoticefirst") {
  288. //console.log("secondorder")
  289. let workAcNo = $("#attendanceConstituency").val();
  290. if (!workAcNo) {
  291. Swal.fire("Warning", "Please select constituency", "warning");
  292. $('#pageLoader').hide();
  293. return;
  294. }
  295. console.log("workAcNo", workAcNo)
  296. apiURL = "/election/api/dataentryadmin/report/SCNotice/sc-notice?workAcNo=" + workAcNo;
  297. }
  298. else if (selected === "scnoticesecond") {
  299. let workAcNo = $("#attendanceConstituency").val();
  300. //console.log("scnotice")
  301. if (!workAcNo) {
  302. Swal.fire("Warning", "Please select constituency", "warning");
  303. $('#pageLoader').hide();
  304. return;
  305. }
  306. apiURL = "/election/api/dataentryadmin/report/SCNoticesecond/sc-notice-second" + "?workAcNo=" + workAcNo;
  307. }
  308. else if (selected === "secondorder") {
  309. let workAcNo = $("#attendanceConstituency").val();
  310. if (!workAcNo) {
  311. Swal.fire("Warning", "Please select constituency", "warning");
  312. $('#pageLoader').hide();
  313. return;
  314. }
  315. // ✅ Use async generate → poll → download flow (avoids blob buffering)
  316. startAsyncReportGeneration(
  317. "/election/api/dataentryadmin/report/SecondOrder/second-order",
  318. workAcNo
  319. );
  320. return; // Don't fall through to the blob AJAX below
  321. }
  322. else if (selected === "secondorderack") {
  323. //console.log("secondorderack");
  324. let workAcNo = $("#attendanceConstituency").val();
  325. if (!workAcNo) {
  326. Swal.fire("Warning", "Please select constituency", "warning");
  327. $('#pageLoader').hide();
  328. return;
  329. }
  330. apiURL = "/election/api/dataentryadmin/report/SecondOrderAck/second-order-ack?workAcNo=" + workAcNo;
  331. }
  332. //ak
  333. else if (selected === "noticesheetfirst") {
  334. //console.log("noticesheet")
  335. let Ccode = $("#attendancenoticeConstituency").val();
  336. if (!Ccode) {
  337. Swal.fire("Warning", "Please select constituency", "warning");
  338. $('#pageLoader').hide();
  339. return;
  340. }
  341. console.log("Ccode", Ccode)
  342. apiURL = "/election/api/dataentryadmin/report/NoticeSheet/notice-sheet?Ccode=" + Ccode;
  343. }
  344. else if (selected === "noticesheetsecond") {
  345. //console.log("noticesheetsecond")
  346. let Ccode = $("#attendancenoticeConstituency").val();
  347. if (!Ccode) {
  348. Swal.fire("Warning", "Please select constituency", "warning");
  349. $('#pageLoader').hide();
  350. return;
  351. }
  352. //console.log("Ccode", Ccode)
  353. apiURL = "/election/api/dataentryadmin/report/NoticeSheetSecond/notice-sheet-second?Ccode=" + Ccode;
  354. }
  355. else if (selected === "noticesheetsecondrepeat") {
  356. //console.log("noticesheetsecond")
  357. let Ccode = $("#attendancenoticeConstituency").val();
  358. if (!Ccode) {
  359. Swal.fire("Warning", "Please select constituency", "warning");
  360. $('#pageLoader').hide();
  361. return;
  362. }
  363. //console.log("Ccode", Ccode)
  364. apiURL = "/election/api/dataentryadmin/report/NoticeSheetSecond/notice-sheet-second-repeat?Ccode=" + Ccode;
  365. }
  366. //ak
  367. else if (selected === "attendancefirstday") {
  368. let Ccode = $("#attendancenoticeConstituency").val();
  369. console.log("attendancefirstday", Ccode)
  370. if (!Ccode) {
  371. Swal.fire("Warning", "Please select constituency", "warning");
  372. $('#pageLoader').hide();
  373. return;
  374. }
  375. apiURL = "/election/api/dataentryadmin/report/Attendance/attendance-order?Ccode=" + Ccode;
  376. }
  377. else if (selected === "attendancesecondday") {
  378. //let acNo = $("#attendanceConstituency").val();
  379. let ccode = $("#attendancenoticeConstituency").val();
  380. if (!ccode) {
  381. Swal.fire("Warning", "Please select Training Center", "warning");
  382. $('#pageLoader').hide();
  383. return;
  384. }
  385. apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day?Ccode=" + ccode;
  386. }
  387. else if (selected === "attendanceseconddayrepeat") {
  388. let ccode = $("#attendancenoticeConstituency").val();
  389. if (!ccode) {
  390. Swal.fire("Warning", "Please select Training Center", "warning");
  391. $('#pageLoader').hide();
  392. return;
  393. }
  394. apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day-repeat?Ccode=" + ccode;
  395. }
  396. else if (selected === "departmentsummary") {
  397. let acNo = $("#departmentConstituency").val();
  398. if (!acNo) {
  399. Swal.fire("Warning", "Please select constituency", "warning");
  400. $('#pageLoader').hide();
  401. return;
  402. }
  403. apiURL = "/election/api/dataentryadmin/report/Department/department-summary?acNo=" + acNo;
  404. }
  405. else if (selected === "countingdepartmentsummary") {
  406. let acNo = $("#departmentConstituency").val();
  407. if (!acNo) {
  408. Swal.fire("Warning", "Please select constituency", "warning");
  409. $('#pageLoader').hide();
  410. return;
  411. }
  412. apiURL = "/election/api/dataentryadmin/report/Department/counting-department-summary?acNo=" + acNo;
  413. }
  414. else if (selected === "countingfinaldepartmentsummary") {
  415. let acNo = $("#departmentConstituency").val();
  416. if (!acNo) {
  417. Swal.fire("Warning", "Please select constituency", "warning");
  418. $('#pageLoader').hide();
  419. return;
  420. }
  421. apiURL = "/election/api/dataentryadmin/report/Department/counting-final-department-summary?acNo=" + acNo;
  422. }
  423. else if (selected === "countingattendance") {
  424. apiURL = "/election/api/dataentryadmin/report/Attendance/counting-attendance";
  425. }
  426. else if (selected === "countingfinalattendance") {
  427. let workAcNo = $("#attendanceConstituency").val();
  428. if (!workAcNo) {
  429. Swal.fire("Warning", "Please select constituency", "warning");
  430. $('#pageLoader').hide();
  431. return;
  432. }
  433. // Cookie-based download detection
  434. let token = new Date().getTime().toString();
  435. window.location.href = "/election/api/dataentryadmin/report/Attendance/counting-final-attendance?workAcNo=" + workAcNo + "&downloadToken=" + token;
  436. // Poll for the cookie the server sets after PDF is written
  437. let downloadCheck = setInterval(function () {
  438. if (document.cookie.indexOf("downloadToken=" + token) !== -1) {
  439. clearInterval(downloadCheck);
  440. // Clear the cookie
  441. document.cookie = "downloadToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
  442. $('#pageLoader').hide();
  443. }
  444. }, 500);
  445. // Failsafe: hide loader after 5 minutes max
  446. setTimeout(function () {
  447. clearInterval(downloadCheck);
  448. $('#pageLoader').hide();
  449. }, 300000);
  450. return;
  451. }
  452. else if (selected === "thirdorder") {
  453. let workAcNo = $("#attendanceConstituency").val();
  454. if (!workAcNo) {
  455. Swal.fire("Warning", "Please select constituency", "warning");
  456. $('#pageLoader').hide();
  457. return;
  458. }
  459. // ✅ Use async generate → poll → download flow (avoids blob buffering)
  460. startAsyncReportGeneration(
  461. "/election/api/dataentryadmin/report/ThirdOrder/third-order",
  462. workAcNo
  463. );
  464. return;
  465. }
  466. else if (selected === "attendancethirdday") {
  467. console.log("attendancethirdday");
  468. let Ccode = $("#attendancenoticeConstituency").val();
  469. if (!Ccode) {
  470. Swal.fire("Warning", "Please select Training", "warning");
  471. $('#pageLoader').hide();
  472. return;
  473. }
  474. apiURL = "/election/api/dataentryadmin/report/ThirdAttendance/attendance-third-day?Ccode=" + Ccode;
  475. }
  476. else if (selected === "noticesheetthird") {
  477. console.log("noticesheetthird")
  478. let Ccode = $("#attendancenoticeConstituency").val();
  479. if (!Ccode) {
  480. Swal.fire("Warning", "Please select Training", "warning");
  481. $('#pageLoader').hide();
  482. return;
  483. }
  484. console.log("Ccode", Ccode)
  485. apiURL = "/election/api/dataentryadmin/report/ThirdNoticeSheet/third-notice-sheet?Ccode=" + Ccode;
  486. }
  487. else if (selected === "tnale") {
  488. console.log("tnale");
  489. let Ccode = $("#attendancenoticeConstituency").val();
  490. if (!Ccode) {
  491. Swal.fire("Warning", "Please select Training", "warning");
  492. $('#pageLoader').hide();
  493. return;
  494. }
  495. apiURL = "/election/api/dataentryadmin/report/ThirdTNALE/third-TNLAE?Ccode=" + Ccode;
  496. }
  497. else if (selected === "zonalparty") {
  498. console.log("zonalparty");
  499. let Ccode = $("#attendancenoticeConstituency").val();
  500. if (!Ccode) {
  501. Swal.fire("Warning", "Please select Training", "warning");
  502. $('#pageLoader').hide();
  503. return;
  504. }
  505. apiURL = "/election/api/dataentryadmin/report/ZonalParty/zonal_party-details?Ccode=" + Ccode;
  506. }
  507. else if (selected === "voucher" || selected === "voucherthird") {
  508. let workAcNo = $("#attendanceConstituency").val();
  509. if (!workAcNo) { // ✅ FIXED
  510. Swal.fire("Warning", "Please select Constituency Center", "warning");
  511. $('#pageLoader').hide();
  512. return;
  513. }
  514. apiURL = "/election/api/dataentryadmin/report/ThirdVoucher/voucher-third?workAcNo=" + workAcNo;
  515. }
  516. else if (selected === "form12report") {
  517. //console.log("form12report")
  518. let AcNo = $("#attendanceConstituency").val();
  519. if (!AcNo) {
  520. Swal.fire("Warning", "Please select constituency", "warning");
  521. $('#pageLoader').hide();
  522. return;
  523. }
  524. //console.log("workAcNo", workAcNo)
  525. apiURL = "/election/api/dataentryadmin/report/Form12/form12?AcNo=" + AcNo;
  526. }
  527. else if (selected === "microobserverfirstorder") {
  528. //console.log("microobserver")
  529. let AcNo = $("#attendanceConstituency").val();
  530. if (!AcNo) {
  531. Swal.fire("Warning", "Please select constituency", "warning");
  532. $('#pageLoader').hide();
  533. return;
  534. }
  535. //console.log("workAcNo", workAcNo)
  536. apiURL = "/election/api/dataentryadmin/report/FirstOrder/micro-observer?workAcNo=" + AcNo;
  537. }
  538. else if (selected === "microobserverdepartment") {
  539. //console.log("microobserver")
  540. let AcNo = $("#departmentConstituency").val();
  541. if (!AcNo) {
  542. Swal.fire("Warning", "Please select constituency", "warning");
  543. $('#pageLoader').hide();
  544. return;
  545. }
  546. //console.log("workAcNo", workAcNo)
  547. apiURL = "/election/api/dataentryadmin/report/Department/micro-observer?acNo=" + AcNo;
  548. }
  549. else if (selected === "microobserverattendance") {
  550. //console.log("microobserver")
  551. let batch = $("#batchSelect").val();
  552. if (!batch) {
  553. Swal.fire("Warning", "Please select batch", "warning");
  554. $('#pageLoader').hide();
  555. return;
  556. }
  557. //console.log("workAcNo", workAcNo)
  558. apiURL = "/election/api/dataentryadmin/report/Attendance/micro-observer?batch=" + batch;
  559. }
  560. else if (selected === "microobservernoticesheet") {
  561. //console.log("microobservernoticesheet")
  562. let batch = $("#batchSelect").val();
  563. if (!batch) {
  564. Swal.fire("Warning", "Please select batch", "warning");
  565. $('#pageLoader').hide();
  566. return;
  567. }
  568. //console.log("batch", batch)
  569. apiURL = "/election/api/dataentryadmin/report/NoticeSheet/micro-observer-notice-sheet?batch=" + batch;
  570. }
  571. else if (selected === "secondtrainingattendancecopy") {
  572. //let acNo = $("#attendanceConstituency").val();
  573. let ccode = $("#attendancenoticeConstituency").val();
  574. if (!ccode) {
  575. Swal.fire("Warning", "Please select Training Center", "warning");
  576. $('#pageLoader').hide();
  577. return;
  578. }
  579. apiURL = "/election/api/dataentryadmin/report/AttendanceSecond/attendance-second-day-copy?Ccode=" + ccode;
  580. }
  581. else if (selected === "microobserverscnotice") {
  582. //console.log("secondorder")
  583. let workAcNo = $("#attendanceConstituency").val();
  584. if (!workAcNo) {
  585. Swal.fire("Warning", "Please select constituency", "warning");
  586. $('#pageLoader').hide();
  587. return;
  588. }
  589. console.log("workAcNo", workAcNo)
  590. apiURL = "/election/api/dataentryadmin/report/SCNotice/micro-observer-notice?workAcNo=" + workAcNo;
  591. }
  592. else if (selected === "pollpersonexcess") {
  593. console.log("Poll person excess")
  594. let workAcNo = $("#attendanceConstituency").val();
  595. if (!workAcNo) {
  596. Swal.fire("Warning", "Please select constituency", "warning");
  597. $('#pageLoader').hide();
  598. return;
  599. }
  600. console.log("workAcNo", workAcNo)
  601. apiURL = "/election/api/dataentryadmin/report/FirstOrder/PollPersonExcess?workAcNo=" + workAcNo;
  602. }
  603. else if (selected === "form12excess") {
  604. //console.log("form12report")
  605. let AcNo = $("#attendanceConstituency").val();
  606. if (!AcNo) {
  607. Swal.fire("Warning", "Please select constituency", "warning");
  608. $('#pageLoader').hide();
  609. return;
  610. }
  611. //console.log("workAcNo", workAcNo)
  612. apiURL = "/election/api/dataentryadmin/report/Form12/form12excess?AcNo=" + AcNo;
  613. }
  614. else if (selected === "mobfinalordercopy") {
  615. //console.log("microobserver")
  616. //let AcNo = $("#attendanceConstituency").val();
  617. let ccode = $("#attendancenoticeConstituency").val();
  618. if (!ccode) {
  619. Swal.fire("Warning", "Please select Training Center", "warning");
  620. $('#pageLoader').hide();
  621. return;
  622. }
  623. //console.log("workAcNo", workAcNo)
  624. apiURL = "/election/api/dataentryadmin/report/FirstOrder/mobfinalordercopy?ccode=" + ccode;
  625. }
  626. //countingfirstorder
  627. else if (selected === "countingfirstorder") {
  628. //console.log("countingfirstorder")
  629. let AcNo = $("#attendanceConstituency").val();
  630. //console.log("AcNo="+AcNo );
  631. if (!AcNo) {
  632. Swal.fire("Warning", "Please select constituency", "warning");
  633. $('#pageLoader').hide();
  634. return;
  635. }
  636. apiURL = "/election/api/dataentryadmin/report/FirstOrder/countingfirstorder?workAcNo=" + AcNo;
  637. }
  638. else if (selected === "countingfinalorder") {
  639. //console.log("countingfirstorder")
  640. let AcNo = $("#attendanceConstituency").val();
  641. //console.log("AcNo="+AcNo );
  642. if (!AcNo) {
  643. Swal.fire("Warning", "Please select constituency", "warning");
  644. $('#pageLoader').hide();
  645. return;
  646. }
  647. apiURL = "/election/api/dataentryadmin/report/FirstOrder/countingfinalorder?workAcNo=" + AcNo;
  648. }
  649. else if (selected === "countingvoucher") {
  650. //console.log("countingfirstorder")
  651. let AcNo = $("#attendanceConstituency").val();
  652. //console.log("AcNo="+AcNo );
  653. if (!AcNo) {
  654. Swal.fire("Warning", "Please select constituency", "warning");
  655. $('#pageLoader').hide();
  656. return;
  657. }
  658. apiURL = "/election/api/dataentryadmin/report/ThirdVoucher/counting-voucher?AcNo=" + AcNo;
  659. }
  660. else if (selected === "mobattendance") {
  661. console.log("microobserverattendance");
  662. let Ccode = $("#attendancenoticeConstituency").val();
  663. if (!Ccode) {
  664. Swal.fire("Warning", "Please select Training", "warning");
  665. $('#pageLoader').hide();
  666. return;
  667. }
  668. apiURL = "/election/api/dataentryadmin/report/ThirdAttendance/mob-attendance?Ccode=" + Ccode;
  669. }
  670. else {
  671. Swal.fire("Info", "Report option not implemented yet.", "info");
  672. return;
  673. }
  674. $.ajax({
  675. url: apiURL,
  676. method: "GET",
  677. timeout: 300000, // 5 minutes — prevents premature abort for large reports
  678. xhrFields: {
  679. responseType: "blob"
  680. },
  681. success: function (data, status, xhr) {
  682. $('#pageLoader').hide();
  683. const blob = new Blob([data], { type: "application/pdf" });
  684. // 🔹 Get filename from response header
  685. let disposition = xhr.getResponseHeader("Content-Disposition");
  686. let filename = "report.pdf";
  687. if (disposition && disposition.indexOf("filename=") !== -1) {
  688. filename = disposition.split("filename=")[1].replace(/"/g, "");
  689. }
  690. const link = document.createElement("a");
  691. link.href = window.URL.createObjectURL(blob);
  692. link.download = filename;
  693. link.click();
  694. },
  695. error: function (xhr) {
  696. if (xhr.status === 404) {
  697. $('#pageLoader').hide();
  698. Swal.fire(
  699. "No Data Found",
  700. "NO Polling persons data available for the selected constituency.",
  701. "info"
  702. );
  703. } else {
  704. $('#pageLoader').hide();
  705. Swal.fire(
  706. "Error",
  707. "Failed to generate PDF. Please check server logs.",
  708. "error"
  709. );
  710. }
  711. }
  712. });
  713. });
  714. // ============================================================
  715. // ✅ ASYNC REPORT GENERATION (for Second Order only)
  716. // Generates PDF on server → polls status → triggers direct download
  717. // This avoids blob buffering and eliminates the 6+ minute frontend wait.
  718. // ============================================================
  719. function startAsyncReportGeneration(baseUrl, workAcNo) {
  720. $('#pageLoader').show();
  721. $('#pageLoader .spinner-border').next('p').text('Generating report... Please wait.');
  722. $.ajax({
  723. url: baseUrl + "/generate?workAcNo=" + workAcNo,
  724. method: "GET",
  725. success: function (data) {
  726. if (data && data.taskId) {
  727. pollReportStatus(baseUrl, data.taskId);
  728. } else {
  729. $('#pageLoader').hide();
  730. Swal.fire("Error", "Failed to start report generation.", "error");
  731. }
  732. },
  733. error: function () {
  734. $('#pageLoader').hide();
  735. Swal.fire("Error", "Failed to start report generation. Please try again.", "error");
  736. }
  737. });
  738. }
  739. function pollReportStatus(baseUrl, taskId) {
  740. let pollInterval = setInterval(function () {
  741. $.ajax({
  742. url: baseUrl + "/status/" + taskId,
  743. method: "GET",
  744. success: function (data) {
  745. if (data.status === "COMPLETED") {
  746. clearInterval(pollInterval);
  747. $('#pageLoader .spinner-border').next('p').text('Downloading...');
  748. // Direct file download — no blob buffering!
  749. window.location.href = data.downloadUrl;
  750. // Hide loader after a short delay (download starts in background)
  751. setTimeout(function () {
  752. $('#pageLoader').hide();
  753. $('#pageLoader .spinner-border').next('p').text('Please wait...');
  754. }, 3000);
  755. } else if (data.status === "FAILED") {
  756. clearInterval(pollInterval);
  757. $('#pageLoader').hide();
  758. Swal.fire("Error", "Report generation failed: " + (data.error || "Unknown error"), "error");
  759. }
  760. // If IN_PROGRESS, keep polling
  761. },
  762. error: function () {
  763. clearInterval(pollInterval);
  764. $('#pageLoader').hide();
  765. Swal.fire("Error", "Lost connection while waiting for report. Please try again.", "error");
  766. }
  767. });
  768. }, 3000); // Poll every 3 seconds
  769. }
  770. </script>
  771. </body>
  772. </html>