7 changed files with 976 additions and 414 deletions
-
7pom.xml
-
6src/main/java/com/gcc/commissionerreview/controller/MainController.java
-
161src/main/java/com/gcc/commissionerreview/controller/PetLicenseApiController.java
-
1src/main/java/com/gcc/commissionerreview/controller/SofaBedCollectionApiController.java
-
733src/main/java/com/gcc/commissionerreview/service/SofaBedCollectionService.java
-
301src/main/resources/templates/modules/pet/petlicense.html
-
171src/main/resources/templates/modules/sofa_bed/zonewise1.html
@ -0,0 +1,161 @@ |
|||||
|
package com.gcc.commissionerreview.controller; |
||||
|
|
||||
|
import java.io.BufferedReader; |
||||
|
import java.io.InputStreamReader; |
||||
|
import java.io.OutputStream; |
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import org.json.JSONArray; |
||||
|
import org.json.JSONObject; |
||||
|
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.RestController; |
||||
|
|
||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
|
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/commissionerreview/api/petlicense") |
||||
|
|
||||
|
public class PetLicenseApiController { |
||||
|
|
||||
|
@GetMapping("/getzonewisedata") |
||||
|
public ResponseEntity<String> getZonewiseData() { |
||||
|
try { |
||||
|
// Step 1: Login and get session token |
||||
|
String loginUrl = "https://petservice.gccservices.in/api/v1/iam/login"; |
||||
|
String loginPayload = "{ \"username\": \"admin@getryt.io\", \"password\": \"Reset@123\" }"; |
||||
|
|
||||
|
String sessionToken = getSessionToken(loginUrl, loginPayload); |
||||
|
//System.out.println("✅ Session Token: " + sessionToken); |
||||
|
|
||||
|
// Step 2: Fetch License Dashboard Data |
||||
|
String dashboardUrl = "https://petservice.gccservices.in/api/v1/dashboard/license-dashboard"; |
||||
|
String dashboardResponse = getDashboardData(dashboardUrl, sessionToken); |
||||
|
|
||||
|
|
||||
|
String dashboardUrl2 = "https://petservice.gccservices.in/api/v1/dashboard/vaccination-dashboard"; |
||||
|
String dashboardResponse2 = getDashboardData(dashboardUrl2, sessionToken); |
||||
|
|
||||
|
String dashboardUrl3 = "https://petservice.gccservices.in/api/v1/dashboard/microchip-dashboard"; |
||||
|
String dashboardResponse3 = getDashboardData(dashboardUrl3, sessionToken); |
||||
|
|
||||
|
// System.out.println("dashboardResponse="+dashboardResponse); |
||||
|
// System.out.println("dashboardResponse2="+dashboardResponse2); |
||||
|
// System.out.println("dashboardResponse3="+dashboardResponse3); |
||||
|
|
||||
|
ObjectMapper mapper = new ObjectMapper(); |
||||
|
ObjectNode wrapper = mapper.createObjectNode(); |
||||
|
ArrayNode errors = mapper.createArrayNode(); |
||||
|
wrapper.put("status", true); |
||||
|
|
||||
|
JsonNode root = mapper.readTree(dashboardResponse); |
||||
|
JsonNode root2 = mapper.readTree(dashboardResponse2); |
||||
|
JsonNode root3 = mapper.readTree(dashboardResponse3); |
||||
|
|
||||
|
// Check if "success" is true |
||||
|
if (root.has("success") && root.get("success").asBoolean()) { |
||||
|
wrapper.set("licensedata", root); |
||||
|
} else { |
||||
|
errors.add("License dashboard returned success=false"); |
||||
|
} |
||||
|
|
||||
|
if (root2.has("success") && root2.get("success").asBoolean()) { |
||||
|
wrapper.set("vaccinationdata", root2); |
||||
|
|
||||
|
} else { |
||||
|
errors.add("Vaccination dashboard returned success=false"); |
||||
|
} |
||||
|
|
||||
|
if (root3.has("success") && root3.get("success").asBoolean()) { |
||||
|
wrapper.set("microchipdata", root3); |
||||
|
} else { |
||||
|
errors.add("Microchip dashboard returned success=false"); |
||||
|
} |
||||
|
|
||||
|
// --- If any failed, mark status false but still return data --- |
||||
|
if (!errors.isEmpty()) { |
||||
|
wrapper.put("status", false); |
||||
|
wrapper.set("errors", errors); |
||||
|
} |
||||
|
|
||||
|
return ResponseEntity.ok() |
||||
|
.header("Content-Type", "application/json") |
||||
|
.body(mapper.writeValueAsString(wrapper)); |
||||
|
|
||||
|
|
||||
|
}catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
ObjectNode error = new ObjectMapper().createObjectNode(); |
||||
|
error.put("status", false); |
||||
|
error.put("message", "Error fetching dashboard data: " + e.getMessage()); |
||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) |
||||
|
.body(error.toString()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Step 1: Get session token |
||||
|
private static String getSessionToken(String urlString, String jsonInput) throws Exception { |
||||
|
URL url = new URL(urlString); |
||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
||||
|
|
||||
|
conn.setRequestMethod("POST"); |
||||
|
conn.setRequestProperty("Content-Type", "application/json"); |
||||
|
conn.setDoOutput(true); |
||||
|
|
||||
|
try (OutputStream os = conn.getOutputStream()) { |
||||
|
os.write(jsonInput.getBytes("UTF-8")); |
||||
|
} |
||||
|
|
||||
|
int responseCode = conn.getResponseCode(); |
||||
|
if (responseCode == 201) { |
||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); |
||||
|
StringBuilder response = new StringBuilder(); |
||||
|
String line; |
||||
|
while ((line = in.readLine()) != null) response.append(line); |
||||
|
in.close(); |
||||
|
|
||||
|
JSONObject jsonResponse = new JSONObject(response.toString()); |
||||
|
JSONObject data = jsonResponse.optJSONObject("data"); |
||||
|
if (data != null && data.has("session")) { |
||||
|
return data.getString("session"); |
||||
|
} else { |
||||
|
throw new RuntimeException("Session not found in response: " + response); |
||||
|
} |
||||
|
} else { |
||||
|
throw new RuntimeException("Login failed. HTTP Code: " + responseCode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Step 2: Fetch dashboard data |
||||
|
private static String getDashboardData(String urlString, String sessionToken) throws Exception { |
||||
|
URL url = new URL(urlString); |
||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
||||
|
|
||||
|
conn.setRequestMethod("GET"); |
||||
|
conn.setRequestProperty("Authorization", "Bearer " + sessionToken); |
||||
|
conn.setRequestProperty("Accept", "application/json"); |
||||
|
|
||||
|
int responseCode = conn.getResponseCode(); |
||||
|
if (responseCode == 200) { |
||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); |
||||
|
StringBuilder response = new StringBuilder(); |
||||
|
String line; |
||||
|
while ((line = in.readLine()) != null) response.append(line); |
||||
|
in.close(); |
||||
|
return response.toString(); |
||||
|
} else { |
||||
|
throw new RuntimeException("Dashboard fetch failed. HTTP Code: " + responseCode); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,301 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org"> |
||||
|
<head> |
||||
|
<title>Pet License Zonewise Report Summary</title> |
||||
|
|
||||
|
|
||||
|
<!-- Bootstrap 5 CSS --> |
||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> |
||||
|
|
||||
|
<!-- DataTables CSS --> |
||||
|
<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"/> |
||||
|
|
||||
|
<style> |
||||
|
table.dataTable th, table.dataTable td { |
||||
|
text-align: center; |
||||
|
vertical-align: middle; |
||||
|
border: 1px solid #000; |
||||
|
} |
||||
|
|
||||
|
table.dataTable th{ |
||||
|
background-color: #003366 !important; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.dataTables_wrapper .dt-buttons { |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.dataTables_filter { |
||||
|
margin-bottom: 25px; /* adjust as needed */ |
||||
|
} |
||||
|
|
||||
|
.page-header-title h4 { |
||||
|
margin: 20px 0; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
#zoneDetailsTable_wrapper .dataTables_scrollBody { |
||||
|
border: none !important; |
||||
|
} |
||||
|
|
||||
|
#zoneDetailsTable td, #zoneDetailsTable th { |
||||
|
vertical-align: middle; |
||||
|
text-align: center; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
|
||||
|
<div class="page-header-title"> |
||||
|
<h4>Pet License - MIS Report</h4> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<div id="opSummaryTable" style="display: block;" class="container"> |
||||
|
<p style="font-weight: bold;">Microchip Details:</p> |
||||
|
<table class="table table-striped table-bordered display nowrap w-100"> |
||||
|
<tr> |
||||
|
<th class="text-center">Total requirement: <span id="micro_total"></span></th> |
||||
|
<th class="text-center">Completed: <span id="micro_completed"></span></th> |
||||
|
<th class="text-center">Pending: <span id="micro_pending"></span></th> |
||||
|
</tr> |
||||
|
</table> |
||||
|
|
||||
|
<table id="ZoneOpDatatable" class="table table-striped table-bordered display nowrap w-100"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th class="text-center" rowspan="2">Zones</th> |
||||
|
<th class="text-center" colspan="3">License</th> |
||||
|
<th class="text-center" colspan="3">Vaccination</th> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<th class="text-center">License Total Request</th> |
||||
|
<th class="text-center">Completed</th> |
||||
|
<th class="text-center">Pending</th> |
||||
|
<th class="text-center">Vaccination Total Request</th> |
||||
|
<th class="text-center">Completed</th> |
||||
|
<th class="text-center">Pending</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
|
||||
|
|
||||
|
</tbody> |
||||
|
<!-- <tfoot> |
||||
|
<tr> |
||||
|
<th class="text-center">TOTAL</th> |
||||
|
<th class="text-center"></th> |
||||
|
<th class="text-center"></th> |
||||
|
<th class="text-center"></th> |
||||
|
<th class="text-center"></th> |
||||
|
<th class="text-center"></th> |
||||
|
<th class="text-center"></th> |
||||
|
</tr> |
||||
|
</tfoot> --> |
||||
|
</table> |
||||
|
</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"></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> |
||||
|
|
||||
|
|
||||
|
<!-- Scripts --> |
||||
|
<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-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
||||
|
|
||||
|
<!-- DataTables JS --> |
||||
|
<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 () { |
||||
|
|
||||
|
$('#pageLoader').show(); |
||||
|
$.ajax({ |
||||
|
url: '/commissionerreview/api/petlicense/getzonewisedata', |
||||
|
method: 'GET', |
||||
|
success: function(response) { |
||||
|
$('#pageLoader').hide(); |
||||
|
console.log(response); |
||||
|
if (response.status === true) { |
||||
|
|
||||
|
|
||||
|
if (response.licensedata && response.vaccinationdata && |
||||
|
response.licensedata.data && |
||||
|
Array.isArray(response.licensedata.data.zoneWise)) { |
||||
|
|
||||
|
const licenseData = response.licensedata?.data?.zoneWise || []; |
||||
|
const vaccData = response.vaccinationdata?.data?.zoneWise || []; |
||||
|
|
||||
|
const microData = response.microchipdata.data; |
||||
|
|
||||
|
$('#micro_total').text(microData.totalRequirement || 0); |
||||
|
$('#micro_completed').text(microData.completed || 0); |
||||
|
$('#micro_pending').text(microData.pending || 0); |
||||
|
|
||||
|
const mergedData = licenseData.map(lic => { |
||||
|
const vacc = vaccData.find(v => v.zone === lic.zone) || {}; |
||||
|
return { |
||||
|
license_zone: lic.zone || '-', |
||||
|
license_total: parseInt(lic.completed || 0) + parseInt(lic.pending || 0), |
||||
|
license_completed: lic.completed || '0', |
||||
|
license_pending: lic.pending || '0', |
||||
|
vacc_zone: vacc.zone || '-', |
||||
|
vacc_total: parseInt(vacc.completed || 0) + parseInt(vacc.pending || 0), |
||||
|
vacc_completed: vacc.completed || '0', |
||||
|
vacc_pending: vacc.pending || '0' |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
// 🧾 Compute total row |
||||
|
const totals = mergedData.reduce( |
||||
|
(acc, curr) => { |
||||
|
acc.license_total += parseInt(curr.license_total || 0); |
||||
|
acc.license_completed += parseInt(curr.license_completed || 0); |
||||
|
acc.license_pending += parseInt(curr.license_pending || 0); |
||||
|
acc.vacc_total += parseInt(curr.vacc_total || 0); |
||||
|
acc.vacc_completed += parseInt(curr.vacc_completed || 0); |
||||
|
acc.vacc_pending += parseInt(curr.vacc_pending || 0); |
||||
|
return acc; |
||||
|
}, |
||||
|
{ |
||||
|
license_total: 0, |
||||
|
license_completed: 0, |
||||
|
license_pending: 0, |
||||
|
vacc_total: 0, |
||||
|
vacc_completed: 0, |
||||
|
vacc_pending: 0 |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
// 🟩 Add total row at end |
||||
|
mergedData.push({ |
||||
|
license_zone: '<strong>TOTAL</strong>', |
||||
|
license_total: `<strong>${totals.license_total}</strong>`, |
||||
|
license_completed: `<strong>${totals.license_completed}</strong>`, |
||||
|
license_pending: `<strong>${totals.license_pending}</strong>`, |
||||
|
vacc_total: `<strong>${totals.vacc_total}</strong>`, |
||||
|
vacc_completed: `<strong>${totals.vacc_completed}</strong>`, |
||||
|
vacc_pending: `<strong>${totals.vacc_pending}</strong>` |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
let table = $('#ZoneOpDatatable').DataTable({ |
||||
|
destroy: true, |
||||
|
autoWidth: true, |
||||
|
info: true, |
||||
|
data: mergedData, |
||||
|
columns: [ |
||||
|
{ data: 'license_zone',defaultContent: '-', className: 'text-center'}, |
||||
|
{ data: 'license_total', defaultContent: '-', className: 'text-center' }, |
||||
|
{ data: 'license_completed', defaultContent: '-', className: 'text-center' }, |
||||
|
{ data: 'license_pending', defaultContent: '-', className: 'text-center' }, |
||||
|
{ data: 'vacc_total', defaultContent: '-', className: 'text-center' }, |
||||
|
{ data: 'vacc_completed',defaultContent: '-', className: 'text-center' }, |
||||
|
{ data: 'vacc_pending',defaultContent: '-', className: 'text-center' } |
||||
|
|
||||
|
], |
||||
|
dom: 'Bfrtip', |
||||
|
buttons: [ |
||||
|
{ |
||||
|
extend: 'excelHtml5', |
||||
|
title: 'Pet_license_Report', |
||||
|
messageTop: 'License and Vaccination Report', |
||||
|
text: '<i class="fa fa-file-excel"></i> Export to Excel', |
||||
|
className: 'btn btn-success btn-sm', |
||||
|
exportOptions: { columns: ':visible' } |
||||
|
}, |
||||
|
{ |
||||
|
extend: 'pdfHtml5', |
||||
|
title: 'Pet_license_Report', |
||||
|
messageTop: 'License and Vaccination Report', |
||||
|
text: '<i class="fa fa-file-pdf"></i> Export to PDF', |
||||
|
className: 'btn btn-danger btn-sm', |
||||
|
orientation: 'portrait', // Optional: 'portrait' or 'landscape' |
||||
|
pageSize: 'A4', // Optional: 'A4', 'LETTER', etc. |
||||
|
exportOptions: { columns: ':visible' } |
||||
|
|
||||
|
} |
||||
|
], |
||||
|
lengthMenu: [ |
||||
|
[50, 100, 200, 500, -1], |
||||
|
['50 rows', '100 rows', '200 rows', 'Show all'] |
||||
|
], |
||||
|
scrollY: 'auto', |
||||
|
scrollX: true, |
||||
|
responsive: false, |
||||
|
searching: false, |
||||
|
ordering: false, |
||||
|
createdRow: function (row, data, dataIndex) { |
||||
|
if (data.license_zone === '<strong>TOTAL</strong>') { |
||||
|
$(row).addClass('font-weight-bold table-warning'); // highlight total row |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
else{ |
||||
|
$('#pageLoader').hide(); |
||||
|
|
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: response.message, |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
error: function(xhr, status, error) { |
||||
|
$('#pageLoader').hide(); |
||||
|
// alert("Request failed: " + error); |
||||
|
Swal.fire({ |
||||
|
icon: 'error', |
||||
|
title: 'Error', |
||||
|
text: error, |
||||
|
showConfirmButton: true, |
||||
|
timer: 3000 |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue