12 changed files with 2883 additions and 43 deletions
-
19src/main/java/com/gcc_manpower/config/DataSourceConfig.java
-
51src/main/java/com/gcc_manpower/config/WebConfig.java
-
17src/main/java/com/gcc_manpower/gccservicedocuments/controller/GccServiceDocumentsController.java
-
4src/main/java/com/gcc_manpower/gccservicedocuments/service/GccServiceDocumentsService.java
-
10src/main/java/com/gcc_manpower/gccservicedocuments/service/VideoCompressionService.java
-
260src/main/java/com/gcc_manpower/gccservicepaymenttracker/controller/GccServicePaymentTrackerController.java
-
285src/main/java/com/gcc_manpower/gccservicepaymenttracker/service/GccServicePaymentTrackerService.java
-
4src/main/resources/application-local.properties
-
6src/main/resources/application.properties
-
4src/main/resources/templates/fragments/navbar.html
-
2151src/main/resources/templates/gccservicepaymenttracker/dashboard.html
-
115src/main/resources/templates/gccservicepaymenttracker/login.html
@ -0,0 +1,260 @@ |
|||||
|
package com.gcc_manpower.gccservicepaymenttracker.controller; |
||||
|
|
||||
|
import com.gcc_manpower.gccservicepaymenttracker.service.GccServicePaymentTrackerService; |
||||
|
import com.gcc_manpower.service.AppUserService; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.ui.Model; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
import jakarta.servlet.http.HttpSession; |
||||
|
import org.springframework.http.CacheControl; |
||||
|
import org.springframework.http.ResponseEntity; |
||||
|
import java.io.File; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Controller |
||||
|
@RequestMapping("/gccservicepaymenttracker") |
||||
|
public class GccServicePaymentTrackerController { |
||||
|
|
||||
|
@Autowired |
||||
|
private GccServicePaymentTrackerService paymentTrackerService; |
||||
|
|
||||
|
@Autowired |
||||
|
private AppUserService appUserService; |
||||
|
|
||||
|
@Value("${payment.tracker.upload.path:gccpaymenttrackerfiles}") |
||||
|
private String paymentTrackerUploadPathConfig; |
||||
|
|
||||
|
@GetMapping({ "", "/", "/dashboard" }) |
||||
|
public String viewDashboard(Model model, HttpSession session) { |
||||
|
String username = (String) session.getAttribute("usrName"); |
||||
|
if (username == null) { |
||||
|
return "redirect:/gccservicepaymenttracker/login"; |
||||
|
} |
||||
|
|
||||
|
String usrRole = (String) session.getAttribute("usrRole"); |
||||
|
boolean isAdmin = "ADMIN".equalsIgnoreCase(usrRole); |
||||
|
|
||||
|
List<Map<String, Object>> vendorDetails = appUserService.getVendorDetailsWithCounts(); |
||||
|
|
||||
|
model.addAttribute("isLoggedIn", true); |
||||
|
model.addAttribute("isAdmin", isAdmin); |
||||
|
model.addAttribute("usrName", username); |
||||
|
model.addAttribute("curPage", "gccservicepaymenttracker"); |
||||
|
model.addAttribute("vendorDetails", vendorDetails); |
||||
|
|
||||
|
return "gccservicepaymenttracker/dashboard"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/login") |
||||
|
public String login(HttpSession session) { |
||||
|
if (session.getAttribute("usrName") != null) { |
||||
|
return "redirect:/gccservicepaymenttracker/dashboard"; |
||||
|
} |
||||
|
return "gccservicepaymenttracker/login"; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/login") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> validateLogin( |
||||
|
@RequestParam("usrName") String usrName, |
||||
|
@RequestParam("usrPass") String usrPass, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> authResult = appUserService.authenticate(usrName, usrPass); |
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
|
||||
|
if (Boolean.TRUE.equals(authResult.get("success"))) { |
||||
|
session.setAttribute("usrName", authResult.get("usrName")); |
||||
|
session.setAttribute("usrRole", authResult.get("usrRole")); |
||||
|
session.setMaxInactiveInterval(1800); // 30 minutes session timeout |
||||
|
response.put("result", true); |
||||
|
response.put("usrName", authResult.get("usrName")); |
||||
|
} else { |
||||
|
response.put("result", false); |
||||
|
response.put("error", authResult.get("error")); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/logout") |
||||
|
public String logout(HttpSession session) { |
||||
|
session.removeAttribute("usrName"); |
||||
|
session.removeAttribute("usrRole"); |
||||
|
session.invalidate(); |
||||
|
return "redirect:/gccservicepaymenttracker/login"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/logout") |
||||
|
public String logoutGet(HttpSession session) { |
||||
|
session.removeAttribute("usrName"); |
||||
|
session.removeAttribute("usrRole"); |
||||
|
session.invalidate(); |
||||
|
return "redirect:/gccservicepaymenttracker/login"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/counts") |
||||
|
@ResponseBody |
||||
|
public ResponseEntity<Map<String, Integer>> getCounts() { |
||||
|
return ResponseEntity.ok() |
||||
|
.cacheControl(CacheControl.noCache().mustRevalidate()) |
||||
|
.body(paymentTrackerService.getCountsByCategory()); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/list") |
||||
|
@ResponseBody |
||||
|
public ResponseEntity<List<Map<String, Object>>> listDetails( |
||||
|
@RequestParam(value = "category", required = false) String category, |
||||
|
@RequestParam(value = "fromDate", required = false) String fromDate, |
||||
|
@RequestParam(value = "toDate", required = false) String toDate, |
||||
|
@RequestParam(value = "status", required = false) String status) { |
||||
|
List<Map<String, Object>> details = paymentTrackerService.searchDetails(category, fromDate, toDate, status); |
||||
|
return ResponseEntity.ok() |
||||
|
.cacheControl(CacheControl.noCache().mustRevalidate()) |
||||
|
.body(details); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveDetail( |
||||
|
@RequestBody Map<String, Object> payload, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access! Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
String usrRole = (String) session.getAttribute("usrRole"); |
||||
|
if (!"ADMIN".equalsIgnoreCase(usrRole)) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Access denied! Only admins can save or update records."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
boolean saved = paymentTrackerService.saveOrUpdateDetail(payload); |
||||
|
response.put("success", saved); |
||||
|
if (!saved) { |
||||
|
response.put("error", "Failed to save details to database."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/delete") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> deleteDetail( |
||||
|
@RequestParam("id") int id, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access! Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
String usrRole = (String) session.getAttribute("usrRole"); |
||||
|
if (!"ADMIN".equalsIgnoreCase(usrRole)) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Access denied! Only admins can delete records."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
boolean deleted = paymentTrackerService.deleteDetail(id); |
||||
|
response.put("success", deleted); |
||||
|
if (!deleted) { |
||||
|
response.put("error", "Failed to delete record."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/upload-pdf") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> uploadPdf( |
||||
|
@RequestParam("file") MultipartFile file, |
||||
|
HttpSession session) { |
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access! Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
String usrRole = (String) session.getAttribute("usrRole"); |
||||
|
if (!"ADMIN".equalsIgnoreCase(usrRole)) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Access denied! Only admins can upload files."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
if (file.isEmpty()) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Please select a file to upload."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(paymentTrackerUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) { |
||||
|
uploadDir.mkdirs(); |
||||
|
} |
||||
|
|
||||
|
String originalFilename = file.getOriginalFilename(); |
||||
|
String nameWithoutExt = "pdf"; |
||||
|
String ext = ".pdf"; |
||||
|
if (originalFilename != null && originalFilename.contains(".")) { |
||||
|
int dotIdx = originalFilename.lastIndexOf("."); |
||||
|
nameWithoutExt = originalFilename.substring(0, dotIdx); |
||||
|
ext = originalFilename.substring(dotIdx); |
||||
|
} |
||||
|
nameWithoutExt = nameWithoutExt.replaceAll("[^a-zA-Z0-9-_]", "_"); |
||||
|
String savedFilename = nameWithoutExt + "_" + System.currentTimeMillis() + ext; |
||||
|
|
||||
|
File destFile = new File(uploadDir, savedFilename).getAbsoluteFile(); |
||||
|
file.transferTo(destFile); |
||||
|
|
||||
|
String fileWebUrl = "/gccpaymenttrackerfiles/" + savedFilename; |
||||
|
response.put("success", true); |
||||
|
response.put("filePath", fileWebUrl); |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "File upload failed: " + e.getMessage()); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/types") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getActiveTypes() { |
||||
|
return paymentTrackerService.getActiveTypes(); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/vendors") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getActiveVendors() { |
||||
|
return paymentTrackerService.getActiveVendors(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,285 @@ |
|||||
|
package com.gcc_manpower.gccservicepaymenttracker.service; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import javax.sql.DataSource; |
||||
|
import jakarta.annotation.PostConstruct; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Service |
||||
|
public class GccServicePaymentTrackerService { |
||||
|
|
||||
|
private JdbcTemplate jdbcTemplate; |
||||
|
|
||||
|
@Autowired |
||||
|
public void setDataSource(@Qualifier("mysqlPaymentTrackingServiceDataSource") DataSource dataSource) { |
||||
|
this.jdbcTemplate = new JdbcTemplate(dataSource); |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> getCountsByCategory() { |
||||
|
Map<String, Integer> counts = new HashMap<>(); |
||||
|
counts.put("sd", 0); |
||||
|
counts.put("tax invoice", 0); |
||||
|
counts.put("emd", 0); |
||||
|
counts.put("bank guarantee", 0); |
||||
|
counts.put("delivery chellan", 0); |
||||
|
counts.put("asd", 0); |
||||
|
counts.put("agreement", 0); |
||||
|
|
||||
|
String sql = "SELECT " |
||||
|
+ "CASE WHEN p.type REGEXP '^[0-9]+$' THEN t.type_name ELSE p.type END as type_resolved, " |
||||
|
+ "COUNT(*) as cnt " |
||||
|
+ "FROM payment_tracking_details p " |
||||
|
+ "LEFT JOIN type_list t ON p.type REGEXP '^[0-9]+$' AND t.id = p.type " |
||||
|
+ "WHERE p.is_active = 1 AND p.is_delete = 0 " |
||||
|
+ "GROUP BY type_resolved"; |
||||
|
|
||||
|
try { |
||||
|
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql); |
||||
|
for (Map<String, Object> row : rows) { |
||||
|
String type = String.valueOf(row.get("type_resolved")).toLowerCase().trim(); |
||||
|
Number countNum = (Number) row.get("cnt"); |
||||
|
int count = countNum != null ? countNum.intValue() : 0; |
||||
|
|
||||
|
// Map database values back to categories |
||||
|
if (type.equals("asd") || type.contains("asd") || type.contains("additional security")) { |
||||
|
counts.put("asd", counts.getOrDefault("asd", 0) + count); |
||||
|
} else if (type.equals("agreement") || type.contains("agreement")) { |
||||
|
counts.put("agreement", counts.getOrDefault("agreement", 0) + count); |
||||
|
} else if (type.equals("sd") || type.contains("security")) { |
||||
|
counts.put("sd", counts.getOrDefault("sd", 0) + count); |
||||
|
} else if (type.contains("invoice") || type.contains("bill")) { |
||||
|
counts.put("tax invoice", counts.getOrDefault("tax invoice", 0) + count); |
||||
|
} else if (type.equals("emd")) { |
||||
|
counts.put("emd", counts.getOrDefault("emd", 0) + count); |
||||
|
} else if (type.contains("guarantee") || type.contains("bg")) { |
||||
|
counts.put("bank guarantee", counts.getOrDefault("bank guarantee", 0) + count); |
||||
|
} else if (type.contains("chellan") || type.contains("challan") || type.contains("dc")) { |
||||
|
counts.put("delivery chellan", counts.getOrDefault("delivery chellan", 0) + count); |
||||
|
} |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error getting category counts: " + e.getMessage()); |
||||
|
} |
||||
|
return counts; |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> searchDetails(String type, String fromDate, String toDate, String status) { |
||||
|
StringBuilder sql = new StringBuilder( |
||||
|
"SELECT p.*, " |
||||
|
+ "t.type_name as resolved_type, " |
||||
|
+ "v.vendor_name as resolved_vendor " |
||||
|
+ "FROM payment_tracking_details p " |
||||
|
+ "LEFT JOIN type_list t ON p.type REGEXP '^[0-9]+$' AND t.id = p.type " |
||||
|
+ "LEFT JOIN vendors_list v ON p.vendor_name REGEXP '^[0-9]+$' AND v.id = p.vendor_name " |
||||
|
+ "WHERE p.is_active = 1 AND p.is_delete = 0"); |
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
|
||||
|
if (type != null && !type.trim().isEmpty()) { |
||||
|
String category = type.trim().toLowerCase(); |
||||
|
if (category.equals("asd")) { |
||||
|
sql.append(" AND (LOWER(p.type) = 'asd' OR LOWER(p.type) LIKE '%asd%' OR LOWER(t.type_name) LIKE '%asd%' OR LOWER(t.type_name) LIKE '%additional security%')"); |
||||
|
} else if (category.equals("agreement")) { |
||||
|
sql.append(" AND (LOWER(p.type) LIKE '%agreement%' OR LOWER(t.type_name) LIKE '%agreement%')"); |
||||
|
} else if (category.equals("sd")) { |
||||
|
sql.append(" AND ((LOWER(p.type) = 'sd' OR LOWER(p.type) LIKE '%security%' OR LOWER(t.type_name) LIKE '%security%') " |
||||
|
+ "AND LOWER(p.type) NOT LIKE '%additional security%' AND LOWER(p.type) NOT LIKE '%asd%' " |
||||
|
+ "AND (t.type_name IS NULL OR (LOWER(t.type_name) NOT LIKE '%additional security%' AND LOWER(t.type_name) NOT LIKE '%asd%')))"); |
||||
|
} else if (category.equals("tax invoice")) { |
||||
|
sql.append(" AND (LOWER(p.type) LIKE '%invoice%' OR LOWER(p.type) LIKE '%bill%' OR LOWER(t.type_name) LIKE '%invoice%' OR LOWER(t.type_name) LIKE '%bill%')"); |
||||
|
} else if (category.equals("emd")) { |
||||
|
sql.append(" AND (LOWER(p.type) = 'emd' OR LOWER(p.type) LIKE '%earnest%' OR LOWER(t.type_name) LIKE '%emd%' OR LOWER(t.type_name) LIKE '%earnest%')"); |
||||
|
} else if (category.equals("bank guarantee")) { |
||||
|
sql.append(" AND (LOWER(p.type) LIKE '%guarantee%' OR LOWER(p.type) = 'bg' OR LOWER(t.type_name) LIKE '%guarantee%' OR LOWER(t.type_name) = 'bg')"); |
||||
|
} else if (category.equals("delivery chellan")) { |
||||
|
sql.append(" AND (LOWER(p.type) LIKE '%chellan%' OR LOWER(p.type) LIKE '%challan%' OR LOWER(p.type) = 'dc' " |
||||
|
+ "OR LOWER(t.type_name) LIKE '%chellan%' OR LOWER(t.type_name) LIKE '%challan%' OR LOWER(t.type_name) = 'dc')"); |
||||
|
} else { |
||||
|
sql.append(" AND (LOWER(p.type) = ? OR LOWER(t.type_name) = ?)"); |
||||
|
params.add(category); |
||||
|
params.add(category); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (fromDate != null && !fromDate.trim().isEmpty()) { |
||||
|
sql.append(" AND p.received_date >= ?"); |
||||
|
params.add(parseDate(fromDate)); |
||||
|
} |
||||
|
|
||||
|
if (toDate != null && !toDate.trim().isEmpty()) { |
||||
|
sql.append(" AND p.received_date <= ?"); |
||||
|
params.add(parseDate(toDate)); |
||||
|
} |
||||
|
|
||||
|
if (status != null && !status.trim().isEmpty()) { |
||||
|
sql.append(" AND LOWER(p.status) = ?"); |
||||
|
params.add(status.trim().toLowerCase()); |
||||
|
} |
||||
|
|
||||
|
sql.append(" ORDER BY p.order_by ASC, p.received_date DESC, p.id DESC"); |
||||
|
|
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql.toString(), params.toArray()); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error searching payment tracking details: " + e.getMessage()); |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Map<String, Object> getDetailById(int id) { |
||||
|
String sql = "SELECT * FROM payment_tracking_details WHERE id = ? AND is_active = 1 AND is_delete = 0"; |
||||
|
try { |
||||
|
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, id); |
||||
|
if (list != null && !list.isEmpty()) { |
||||
|
return list.get(0); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error fetching payment tracking detail ID " + id + ": " + e.getMessage()); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public boolean saveOrUpdateDetail(Map<String, Object> payload) { |
||||
|
Object idObj = payload.get("id"); |
||||
|
java.sql.Date receivedDate = parseDate(payload.get("received_date")); |
||||
|
String vendorName = (String) payload.get("vendor_name"); |
||||
|
String subject = (String) payload.get("subject"); |
||||
|
String amount = (String) payload.get("amount"); |
||||
|
String invoiceNo = (String) payload.get("invoice_no"); |
||||
|
String receiptNo = payload.get("receiptno") != null ? String.valueOf(payload.get("receiptno")) : null; |
||||
|
java.sql.Date invoiceDate = parseDate(payload.get("invoice_date")); |
||||
|
String type = (String) payload.get("type"); |
||||
|
String physicalFileNo = (String) payload.get("physical_file_no"); |
||||
|
String remarks = (String) payload.get("remarks"); |
||||
|
String tat = (String) payload.get("tat"); |
||||
|
String status = (String) payload.get("status"); |
||||
|
String followup = (String) payload.get("followup"); |
||||
|
String myfollowup = (String) payload.get("myfollowup"); |
||||
|
String orderBy = (String) payload.get("order_by"); |
||||
|
String filePath = (String) payload.get("file_path"); |
||||
|
|
||||
|
if (idObj != null && !String.valueOf(idObj).trim().isEmpty()) { |
||||
|
// Update |
||||
|
int id = Integer.parseInt(String.valueOf(idObj).trim()); |
||||
|
String sql = "UPDATE payment_tracking_details SET " |
||||
|
+ "received_date = ?, vendor_name = ?, subject = ?, amount = ?, invoice_no = ?, " |
||||
|
+ "receiptno = ?, invoice_date = ?, type = ?, physical_file_no = ?, remarks = ?, " |
||||
|
+ "tat = ?, status = ?, followup = ?, myfollowup = ?, order_by = ?, file_path = ? " |
||||
|
+ "WHERE id = ? AND is_active = 1 AND is_delete = 0"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo, |
||||
|
receiptNo, invoiceDate, type, physicalFileNo, remarks, |
||||
|
tat, status, followup, myfollowup, orderBy, filePath, id); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error updating payment tracking detail ID " + id + ": " + e.getMessage()); |
||||
|
return false; |
||||
|
} |
||||
|
} else { |
||||
|
// Insert |
||||
|
String sql = "INSERT INTO payment_tracking_details (" |
||||
|
+ "received_date, vendor_name, subject, amount, invoice_no, receiptno, " |
||||
|
+ "invoice_date, type, physical_file_no, remarks, tat, status, " |
||||
|
+ "followup, myfollowup, is_active, is_delete, order_by, file_path" |
||||
|
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?, ?)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo, |
||||
|
receiptNo, invoiceDate, type, physicalFileNo, remarks, |
||||
|
tat, status, followup, myfollowup, orderBy, filePath); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error saving payment tracking detail: " + e.getMessage()); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public boolean deleteDetail(int id) { |
||||
|
String sql = "UPDATE payment_tracking_details SET is_active = 0, is_delete = 1 WHERE id = ?"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, id); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error soft-deleting payment tracking detail ID " + id + ": " + e.getMessage()); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private java.sql.Date parseDate(Object obj) { |
||||
|
if (obj == null || String.valueOf(obj).trim().isEmpty()) { |
||||
|
return null; |
||||
|
} |
||||
|
String str = String.valueOf(obj).trim(); |
||||
|
try { |
||||
|
// Support both yyyy-MM-dd and dd/MM/yyyy |
||||
|
if (str.contains("/")) { |
||||
|
String[] parts = str.split("/"); |
||||
|
if (parts.length == 3) { |
||||
|
// Convert dd/MM/yyyy to yyyy-MM-dd |
||||
|
str = parts[2] + "-" + parts[1] + "-" + parts[0]; |
||||
|
} |
||||
|
} |
||||
|
return java.sql.Date.valueOf(str); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error parsing date '" + obj + "': " + e.getMessage()); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private java.sql.Timestamp parseTimestamp(Object obj) { |
||||
|
if (obj == null || String.valueOf(obj).trim().isEmpty()) { |
||||
|
return null; |
||||
|
} |
||||
|
String str = String.valueOf(obj).trim(); |
||||
|
try { |
||||
|
if (str.contains("/")) { |
||||
|
// Parse format dd/MM/yyyy HH:mm:ss or similar if provided |
||||
|
// For simplicity, fallback to current time or standard parsing if it fails |
||||
|
} |
||||
|
if (str.contains("T")) { |
||||
|
str = str.replace("T", " "); |
||||
|
} |
||||
|
if (str.length() == 16) { |
||||
|
str = str + ":00"; |
||||
|
} |
||||
|
return java.sql.Timestamp.valueOf(str); |
||||
|
} catch (Exception e) { |
||||
|
// Try parsing as DATE first, then convert to TIMESTAMP |
||||
|
java.sql.Date d = parseDate(obj); |
||||
|
if (d != null) { |
||||
|
return new java.sql.Timestamp(d.getTime()); |
||||
|
} |
||||
|
System.err.println("Error parsing timestamp '" + obj + "': " + e.getMessage()); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getActiveTypes() { |
||||
|
String sql = "SELECT id, type_name FROM type_list " |
||||
|
+ "WHERE is_active = 1 AND is_delete = 0 " |
||||
|
+ "ORDER BY order_by ASC, type_name ASC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error fetching active types: " + e.getMessage()); |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getActiveVendors() { |
||||
|
String sql = "SELECT id, vendor_name FROM vendors_list " |
||||
|
+ "WHERE is_active = 1 AND is_delete = 0 " |
||||
|
+ "ORDER BY order_by ASC, vendor_name ASC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
System.err.println("Error fetching active vendors: " + e.getMessage()); |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
#spring.profiles.active=local |
|
||||
spring.profiles.active=prod |
|
||||
|
spring.profiles.active=local |
||||
|
#spring.profiles.active=prod |
||||
spring.application.name=gcc-manpower |
spring.application.name=gcc-manpower |
||||
server.servlet.session.timeout=10m |
server.servlet.session.timeout=10m |
||||
|
|
||||
|
|
||||
2151
src/main/resources/templates/gccservicepaymenttracker/dashboard.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,115 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html xmlns:th="http://www.thymeleaf.org" lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<title>GCC Payment Tracker - Login</title> |
||||
|
|
||||
|
<!-- CSRF Tokens --> |
||||
|
<meta th:if="${_csrf != null}" name="_csrf" th:content="${_csrf.token}" /> |
||||
|
<meta th:if="${_csrf != null}" name="_csrf_header" th:content="${_csrf.headerName}" /> |
||||
|
|
||||
|
<!-- Include CSS --> |
||||
|
<link rel="stylesheet" type="text/css" th:href="@{/assets/css/login-form-styles.css}"> |
||||
|
|
||||
|
<!-- Awesome Font --> |
||||
|
<link th:href="@{/assets/font-awesome-6.5.2/css/all.min.css}" rel="stylesheet" type="text/css"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div class="container"> |
||||
|
<img th:src="@{/assets/header-images/gcc1.png}" alt="Greater Chennai Corporation" class="small-logo"> |
||||
|
<h3>GREATER CHENNAI CORPORATION</h3> |
||||
|
<h4>பெருநகர சென்னை மாநகராட்சி</h4> |
||||
|
<br> |
||||
|
<h3>GCC Service Payment Processing Tracker</h3> |
||||
|
<br> |
||||
|
<h2>Login</h2> |
||||
|
|
||||
|
<div id="error-box" |
||||
|
style="color: #c0392b; font-weight: 500; font-size: 0.85rem; margin-bottom: 1.5rem; text-align: center; display: none;"> |
||||
|
<i class="fa-solid fa-circle-exclamation"></i> <span id="error-text">Invalid username or password!</span> |
||||
|
</div> |
||||
|
|
||||
|
<form id="loginForm" onsubmit="handleLogin(event)"> |
||||
|
<div class="input-field"> |
||||
|
<input type="text" name="usrName" id="usrName" placeholder="Enter Username" required |
||||
|
autocomplete="username"> |
||||
|
<div class="underline"></div> |
||||
|
</div> |
||||
|
<div class="input-field"> |
||||
|
<input type="password" name="usrPass" id="usrPass" placeholder="Enter Password" required |
||||
|
autocomplete="current-password"> |
||||
|
<div class="underline"></div> |
||||
|
</div> |
||||
|
<input type="submit" value="Login" id="submit-btn"> |
||||
|
</form> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Footer Fragment --> |
||||
|
<th:block th:replace="~{fragments/footer :: footer}"></th:block> |
||||
|
|
||||
|
<!-- Custom JS --> |
||||
|
<script th:inline="javascript"> |
||||
|
const contextPath = /*[[@{/}]]*/ ''; |
||||
|
</script> |
||||
|
|
||||
|
<script> |
||||
|
function handleLogin(event) { |
||||
|
event.preventDefault(); |
||||
|
|
||||
|
const errorBox = document.getElementById("error-box"); |
||||
|
const errorText = document.getElementById("error-text"); |
||||
|
const submitBtn = document.getElementById("submit-btn"); |
||||
|
|
||||
|
errorBox.style.display = "none"; |
||||
|
submitBtn.disabled = true; |
||||
|
submitBtn.value = 'Authenticating...'; |
||||
|
|
||||
|
const username = document.getElementById("usrName").value; |
||||
|
const password = document.getElementById("usrPass").value; |
||||
|
|
||||
|
const urlParams = new URLSearchParams(); |
||||
|
urlParams.append('usrName', username); |
||||
|
urlParams.append('usrPass', password); |
||||
|
|
||||
|
// Fetch CSRF tokens |
||||
|
const csrfToken = document.querySelector("meta[name='_csrf']")?.getAttribute("content"); |
||||
|
const csrfHeader = document.querySelector("meta[name='_csrf_header']")?.getAttribute("content"); |
||||
|
|
||||
|
const headers = { |
||||
|
'Content-Type': 'application/x-www-form-urlencoded' |
||||
|
}; |
||||
|
if (csrfToken && csrfHeader) { |
||||
|
headers[csrfHeader] = csrfToken; |
||||
|
} |
||||
|
|
||||
|
fetch(contextPath + 'gccservicepaymenttracker/api/login', { |
||||
|
method: 'POST', |
||||
|
headers: headers, |
||||
|
body: urlParams |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(data => { |
||||
|
if (data.result) { |
||||
|
window.location.href = contextPath + 'gccservicepaymenttracker/dashboard'; |
||||
|
} else { |
||||
|
submitBtn.disabled = false; |
||||
|
submitBtn.value = 'Login'; |
||||
|
errorText.textContent = data.error || "Authentication failed."; |
||||
|
errorBox.style.display = "block"; |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
console.error("Login Error:", err); |
||||
|
submitBtn.disabled = false; |
||||
|
submitBtn.value = 'Login'; |
||||
|
errorText.textContent = "Network error. Please try again later."; |
||||
|
errorBox.style.display = "block"; |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue