Browse Source

for permanent flagpole or statue updated service, message content and pages

master
yoganandhan 8 months ago
parent
commit
6fc829696f
  1. 9
      src/main/java/com/gcc/flagpoles_services/configuration/DataSourceConfig.java
  2. 3
      src/main/java/com/gcc/flagpoles_services/configuration/WebMvcConfig.java
  3. 297
      src/main/java/com/gcc/flagpoles_services/flagpoles/controller/FlagPoleApiController.java
  4. 4
      src/main/java/com/gcc/flagpoles_services/flagpoles/controller/MainController.java
  5. 81
      src/main/java/com/gcc/flagpoles_services/flagpoles/service/FlagpoleSMSService.java
  6. 1256
      src/main/java/com/gcc/flagpoles_services/flagpoles/service/RdoService.java
  7. 3
      src/main/resources/application-dev.properties
  8. 2
      src/main/resources/application-prod.properties
  9. 751
      src/main/resources/templates/modules/flagpole/adminreports.html
  10. 106
      src/main/resources/templates/modules/flagpole/approvedandrejectedlist.html
  11. 369
      src/main/resources/templates/modules/flagpole/requestlist.html

9
src/main/java/com/gcc/flagpoles_services/configuration/DataSourceConfig.java

@ -23,12 +23,13 @@ import java.util.Properties;
public class DataSourceConfig {
// local
// private static String host = "localhost:3306";
// private static String dbpassword = "root";
private static String host = "localhost:3306";
private static String dbpassword = "root";
// AWS
private static String host = "gcc-facial-db-instance-1.cf48eqcciziq.ap-south-1.rds.amazonaws.com:3306";
private static String dbpassword = "gcc-facial-password";
// private static String host =
// "gcc-facial-db-instance-1.cf48eqcciziq.ap-south-1.rds.amazonaws.com:3306";
// private static String dbpassword = "gcc-facial-password";
@Configuration
@EnableTransactionManagement

3
src/main/java/com/gcc/flagpoles_services/configuration/WebMvcConfig.java

@ -61,7 +61,8 @@ public class WebMvcConfig implements WebMvcConfigurer {
appModuleRepository,
menuItemRepository,
subMenuItemRepository,
environment));
environment))
.excludePathPatterns("/assets/**", "/files/**", "/images/**", "/css/**", "/js/**", "/fonts/**");
}
@Override

297
src/main/java/com/gcc/flagpoles_services/flagpoles/controller/FlagPoleApiController.java

@ -36,97 +36,12 @@ public class FlagPoleApiController {
this.appConfig = appConfig;
}
// new
// @GetMapping("/getAllDetails")
// public ResponseEntity<?> getAllRequestDetails(
// @RequestParam String userLogin,
// @RequestParam(required = false) String startDate,
// @RequestParam(required = false) String endDate) {
// try {
// List<Map<String, Object>> result =
// rdoService.getAllRequestDetailsByUserLogin(
// userLogin, startDate, endDate);
// // 🔥 Attach HISTORY per refid
// for (Map<String, Object> record : result) {
// String refid = (String) record.get("refid");
// // List<Map<String, Object>> history =
// // rdoService.getRequestHistoryByRefId(refid);
// List<Map<String, Object>> history =
// rdoService.getOfficerFeedbackHistoryByRefId(refid,
// userLogin);
// record.put("history", history);
// }
// return ResponseEntity.ok(
// Map.of(
// "status", "success",
// "count", result.size(),
// "data", result));
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(Map.of(
// "status", "error",
// "message", "Failed to fetch data",
// "error", e.getMessage()));
// }
// }
// @GetMapping("/getAllDetails")
// public ResponseEntity<?> getAllRequestDetails(
// @RequestParam String gccUserId,
// @RequestParam(required = false) String startDate,
// @RequestParam(required = false) String endDate) {
// try {
// // 🔥 Resolve username ONCE (backend trust)
// String username = rdoService.getUsernameByUserId(gccUserId);
// if (username == null) {
// throw new RuntimeException("Invalid gccUserId : " + gccUserId);
// }
// List<Map<String, Object>> result =
// rdoService.getAllRequestDetailsByUserLogin(
// gccUserId, startDate, endDate);
// // 🔥 Attach HISTORY per refid (dept-wise)
// for (Map<String, Object> record : result) {
// String refid = (String) record.get("refid");
// List<Map<String, Object>> history =
// rdoService.getOfficerFeedbackHistoryByRefId(
// refid, username);
// record.put("history", history);
// }
// return ResponseEntity.ok(
// Map.of(
// "status", "success",
// "count", result.size(),
// "data", result));
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(Map.of(
// "status", "error",
// "message", "Failed to fetch data",
// "error", e.getMessage()));
// }
// }
@GetMapping("/getAllDetails")
public ResponseEntity<?> getAllRequestDetails(
@RequestParam String gccUserId,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate) {
@RequestParam(required = false) String endDate,
@RequestParam(required = false) String applicationType) {
try {
@ -134,7 +49,7 @@ public class FlagPoleApiController {
gccUserId = rdoService.resolveGccUserId(gccUserId);
List<Map<String, Object>> result = rdoService.getAllRequestDetailsByUserLogin(gccUserId,
startDate, endDate);
startDate, endDate, applicationType);
/* 🔥 Attach HISTORY per refid */
for (Map<String, Object> record : result) {
@ -163,68 +78,14 @@ public class FlagPoleApiController {
}
}
// old
// @PostMapping("/rdo/updateDecision")
// public ResponseEntity<?> updateRdoDecision(
// @RequestParam String refid,
// @RequestParam String status,
// @RequestParam String remarks,
// @RequestParam String approvedBy) {
// int count = rdoService.updateRdoDecision(refid, status, remarks, approvedBy);
// if (count > 0) {
// return ResponseEntity.ok(Map.of(
// "status", "SUCCESS",
// "message", "Decision updated successfully"));
// } else {
// return ResponseEntity.badRequest().body(Map.of(
// "status", "FAILED",
// "message", "Unable to update decision"));
// }
// }
// @PostMapping("/rdo/updateDecision")
// public ResponseEntity<?> updateRdoDecision(
// @RequestParam String refid,
// @RequestParam String status,
// @RequestParam String remarks,
// @RequestParam String gccUserId) {
// try {
// /* 🔥 Normalize username OR id → gccuserid */
// gccUserId = rdoService.resolveGccUserId(gccUserId);
// int count = rdoService.updateRdoDecision(
// refid, status, remarks, gccUserId);
// if (count > 0) {
// return ResponseEntity.ok(Map.of(
// "status", "SUCCESS",
// "message", "Decision updated successfully"));
// } else {
// return ResponseEntity.badRequest().body(Map.of(
// "status", "FAILED",
// "message", "Unable to update decision"));
// }
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(Map.of(
// "status", "ERROR",
// "message", e.getMessage()));
// }
// }
@PostMapping("/officer/updateDecision")
public ResponseEntity<?> updateOfficerDecision(
@RequestParam String refid,
@RequestParam String status,
@RequestParam String remarks,
@RequestParam String gccUserId,
@RequestParam String username) {
@RequestParam String username,
@RequestParam(required = false) String answers) {
try {
@ -236,7 +97,8 @@ public class FlagPoleApiController {
status,
remarks,
gccUserId,
username);
username,
answers);
if (count > 0) {
return ResponseEntity.ok(Map.of(
@ -257,112 +119,6 @@ public class FlagPoleApiController {
}
}
// old
// @GetMapping("/getApprovedAndRejectedDetails")
// public ResponseEntity<?> getApprovedRequestDetails(
// @RequestParam String userLogin,
// @RequestParam(required = false) String startDate,
// @RequestParam(required = false) String endDate,
// @RequestParam(required = false) String status) {
// try {
// List<Map<String, Object>> result =
// rdoService.getRdoApprovedRequestDetailsByUserLogin(
// userLogin, startDate, endDate, status);
// return ResponseEntity.ok(
// Map.of(
// "status", "success",
// "count", result.size(),
// "data", result));
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(
// Map.of(
// "status", "error",
// "message", "Failed to fetch data",
// "error", e.getMessage()));
// }
// }
// new
// @GetMapping("/getApprovedAndRejectedDetails")
// public ResponseEntity<?> getApprovedRequestDetails(
// @RequestParam String userLogin,
// @RequestParam(required = false) String startDate,
// @RequestParam(required = false) String endDate,
// @RequestParam(required = false) String status) {
// try {
// List<Map<String, Object>> result =
// rdoService.getRdoApprovedRequestDetailsByUserLogin(
// userLogin, startDate, endDate, status);
// // 🔥 Attach HISTORY per refid
// for (Map<String, Object> record : result) {
// String refid = (String) record.get("refid");
// List<Map<String, Object>> history =
// rdoService.getRequestHistoryByRefId(refid);
// record.put("history", history);
// }
// return ResponseEntity.ok(
// Map.of(
// "status", "success",
// "count", result.size(),
// "data", result));
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(Map.of(
// "status", "error",
// "message", "Failed to fetch data",
// "error", e.getMessage()));
// }
// }
// @GetMapping("/getApprovedAndRejectedDetails")
// public ResponseEntity<?> getApprovedRequestDetails(
// @RequestParam String userLogin,
// @RequestParam(required = false) String startDate,
// @RequestParam(required = false) String endDate) {
// try {
// List<Map<String, Object>> result =
// rdoService.getRdoApprovedRequestDetailsByUserLogin(
// userLogin, startDate, endDate, null);
// for (Map<String, Object> record : result) {
// String refid = (String) record.get("refid");
// // 🔥 NEW: officer feedback history
// List<Map<String, Object>> history =
// rdoService.getOfficerFeedbackHistoryByRefId(refid,
// userLogin);
// record.put("history", history);
// }
// return ResponseEntity.ok(Map.of(
// "status", "success",
// "count", result.size(),
// "data", result));
// } catch (Exception e) {
// e.printStackTrace();
// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
// .body(Map.of(
// "status", "error",
// "message", "Failed to fetch data",
// "error", e.getMessage()));
// }
// }
@GetMapping("/getApprovedAndRejectedDetails")
public ResponseEntity<?> getApprovedRequestDetails(
@RequestParam String gccUserId,
@ -422,4 +178,43 @@ public class FlagPoleApiController {
return flagpoleSMSService.unauthorizedFlagPoleSms(mobileNo, location, fineAmount, refid);
}
@GetMapping("/sendPermanentRequestApproved")
public String sendPermanentRequestApproved(@RequestParam String mobileNo, @RequestParam String requestId) {
return flagpoleSMSService.sendPermanentRequestApproved(mobileNo, requestId);
}
@GetMapping("/sendPermanentRequestRejected")
public String sendPermanentRequestRejected(@RequestParam String mobileNo, @RequestParam String requestId) {
return flagpoleSMSService.sendPermanentRequestRejected(mobileNo, requestId);
}
@GetMapping("/getAdminReports")
public ResponseEntity<?> getAdminReports(
@RequestParam String gccUserId,
@RequestParam(required = false) String startDate,
@RequestParam(required = false) String endDate,
@RequestParam(required = false) String status) {
try {
/* 🔥 Normalize username OR id → gccuserid */
gccUserId = rdoService.resolveGccUserId(gccUserId);
List<Map<String, Object>> result = rdoService.getAdminReportDetails(gccUserId, startDate,
endDate, status);
return ResponseEntity.ok(Map.of(
"status", "success",
"count", result.size(),
"data", result));
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"status", "error",
"message", "Failed to fetch admin report data",
"error", e.getMessage()));
}
}
}

4
src/main/java/com/gcc/flagpoles_services/flagpoles/controller/MainController.java

@ -38,7 +38,7 @@ public class MainController {
return "modules/flagpole/approvedandrejectedlist";
}
@GetMapping("/reports")
@GetMapping("/adminreports")
public String dataentry(Model model) {
String LoginUserId = LoginUserInfo.getLoginUserId();
model.addAttribute("LoginUserId", LoginUserId);
@ -48,6 +48,6 @@ public class MainController {
String UserRole = LoginUserInfo.getUserRole();
model.addAttribute("UserRole", UserRole);
return "modules/flagpole/reports";
return "modules/flagpole/adminreports";
}
}

81
src/main/java/com/gcc/flagpoles_services/flagpoles/service/FlagpoleSMSService.java

@ -245,4 +245,85 @@ public class FlagpoleSMSService {
}
}
///// permanent request approved and rejected sms
public String sendPermanentRequestApproved(String mobileNo, String requestId) {
String message = "Your Permanent Flag Pole / Statue permission request has been approved. "
+ "Request ID: " + requestId
+ ". Please proceed as per the permitted guidelines. By GCC";
// Encode message and fix colon issue (gateway not decoding %3A)
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8)
.replace("%3A", ":")
.replace("%2F", "/");
String urlString = appConfig.getOtpUrl()
+ "from=GCCCRP"
+ "&key=" + key
+ "&sender=GCCCRP"
+ "&to=" + mobileNo
+ "&body=" + encodedMsg
+ "&entityid=1401572690000011081"
+ "&templateid=1407177062247610982";
System.out.println("SMS URL:- " + urlString);
String response = messageUtility.sendSMS(urlString);
System.out.println("SMS RESPONSE:- " + response);
return response;
}
public String sendPermanentRequestRejected(String mobileNo,
String requestId) {
try {
String message = "Your Permanent Flag Pole / Statue permission request has been rejected. "
+ "Request ID: " + requestId
+ ". Review the details in the portal https://gccservices.in/flagpolesregistration/status\r\n"
+ "By GCC";
String encodedMsg = URLEncoder.encode(message, StandardCharsets.UTF_8);
String urlString = appConfig.getOtpUrl()
+ "from=GCCCRP"
+ "&key=" + key
+ "&sender=GCCCRP"
+ "&to=" + mobileNo
+ "&body=" + encodedMsg
+ "&entityid=1401572690000011081"
+ "&templateid=1407177062255650311";
System.out.println("FINAL SMS URL:- " + urlString);
URL apiUrl = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(15000);
conn.setReadTimeout(15000);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
conn.disconnect();
System.out.println("DIRECT SMS RESPONSE:- " + content.toString());
return content.toString();
} catch (Exception e) {
e.printStackTrace();
return "FAILED";
}
}
}

1256
src/main/java/com/gcc/flagpoles_services/flagpoles/service/RdoService.java
File diff suppressed because it is too large
View File

3
src/main/resources/application-dev.properties

@ -2,4 +2,7 @@ assets.base-url=/assets/
fileBaseUrl=http://localhost:8061
fileBaseUrlImages=http://localhost:8061
#fileBaseUrlImages=https://gccservices.in
#fileBaseUrl = D:/Projects/Election_Project/election_v1/gcc_election_uploads

2
src/main/resources/application-prod.properties

@ -1,3 +1,5 @@
assets.base-url=/flagpoles/assets/
fileBaseUrl=https://gccservices.in/flagpoles
fileBaseUrlImages=https://gccservices.in

751
src/main/resources/templates/modules/flagpole/adminreports.html

@ -0,0 +1,751 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="~{fragments/modules/base/head :: head}"></head>
<style>
.width1 {
width: 120px;
}
.width2 {
width: 150px;
}
.modal-label {
font-weight: 600;
color: #333;
}
.modal-value {
color: #444;
}
.modal-section-title {
font-size: 1.2rem;
font-weight: bold;
margin-top: 20px;
margin-bottom: 10px;
border-bottom: 2px solid #dee2e6;
padding-bottom: 5px;
}
.modal-title-big {
font-size: 20px;
font-weight: 700;
}
.modal-subtext {
color: #b4c5d3;
font-size: 13px;
}
.card-section {
background: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 25px;
border: 1px solid #eee;
}
.section-title {
font-weight: 700;
color: #333;
margin-bottom: 15px;
font-size: 16px;
}
.label-text {
font-size: 13px;
color: #6c757d;
}
.value-text {
font-size: 15px;
font-weight: 600;
color: #333;
}
.info-block {
display: flex;
flex-direction: column;
}
.badge-status {
background: #2dce89;
color: #212121;
padding: 6px 10px;
border-radius: 5px;
font-size: 13px;
}
.btn-big {
padding: 12px 25px;
border-radius: 8px;
width: 200px;
}
.rdo-box {
border: 1px solid #eee;
border-radius: 10px;
padding: 20px;
}
</style>
<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">
<div class="row align-items-end">
<div class="col-lg-6">
<div class="page-header-title">
<i class="fa fa-list-alt bg-blue"></i>
<div class="d-inline">
<h5>Admin Reports</h5>
<span>Flag Pole Admin Reports</span>
</div>
</div>
</div>
<div class="col-lg-6">
<nav class="breadcrumb-container" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/flagpoles/index"><i class="ik ik-home"></i></a>
</li>
<li class="breadcrumb-item" aria-current="page">Flag Pole Admin Reports</li>
<li class="breadcrumb-item active" aria-current="page">Admin Reports</li>
</ol>
</nav>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-12">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center fw-bold">
<h3 class="mb-0">Temporary Flag Poles - Admin Reports : <span
th:text="${officer_name}"></span></h3>
<input type="hidden" id="userName" th:value="${officer_name}">
<input type="hidden" id="loginuserid" th:value="${LoginUserId}">
</div>
<div class="row mt-3 ml-2">
<div class="col-md-3">
<label for="startDate" class="form-label" style="font-size: medium;">From
Date:</label>
<input type="date" id="startDate" class="form-control" placeholder="Start Date">
</div>
<div class="col-md-3">
<label for="endDate" class="form-label" style="font-size: medium;">To
Date:</label>
<input type="date" id="endDate" class="form-control" placeholder="End Date">
</div>
<div class="col-md-3">
<label class="form-label">Status:</label>
<select id="statusFilter" class="form-control">
<option value="">All</option>
<option value="APPROVED">Approved</option>
<option value="REJECTED">Rejected</option>
</select>
</div>
<div class="col-md-3" style="margin-top: 30px;">
<button id="searchBtn" class="btn btn-primary">Search</button>
<button id="resetBtn" class="btn btn-secondary">Reset</button>
</div>
</div>
<div class="card-body">
<div>
<div class="row mt-2">
<div class="col-xl-3 col-md-3 col-sm-12">
<div class="card card-box p-4">
<h6 class="text-facebook mb-20 mt-2 text-center fw-bold"><b>Total
Request</b>
</h6>
<h4 class="text-twitter fw-700 text-center" id="totalrequest">10
</h4>
</div>
</div>
<div class="col-xl-3 col-md-3 col-sm-12" style="display: none;">
<div class="card card-box p-4">
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Pending Decision
</b></h6>
<h4 class="text-twitter fw-700 text-center" id="pendingdecision">9
</h4>
</div>
</div>
<div class="col-xl-3 col-md-3 col-sm-12">
<div class="card card-box p-4">
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Approved</b>
</h6>
<h4 class="text-twitter fw-700 text-center" id="approved">1</h4>
</div>
</div>
<div class="col-xl-3 col-md-3 col-sm-12">
<div class="card card-box p-4">
<h6 class="text-facebook mb-20 mt-2 text-center"><b>Rejected</b>
</h6>
<h4 class="text-twitter fw-700 text-center" id="rejected">0</h4>
</div>
</div>
</div>
<div>
<table id="QaqcDatatable"
class="table table-striped table-bordered table-hover dataTable"
role="grid">
<thead class="thead-dark">
<tr role="row">
<th class="text-center">S.No</th>
<th class="text-center no-sort">Applicant Name</th>
<th class="text-center">RequestId</th>
<th class="text-center">Application Type</th>
<th class="text-center">Zone/Ward</th>
<th class="text-center">Event Type</th>
<th class="text-center">Event Date</th>
<th class="text-center">Total Cost</th>
<th class="text-center">Status</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</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>
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div>
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer>
</div>
</div>
<!-- Details Modal -->
<div class="modal fade" id="detailsModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header" style="background:#2f3e54; color:white;">
<div>
<h4 class="modal-title-big" id="modalTitle"></h4>
<div id="modalSubTitle" class="modal-subtext"></div>
</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div id="modalContent"></div>
<div class="text-center mt-4">
<button type="button" class="btn btn-primary btn-big" data-dismiss="modal"
style="background:#2f3e54;">Close</button>
</div>
</div>
</div>
</div>
</div>
<script th:replace="~{fragments/modules/base/script :: script}"></script>
<script type="text/javascript">
let table;
$(document).ready(function () {
loadTable();
$("#searchBtn").on("click", loadTable);
$("#resetBtn").on("click", function () {
$("#startDate").val("");
$("#endDate").val("");
$("#statusFilter").val("");
loadTable();
});
});
function loadTable() {
//let officer_name = $("#userName").val();
let gccUserId = $("#loginuserid").val();
let startDate = $("#startDate").val();
let endDate = $("#endDate").val();
let status = $("#statusFilter").val();
console.log("gccuserid", gccUserId);
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) {
$('#QaqcDatatable').DataTable().clear().destroy();
}
table = $('#QaqcDatatable').DataTable({
processing: true,
responsive: true,
scrollY: '50vh',
dom: 'Bfrtip',
ajax: {
url: "/flagpoles/api/flagpoleregistration/getAdminReports",
type: "GET",
data: {
gccUserId: gccUserId,
startDate: startDate,
endDate: endDate,
status: status
},
dataSrc: function (json) {
const data = json.data || [];
// 🔹 Dashboard counts
let pending = 0, approved = 0, rejected = 0;
data.forEach(r => {
let status = r.history && r.history.length > 0
? r.history[r.history.length - 1].status
: null;
if (!status) pending++;
else if (status === 'APPROVED') approved++;
else if (status === 'REJECTED') rejected++;
});
// data.forEach(r => {
// if (!r.rdo_status) pending++;
// else if (r.rdo_status === 'APPROVED') approved++;
// else if (r.rdo_status === 'REJECTED') rejected++;
// });
$("#totalrequest").text(data.length);
$("#pendingdecision").text(pending);
$("#approved").text(approved);
$("#rejected").text(rejected);
return data; // ✅ already unique per refid
}
},
columns: [
{
data: null,
className: "text-center",
render: (d, t, r, m) => m.row + 1
},
{
data: "applicant_name",
className: "text-center"
},
{
data: "refid",
className: "text-center"
},
{
data: "application_type_name",
className: "text-center",
render: d =>
d === "TEMPORARY"
? `<span class="badge bg-info text-white">Temporary</span>`
: `<span class="badge bg-primary text-white">Permanent</span>`
},
{
data: null,
className: "text-center",
render: row => {
if (!row.streets || row.streets.length === 0) return "-";
return `${row.streets[0].zone} / ${row.streets[0].ward}`;
}
},
{
data: "event_name",
className: "text-center",
render: (d, t, r) =>
r.application_type_name === "PERMANENT"
? `<span class="text-muted">NA</span>`
: (d || "NA")
},
{
data: "event_date",
className: "text-center",
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? new Date(d).toLocaleDateString("en-GB") : "NA";
}
},
{
data: "total_cost",
className: "text-center",
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? d.toLocaleString("en-GB") : "NA";
}
},
// {
// data: "rdo_status",
// className: "text-center",
// render: d => {
// if (!d)
// return `<span class="badge bg-warning text-dark">Pending</span>`;
// if (d === 'APPROVED')
// return `<span class="badge bg-success">Approved</span>`;
// return `<span class="badge bg-danger">Rejected</span>`;
// }
// },
{
data: null,
className: "text-center",
render: row => {
let status = row.history && row.history.length > 0
? row.history[row.history.length - 1].status
: null;
if (!status)
return `<span class="badge bg-warning text-white">Pending</span>`;
if (status === 'APPROVED')
return `<span class="badge bg-success text-white">Approved</span>`;
return `<span class="badge bg-danger text-white">Rejected</span>`;
}
},
// {
// data: "remarks",
// className: "text-center"
// },
// {
// data: null,
// className: "text-center",
// render: function (row) {
// if (!row.history || row.history.length === 0)
// return "-";
// // history already filtered by backend for login dept
// return row.history[0].remarks || "-";
// }
// },
{
data: null,
className: "text-center",
render: row =>
`<button class="btn btn-primary btn-sm viewBtn"
data-refid="${row.refid}">
View
</button>`
}
]
});
}
// Destroy previous instance if exists
if ($.fn.DataTable.isDataTable('#QaqcDatatable')) {
$('#QaqcDatatable').DataTable().clear().destroy();
}
// $('#QaqcDatatable').on("click", ".viewBtn", function () {
// // 🔹 Get row data directly from DataTable
// const rowData = table.row($(this).closest('tr')).data();
// if (!rowData) {
// alert("No details found");
// return;
// }
// populateModal(rowData);
// $("#detailsModal").modal("show");
// });
$('#QaqcDatatable').on("click", ".viewBtn", function () {
let tr = $(this).closest('tr');
// ✅ If responsive child row, get previous row
if (tr.hasClass('child')) {
tr = tr.prev();
}
const rowData = table.row(tr).data();
if (!rowData) {
alert("No details found");
return;
}
populateModal(rowData);
$("#detailsModal").modal("show");
});
// -----------------------------
// VIEW BUTTON → OPEN MODAL
// -----------------------------
function populateModal(record) {
// HEADER
$("#modalTitle").html(`Application Details - ${record.applicant_name}`);
$("#modalSubTitle").html(
`Ref ID: ${record.refid} - ${record.streets.length} Streets`
);
$("#detailsModal").data("refid", record.refid);
// 🔹 Streets
let streetHtml = "";
record.streets.forEach((s, index) => {
const isStatue = s.no_of_statue > 0;
streetHtml += `
<div class="card-section">
<div class="section-title">Street ${index + 1}</div>
<div class="row mb-2">
<div class="col-md-4">
<div class="label-text">Street Name</div>
<div class="value-text">${s.street_name || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Zone / Ward</div>
<div class="value-text">${s.zone} / ${s.ward}</div>
</div>
${isStatue ? `
<div class="col-md-4">
<div class="label-text">No. of Statue</div>
<div class="value-text">${s.no_of_statue}</div>
</div>
<div class="col-md-4">
<div class="label-text">Statue Material</div>
<div class="value-text">
${s.statue_material || '-'}
${(s.statue_material || '').toLowerCase() === 'others'
? `(${record.others_specify_statue_material || '-'})`
: ''}
</div>
</div>
<div class="col-md-4">
<div class="label-text">Pedestal Material</div>
<div class="value-text">${s.pedestal_material || '-'}</div>
</div>
` : `
<div class="col-md-4">
<div class="label-text">No. of Poles</div>
<div class="value-text">${s.no_of_poles}</div>
</div>
<div class="col-md-4">
<div class="label-text">Flag Material</div>
<div class="value-text">${s.flag_material || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Pole Material</div>
<div class="value-text">${s.pole_material || '-'}</div>
</div>
`}
<div class="col-md-4">
<div class="label-text">Height</div>
<div class="value-text">${s.height || '-'}</div>
</div>
</div>
</div>`;
});
let historyHtml = "";
if (record.history && record.history.length > 0) {
historyHtml += `
<div class="card-section">
<div class="section-title">Application History</div>
`;
record.history.forEach((h, index) => {
historyHtml += `
<div class="row mb-2 border-bottom pb-2">
<div class="col-md-3">
<div class="label-text">Action Date</div>
<div class="value-text">${h.action_date}</div>
</div>
<div class="col-md-3">
<div class="label-text">Department</div>
<div class="value-text">${h.department_name}</div>
</div>
<div class="col-md-3">
<div class="label-text">Status</div>
<div class="value-text">${h.status}</div>
</div>
${h.remarks ? `
<div class="col-md-3">
<div class="label-text">Remarks</div>
<div class="value-text">${h.remarks}</div>
</div>` : ""}
</div>
`;
});
historyHtml += `</div>`;
}
const isPermanent = record.application_type_name === "PERMANENT";
let html = `
<!-- APPLICANT INFO -->
<div class="card-section">
<div class="section-title">Applicant Information</div>
<div class="row mb-2">
<div class="col-md-6">
<div class="label-text">Applicant Name</div>
<div class="value-text">${record.applicant_name}</div>
</div>
<div class="col-md-6">
<div class="label-text">Mobile Number</div>
<div class="value-text">${record.mobile_number}</div>
</div>
</div>
<div class="row mb-2">
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Event Type</div>
<div class="value-text">${record.event_name}</div>
</div>
<div class="col-md-6">
<div class="label-text">Event Date</div>
<div class="value-text">
${new Date(record.event_date).toLocaleDateString("en-GB")}
</div>
</div>
` : ""}
<div class="col-md-6">
<div class="label-text">Application Type</div>
<div class="value-text">${record.application_type_name}</div>
</div>
<div class="col-md-6">
<div class="label-text">Installation Type</div>
<div class="value-text">${record.installation_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Option</div>
<div class="value-text">${record.option_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Address</div>
<div class="value-text">
${record.applicant_address}
</div>
</div>
<div class="col-md-6">
<div class="label-text">Place of Erection</div>
<div class="value-text">
${record.place_of_erection || '-'}
</div>
</div>
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Total Cost</div>
<div class="value-text">
${record.total_cost.toLocaleString("en-GB")}
</div>
</div>
<div class="col-md-6">
<div class="label-text">No. of Days</div>
<div class="value-text">${record.no_of_days}</div>
</div>
<div class="col-md-6">
<div class="label-text">Event Description</div>
<div class="value-text">${record.event_desc}</div>
</div>
` : ""}
</div>
<div class="row mb-2">
<div class="col-md-6">
<div class="label-text">Applied Date</div>
<div class="value-text">${record.cdate}</div>
</div>
</div>
</div>
${streetHtml}
${historyHtml}
`;
$("#modalContent").html(html);
}
</script>
</body>
</html>

106
src/main/resources/templates/modules/flagpole/approvedandrejectedlist.html

@ -217,6 +217,7 @@
<th class="text-center">S.No</th>
<th class="text-center no-sort">Applicant Name</th>
<th class="text-center">RequestId</th>
<th class="text-center">Application Type</th>
<th class="text-center">Zone/Ward</th>
<th class="text-center">Event Type</th>
<th class="text-center">Event Date</th>
@ -389,6 +390,14 @@
data: "refid",
className: "text-center"
},
{
data: "application_type_name",
className: "text-center",
render: d =>
d === "TEMPORARY"
? `<span class="badge bg-info text-white">Temporary</span>`
: `<span class="badge bg-primary text-white">Permanent</span>`
},
{
data: null,
className: "text-center",
@ -399,17 +408,27 @@
},
{
data: "event_name",
className: "text-center"
className: "text-center",
render: (d, t, r) =>
r.application_type_name === "PERMANENT"
? `<span class="text-muted">NA</span>`
: (d || "NA")
},
{
data: "event_date",
className: "text-center",
render: d => new Date(d).toLocaleDateString("en-GB")
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? new Date(d).toLocaleDateString("en-GB") : "NA";
}
},
{
data: "total_cost",
className: "text-center",
render: d => d.toLocaleString("en-GB")
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? d.toLocaleString("en-GB") : "NA";
}
},
// {
// data: "rdo_status",
@ -433,10 +452,10 @@
if (!status)
return `<span class="badge bg-warning text-dark">Pending</span>`;
return `<span class="badge bg-warning text-white">Pending</span>`;
if (status === 'APPROVED')
return `<span class="badge bg-success">Approved</span>`;
return `<span class="badge bg-danger">Rejected</span>`;
return `<span class="badge bg-success text-white">Approved</span>`;
return `<span class="badge bg-danger text-white">Rejected</span>`;
}
},
@ -532,6 +551,7 @@
let streetHtml = "";
record.streets.forEach((s, index) => {
const isStatue = s.no_of_statue > 0;
streetHtml += `
<div class="card-section">
<div class="section-title">Street ${index + 1}</div>
@ -539,40 +559,52 @@
<div class="row mb-2">
<div class="col-md-4">
<div class="label-text">Street Name</div>
<div class="value-text">${s.street_name}</div>
<div class="value-text">${s.street_name || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Zone</div>
<div class="value-text">${s.zone}</div>
<div class="label-text">Zone / Ward</div>
<div class="value-text">${s.zone} / ${s.ward}</div>
</div>
${isStatue ? `
<div class="col-md-4">
<div class="label-text">Ward</div>
<div class="value-text">${s.ward}</div>
<div class="label-text">No. of Statue</div>
<div class="value-text">${s.no_of_statue}</div>
</div>
<div class="col-md-4">
<div class="label-text">No. of Poles</div>
<div class="value-text">${s.no_of_poles}</div>
<div class="label-text">Statue Material</div>
<div class="value-text">
${s.statue_material || '-'}
${(s.statue_material || '').toLowerCase() === 'others'
? `(${record.others_specify_statue_material || '-'})`
: ''}
</div>
</div>
<div class="col-md-4">
<div class="label-text">Height</div>
<div class="value-text">${s.height}</div>
<div class="label-text">Pedestal Material</div>
<div class="value-text">${s.pedestal_material || '-'}</div>
</div>
` : `
<div class="col-md-4">
<div class="label-text">No. of Poles</div>
<div class="value-text">${s.no_of_poles}</div>
</div>
<div class="col-md-4">
<div class="label-text">Flag Material</div>
<div class="value-text">${s.flag_material}</div>
<div class="value-text">${s.flag_material || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Pole Material</div>
<div class="value-text">${s.pole_material}</div>
<div class="value-text">${s.pole_material || '-'}</div>
</div>
`}
<div class="col-md-4">
<div class="label-text">Height</div>
<div class="value-text">${s.height || '-'}</div>
</div>
</div>
</div>`;
});
@ -620,6 +652,8 @@
historyHtml += `</div>`;
}
const isPermanent = record.application_type_name === "PERMANENT";
let html = `
<!-- APPLICANT INFO -->
<div class="card-section">
@ -637,6 +671,7 @@
</div>
<div class="row mb-2">
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Event Type</div>
<div class="value-text">${record.event_name}</div>
@ -647,12 +682,38 @@
${new Date(record.event_date).toLocaleDateString("en-GB")}
</div>
</div>
` : ""}
<div class="col-md-6">
<div class="label-text">Application Type</div>
<div class="value-text">${record.application_type_name}</div>
</div>
<div class="col-md-6">
<div class="label-text">Installation Type</div>
<div class="value-text">${record.installation_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Option</div>
<div class="value-text">${record.option_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Address</div>
<div class="value-text">
${record.applicant_address}
</div>
</div>
<div class="col-md-6">
<div class="label-text">Place of Erection</div>
<div class="value-text">
${record.place_of_erection || '-'}
</div>
</div>
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Total Cost</div>
<div class="value-text">
@ -667,6 +728,7 @@
<div class="label-text">Event Description</div>
<div class="value-text">${record.event_desc}</div>
</div>
` : ""}
</div>
<div class="row mb-2">
<div class="col-md-6">

369
src/main/resources/templates/modules/flagpole/requestlist.html

@ -92,6 +92,21 @@
border-radius: 10px;
padding: 20px;
}
.doc-box {
width: 180px;
}
.doc-title {
font-weight: 600;
margin-bottom: 6px;
}
.doc-thumb {
height: 150px;
object-fit: cover;
cursor: pointer;
}
</style>
<body>
@ -142,6 +157,9 @@
<input type="hidden" id="loginuserid" th:value="${LoginUserId}">
</div>
<div class="row mt-3 ml-2">
<div class="col-md-3">
<label for="startDate" class="form-label" style="font-size: medium;">From
@ -206,6 +224,7 @@
<th class="text-center">S.No</th>
<th class="text-center no-sort">Applicant Name</th>
<th class="text-center">RequestId</th>
<th class="text-center">Application Type</th>
<th class="text-center">Zone/Ward</th>
<th class="text-center">Event Type</th>
<th class="text-center">Event Date</th>
@ -278,12 +297,13 @@
<div class="modal fade" id="imagePreviewModal" tabindex="-1">
<div class="modal fade" id="imagePreviewModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Document Preview</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body text-center">
<img id="previewImage" class="img-fluid">
@ -297,7 +317,7 @@
<script th:replace="~{fragments/modules/base/script :: script}"></script>
<script type="text/javascript">
let selectedApplicationType = ""; // 1 TEMP , 2 PERM , empty = ALL
let table;
$(document).ready(function () {
@ -310,6 +330,16 @@
$("#endDate").val("");
loadTable();
});
$("#allBtn").click(function () {
selectedApplicationType = "";
loadTable();
});
$("#tempBtn,#permBtn").click(function () {
selectedApplicationType = $(this).data("type");
loadTable();
});
});
$(document).on("click", ".zoom-img", function () {
@ -454,7 +484,8 @@
data: {
gccUserId: gccUserId,
startDate: startDate,
endDate: endDate
endDate: endDate,
applicationType: selectedApplicationType
},
dataSrc: function (json) {
@ -492,24 +523,47 @@
{ data: null, render: (d, t, r, m) => m.row + 1, className: "text-center" },
{ data: "applicant_name", className: "text-center" },
{ data: "refid", className: "text-center" },
// 🔥 Application Type
{
data: "application_type_name",
className: "text-center",
render: d =>
d === "TEMPORARY"
? `<span class="badge bg-info text-white">Temporary</span>`
: `<span class="badge bg-primary text-white">Permanent</span>`
},
{
data: null,
className: "text-center",
render: r =>
r.streets?.length
? `${r.streets[0].zone} / ${r.streets[0].ward}`
: "-"
: "NA"
},
// 🔥 Event Type
{
data: "event_name",
className: "text-center",
render: (d, t, r) =>
r.application_type_name === "PERMANENT"
? `<span class="text-muted">NA</span>`
: (d || "NA")
},
{ data: "event_name", className: "text-center" },
{
data: "event_date",
className: "text-center",
render: d => new Date(d).toLocaleDateString("en-GB")
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? new Date(d).toLocaleDateString("en-GB") : "NA";
}
},
{
data: "total_cost",
className: "text-center",
render: d => d.toLocaleString("en-GB")
render: (d, t, r) => {
if (r.application_type_name === "PERMANENT") return "NA";
return d ? d.toLocaleString("en-GB") : "NA";
}
},
// {
// data: "rdo_status",
@ -529,11 +583,11 @@
const status = r.final_status;
if (!status)
return `<span class="badge bg-warning text-dark">Pending</span>`;
return `<span class="badge bg-warning text-white">Pending</span>`;
else if (status === 'APPROVED')
return `<span class="badge bg-success">Approved</span>`;
return `<span class="badge bg-success text-white">Approved</span>`;
else
return `<span class="badge bg-danger">Rejected</span>`;
return `<span class="badge bg-danger text-white">Rejected</span>`;
}
},
@ -599,6 +653,24 @@
function renderImage(label, url) {
if (!url) {
return `
<div class="doc-box text-center">
<div class="doc-title">${label}</div>
<div class="text-muted">Not Uploaded</div>
</div>`;
}
return `
<div class="doc-box text-center">
<div class="doc-title">${label}</div>
<img src="${url}"
class="img-thumbnail doc-thumb zoom-img"
data-src="${url}" />
</div>`;
}
function populateModal(record) {
@ -615,6 +687,7 @@
let streetHtml = "";
record.streets.forEach((s, i) => {
const isStatue = s.no_of_statue > 0;
streetHtml += `
<div class="card-section">
<div class="section-title">Street ${i + 1}</div>
@ -622,40 +695,51 @@
<div class="row mb-2">
<div class="col-md-4">
<div class="label-text">Street Name</div>
<div class="value-text">${s.street_name}</div>
<div class="value-text">${s.street_name || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Zone</div>
<div class="value-text">${s.zone}</div>
<div class="label-text">Zone / Ward</div>
<div class="value-text">${s.zone} / ${s.ward}</div>
</div>
${isStatue ? `
<div class="col-md-4">
<div class="label-text">Ward</div>
<div class="value-text">${s.ward}</div>
<div class="label-text">No. of Statue</div>
<div class="value-text">${s.no_of_statue}</div>
</div>
<div class="col-md-4">
<div class="label-text">No. of Poles</div>
<div class="value-text">${s.no_of_poles}</div>
<div class="label-text">Statue Material</div>
<div class="value-text">
${s.statue_material || '-'}
${(s.statue_material || '').toLowerCase() === 'others'
? `(${record.others_specify_statue_material || '-'})`
: ''}
</div>
</div>
<div class="col-md-4">
<div class="label-text">Height</div>
<div class="value-text">${s.height}</div>
<div class="label-text">Pedestal Material</div>
<div class="value-text">${s.pedestal_material || '-'}</div>
</div>
` : `
<div class="col-md-4">
<div class="label-text">No. of Poles</div>
<div class="value-text">${s.no_of_poles}</div>
</div>
<div class="col-md-4">
<div class="label-text">Flag Material</div>
<div class="value-text">${s.flag_material}</div>
<div class="value-text">${s.flag_material || '-'}</div>
</div>
<div class="col-md-4">
<div class="label-text">Pole Material</div>
<div class="value-text">${s.pole_material}</div>
<div class="value-text">${s.pole_material || '-'}</div>
</div>
`}
<div class="col-md-4">
<div class="label-text">Height</div>
<div class="value-text">${s.height || '-'}</div>
</div>
</div>
</div>`;
});
@ -701,14 +785,117 @@
historyHtml += `</div>`;
}
let documentsHtml = "";
if (record.is_final_authority_perm === true) {
// 🔥 Final Authority Permanent → Hide ALL Documents (including Aadhaar)
documentsHtml = "";
} else {
// 🔥 Normal Flow
documentsHtml = `
<div class="card-section">
<div class="section-title">Land Related Documents</div>
<div class="d-flex flex-wrap gap-3">
${renderImage("Land Patta", record.patta_image_url)}
${renderImage("Affidavit", record.affidavit_image_url)}
${renderImage("EC", record.ec_image_url)}
${renderImage("FMB Sketch", record.fmb_sketch_url)}
${renderImage("Aadhaar", record.aadhaar_image_url)}
</div>
</div>`;
}
// let documentsHtml = `
// <div class="card-section">
// <div class="section-title">Land Related Documents</div>
// <div class="row g-3">
// <div class="col-md-3 col-sm-4 col-6 text-center">
// <div class="doc-title">Land Patta</div>
// <a href="https://picsum.photos/300/400?random=1" target="_blank">
// <img src="https://picsum.photos/300/400?random=1"
// class="img-thumbnail doc-thumb">
// </a>
// </div>
// <div class="col-md-3 col-sm-4 col-6 text-center">
// <div class="doc-title">Affidavit</div>
// <a href="https://picsum.photos/300/400?random=2" target="_blank">
// <img src="https://picsum.photos/300/400?random=2"
// class="img-thumbnail doc-thumb">
// </a>
// </div>
// <div class="col-md-3 col-sm-4 col-6 text-center">
// <div class="doc-title">EC</div>
// <a href="https://picsum.photos/300/200?random=3" target="_blank">
// <img src="https://picsum.photos/300/200?random=3"
// class="img-thumbnail doc-thumb">
// </a>
// </div>
// <div class="col-md-3 col-sm-4 col-6 text-center">
// <div class="doc-title">FMB Sketch</div>
// <a href="https://picsum.photos/300/400?random=4" target="_blank">
// <img src="https://picsum.photos/300/400?random=4"
// class="img-thumbnail doc-thumb">
// </a>
// </div>
// <div class="col-md-3 col-sm-4 col-6 text-center">
// <div class="doc-title">Aadhaar</div>
// <a href="https://picsum.photos/300/200?random=5" target="_blank">
// <img src="https://picsum.photos/300/200?random=5"
// class="img-thumbnail doc-thumb">
// </a>
// </div>
// </div>
// </div>`;
// $("#modalContent").html(`
// ${documentsHtml}
// `);
let verificationHtml = "";
if (record.verification_questions && record.verification_questions.length > 0) {
verificationHtml = `
<div class="rdo-box mb-3">
<div class="section-title">Verification Questions</div>
<div id="verificationQuestionsContainer">
`;
record.verification_questions.forEach((q, i) => {
verificationHtml += `
<div class="mb-3 verification-item" data-ques-id="${q.id}">
<label class="form-label">${i + 1}. ${q.question_name}</label>
<select class="form-control verification-answer">
<option value="">Select</option>
${q.answers.map(a => `<option value="${a.id}">${a.answer_name}</option>`).join('')}
</select>
</div>
`;
});
verificationHtml += `
</div>
</div>`;
}
let decisionHtml = "";
// 🔹 Show decision buttons ONLY if pending
if (!record.final_status) {
decisionHtml = `
${documentsHtml}
<div class="rdo-box">
<div class="section-title">Department Decision</div>
${verificationHtml}
<textarea id="rdoRemarks" class="form-control mb-3"
rows="4" placeholder="Enter remarks..."></textarea>
@ -724,6 +911,8 @@
const isPermanent = record.application_type_name === "PERMANENT";
let html = `
<div class="card-section">
<div class="section-title">Applicant Information</div>
@ -740,6 +929,7 @@
</div>
<div class="row mb-2">
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Event Type</div>
<div class="value-text">${record.event_name}</div>
@ -750,12 +940,40 @@
${new Date(record.event_date).toLocaleDateString("en-GB")}
</div>
</div>
` : ""}
<div class="col-md-6">
<div class="label-text">Application Type</div>
<div class="value-text">${record.application_type_name}</div>
</div>
${isPermanent ? `
<div class="col-md-6">
<div class="label-text">Installation Type</div>
<div class="value-text">${record.installation_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Option</div>
<div class="value-text">${record.option_name || '-'}</div>
</div>
<div class="col-md-6">
<div class="label-text">Place of Erection</div>
<div class="value-text">
${record.place_of_erection || '-'}
</div>
</div>
` : ""}
<div class="col-md-6">
<div class="label-text">Address</div>
<div class="value-text">
${record.applicant_address}
</div>
</div>
${!isPermanent ? `
<div class="col-md-6">
<div class="label-text">Total Cost</div>
<div class="value-text">
@ -770,6 +988,7 @@
<div class="label-text">Event Description</div>
<div class="value-text">${record.event_desc}</div>
</div>
` : ""}
</div>
@ -860,6 +1079,7 @@
// });
// }
function submitOfficerDecision(status) {
let remarks = ($("#rdoRemarks").val() || "").trim();
@ -868,6 +1088,32 @@
let gccUserId = $("#loginuserid").val(); // login user id
let username = $("#userName").val(); // display username
// 🔥 Collect verification answers
let answers = [];
$(".verification-item").each(function () {
const quesId = $(this).data("ques-id");
const ansId = $(this).find(".verification-answer").val();
if (!ansId) {
Swal.fire({
icon: 'warning',
title: 'Validation',
text: 'Please answer all verification questions'
});
answers = null;
return false; // break loop
}
answers.push({
quesId: quesId,
ansId: ansId
});
});
if (answers === null) return;
if (!remarks) {
Swal.fire({
icon: 'warning',
@ -897,7 +1143,8 @@
status: status,
remarks: remarks,
gccUserId: gccUserId,
username: username // ✅ NEW
username: username,
answers: JSON.stringify(answers) // 🔥 IMPORTANT
},
success: function (res) {
@ -924,6 +1171,70 @@
}
// function submitOfficerDecision(status) {
// let remarks = ($("#rdoRemarks").val() || "").trim();
// let refid = $("#detailsModal").data("refid");
// let gccUserId = $("#loginuserid").val(); // login user id
// let username = $("#userName").val(); // display username
// if (!remarks) {
// Swal.fire({
// icon: 'warning',
// title: 'Remarks Required',
// text: 'Please enter remarks before submitting'
// });
// return;
// }
// Swal.fire({
// title: `Are you sure?`,
// text: `You want to ${status.toLowerCase()} this request`,
// icon: status === 'APPROVED' ? 'success' : 'error',
// showCancelButton: true,
// confirmButtonColor: status === 'APPROVED' ? '#28a745' : '#dc3545',
// cancelButtonColor: '#6c757d',
// confirmButtonText: `Yes, ${status}`
// }).then((result) => {
// if (!result.isConfirmed) return;
// $.ajax({
// url: "/flagpoles/api/flagpoleregistration/officer/updateDecision",
// type: "POST",
// data: {
// refid: refid,
// status: status,
// remarks: remarks,
// gccUserId: gccUserId,
// username: username // ✅ NEW
// },
// success: function (res) {
// Swal.fire({
// icon: 'success',
// title: status === 'APPROVED' ? 'Approved!' : 'Rejected!',
// text: res.message || `Request has been ${status.toLowerCase()}`,
// timer: 2000,
// showConfirmButton: false
// });
// $("#detailsModal").modal("hide");
// $("#QaqcDatatable").DataTable().ajax.reload(null, false);
// },
// error: function () {
// Swal.fire({
// icon: 'error',
// title: 'Error',
// text: 'Failed to update decision'
// });
// }
// });
// });
// }
</script>
</body>
Loading…
Cancel
Save