10 changed files with 7872 additions and 1519 deletions
-
14src/main/java/com/gcc_manpower/config/SecurityConfig.java
-
12src/main/java/com/gcc_manpower/config/WebConfig.java
-
518src/main/java/com/gcc_manpower/gccrentalmanagement/controller/RentalController.java
-
491src/main/java/com/gcc_manpower/gccrentalmanagement/service/RentalService.java
-
247src/main/java/com/gcc_manpower/gcctonermanagement/controller/TonerController.java
-
272src/main/java/com/gcc_manpower/gcctonermanagement/service/TonerService.java
-
22src/main/resources/templates/fragments/rentalheader.html
-
3080src/main/resources/templates/gccrentalmanagement/dashboard.html
-
429src/main/resources/templates/gccrentalmanagement/login.html
-
4300src/main/resources/templates/gcctonermanagement/upload.html
@ -0,0 +1,518 @@ |
|||||
|
package com.gcc_manpower.gccrentalmanagement.controller; |
||||
|
|
||||
|
import java.io.File; |
||||
|
import java.io.FileOutputStream; |
||||
|
import java.io.InputStream; |
||||
|
import java.io.OutputStream; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.Date; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
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.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import com.gcc_manpower.gccrentalmanagement.service.RentalService; |
||||
|
import com.gcc_manpower.service.AppUserService; |
||||
|
import jakarta.servlet.http.HttpSession; |
||||
|
import jakarta.servlet.http.HttpServletRequest; |
||||
|
|
||||
|
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("/gccrentalmanagement") |
||||
|
public class RentalController { |
||||
|
|
||||
|
@Autowired |
||||
|
private AppUserService appUserService; |
||||
|
|
||||
|
@Autowired |
||||
|
private RentalService rentalService; |
||||
|
|
||||
|
@Autowired |
||||
|
private AuthenticationManager authenticationManager; |
||||
|
|
||||
|
@Value("${rental.upload.path:gccrentalmanagementfiles}") |
||||
|
private String rentalUploadPathConfig; |
||||
|
|
||||
|
@GetMapping({ "", "/", "/dashboard" }) |
||||
|
public String viewDashboard(Model model, HttpSession session) { |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
return "redirect:/gccrentalmanagement/login"; |
||||
|
} |
||||
|
|
||||
|
String usrRole = (String) session.getAttribute("rental_usrRole"); |
||||
|
boolean isAdmin = "ADMIN".equalsIgnoreCase(usrRole); |
||||
|
|
||||
|
model.addAttribute("isLoggedIn", true); |
||||
|
model.addAttribute("isAdmin", isAdmin); |
||||
|
model.addAttribute("usrName", username); |
||||
|
model.addAttribute("usrRole", usrRole != null ? usrRole : "USER"); |
||||
|
model.addAttribute("curPage", "gccrentalmanagement"); |
||||
|
|
||||
|
return "gccrentalmanagement/dashboard"; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/login") |
||||
|
public String login(HttpSession session) { |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username != null) { |
||||
|
return "redirect:/gccrentalmanagement/dashboard"; |
||||
|
} |
||||
|
return "gccrentalmanagement/login"; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/login") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> validateLogin( |
||||
|
@RequestParam("usrName") String usrName, |
||||
|
@RequestParam("usrPass") String usrPass, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> 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("rental_usrName", usrName); |
||||
|
session.setAttribute("rental_usrRole", role); |
||||
|
session.setMaxInactiveInterval(1800); // 30 minutes session timeout |
||||
|
response.put("result", true); |
||||
|
response.put("usrName", usrName); |
||||
|
response.put("usrRole", role); |
||||
|
} catch (AuthenticationException e) { |
||||
|
response.put("result", false); |
||||
|
response.put("error", e.getMessage() != null ? e.getMessage() : "Invalid username or password!"); |
||||
|
} |
||||
|
|
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/logout") |
||||
|
public String logoutGet(HttpSession session, HttpServletRequest request) { |
||||
|
SecurityContextHolder.clearContext(); |
||||
|
if (session != null) { |
||||
|
session.removeAttribute("rental_usrName"); |
||||
|
session.removeAttribute("rental_usrRole"); |
||||
|
session.invalidate(); |
||||
|
} |
||||
|
request.getSession(true); |
||||
|
return "redirect:/gccrentalmanagement/login"; |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/logout") |
||||
|
public String logoutPost(HttpSession session, HttpServletRequest request) { |
||||
|
return logoutGet(session, request); |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// MASTER LOOKUPS APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/departments") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getDepartments(HttpSession session) { |
||||
|
return rentalService.getActiveDepartments(); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/zones") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getZones(HttpSession session) { |
||||
|
return rentalService.getActiveZones(); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/vendors") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getVendors(HttpSession session) { |
||||
|
return rentalService.getActiveVendors(); |
||||
|
} |
||||
|
|
||||
|
@GetMapping("/api/statuses") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getStatuses( |
||||
|
@RequestParam(value = "type", required = false) String type, |
||||
|
HttpSession session) { |
||||
|
return rentalService.getMasterStatuses(type); |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 1. WORK ORDER (WO) APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/workorders") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getWorkOrders(HttpSession session) { |
||||
|
return rentalService.getAllWorkOrders(); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/workorders/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveWorkOrder( |
||||
|
@RequestParam("woFileNo") String woFileNo, |
||||
|
@RequestParam("fileSubject") String fileSubject, |
||||
|
@RequestParam("periodFromDate") String periodFromDate, |
||||
|
@RequestParam("periodToDate") String periodToDate, |
||||
|
@RequestParam("vendorName") String vendorName, |
||||
|
@RequestParam(value = "systemsQty", defaultValue = "0") Integer systemsQty, |
||||
|
@RequestParam(value = "systemsModel", defaultValue = "") String systemsModel, |
||||
|
@RequestParam(value = "printersQty", defaultValue = "0") Integer printersQty, |
||||
|
@RequestParam(value = "printersModel", defaultValue = "") String printersModel, |
||||
|
@RequestParam(value = "laptopsQty", defaultValue = "0") Integer laptopsQty, |
||||
|
@RequestParam(value = "laptopsModel", defaultValue = "") String laptopsModel, |
||||
|
@RequestParam(value = "woCopyFile", required = false) MultipartFile woCopyFile, |
||||
|
@RequestParam(value = "remarks", defaultValue = "") String remarks, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access. Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(rentalUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) uploadDir.mkdirs(); |
||||
|
|
||||
|
String woCopyPath = null; |
||||
|
if (woCopyFile != null && !woCopyFile.isEmpty()) { |
||||
|
woCopyPath = saveUploadedFile(woCopyFile, "wo", uploadDir); |
||||
|
} |
||||
|
|
||||
|
boolean saved = rentalService.saveWorkOrder( |
||||
|
woFileNo, fileSubject, periodFromDate, periodToDate, vendorName, |
||||
|
systemsQty, systemsModel, printersQty, printersModel, |
||||
|
laptopsQty, laptopsModel, woCopyPath, remarks, username); |
||||
|
|
||||
|
if (saved) { |
||||
|
response.put("success", true); |
||||
|
response.put("message", "Work order registered successfully."); |
||||
|
} else { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Failed to save work order to database."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 2. DEPARTMENT USER REQUEST APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/requests") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getRequests(HttpSession session) { |
||||
|
return rentalService.getAllUserRequests(); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/requests/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveUserRequest( |
||||
|
@RequestParam("tapalNo") String tapalNo, |
||||
|
@RequestParam("tapalDate") String tapalDate, |
||||
|
@RequestParam("deptId") Integer deptId, |
||||
|
@RequestParam(value = "zoneId", required = false) Integer zoneId, |
||||
|
@RequestParam(value = "reqSystemsQty", defaultValue = "0") Integer reqSystemsQty, |
||||
|
@RequestParam(value = "reqPrintersQty", defaultValue = "0") Integer reqPrintersQty, |
||||
|
@RequestParam(value = "reqLaptopsQty", defaultValue = "0") Integer reqLaptopsQty, |
||||
|
@RequestParam("requiredFromDate") String requiredFromDate, |
||||
|
@RequestParam("requiredToDate") String requiredToDate, |
||||
|
@RequestParam(value = "mailCopyFile", required = false) MultipartFile mailCopyFile, |
||||
|
@RequestParam(value = "reqStatusId", defaultValue = "1") Integer reqStatusId, |
||||
|
@RequestParam(value = "requestingOfficer", defaultValue = "") String requestingOfficer, |
||||
|
@RequestParam(value = "contactNo", defaultValue = "") String contactNo, |
||||
|
@RequestParam(value = "purpose", defaultValue = "") String purpose, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access. Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(rentalUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) uploadDir.mkdirs(); |
||||
|
|
||||
|
String mailCopyPath = null; |
||||
|
if (mailCopyFile != null && !mailCopyFile.isEmpty()) { |
||||
|
mailCopyPath = saveUploadedFile(mailCopyFile, "request_mail", uploadDir); |
||||
|
} |
||||
|
|
||||
|
boolean saved = rentalService.saveUserRequest( |
||||
|
tapalNo, tapalDate, deptId, zoneId, |
||||
|
reqSystemsQty, reqPrintersQty, reqLaptopsQty, |
||||
|
requiredFromDate, requiredToDate, mailCopyPath, reqStatusId, |
||||
|
requestingOfficer, contactNo, purpose, username); |
||||
|
|
||||
|
if (saved) { |
||||
|
response.put("success", true); |
||||
|
response.put("message", "Department request registered successfully."); |
||||
|
} else { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Failed to save department request."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 3. INWARD DELIVERY CHALLAN (DC) APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/inward-challans") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getInwardChallans(HttpSession session) { |
||||
|
return rentalService.getAllInwardChallans(); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/inward-challans/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveInwardChallan( |
||||
|
@RequestParam("woId") Integer woId, |
||||
|
@RequestParam("dcNo") String dcNo, |
||||
|
@RequestParam("dcDate") String dcDate, |
||||
|
@RequestParam(value = "vendorName", defaultValue = "") String vendorName, |
||||
|
@RequestParam(value = "inSystemsQty", defaultValue = "0") Integer inSystemsQty, |
||||
|
@RequestParam(value = "inPrintersQty", defaultValue = "0") Integer inPrintersQty, |
||||
|
@RequestParam(value = "inLaptopsQty", defaultValue = "0") Integer inLaptopsQty, |
||||
|
@RequestParam(value = "dcFile", required = false) MultipartFile dcFile, |
||||
|
@RequestParam(value = "vehicleNo", defaultValue = "") String vehicleNo, |
||||
|
@RequestParam(value = "receivedBy", defaultValue = "") String receivedBy, |
||||
|
@RequestParam(value = "remarks", defaultValue = "") String remarks, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access. Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(rentalUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) uploadDir.mkdirs(); |
||||
|
|
||||
|
String dcFilePath = null; |
||||
|
if (dcFile != null && !dcFile.isEmpty()) { |
||||
|
dcFilePath = saveUploadedFile(dcFile, "inward_dc", uploadDir); |
||||
|
} |
||||
|
|
||||
|
boolean saved = rentalService.saveInwardChallan( |
||||
|
woId, dcNo, dcDate, vendorName, |
||||
|
inSystemsQty, inPrintersQty, inLaptopsQty, |
||||
|
dcFilePath, vehicleNo, receivedBy, remarks, username); |
||||
|
|
||||
|
if (saved) { |
||||
|
response.put("success", true); |
||||
|
response.put("message", "Inward Delivery Challan registered successfully."); |
||||
|
} else { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Failed to save inward Delivery Challan."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 4. ISSUED DETAILS APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/issued-assets") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getIssuedAssets(HttpSession session) { |
||||
|
return rentalService.getAllIssuedDetails(); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/issued-assets/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveIssuedDetails( |
||||
|
@RequestParam("requestId") Integer requestId, |
||||
|
@RequestParam(value = "inwardDcId", required = false) Integer inwardDcId, |
||||
|
@RequestParam(value = "woId", required = false) Integer woId, |
||||
|
@RequestParam("issuedDate") String issuedDate, |
||||
|
@RequestParam(value = "issuedSystemsQty", defaultValue = "0") Integer issuedSystemsQty, |
||||
|
@RequestParam(value = "issuedPrintersQty", defaultValue = "0") Integer issuedPrintersQty, |
||||
|
@RequestParam(value = "issuedLaptopsQty", defaultValue = "0") Integer issuedLaptopsQty, |
||||
|
@RequestParam(value = "assetSerialDetails", defaultValue = "") String assetSerialDetails, |
||||
|
@RequestParam("issuedFromDate") String issuedFromDate, |
||||
|
@RequestParam("issuedToDate") String issuedToDate, |
||||
|
@RequestParam(value = "stockCopyFile", required = false) MultipartFile stockCopyFile, |
||||
|
@RequestParam(value = "custodianOfficer", defaultValue = "") String custodianOfficer, |
||||
|
@RequestParam(value = "contactNo", defaultValue = "") String contactNo, |
||||
|
@RequestParam(value = "issuedBy", defaultValue = "") String issuedBy, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access. Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(rentalUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) uploadDir.mkdirs(); |
||||
|
|
||||
|
String stockCopyPath = null; |
||||
|
if (stockCopyFile != null && !stockCopyFile.isEmpty()) { |
||||
|
stockCopyPath = saveUploadedFile(stockCopyFile, "issue_stock", uploadDir); |
||||
|
} |
||||
|
|
||||
|
boolean saved = rentalService.saveIssuedDetails( |
||||
|
requestId, inwardDcId, woId, issuedDate, |
||||
|
issuedSystemsQty, issuedPrintersQty, issuedLaptopsQty, |
||||
|
assetSerialDetails, issuedFromDate, issuedToDate, stockCopyPath, |
||||
|
custodianOfficer, contactNo, issuedBy, username); |
||||
|
|
||||
|
if (saved) { |
||||
|
response.put("success", true); |
||||
|
response.put("message", "Asset issued successfully."); |
||||
|
} else { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Failed to register issued details."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 5. RETURN DETAILS APIS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/returns") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getReturns(HttpSession session) { |
||||
|
return rentalService.getAllReturnDetails(); |
||||
|
} |
||||
|
|
||||
|
@PostMapping("/api/returns/save") |
||||
|
@ResponseBody |
||||
|
public Map<String, Object> saveReturnDetails( |
||||
|
@RequestParam("issueId") Integer issueId, |
||||
|
@RequestParam("requestId") Integer requestId, |
||||
|
@RequestParam("returnDate") String returnDate, |
||||
|
@RequestParam(value = "retSystemsQty", defaultValue = "0") Integer retSystemsQty, |
||||
|
@RequestParam(value = "retPrintersQty", defaultValue = "0") Integer retPrintersQty, |
||||
|
@RequestParam(value = "retLaptopsQty", defaultValue = "0") Integer retLaptopsQty, |
||||
|
@RequestParam(value = "stockCopyFile", required = false) MultipartFile stockCopyFile, |
||||
|
@RequestParam(value = "postReturnStatusId", defaultValue = "6") Integer postReturnStatusId, |
||||
|
@RequestParam(value = "conditionGrade", defaultValue = "Good") String conditionGrade, |
||||
|
@RequestParam(value = "penaltyCharges", defaultValue = "0.0") Double penaltyCharges, |
||||
|
@RequestParam(value = "receivedBy", defaultValue = "") String receivedBy, |
||||
|
@RequestParam(value = "remarks", defaultValue = "") String remarks, |
||||
|
HttpSession session) { |
||||
|
|
||||
|
Map<String, Object> response = new HashMap<>(); |
||||
|
String username = (String) session.getAttribute("rental_usrName"); |
||||
|
if (username == null) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Unauthorized access. Please log in."); |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
File uploadDir = new File(rentalUploadPathConfig).getAbsoluteFile(); |
||||
|
if (!uploadDir.exists()) uploadDir.mkdirs(); |
||||
|
|
||||
|
String stockCopyPath = null; |
||||
|
if (stockCopyFile != null && !stockCopyFile.isEmpty()) { |
||||
|
stockCopyPath = saveUploadedFile(stockCopyFile, "return_stock", uploadDir); |
||||
|
} |
||||
|
|
||||
|
boolean saved = rentalService.saveReturnDetails( |
||||
|
issueId, requestId, returnDate, |
||||
|
retSystemsQty, retPrintersQty, retLaptopsQty, |
||||
|
stockCopyPath, postReturnStatusId, conditionGrade, |
||||
|
penaltyCharges, receivedBy, remarks, username); |
||||
|
|
||||
|
if (saved) { |
||||
|
response.put("success", true); |
||||
|
response.put("message", "Asset return intake processed successfully."); |
||||
|
} else { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Failed to register return details."); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
response.put("success", false); |
||||
|
response.put("error", "Error: " + e.getMessage()); |
||||
|
} |
||||
|
return response; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 6. REMINDERS & DUE ALERTS API |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@GetMapping("/api/reminders") |
||||
|
@ResponseBody |
||||
|
public List<Map<String, Object>> getReminders(HttpSession session) { |
||||
|
return rentalService.getOverdueAndDueSoonReminders(); |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// FILE UPLOAD HELPER METHODS |
||||
|
// ========================================================================= |
||||
|
|
||||
|
private String saveUploadedFile(MultipartFile file, String prefix, File uploadDir) throws Exception { |
||||
|
String originalFilename = file.getOriginalFilename(); |
||||
|
String extension = ""; |
||||
|
if (originalFilename != null && originalFilename.contains(".")) { |
||||
|
extension = originalFilename.substring(originalFilename.lastIndexOf(".")); |
||||
|
} |
||||
|
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS").format(new Date()); |
||||
|
String newFilename = prefix + "_" + timestamp + extension; |
||||
|
|
||||
|
File targetFile = new File(uploadDir, newFilename); |
||||
|
try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(targetFile)) { |
||||
|
byte[] buffer = new byte[8192]; |
||||
|
int bytesRead; |
||||
|
while ((bytesRead = in.read(buffer)) != -1) { |
||||
|
out.write(buffer, 0, bytesRead); |
||||
|
} |
||||
|
} |
||||
|
return newFilename; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,491 @@ |
|||||
|
package com.gcc_manpower.gccrentalmanagement.service; |
||||
|
|
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.Statement; |
||||
|
import java.time.LocalDate; |
||||
|
import java.time.temporal.ChronoUnit; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import javax.sql.DataSource; |
||||
|
|
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||
|
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
import org.springframework.jdbc.support.GeneratedKeyHolder; |
||||
|
import org.springframework.jdbc.support.KeyHolder; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
@Service |
||||
|
public class RentalService { |
||||
|
|
||||
|
private JdbcTemplate jdbcTemplate; |
||||
|
|
||||
|
@Autowired |
||||
|
public void setDataSource(@Qualifier("mysqlItcellManagementDataSource") DataSource dataSource) { |
||||
|
this.jdbcTemplate = new JdbcTemplate(dataSource); |
||||
|
} |
||||
|
|
||||
|
public JdbcTemplate getJdbcTemplate() { |
||||
|
return this.jdbcTemplate; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 1. MASTER LOOKUPS (Departments, Zones, Vendors, Master Statuses) |
||||
|
// ========================================================================= |
||||
|
|
||||
|
public List<Map<String, Object>> getActiveDepartments() { |
||||
|
String sql = "SELECT id, dept_name FROM toner_department_list WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) ORDER BY dept_name ASC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getActiveZones() { |
||||
|
String sql = "SELECT id, zone_name FROM toner_zone_list WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) ORDER BY id ASC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getActiveVendors() { |
||||
|
String sql = "SELECT id, vendor_name FROM payment_vendors_list WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) ORDER BY vendor_name ASC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getMasterStatuses(String statusType) { |
||||
|
String sql; |
||||
|
try { |
||||
|
if (statusType != null && !statusType.trim().isEmpty() && !"ALL".equalsIgnoreCase(statusType)) { |
||||
|
sql = "SELECT id, status_name, status_type, badge_color FROM rental_master_status_list " + |
||||
|
"WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) " + |
||||
|
"AND status_type = ? ORDER BY id ASC"; |
||||
|
return jdbcTemplate.queryForList(sql, statusType.toUpperCase().trim()); |
||||
|
} else { |
||||
|
sql = "SELECT id, status_name, status_type, badge_color FROM rental_master_status_list " + |
||||
|
"WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) ORDER BY id ASC"; |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
return getDefaultStatusFallback(statusType); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private List<Map<String, Object>> getDefaultStatusFallback(String type) { |
||||
|
List<Map<String, Object>> list = new ArrayList<>(); |
||||
|
if ("REQUEST".equalsIgnoreCase(type) || type == null) { |
||||
|
list.add(Map.of("id", 1, "status_name", "Pending Sanction", "status_type", "REQUEST", "badge_color", |
||||
|
"warning")); |
||||
|
list.add(Map.of("id", 2, "status_name", "Sanctioned & Approved", "status_type", "REQUEST", "badge_color", |
||||
|
"info")); |
||||
|
list.add(Map.of("id", 3, "status_name", "Issued to Dept", "status_type", "REQUEST", "badge_color", |
||||
|
"primary")); |
||||
|
list.add(Map.of("id", 4, "status_name", "Completed & Returned", "status_type", "REQUEST", "badge_color", |
||||
|
"success")); |
||||
|
list.add(Map.of("id", 5, "status_name", "Rejected", "status_type", "REQUEST", "badge_color", "danger")); |
||||
|
} |
||||
|
if ("RETURN".equalsIgnoreCase(type) || type == null) { |
||||
|
list.add(Map.of("id", 6, "status_name", "Completed", "status_type", "RETURN", "badge_color", "success")); |
||||
|
list.add(Map.of("id", 7, "status_name", "Partially Returned", "status_type", "RETURN", "badge_color", |
||||
|
"warning")); |
||||
|
list.add( |
||||
|
Map.of("id", 8, "status_name", "Pending Return", "status_type", "RETURN", "badge_color", "danger")); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 2. WORK ORDER (WO) FILE CREATION & REGISTRY |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean saveWorkOrder(String woFileNo, String fileSubject, String fromDate, String toDate, |
||||
|
String vendorName, Integer systemsQty, String systemsModel, |
||||
|
Integer printersQty, String printersModel, Integer laptopsQty, |
||||
|
String laptopsModel, String woCopyPath, String remarks, String updatedBy) { |
||||
|
String sql = "INSERT INTO rental_workorder_register " + |
||||
|
"(wo_file_no, file_subject, period_from_date, period_to_date, vendor_name, " + |
||||
|
"systems_qty, systems_model_name, printers_qty, printers_model_name, " + |
||||
|
"laptops_qty, laptops_model_name, wo_copy_file, status, remarks, created_by, is_active, is_delete) " + |
||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'Active', ?, ?, 1, 0)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, |
||||
|
woFileNo != null ? woFileNo.trim() : null, |
||||
|
fileSubject != null ? fileSubject.trim() : null, |
||||
|
fromDate, toDate, |
||||
|
vendorName != null ? vendorName.trim() : null, |
||||
|
systemsQty != null ? systemsQty : 0, |
||||
|
systemsModel != null ? systemsModel.trim() : "", |
||||
|
printersQty != null ? printersQty : 0, |
||||
|
printersModel != null ? printersModel.trim() : "", |
||||
|
laptopsQty != null ? laptopsQty : 0, |
||||
|
laptopsModel != null ? laptopsModel.trim() : "", |
||||
|
woCopyPath, remarks, updatedBy); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getAllWorkOrders() { |
||||
|
String sql = "SELECT id, wo_file_no, file_subject, period_from_date, period_to_date, vendor_name, " + |
||||
|
"systems_qty, systems_model_name, printers_qty, printers_model_name, " + |
||||
|
"laptops_qty, laptops_model_name, (systems_qty + printers_qty + laptops_qty) AS total_units, " + |
||||
|
"wo_copy_file, status, remarks, created_by, created_at " + |
||||
|
"FROM rental_workorder_register " + |
||||
|
"WHERE (is_active IS NULL OR is_active = 1) AND (is_delete IS NULL OR is_delete = 0) " + |
||||
|
"ORDER BY id DESC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Map<String, Object> getWorkOrderById(int id) { |
||||
|
String sql = "SELECT * FROM rental_workorder_register WHERE id = ?"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForMap(sql, id); |
||||
|
} catch (Exception e) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 3. DEPARTMENT USER REQUEST CREATION (Tapal, Dept, Zone, Qty, Dates) |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean saveUserRequest(String tapalNo, String tapalDate, Integer deptId, Integer zoneId, |
||||
|
Integer reqSystemsQty, Integer reqPrintersQty, Integer reqLaptopsQty, |
||||
|
String fromDate, String toDate, String mailCopyPath, Integer statusId, |
||||
|
String requestingOfficer, String contactNo, String purpose, String updatedBy) { |
||||
|
|
||||
|
int calculatedDays = calculateDaysBetween(fromDate, toDate); |
||||
|
int finalStatusId = (statusId != null && statusId > 0) ? statusId : 1; // Default to 'Pending Sanction' |
||||
|
|
||||
|
String sql = "INSERT INTO rental_user_request " + |
||||
|
"(tapal_no, tapal_date, department_id, zone_id, " + |
||||
|
"req_systems_qty, req_printers_qty, req_laptops_qty, " + |
||||
|
"required_from_date, required_to_date, calculated_days, " + |
||||
|
"mail_copy_file, req_status_id, requesting_officer, contact_no, purpose, " + |
||||
|
"created_by, is_active, is_delete) " + |
||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, |
||||
|
tapalNo != null ? tapalNo.trim() : null, |
||||
|
tapalDate, |
||||
|
deptId, zoneId, |
||||
|
reqSystemsQty != null ? reqSystemsQty : 0, |
||||
|
reqPrintersQty != null ? reqPrintersQty : 0, |
||||
|
reqLaptopsQty != null ? reqLaptopsQty : 0, |
||||
|
fromDate, toDate, calculatedDays, |
||||
|
mailCopyPath, finalStatusId, |
||||
|
requestingOfficer != null ? requestingOfficer.trim() : null, |
||||
|
contactNo != null ? contactNo.trim() : null, |
||||
|
purpose, updatedBy); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getAllUserRequests() { |
||||
|
String sql = "SELECT r.id, r.tapal_no, r.tapal_date, r.department_id, d.dept_name, " + |
||||
|
"r.zone_id, z.zone_name, r.req_systems_qty, r.req_printers_qty, r.req_laptops_qty, " + |
||||
|
"(r.req_systems_qty + r.req_printers_qty + r.req_laptops_qty) AS total_req_qty, " + |
||||
|
"r.required_from_date, r.required_to_date, r.calculated_days, r.mail_copy_file, " + |
||||
|
"r.req_status_id, COALESCE(s.status_name, 'Pending') AS status_name, " + |
||||
|
"COALESCE(s.badge_color, 'warning') AS badge_color, " + |
||||
|
"r.requesting_officer, r.contact_no, r.purpose, r.created_by, r.created_at " + |
||||
|
"FROM rental_user_request r " + |
||||
|
"LEFT JOIN toner_department_list d ON r.department_id = d.id " + |
||||
|
"LEFT JOIN toner_zone_list z ON r.zone_id = z.id " + |
||||
|
"LEFT JOIN rental_master_status_list s ON r.req_status_id = s.id " + |
||||
|
"WHERE (r.is_active IS NULL OR r.is_active = 1) AND (r.is_delete IS NULL OR r.is_delete = 0) " + |
||||
|
"ORDER BY r.id DESC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean updateUserRequestStatus(int requestId, int statusId, String updatedBy) { |
||||
|
String sql = "UPDATE rental_user_request SET req_status_id = ? WHERE id = ?"; |
||||
|
try { |
||||
|
return jdbcTemplate.update(sql, statusId, requestId) > 0; |
||||
|
} catch (Exception e) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 4. DELIVERY CHALLAN (DC) - INWARD STOCK AGAINST REGISTERED WORK ORDER |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean saveInwardChallan(Integer woId, String dcNo, String dcDate, String vendorName, |
||||
|
Integer inSystemsQty, Integer inPrintersQty, Integer inLaptopsQty, |
||||
|
String dcFilePath, String vehicleNo, String receivedBy, |
||||
|
String remarks, String updatedBy) { |
||||
|
String sql = "INSERT INTO rental_inward_delivery_challan " + |
||||
|
"(wo_id, dc_no, dc_date, vendor_name, " + |
||||
|
"inward_systems_qty, inward_printers_qty, inward_laptops_qty, " + |
||||
|
"dc_file_path, vehicle_no, received_by, remarks, created_by, is_active, is_delete) " + |
||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, |
||||
|
woId, |
||||
|
dcNo != null ? dcNo.trim() : null, |
||||
|
dcDate, |
||||
|
vendorName != null ? vendorName.trim() : null, |
||||
|
inSystemsQty != null ? inSystemsQty : 0, |
||||
|
inPrintersQty != null ? inPrintersQty : 0, |
||||
|
inLaptopsQty != null ? inLaptopsQty : 0, |
||||
|
dcFilePath, |
||||
|
vehicleNo != null ? vehicleNo.trim() : null, |
||||
|
receivedBy != null ? receivedBy.trim() : null, |
||||
|
remarks, updatedBy); |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getAllInwardChallans() { |
||||
|
String sql = "SELECT c.id, c.wo_id, w.wo_file_no, w.file_subject, c.dc_no, c.dc_date, " + |
||||
|
"COALESCE(c.vendor_name, w.vendor_name) AS vendor_name, " + |
||||
|
"c.inward_systems_qty, c.inward_printers_qty, c.inward_laptops_qty, " + |
||||
|
"(c.inward_systems_qty + c.inward_printers_qty + c.inward_laptops_qty) AS total_inward_qty, " + |
||||
|
"c.dc_file_path, c.vehicle_no, c.received_by, c.remarks, c.created_by, c.created_at " + |
||||
|
"FROM rental_inward_delivery_challan c " + |
||||
|
"LEFT JOIN rental_workorder_register w ON c.wo_id = w.id " + |
||||
|
"WHERE (c.is_active IS NULL OR c.is_active = 1) AND (c.is_delete IS NULL OR c.is_delete = 0) " + |
||||
|
"ORDER BY c.id DESC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 5. ISSUED DETAILS (From Inward Stock & User Request) |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean saveIssuedDetails(Integer requestId, Integer inwardDcId, Integer woId, |
||||
|
String issuedDate, Integer issuedSystemsQty, Integer issuedPrintersQty, |
||||
|
Integer issuedLaptopsQty, String assetSerialDetails, |
||||
|
String issuedFromDate, String issuedToDate, String stockCopyPath, |
||||
|
String custodianOfficer, String contactNo, String issuedBy, String updatedBy) { |
||||
|
|
||||
|
int periodDays = calculateDaysBetween(issuedFromDate, issuedToDate); |
||||
|
|
||||
|
String sql = "INSERT INTO rental_issued_details " + |
||||
|
"(request_id, inward_dc_id, wo_id, issued_date, " + |
||||
|
"issued_systems_qty, issued_printers_qty, issued_laptops_qty, " + |
||||
|
"asset_serial_details, issued_from_date, issued_to_date, issued_period_days, " + |
||||
|
"stock_copy_path, custodian_officer, contact_no, issued_by, status, " + |
||||
|
"created_by, is_active, is_delete) " + |
||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'Issued', ?, 1, 0)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, |
||||
|
requestId, inwardDcId, woId, issuedDate, |
||||
|
issuedSystemsQty != null ? issuedSystemsQty : 0, |
||||
|
issuedPrintersQty != null ? issuedPrintersQty : 0, |
||||
|
issuedLaptopsQty != null ? issuedLaptopsQty : 0, |
||||
|
assetSerialDetails, issuedFromDate, issuedToDate, periodDays, |
||||
|
stockCopyPath, |
||||
|
custodianOfficer != null ? custodianOfficer.trim() : null, |
||||
|
contactNo != null ? contactNo.trim() : null, |
||||
|
issuedBy != null ? issuedBy.trim() : null, |
||||
|
updatedBy); |
||||
|
|
||||
|
if (rows > 0 && requestId != null) { |
||||
|
// Automatically update request status to 'Issued' (status_id = 3) |
||||
|
jdbcTemplate.update("UPDATE rental_user_request SET req_status_id = 3 WHERE id = ?", requestId); |
||||
|
} |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getAllIssuedDetails() { |
||||
|
String sql = "SELECT i.id, i.request_id, r.tapal_no, d.dept_name, z.zone_name, " + |
||||
|
"i.inward_dc_id, dc.dc_no, i.wo_id, w.wo_file_no, i.issued_date, " + |
||||
|
"i.issued_systems_qty, i.issued_printers_qty, i.issued_laptops_qty, " + |
||||
|
"(i.issued_systems_qty + i.issued_printers_qty + i.issued_laptops_qty) AS total_issued_qty, " + |
||||
|
"i.asset_serial_details, i.issued_from_date, i.issued_to_date, i.issued_period_days, " + |
||||
|
"i.stock_copy_path, i.custodian_officer, i.contact_no, i.issued_by, i.status, " + |
||||
|
"i.created_by, i.created_at, " + |
||||
|
"COALESCE(ret.total_returned_qty, 0) AS total_returned_qty " + |
||||
|
"FROM rental_issued_details i " + |
||||
|
"LEFT JOIN rental_user_request r ON i.request_id = r.id " + |
||||
|
"LEFT JOIN toner_department_list d ON r.department_id = d.id " + |
||||
|
"LEFT JOIN toner_zone_list z ON r.zone_id = z.id " + |
||||
|
"LEFT JOIN rental_inward_delivery_challan dc ON i.inward_dc_id = dc.id " + |
||||
|
"LEFT JOIN rental_workorder_register w ON i.wo_id = w.id " + |
||||
|
"LEFT JOIN (SELECT issue_id, SUM(returned_systems_qty + returned_printers_qty + returned_laptops_qty) AS total_returned_qty " |
||||
|
+ |
||||
|
" FROM rental_return_details WHERE is_delete = 0 GROUP BY issue_id) ret ON i.id = ret.issue_id " |
||||
|
+ |
||||
|
"WHERE (i.is_active IS NULL OR i.is_active = 1) AND (i.is_delete IS NULL OR i.is_delete = 0) " + |
||||
|
"ORDER BY i.id DESC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 6. RETURN DETAILS (Return Date, Returned Qty, Stock Copy, Status) |
||||
|
// ========================================================================= |
||||
|
|
||||
|
@Transactional |
||||
|
public boolean saveReturnDetails(Integer issueId, Integer requestId, String returnDate, |
||||
|
Integer retSystemsQty, Integer retPrintersQty, Integer retLaptopsQty, |
||||
|
String stockCopyPath, Integer postReturnStatusId, String conditionGrade, |
||||
|
Double penaltyCharges, String receivedBy, String remarks, String updatedBy) { |
||||
|
|
||||
|
int finalStatusId = (postReturnStatusId != null && postReturnStatusId > 0) ? postReturnStatusId : 6; // Default |
||||
|
// to |
||||
|
// 'Completed' |
||||
|
|
||||
|
String sql = "INSERT INTO rental_return_details " + |
||||
|
"(issue_id, request_id, return_date, " + |
||||
|
"returned_systems_qty, returned_printers_qty, returned_laptops_qty, " + |
||||
|
"stock_copy_path, post_return_status_id, condition_grade, penalty_charges, " + |
||||
|
"received_by, remarks, created_by, is_active, is_delete) " + |
||||
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; |
||||
|
try { |
||||
|
int rows = jdbcTemplate.update(sql, |
||||
|
issueId, requestId, returnDate, |
||||
|
retSystemsQty != null ? retSystemsQty : 0, |
||||
|
retPrintersQty != null ? retPrintersQty : 0, |
||||
|
retLaptopsQty != null ? retLaptopsQty : 0, |
||||
|
stockCopyPath, finalStatusId, |
||||
|
conditionGrade != null ? conditionGrade.trim() : "Good", |
||||
|
penaltyCharges != null ? penaltyCharges : 0.0, |
||||
|
receivedBy != null ? receivedBy.trim() : null, |
||||
|
remarks, updatedBy); |
||||
|
|
||||
|
if (rows > 0) { |
||||
|
// Update issued details status |
||||
|
String postStatusText = (finalStatusId == 6) ? "Returned - Completed" : "Partially Returned"; |
||||
|
if (issueId != null) { |
||||
|
jdbcTemplate.update("UPDATE rental_issued_details SET status = ? WHERE id = ?", postStatusText, |
||||
|
issueId); |
||||
|
} |
||||
|
if (requestId != null && finalStatusId == 6) { |
||||
|
jdbcTemplate.update("UPDATE rental_user_request SET req_status_id = 4 WHERE id = ?", requestId); // 4 |
||||
|
// = |
||||
|
// Completed |
||||
|
} |
||||
|
} |
||||
|
return rows > 0; |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Map<String, Object>> getAllReturnDetails() { |
||||
|
String sql = "SELECT rt.id, rt.issue_id, rt.request_id, r.tapal_no, d.dept_name, z.zone_name, " + |
||||
|
"iss.custodian_officer, iss.issued_to_date, rt.return_date, " + |
||||
|
"rt.returned_systems_qty, rt.returned_printers_qty, rt.returned_laptops_qty, " + |
||||
|
"(rt.returned_systems_qty + rt.returned_printers_qty + rt.returned_laptops_qty) AS total_returned_qty, " |
||||
|
+ |
||||
|
"rt.stock_copy_path, rt.post_return_status_id, " + |
||||
|
"COALESCE(s.status_name, 'Completed') AS post_return_status_name, " + |
||||
|
"COALESCE(s.badge_color, 'success') AS badge_color, " + |
||||
|
"rt.condition_grade, rt.penalty_charges, rt.received_by, rt.remarks, " + |
||||
|
"rt.created_by, rt.created_at " + |
||||
|
"FROM rental_return_details rt " + |
||||
|
"LEFT JOIN rental_issued_details iss ON rt.issue_id = iss.id " + |
||||
|
"LEFT JOIN rental_user_request r ON rt.request_id = r.id " + |
||||
|
"LEFT JOIN toner_department_list d ON r.department_id = d.id " + |
||||
|
"LEFT JOIN toner_zone_list z ON r.zone_id = z.id " + |
||||
|
"LEFT JOIN rental_master_status_list s ON rt.post_return_status_id = s.id " + |
||||
|
"WHERE (rt.is_active IS NULL OR rt.is_active = 1) AND (rt.is_delete IS NULL OR rt.is_delete = 0) " + |
||||
|
"ORDER BY rt.id DESC"; |
||||
|
try { |
||||
|
return jdbcTemplate.queryForList(sql); |
||||
|
} catch (Exception e) { |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ========================================================================= |
||||
|
// 7. REAL-TIME DATE MATH & REMINDERS CALCULATION |
||||
|
// ========================================================================= |
||||
|
|
||||
|
public List<Map<String, Object>> getOverdueAndDueSoonReminders() { |
||||
|
List<Map<String, Object>> issuedList = getAllIssuedDetails(); |
||||
|
List<Map<String, Object>> result = new ArrayList<>(); |
||||
|
|
||||
|
LocalDate today = LocalDate.now(); |
||||
|
|
||||
|
for (Map<String, Object> item : issuedList) { |
||||
|
Object dueDateObj = item.get("issued_to_date"); |
||||
|
if (dueDateObj == null) |
||||
|
continue; |
||||
|
|
||||
|
try { |
||||
|
LocalDate dueDate = LocalDate.parse(dueDateObj.toString()); |
||||
|
long daysDiff = ChronoUnit.DAYS.between(today, dueDate); |
||||
|
|
||||
|
Map<String, Object> alert = new HashMap<>(item); |
||||
|
alert.put("daysDiff", daysDiff); |
||||
|
|
||||
|
if (daysDiff < 0) { |
||||
|
alert.put("calculated_status", "OVERDUE"); |
||||
|
alert.put("overdue_days", Math.abs(daysDiff)); |
||||
|
alert.put("badge_class", "status-overdue"); |
||||
|
alert.put("status_label", "OVERDUE by " + Math.abs(daysDiff) + " Days"); |
||||
|
result.add(alert); |
||||
|
} else if (daysDiff <= 7) { |
||||
|
alert.put("calculated_status", "DUE_SOON"); |
||||
|
alert.put("due_days", daysDiff); |
||||
|
alert.put("badge_class", "status-due-soon"); |
||||
|
alert.put("status_label", "Due in " + daysDiff + " Days"); |
||||
|
result.add(alert); |
||||
|
} |
||||
|
} catch (Exception ignored) { |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private int calculateDaysBetween(String fromDateStr, String toDateStr) { |
||||
|
if (fromDateStr == null || toDateStr == null) |
||||
|
return 0; |
||||
|
try { |
||||
|
LocalDate from = LocalDate.parse(fromDateStr); |
||||
|
LocalDate to = LocalDate.parse(toDateStr); |
||||
|
long days = ChronoUnit.DAYS.between(from, to) + 1; |
||||
|
return (int) Math.max(days, 0); |
||||
|
} catch (Exception e) { |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
<th:block th:fragment="rentalheader"> |
||||
|
<!-- Awesome Font --> |
||||
|
<link rel="stylesheet" th:href="@{/assets/font-awesome-6.5.2/css/all.min.css}" type="text/css"> |
||||
|
<!-- Bootstrap CSS --> |
||||
|
<link rel="stylesheet" th:href="@{/assets/bootstrap-5.3.2/css/bootstrap.min.css}" type="text/css"> |
||||
|
<!-- CSS for Header --> |
||||
|
<link rel="stylesheet" th:href="@{/assets/css/header-styles.css}" type="text/css"> |
||||
|
<div class="header"> |
||||
|
<div class="logo-left"> |
||||
|
<img th:src="@{/assets/header-images/gcc1.png}" alt="Greater Chennai Corporation Logo"> |
||||
|
<div class="logo-text"> |
||||
|
<h2>GREATER</h2> |
||||
|
<h2>CHENNAI</h2> |
||||
|
<h2>CORPORATION</h2> |
||||
|
<p>பெருநகர சென்னை மாநகராட்சி</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="title"> |
||||
|
<h2>GCC IT Cell Rental Asset & Material Management System</h2> |
||||
|
</div> |
||||
|
</div> |
||||
|
</th:block> |
||||
3080
src/main/resources/templates/gccrentalmanagement/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,429 @@ |
|||||
|
<!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 IT Cell Rental Asset Management - 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}" /> |
||||
|
|
||||
|
<!-- Google Fonts --> |
||||
|
<link rel="preconnect" href="https://fonts.googleapis.com"> |
||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
||||
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet"> |
||||
|
|
||||
|
<!-- Bootstrap CSS --> |
||||
|
<link rel="stylesheet" th:href="@{/assets/bootstrap-5.3.2/css/bootstrap.min.css}" type="text/css"> |
||||
|
<!-- Awesome Font --> |
||||
|
<link th:href="@{/assets/font-awesome-6.5.2/css/all.min.css}" rel="stylesheet" type="text/css"> |
||||
|
|
||||
|
<style> |
||||
|
:root { |
||||
|
--primary-brand: #0d4b68; |
||||
|
--primary-dark: #072e41; |
||||
|
--accent-cyan: #06b6d4; |
||||
|
--accent-amber: #f59e0b; |
||||
|
--gradient-bg: linear-gradient(135deg, #072e41 0%, #0d4b68 50%, #155e75 100%); |
||||
|
--card-bg: rgba(255, 255, 255, 0.96); |
||||
|
} |
||||
|
|
||||
|
* { |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
body { |
||||
|
font-family: 'Poppins', sans-serif; |
||||
|
background: var(--gradient-bg); |
||||
|
min-height: 100vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
padding: 20px; |
||||
|
position: relative; |
||||
|
overflow-x: hidden; |
||||
|
} |
||||
|
|
||||
|
/* Decorative ambient glow circles */ |
||||
|
.ambient-glow { |
||||
|
position: absolute; |
||||
|
border-radius: 50%; |
||||
|
filter: blur(80px); |
||||
|
opacity: 0.25; |
||||
|
pointer-events: none; |
||||
|
z-index: 0; |
||||
|
} |
||||
|
|
||||
|
.glow-1 { |
||||
|
width: 350px; |
||||
|
height: 350px; |
||||
|
background: #06b6d4; |
||||
|
top: -50px; |
||||
|
left: -50px; |
||||
|
} |
||||
|
|
||||
|
.glow-2 { |
||||
|
width: 400px; |
||||
|
height: 400px; |
||||
|
background: #f59e0b; |
||||
|
bottom: -80px; |
||||
|
right: -80px; |
||||
|
} |
||||
|
|
||||
|
.login-card { |
||||
|
position: relative; |
||||
|
z-index: 1; |
||||
|
width: 100%; |
||||
|
max-width: 460px; |
||||
|
background: var(--card-bg); |
||||
|
backdrop-filter: blur(12px); |
||||
|
border-radius: 24px; |
||||
|
padding: 40px 36px; |
||||
|
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.2); |
||||
|
animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1); |
||||
|
} |
||||
|
|
||||
|
@keyframes slideUp { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
transform: translateY(25px); |
||||
|
} |
||||
|
to { |
||||
|
opacity: 1; |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.header-branding { |
||||
|
text-align: center; |
||||
|
margin-bottom: 28px; |
||||
|
} |
||||
|
|
||||
|
.logo-wrap { |
||||
|
width: 84px; |
||||
|
height: 84px; |
||||
|
margin: 0 auto 16px; |
||||
|
border-radius: 20px; |
||||
|
background: #ffffff; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
box-shadow: 0 8px 20px rgba(13, 75, 104, 0.15); |
||||
|
padding: 10px; |
||||
|
transition: transform 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.logo-wrap:hover { |
||||
|
transform: scale(1.05) rotate(2deg); |
||||
|
} |
||||
|
|
||||
|
.logo-wrap img { |
||||
|
max-width: 100%; |
||||
|
max-height: 100%; |
||||
|
object-fit: contain; |
||||
|
} |
||||
|
|
||||
|
.brand-title-en { |
||||
|
font-family: 'Outfit', sans-serif; |
||||
|
font-size: 1.15rem; |
||||
|
font-weight: 800; |
||||
|
letter-spacing: 0.8px; |
||||
|
color: #0d4b68; |
||||
|
text-transform: uppercase; |
||||
|
margin-bottom: 2px; |
||||
|
} |
||||
|
|
||||
|
.brand-title-ta { |
||||
|
font-size: 0.82rem; |
||||
|
color: #475569; |
||||
|
font-weight: 600; |
||||
|
margin-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.badge-module { |
||||
|
display: inline-flex; |
||||
|
align-items: center; |
||||
|
gap: 6px; |
||||
|
padding: 6px 14px; |
||||
|
background: linear-gradient(135deg, #e0f2fe, #e2e8f0); |
||||
|
color: #0369a1; |
||||
|
border: 1px solid #bae6fd; |
||||
|
border-radius: 30px; |
||||
|
font-size: 0.78rem; |
||||
|
font-weight: 700; |
||||
|
text-transform: uppercase; |
||||
|
letter-spacing: 0.5px; |
||||
|
} |
||||
|
|
||||
|
.badge-module i { |
||||
|
color: #0284c7; |
||||
|
} |
||||
|
|
||||
|
.form-title { |
||||
|
font-family: 'Outfit', sans-serif; |
||||
|
font-size: 1.4rem; |
||||
|
font-weight: 700; |
||||
|
color: #0f172a; |
||||
|
margin: 18px 0 6px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.form-subtitle { |
||||
|
font-size: 0.85rem; |
||||
|
color: #64748b; |
||||
|
text-align: center; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.form-floating-custom { |
||||
|
position: relative; |
||||
|
margin-bottom: 20px; |
||||
|
} |
||||
|
|
||||
|
.form-floating-custom .input-icon { |
||||
|
position: absolute; |
||||
|
left: 16px; |
||||
|
top: 50%; |
||||
|
transform: translateY(-50%); |
||||
|
color: #94a3b8; |
||||
|
font-size: 1.1rem; |
||||
|
transition: color 0.3s ease; |
||||
|
pointer-events: none; |
||||
|
} |
||||
|
|
||||
|
.form-floating-custom input { |
||||
|
width: 100%; |
||||
|
height: 52px; |
||||
|
padding: 12px 16px 12px 46px; |
||||
|
font-size: 0.92rem; |
||||
|
color: #1e293b; |
||||
|
background: #f8fafc; |
||||
|
border: 1.5px solid #e2e8f0; |
||||
|
border-radius: 12px; |
||||
|
outline: none; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.form-floating-custom input:focus { |
||||
|
background: #ffffff; |
||||
|
border-color: #0284c7; |
||||
|
box-shadow: 0 0 0 4px rgba(2, 132, 199, 0.12); |
||||
|
} |
||||
|
|
||||
|
.form-floating-custom input:focus + .input-icon { |
||||
|
color: #0284c7; |
||||
|
} |
||||
|
|
||||
|
.btn-submit { |
||||
|
width: 100%; |
||||
|
height: 52px; |
||||
|
background: linear-gradient(135deg, #0d4b68 0%, #0284c7 100%); |
||||
|
color: #ffffff; |
||||
|
border: none; |
||||
|
border-radius: 12px; |
||||
|
font-family: 'Outfit', sans-serif; |
||||
|
font-size: 1rem; |
||||
|
font-weight: 700; |
||||
|
letter-spacing: 0.5px; |
||||
|
cursor: pointer; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
gap: 10px; |
||||
|
transition: all 0.3s ease; |
||||
|
box-shadow: 0 8px 20px rgba(13, 75, 104, 0.25); |
||||
|
margin-top: 10px; |
||||
|
} |
||||
|
|
||||
|
.btn-submit:hover:not(:disabled) { |
||||
|
background: linear-gradient(135deg, #093448 0%, #0369a1 100%); |
||||
|
box-shadow: 0 12px 25px rgba(13, 75, 104, 0.35); |
||||
|
transform: translateY(-2px); |
||||
|
} |
||||
|
|
||||
|
.btn-submit:disabled { |
||||
|
opacity: 0.7; |
||||
|
cursor: not-allowed; |
||||
|
} |
||||
|
|
||||
|
#error-box { |
||||
|
background: #fef2f2; |
||||
|
border: 1px solid #fecaca; |
||||
|
color: #b91c1c; |
||||
|
padding: 12px 16px; |
||||
|
border-radius: 10px; |
||||
|
font-size: 0.84rem; |
||||
|
font-weight: 500; |
||||
|
margin-bottom: 20px; |
||||
|
display: none; |
||||
|
align-items: center; |
||||
|
gap: 10px; |
||||
|
animation: shake 0.4s ease; |
||||
|
} |
||||
|
|
||||
|
@keyframes shake { |
||||
|
0%, 100% { transform: translateX(0); } |
||||
|
25% { transform: translateX(-5px); } |
||||
|
75% { transform: translateX(5px); } |
||||
|
} |
||||
|
|
||||
|
.system-badge-footer { |
||||
|
margin-top: 25px; |
||||
|
text-align: center; |
||||
|
font-size: 0.76rem; |
||||
|
color: #94a3b8; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
gap: 8px; |
||||
|
} |
||||
|
|
||||
|
.system-badge-footer span { |
||||
|
display: inline-block; |
||||
|
width: 6px; |
||||
|
height: 6px; |
||||
|
background: #22c55e; |
||||
|
border-radius: 50%; |
||||
|
box-shadow: 0 0 8px #22c55e; |
||||
|
} |
||||
|
|
||||
|
.back-portal-link { |
||||
|
display: block; |
||||
|
text-align: center; |
||||
|
margin-top: 18px; |
||||
|
color: #0284c7; |
||||
|
text-decoration: none; |
||||
|
font-size: 0.85rem; |
||||
|
font-weight: 600; |
||||
|
transition: color 0.2s; |
||||
|
} |
||||
|
|
||||
|
.back-portal-link:hover { |
||||
|
color: #0369a1; |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div class="ambient-glow glow-1"></div> |
||||
|
<div class="ambient-glow glow-2"></div> |
||||
|
|
||||
|
<div class="login-card"> |
||||
|
<div class="header-branding"> |
||||
|
<div class="logo-wrap"> |
||||
|
<img th:src="@{/assets/header-images/gcc1.png}" alt="Greater Chennai Corporation Logo"> |
||||
|
</div> |
||||
|
<h2 class="brand-title-en">Greater Chennai Corporation</h2> |
||||
|
<p class="brand-title-ta">பெருநகர சென்னை மாநகராட்சி</p> |
||||
|
<div class="badge-module"> |
||||
|
<i class="fa-solid fa-boxes-packing"></i> |
||||
|
<span>Rental Management System</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<h3 class="form-title">Portal Sign In</h3> |
||||
|
<p class="form-subtitle">Work Orders • Requests • Challans • Issue & Return</p> |
||||
|
|
||||
|
<div id="error-box"> |
||||
|
<i class="fa-solid fa-circle-exclamation fs-5"></i> |
||||
|
<span id="error-text">Invalid username or password!</span> |
||||
|
</div> |
||||
|
|
||||
|
<form id="rentalLoginForm" onsubmit="handleRentalLogin(event)"> |
||||
|
<div class="form-floating-custom"> |
||||
|
<input type="text" name="usrName" id="usrName" placeholder="Enter Username / Employee ID" required autocomplete="username"> |
||||
|
<i class="fa-solid fa-user input-icon"></i> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-floating-custom"> |
||||
|
<input type="password" name="usrPass" id="usrPass" placeholder="Enter Password" required autocomplete="current-password"> |
||||
|
<i class="fa-solid fa-lock input-icon"></i> |
||||
|
</div> |
||||
|
|
||||
|
<button type="submit" id="submit-btn" class="btn-submit"> |
||||
|
<span>Sign In to Rental System</span> |
||||
|
<i class="fa-solid fa-arrow-right-to-bracket"></i> |
||||
|
</button> |
||||
|
</form> |
||||
|
|
||||
|
<a th:href="@{/}" class="back-portal-link"> |
||||
|
<i class="fa-solid fa-arrow-left me-1"></i> Return to Main GCC Home |
||||
|
</a> |
||||
|
|
||||
|
<div class="system-badge-footer"> |
||||
|
<span></span> |
||||
|
<span>GCC IT Cell Secured System • Active Version 2.0</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Custom JS --> |
||||
|
<script th:inline="javascript"> |
||||
|
const contextPath = /*[[@{/}]]*/ '/'; |
||||
|
</script> |
||||
|
|
||||
|
<script> |
||||
|
function handleRentalLogin(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.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Authenticating...'; |
||||
|
|
||||
|
const username = document.getElementById("usrName").value.trim(); |
||||
|
const password = document.getElementById("usrPass").value; |
||||
|
|
||||
|
const urlParams = new URLSearchParams(); |
||||
|
urlParams.append('usrName', username); |
||||
|
urlParams.append('usrPass', password); |
||||
|
|
||||
|
// Fetch CSRF tokens if available |
||||
|
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 + 'gccrentalmanagement/api/login', { |
||||
|
method: 'POST', |
||||
|
headers: headers, |
||||
|
body: urlParams |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(data => { |
||||
|
if (data.result) { |
||||
|
sessionStorage.setItem("rental_usrName", data.usrName); |
||||
|
sessionStorage.setItem("rental_usrRole", data.usrRole || "USER"); |
||||
|
window.location.href = contextPath + 'gccrentalmanagement/dashboard'; |
||||
|
} else { |
||||
|
submitBtn.disabled = false; |
||||
|
submitBtn.innerHTML = '<span>Sign In to Rental System</span> <i class="fa-solid fa-arrow-right-to-bracket"></i>'; |
||||
|
errorText.textContent = data.error || "Authentication failed. Check your username and password."; |
||||
|
errorBox.style.display = "flex"; |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
console.error("Login Error:", err); |
||||
|
submitBtn.disabled = false; |
||||
|
submitBtn.innerHTML = '<span>Sign In to Rental System</span> <i class="fa-solid fa-arrow-right-to-bracket"></i>'; |
||||
|
errorText.textContent = "Network error. Please try again later."; |
||||
|
errorBox.style.display = "flex"; |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
4300
src/main/resources/templates/gcctonermanagement/upload.html
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue