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 jakarta.servlet.http.HttpServletRequest; 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; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; @Controller @RequestMapping("/gccservicepaymenttracker") public class GccServicePaymentTrackerController { @Autowired private GccServicePaymentTrackerService paymentTrackerService; @Autowired private AppUserService appUserService; @Autowired private AuthenticationManager authenticationManager; @Value("${payment.tracker.upload.path:gccpaymenttrackerfiles}") private String paymentTrackerUploadPathConfig; @GetMapping({ "", "/", "/dashboard" }) public String viewDashboard(Model model, HttpSession session) { String username = (String) session.getAttribute("pay_usrName"); if (username == null) { return "redirect:/gccservicepaymenttracker/login"; } String usrRole = (String) session.getAttribute("pay_usrRole"); boolean isAdmin = "ADMIN".equalsIgnoreCase(usrRole); List> 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("/details") public String viewDetails(HttpSession session, Model model) { String username = (String) session.getAttribute("pay_usrName"); if (username == null) { return "redirect:/gccservicepaymenttracker/login"; } String usrRole = (String) session.getAttribute("pay_usrRole"); boolean isAdmin = "ADMIN".equalsIgnoreCase(usrRole); model.addAttribute("isLoggedIn", true); model.addAttribute("isAdmin", isAdmin); model.addAttribute("usrName", username); model.addAttribute("curPage", "gccservicepaymenttracker"); return "gccservicepaymenttracker/details"; } @GetMapping("/login") public String login(HttpSession session) { return "gccservicepaymenttracker/login"; } @PostMapping("/api/login") @ResponseBody public Map validateLogin( @RequestParam("usrName") String usrName, @RequestParam("usrPass") String usrPass, HttpSession session) { Map response = new HashMap<>(); try { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(usrName, usrPass); Authentication authentication = authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); String role = authentication.getAuthorities().stream() .map(auth -> auth.getAuthority().replace("ROLE_", "")) .findFirst() .orElse("USER"); session.setAttribute("pay_usrName", usrName); session.setAttribute("pay_usrRole", role); session.setMaxInactiveInterval(1800); // 30 minutes session timeout response.put("result", true); response.put("usrName", usrName); } catch (AuthenticationException e) { response.put("result", false); response.put("error", e.getMessage() != null ? e.getMessage() : "Invalid username or password!"); } return response; } @PostMapping("/logout") public String logout(HttpSession session, HttpServletRequest request) { SecurityContextHolder.clearContext(); if (session != null) { session.removeAttribute("pay_usrName"); session.removeAttribute("pay_usrRole"); session.invalidate(); } request.getSession(true); return "redirect:/gccservicepaymenttracker/login"; } @GetMapping("/logout") public String logoutGet(HttpSession session, HttpServletRequest request) { SecurityContextHolder.clearContext(); if (session != null) { session.removeAttribute("pay_usrName"); session.removeAttribute("pay_usrRole"); session.invalidate(); } request.getSession(true); return "redirect:/gccservicepaymenttracker/login"; } @GetMapping("/api/counts") @ResponseBody public ResponseEntity> getCounts() { return ResponseEntity.ok() .cacheControl(CacheControl.noCache().mustRevalidate()) .body(paymentTrackerService.getCountsByCategory()); } @GetMapping("/api/list") @ResponseBody public ResponseEntity>> 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> details = paymentTrackerService.searchDetails(category, fromDate, toDate, status); return ResponseEntity.ok() .cacheControl(CacheControl.noCache().mustRevalidate()) .body(details); } @PostMapping("/api/save") @ResponseBody public Map saveDetail( @RequestBody Map payload, HttpSession session) { Map response = new HashMap<>(); String username = (String) session.getAttribute("pay_usrName"); if (username == null) { 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("pay_usrRole"); if (usrRole == null) { 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, username); 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 deleteDetail( @RequestParam("id") int id, @RequestParam(value = "remarks", required = false, defaultValue = "") String remarks, HttpSession session) { Map response = new HashMap<>(); String username = (String) session.getAttribute("pay_usrName"); if (username == null) { 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("pay_usrRole"); if (usrRole == null) { 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, remarks, username); 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 uploadPdf( @RequestParam("file") MultipartFile file, HttpSession session) { Map response = new HashMap<>(); String username = (String) session.getAttribute("pay_usrName"); if (username == null) { 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("pay_usrRole"); if (usrRole == null) { 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; } @PostMapping("/api/upload-screenshot") @ResponseBody public Map uploadScreenshot( @RequestParam("file") MultipartFile file, HttpSession session) { Map response = new HashMap<>(); String username = (String) session.getAttribute("pay_usrName"); if (username == null) { 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("pay_usrRole"); if (usrRole == null) { 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 parentDir = new File(paymentTrackerUploadPathConfig).getAbsoluteFile(); File screenshotDir = new File(parentDir, "screenshots"); if (!screenshotDir.exists()) { screenshotDir.mkdirs(); } String originalFilename = file.getOriginalFilename(); String nameWithoutExt = "screenshot"; String ext = ".png"; 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(screenshotDir, savedFilename).getAbsoluteFile(); file.transferTo(destFile); String fileWebUrl = "/gccpaymenttrackerfiles/screenshots/" + savedFilename; response.put("success", true); response.put("filePath", fileWebUrl); } catch (Exception e) { response.put("success", false); response.put("error", "Screenshot upload failed: " + e.getMessage()); } return response; } @GetMapping("/api/types") @ResponseBody public List> getActiveTypes() { return paymentTrackerService.getActiveTypes(); } @GetMapping("/api/vendors") @ResponseBody public List> getActiveVendors() { return paymentTrackerService.getActiveVendors(); } @GetMapping("/api/statuslist") @ResponseBody public List> getStatusList() { return paymentTrackerService.getStatusList(); } @GetMapping("/api/history") @ResponseBody public ResponseEntity>> getHistory( @RequestParam("id") int id, HttpSession session) { String username = (String) session.getAttribute("pay_usrName"); if (username == null) { username = (String) session.getAttribute("usrName"); } if (username == null) { return ResponseEntity.status(401).body(null); } return ResponseEntity.ok() .cacheControl(CacheControl.noCache().mustRevalidate()) .body(paymentTrackerService.getHistory(id)); } @GetMapping("/api/deleted-list") @ResponseBody public ResponseEntity>> getDeletedList(HttpSession session) { String username = (String) session.getAttribute("pay_usrName"); if (username == null) { username = (String) session.getAttribute("usrName"); } if (username == null) { return ResponseEntity.status(401).body(null); } return ResponseEntity.ok() .cacheControl(CacheControl.noCache().mustRevalidate()) .body(paymentTrackerService.getDeletedDetails()); } @PostMapping("/api/restore") @ResponseBody public Map restoreDetail( @RequestParam("id") int id, HttpSession session) { Map response = new HashMap<>(); String username = (String) session.getAttribute("pay_usrName"); if (username == null) { 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("pay_usrRole"); if (usrRole == null) { usrRole = (String) session.getAttribute("usrRole"); } if (!"ADMIN".equalsIgnoreCase(usrRole)) { response.put("success", false); response.put("error", "Access denied! Only admins can restore records."); return response; } try { boolean restored = paymentTrackerService.restoreDetail(id, username); response.put("success", restored); if (!restored) { response.put("error", "Failed to restore record."); } } catch (Exception e) { response.put("success", false); response.put("error", "Error: " + e.getMessage()); } return response; } }