From b7451652b09c35f18d14410ee992a6a90ce2eaef Mon Sep 17 00:00:00 2001 From: yoganandhank Date: Thu, 23 Jul 2026 13:09:12 +0530 Subject: [PATCH] new changes in manpower and toner management and payment tracker api and UI changes --- .../controller/HomeController.java | 10 + .../controller/TonerController.java | 268 +- .../service/TonerService.java | 380 +- .../gcc_manpower/service/AppUserService.java | 18 + .../resources/templates/fragments/navbar.html | 5 + .../gccservicepaymenttracker/dashboard.html | 242 +- .../gccservicepaymenttracker/details.html | 30 + .../templates/gcctonermanagement/upload.html | 3754 +++++++++++++++-- src/main/resources/templates/home/home.html | 126 +- 9 files changed, 4283 insertions(+), 550 deletions(-) diff --git a/src/main/java/com/gcc_manpower/controller/HomeController.java b/src/main/java/com/gcc_manpower/controller/HomeController.java index 67f0ae1..fa22f40 100644 --- a/src/main/java/com/gcc_manpower/controller/HomeController.java +++ b/src/main/java/com/gcc_manpower/controller/HomeController.java @@ -653,6 +653,16 @@ public class HomeController { return appUserService.getDeletedWorkOrders(); } + @GetMapping("/api/employee/recent-updates") + @ResponseBody + public List> getRecentEmployeeUpdates(HttpSession session) { + String usrName = (String) session.getAttribute("usrName"); + if (usrName == null) { + return new ArrayList<>(); + } + return appUserService.getRecentEmployeeUpdates(); + } + @PostMapping("/usr-logout") public String logout(HttpSession session) { SecurityContextHolder.clearContext(); diff --git a/src/main/java/com/gcc_manpower/gcctonermanagement/controller/TonerController.java b/src/main/java/com/gcc_manpower/gcctonermanagement/controller/TonerController.java index 699f342..87dabad 100644 --- a/src/main/java/com/gcc_manpower/gcctonermanagement/controller/TonerController.java +++ b/src/main/java/com/gcc_manpower/gcctonermanagement/controller/TonerController.java @@ -1,5 +1,6 @@ package com.gcc_manpower.gcctonermanagement.controller; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -16,6 +17,8 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.multipart.MultipartFile; import java.io.File; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.type.TypeReference; import com.gcc_manpower.gcctonermanagement.service.TonerService; import com.gcc_manpower.service.AppUserService; import jakarta.servlet.http.HttpSession; @@ -137,14 +140,25 @@ public class TonerController { return tonerService.getActiveTonersByPrinter(pid); } + @GetMapping("/api/departments") + @ResponseBody + public List> getDepartments(HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return java.util.Collections.emptyList(); + } + return tonerService.getActiveDepartments(); + } + @PostMapping("/api/inward") @ResponseBody public Map uploadInward( + @RequestParam("refNo") String refNo, @RequestParam("companyName") String companyName, @RequestParam("pid") int pid, @RequestParam("tid") int tid, @RequestParam("qty") String qty, @RequestParam(value = "dcFile", required = false) MultipartFile dcFile, + @RequestParam(value = "requestId", required = false) Integer requestId, HttpSession session) { Map response = new HashMap<>(); @@ -155,7 +169,17 @@ public class TonerController { return response; } - if (dcFile != null && !dcFile.isEmpty() && !isPdfFile(dcFile)) { + String updatedBy = appUserService.getUserIdByName(username); + if (updatedBy == null) + updatedBy = username; + + if (dcFile == null || dcFile.isEmpty()) { + response.put("success", false); + response.put("error", "Delivery Challan (DC) PDF file is required."); + return response; + } + + if (!isPdfFile(dcFile)) { response.put("success", false); response.put("error", "Delivery Challan file must be a PDF."); return response; @@ -170,7 +194,7 @@ public class TonerController { String dcPath = saveUploadedFile(dcFile, "dc", uploadDir); boolean saved = tonerService.saveInwardRegister( - companyName.trim(), pid, tid, qty.trim(), dcPath, username); + refNo.trim(), companyName.trim(), pid, tid, qty.trim(), dcPath, updatedBy, requestId); if (saved) { response.put("success", true); @@ -207,12 +231,38 @@ public class TonerController { return response; } - if (userRequestFile != null && !userRequestFile.isEmpty() && !isPdfFile(userRequestFile)) { + String updatedBy = appUserService.getUserIdByName(username); + if (updatedBy == null) + updatedBy = username; + + if (userRequestFile == null || userRequestFile.isEmpty()) { + response.put("success", false); + response.put("error", "User Request Letter PDF file is required."); + return response; + } + + if (!isPdfFile(userRequestFile)) { response.put("success", false); response.put("error", "User Request file must be a PDF."); return response; } + int qtyReq; + try { + qtyReq = Integer.parseInt(qtyRequested.trim()); + } catch (NumberFormatException e) { + response.put("success", false); + response.put("error", "Quantity requested must be a valid number."); + return response; + } + + int availStock = tonerService.getTonerAvailableStock(tid); + if (qtyReq > availStock) { + response.put("success", false); + response.put("error", "Requested quantity (" + qtyReq + ") exceeds available stock (" + availStock + ")."); + return response; + } + try { File uploadDir = new File(tonerUploadPathConfig).getAbsoluteFile(); if (!uploadDir.exists()) { @@ -222,7 +272,7 @@ public class TonerController { String urPath = saveUploadedFile(userRequestFile, "user_request", uploadDir); String reqNo = tonerService.saveUserRequest( - itcellRefNo.trim(), deptId.trim(), pid, tid, qtyRequested.trim(), urPath, username); + itcellRefNo.trim(), deptId.trim(), pid, tid, qtyRequested.trim(), urPath, updatedBy); if (reqNo != null) { response.put("success", true); @@ -257,6 +307,10 @@ public class TonerController { return response; } + String updatedBy = appUserService.getUserIdByName(username); + if (updatedBy == null) + updatedBy = username; + if (finalDeliveredFile != null && !finalDeliveredFile.isEmpty() && !isPdfFile(finalDeliveredFile)) { response.put("success", false); response.put("error", "Final Delivered file must be a PDF."); @@ -272,7 +326,7 @@ public class TonerController { String fdPath = saveUploadedFile(finalDeliveredFile, "final_delivered", uploadDir); boolean saved = tonerService.saveOutwardRegister( - id, qtyIssued.trim(), fdPath, username); + id, qtyIssued.trim(), fdPath, updatedBy); if (saved) { response.put("success", true); @@ -290,6 +344,88 @@ public class TonerController { return response; } + @PostMapping("/api/workorder") + @ResponseBody + public Map saveWorkorder( + @RequestParam("fileNumber") String fileNumber, + @RequestParam("vendorName") String vendorName, + @RequestParam("startDate") String startDate, + @RequestParam("endDate") String endDate, + @RequestParam("totalQty") String totalQty, + @RequestParam("itemsJson") String itemsJson, + @RequestParam("dcFile") MultipartFile dcFile, + HttpSession session) { + + Map response = new HashMap<>(); + String username = (String) session.getAttribute("toner_usrName"); + if (username == null) { + response.put("success", false); + response.put("error", "Unauthorized access. Please log in."); + return response; + } + + String updatedBy = appUserService.getUserIdByName(username); + if (updatedBy == null) + updatedBy = username; + + if (dcFile == null || dcFile.isEmpty()) { + response.put("success", false); + response.put("error", "Delivery Challan (DC) PDF upload file is required."); + return response; + } + + if (!isPdfFile(dcFile)) { + response.put("success", false); + response.put("error", "Delivery Challan file must be a PDF."); + return response; + } + + // Auto-generate refNo: ITCell-YYYY/MM/DD/XXXX + java.time.LocalDate today = java.time.LocalDate.now(); + int randomNum = (int) (Math.random() * 9000) + 1000; // 4-digit random number + String refNo = String.format("ITCell-%d/%02d/%02d/%d", today.getYear(), today.getMonthValue(), + today.getDayOfMonth(), randomNum); + + try { + ObjectMapper mapper = new ObjectMapper(); + List> items = mapper.readValue(itemsJson, + new TypeReference>>() { + }); + + if (items == null || items.isEmpty()) { + response.put("success", false); + response.put("error", "Please add at least one printer/toner model quantity entry."); + return response; + } + + File uploadDir = new File(tonerUploadPathConfig).getAbsoluteFile(); + if (!uploadDir.exists()) { + uploadDir.mkdirs(); + } + + String dcPath = saveUploadedFile(dcFile, "workorder_dc", uploadDir); + + boolean saved = tonerService.saveWorkorder( + refNo, fileNumber.trim(), vendorName.trim(), + startDate, endDate, dcPath, totalQty.trim(), items, updatedBy); + + if (saved) { + response.put("success", true); + response.put("refNo", refNo); + response.put("message", "Workorder registered successfully."); + } else { + deleteFileIfExists(dcPath, uploadDir); + response.put("success", false); + response.put("error", "Failed to save workorder details in the database."); + } + } catch (Exception e) { + response.put("success", false); + response.put("error", "An error occurred: " + e.getMessage()); + e.printStackTrace(); + } + return response; + } + @GetMapping("/api/report") @ResponseBody public Map getReportData(HttpSession session) { @@ -359,7 +495,7 @@ public class TonerController { File destFile = new File(uploadDir, savedFilename).getAbsoluteFile(); file.transferTo(destFile); - return "/gcctonermanagementfiles/" + savedFilename; + return "gcctonermanagementfiles/" + savedFilename; } private void deleteFileIfExists(String webPath, File uploadDir) { @@ -375,4 +511,124 @@ public class TonerController { System.err.println("Error deleting file: " + e.getMessage()); } } + + @GetMapping("/api/workorders/active") + @ResponseBody + public List getActiveWorkorderRefNos(HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getActiveWorkorderRefNos(); + } + + @PostMapping("/api/workorder-request") + @ResponseBody + public Map uploadWorkorderModelRequest( + @RequestParam("refNo") String refNo, + @RequestParam("companyName") String companyName, + @RequestParam("pid") String pid, + @RequestParam("tid") String tid, + @RequestParam("qtyRequested") String qtyRequested, + @RequestParam("emailCopyFile") MultipartFile emailCopyFile, + HttpSession session) { + + Map response = new HashMap<>(); + String username = (String) session.getAttribute("toner_usrName"); + if (username == null) { + response.put("success", false); + response.put("error", "Unauthorized access. Please log in."); + return response; + } + + String updatedBy = appUserService.getUserIdByName(username); + if (updatedBy == null) + updatedBy = username; + + if (emailCopyFile == null || emailCopyFile.isEmpty()) { + response.put("success", false); + response.put("error", "Email copy PDF upload file is required."); + return response; + } + + if (!isPdfFile(emailCopyFile)) { + response.put("success", false); + response.put("error", "Email copy file must be a PDF."); + return response; + } + + try { + File uploadDir = new File(tonerUploadPathConfig).getAbsoluteFile(); + if (!uploadDir.exists()) { + uploadDir.mkdirs(); + } + + String ecPath = saveUploadedFile(emailCopyFile, "workorder_request_email", uploadDir); + + boolean saved = tonerService.saveWorkorderModelRequest( + refNo.trim(), companyName.trim(), pid.trim(), tid.trim(), qtyRequested.trim(), ecPath, updatedBy); + + if (saved) { + response.put("success", true); + response.put("message", "Workorder model request details saved successfully."); + } else { + deleteFileIfExists(ecPath, uploadDir); + response.put("success", false); + response.put("error", "Failed to save workorder request details in the database."); + } + } catch (Exception e) { + response.put("success", false); + response.put("error", "An error occurred: " + e.getMessage()); + e.printStackTrace(); + } + return response; + } + + @GetMapping("/api/workorders/items") + @ResponseBody + public List> getWorkorderRegisteredItems( + @RequestParam("refNo") String refNo, + HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getWorkorderRegisteredItems(refNo); + } + + @GetMapping("/api/workorders/active-requests") + @ResponseBody + public List getActiveWorkorderRequestRefNos(HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getActiveWorkorderRequestRefNos(); + } + + @GetMapping("/api/workorders/requests") + @ResponseBody + public List> getWorkorderRequests( + @RequestParam("refNo") String refNo, + HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getWorkorderRequests(refNo); + } + + @GetMapping("/api/workorder/history") + @ResponseBody + public List> getWorkorderRegisterHistory(HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getWorkorderRegisterHistory(); + } + + @GetMapping("/api/workorder-request/history") + @ResponseBody + public List> getWorkorderModelRequestHistory(HttpSession session) { + if (session.getAttribute("toner_usrName") == null) { + return new ArrayList<>(); + } + return tonerService.getWorkorderModelRequestHistory(); + } } diff --git a/src/main/java/com/gcc_manpower/gcctonermanagement/service/TonerService.java b/src/main/java/com/gcc_manpower/gcctonermanagement/service/TonerService.java index fda9cd5..ba10c58 100644 --- a/src/main/java/com/gcc_manpower/gcctonermanagement/service/TonerService.java +++ b/src/main/java/com/gcc_manpower/gcctonermanagement/service/TonerService.java @@ -6,11 +6,13 @@ import java.util.List; import java.util.Map; import javax.sql.DataSource; +import jakarta.annotation.PostConstruct; 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 org.springframework.transaction.annotation.Transactional; @Service public class TonerService { @@ -22,50 +24,6 @@ public class TonerService { this.jdbcTemplate = new JdbcTemplate(dataSource); } - @jakarta.annotation.PostConstruct - public void initTables() { - try { - jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS stock_register_details (" + - "id INT AUTO_INCREMENT PRIMARY KEY, " + - "company_name VARCHAR(30), " + - "pid VARCHAR(20), " + - "tid VARCHAR(30), " + - "qty_registered VARCHAR(30), " + - "dc_upload VARCHAR(250), " + - "cdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " + - "updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " + - "order_by VARCHAR(45), " + - "is_active TINYINT DEFAULT 1, " + - "is_delete TINYINT DEFAULT 0" + - ")"); - - jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS department_requested_details (" + - "id INT AUTO_INCREMENT PRIMARY KEY, " + - "req_no VARCHAR(70), " + - "company_name VARCHAR(30), " + - "itcell_ref_no VARCHAR(45), " + - "dept_id VARCHAR(30), " + - "pid VARCHAR(20), " + - "tid VARCHAR(30), " + - "qty_registered VARCHAR(30), " + - "qty_requested VARCHAR(30), " + - "qty_delivered VARCHAR(30), " + - "dc_upload VARCHAR(250), " + - "user_request_upload VARCHAR(250), " + - "final_delivered_upload VARCHAR(250), " + - "cdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " + - "updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " + - "updated_by VARCHAR(45), " + - "order_by VARCHAR(45), " + - "is_active TINYINT DEFAULT 1, " + - "is_delete TINYINT DEFAULT 0" + - ")"); - } catch (Exception e) { - System.err.println("Error initializing tables: " + e.getMessage()); - e.printStackTrace(); - } - } - public List> getActivePrinters() { String sql = "SELECT id, printer_name FROM printer_model_list where is_active = 1 AND is_delete = 0 "; try { @@ -77,7 +35,12 @@ public class TonerService { } public List> getActiveTonersByPrinter(int pid) { - String sql = "SELECT id, model_name FROM toner_model_list WHERE pid = ? AND is_active = 1 AND is_delete = 0 "; + String sql = "SELECT t.id, t.model_name, t.part_code, " + + "(COALESCE((SELECT SUM(CAST(sr.qty_registered AS SIGNED)) FROM stock_register_details sr WHERE CAST(sr.pid AS SIGNED) = t.pid AND CAST(sr.tid AS SIGNED) = t.id AND sr.is_active = 1 AND sr.is_delete = 0), 0) - " + + + "COALESCE((SELECT SUM(CAST(dr.qty_delivered AS SIGNED)) FROM department_requested_details dr WHERE CAST(dr.pid AS SIGNED) = t.pid AND CAST(dr.tid AS SIGNED) = t.id AND dr.is_active = 1 AND dr.is_delete = 0), 0)) AS available_stock " + + + "FROM toner_model_list t WHERE t.pid = ? AND t.is_active = 1 AND t.is_delete = 0"; try { return jdbcTemplate.queryForList(sql, pid); } catch (Exception e) { @@ -96,13 +59,32 @@ public class TonerService { } } - public boolean saveInwardRegister(String companyName, int pid, int tid, String qty, String dcUpload, String username) { + public int getTonerAvailableStock(int tid) { + String sql = "SELECT " + + "(COALESCE((SELECT SUM(CAST(sr.qty_registered AS SIGNED)) FROM stock_register_details sr WHERE CAST(sr.tid AS SIGNED) = t.id AND sr.is_active = 1 AND sr.is_delete = 0), 0) - " + + + "COALESCE((SELECT SUM(CAST(dr.qty_delivered AS SIGNED)) FROM department_requested_details dr WHERE CAST(dr.tid AS SIGNED) = t.id AND dr.is_active = 1 AND dr.is_delete = 0), 0)) AS available_stock " + + + "FROM toner_model_list t WHERE t.id = ?"; + try { + return jdbcTemplate.queryForObject(sql, Integer.class, tid); + } catch (Exception e) { + System.err.println("Error fetching toner available stock for id " + tid + ": " + e.getMessage()); + return 0; + } + } + + public boolean saveInwardRegister(String refNo, String companyName, int pid, int tid, String qty, String dcUpload, + String username, Integer requestId) { String sql = "INSERT INTO stock_register_details " + - "(company_name, pid, tid, qty_registered, dc_upload, cdate, updated_date, order_by, is_active, is_delete) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; + "(ref_no, company_name, pid, tid, qty_registered, dc_upload, cdate, updated_date, updated_by, is_active, is_delete, request_id) " + + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?)"; java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis()); try { - int rows = jdbcTemplate.update(sql, companyName, String.valueOf(pid), String.valueOf(tid), qty, dcUpload, now, now, username); + int rows = jdbcTemplate.update(sql, refNo, companyName, String.valueOf(pid), String.valueOf(tid), qty, + dcUpload, + now, now, username, requestId); return rows > 0; } catch (Exception e) { System.err.println("Error saving inward register: " + e.getMessage()); @@ -121,7 +103,8 @@ public class TonerService { } } - public String saveUserRequest(String itCellRefNo, String deptId, int pid, int tid, String qtyRequested, String userRequestUpload, String username) { + public String saveUserRequest(String itCellRefNo, String deptId, int pid, int tid, String qtyRequested, + String userRequestUpload, String username) { String tonerModel = getTonerModelName(tid); String cleanModel = tonerModel.trim().replaceAll("\\s+", "-").replaceAll("[^a-zA-Z0-9-]", ""); int maxId = getMaxRequestId(); @@ -130,11 +113,13 @@ public class TonerService { String reqNo = String.format("%s-%d-%04d", cleanModel, year, seqNum); String sql = "INSERT INTO department_requested_details " + - "(req_no, itcell_ref_no, dept_id, pid, tid, qty_requested, qty_delivered, user_request_upload, cdate, updated_date, updated_by, is_active, is_delete) " + + "(req_no, itcell_ref_no, dept_id, pid, tid, qty_requested, qty_delivered, user_request_upload, cdate, updated_date, updated_by, is_active, is_delete) " + + "VALUES (?, ?, ?, ?, ?, ?, '0', ?, ?, ?, ?, 1, 0)"; java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis()); try { - int rows = jdbcTemplate.update(sql, reqNo, itCellRefNo, deptId, String.valueOf(pid), String.valueOf(tid), qtyRequested, userRequestUpload, now, now, username); + int rows = jdbcTemplate.update(sql, reqNo, itCellRefNo, deptId, String.valueOf(pid), String.valueOf(tid), + qtyRequested, userRequestUpload, now, now, username); return rows > 0 ? reqNo : null; } catch (Exception e) { System.err.println("Error saving user request: " + e.getMessage()); @@ -144,11 +129,13 @@ public class TonerService { } public List> getPendingRequests() { - String sql = "SELECT r.id, r.req_no, r.dept_id, r.pid, r.tid, r.qty_requested, r.qty_delivered, " + + String sql = "SELECT r.id, r.req_no, COALESCE(d.dept_name, r.dept_id) AS dept_id, r.pid, r.tid, r.qty_requested, r.qty_delivered, " + + "p.printer_name, t.model_name " + "FROM department_requested_details r " + "LEFT JOIN printer_model_list p ON r.pid = p.id " + "LEFT JOIN toner_model_list t ON r.tid = t.id " + + "LEFT JOIN department_list d ON CAST(r.dept_id AS SIGNED) = d.id " + "WHERE r.is_active = 1 AND r.is_delete = 0 " + "AND (r.qty_delivered IS NULL OR CAST(r.qty_delivered AS SIGNED) < CAST(r.qty_requested AS SIGNED)) " + "ORDER BY r.id DESC"; @@ -161,17 +148,29 @@ public class TonerService { } public boolean saveOutwardRegister(int id, String qtyIssued, String finalDeliveredUpload, String username) { - String sql = "UPDATE department_requested_details " + - "SET qty_delivered = ?, final_delivered_upload = ?, updated_date = ?, updated_by = ? " + - "WHERE id = ?"; + String sql; + int rows; java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis()); try { - int rows = jdbcTemplate.update(sql, qtyIssued, finalDeliveredUpload, now, username, id); + if (finalDeliveredUpload != null) { + sql = "UPDATE department_requested_details " + + "SET final_delivered_upload = CASE WHEN final_delivered_upload IS NULL OR final_delivered_upload = '' THEN ? ELSE CONCAT(final_delivered_upload, ',', ?) END, " + + + "updated_date = ?, updated_by = ? " + + "WHERE id = ?"; + rows = jdbcTemplate.update(sql, finalDeliveredUpload, finalDeliveredUpload, now, username, id); + } else { + sql = "UPDATE department_requested_details " + + "SET qty_delivered = CAST(COALESCE(qty_delivered, 0) AS SIGNED) + CAST(? AS SIGNED), " + + "updated_date = ?, updated_by = ? " + + "WHERE id = ?"; + rows = jdbcTemplate.update(sql, qtyIssued, now, username, id); + } return rows > 0; } catch (Exception e) { System.err.println("Error updating outward register: " + e.getMessage()); e.printStackTrace(); - return false; + throw new RuntimeException("Rollback saveOutwardRegister due to: " + e.getMessage()); } } @@ -181,29 +180,41 @@ public class TonerService { String sqlRaised = "SELECT COALESCE(SUM(CAST(qty_requested AS SIGNED)), 0) FROM department_requested_details WHERE is_active = 1 AND is_delete = 0"; String sqlDistributed = "SELECT COALESCE(SUM(CAST(qty_delivered AS SIGNED)), 0) FROM department_requested_details WHERE is_active = 1 AND is_delete = 0"; String sqlInward = "SELECT COALESCE(SUM(CAST(qty_registered AS SIGNED)), 0) FROM stock_register_details WHERE is_active = 1 AND is_delete = 0"; + String sqlWorkorderRegistered = "SELECT COALESCE(SUM(CAST(qty_registered AS SIGNED)), 0) FROM workorder_printermodel_qty WHERE is_active = 1 AND is_delete = 0"; + String sqlWorkorderRequested = "SELECT COALESCE(SUM(CAST(qty_requested AS SIGNED)), 0) FROM workorder_model_request_details WHERE is_active = 1 AND is_delete = 0"; try { int totalRaised = jdbcTemplate.queryForObject(sqlRaised, Integer.class); int totalDistributed = jdbcTemplate.queryForObject(sqlDistributed, Integer.class); int inwardStock = jdbcTemplate.queryForObject(sqlInward, Integer.class); int availableStock = inwardStock - totalDistributed; + int workorderRegistered = jdbcTemplate.queryForObject(sqlWorkorderRegistered, Integer.class); + int workorderRequested = jdbcTemplate.queryForObject(sqlWorkorderRequested, Integer.class); metrics.put("totalRaised", totalRaised); metrics.put("totalDistributed", totalDistributed); + metrics.put("inwardStock", inwardStock); metrics.put("availableStock", availableStock); + metrics.put("workorderRegistered", workorderRegistered); + metrics.put("workorderRequested", workorderRequested); } catch (Exception e) { System.err.println("Error computing dashboard metrics: " + e.getMessage()); metrics.put("totalRaised", 0); metrics.put("totalDistributed", 0); + metrics.put("inwardStock", 0); metrics.put("availableStock", 0); + metrics.put("workorderRegistered", 0); + metrics.put("workorderRequested", 0); } return metrics; } public List> getInventorySummary() { - String safeSql = "SELECT p.printer_name, t.model_name, " + - "COALESCE((SELECT SUM(CAST(sr.qty_registered AS SIGNED)) FROM stock_register_details sr WHERE CAST(sr.pid AS SIGNED) = t.pid AND CAST(sr.tid AS SIGNED) = t.id AND sr.is_active = 1 AND sr.is_delete = 0), 0) AS inward_qty, " + - "COALESCE((SELECT SUM(CAST(dr.qty_delivered AS SIGNED)) FROM department_requested_details dr WHERE CAST(dr.pid AS SIGNED) = t.pid AND CAST(dr.tid AS SIGNED) = t.id AND dr.is_active = 1 AND dr.is_delete = 0), 0) AS outward_qty " + + String safeSql = "SELECT p.id AS pid, p.printer_name, t.id AS tid, t.model_name, " + + "COALESCE((SELECT SUM(CAST(sr.qty_registered AS SIGNED)) FROM stock_register_details sr WHERE CAST(sr.pid AS SIGNED) = t.pid AND CAST(sr.tid AS SIGNED) = t.id AND sr.is_active = 1 AND sr.is_delete = 0), 0) AS inward_qty, " + + + "COALESCE((SELECT SUM(CAST(dr.qty_delivered AS SIGNED)) FROM department_requested_details dr WHERE CAST(dr.pid AS SIGNED) = t.pid AND CAST(dr.tid AS SIGNED) = t.id AND dr.is_active = 1 AND dr.is_delete = 0), 0) AS outward_qty " + + "FROM toner_model_list t " + "JOIN printer_model_list p ON t.pid = p.id " + "WHERE t.is_active = 1 AND t.is_delete = 0 " + @@ -225,13 +236,19 @@ public class TonerService { } public List> getInwardHistory() { - String sql = "SELECT s.id, s.company_name, s.qty_registered, s.dc_upload, s.cdate, s.order_by, " + - "p.printer_name, t.model_name " + - "FROM stock_register_details s " + - "LEFT JOIN printer_model_list p ON CAST(s.pid AS SIGNED) = p.id " + - "LEFT JOIN toner_model_list t ON CAST(s.tid AS SIGNED) = t.id " + - "WHERE s.is_active = 1 AND s.is_delete = 0 " + - "ORDER BY s.id DESC"; + String sql = "SELECT MAX(s.id) AS id, s.ref_no, s.pid, s.tid, s.company_name, " + + "SUM(CAST(s.qty_registered AS SIGNED)) AS qty_registered, MAX(s.dc_upload) AS dc_upload, " + + "MAX(s.cdate) AS cdate, COALESCE(MAX(u.usr_name), MAX(s.updated_by)) AS order_by, " + + "p.printer_name, t.model_name, " + + "COALESCE((SELECT w.qty_registered FROM workorder_printermodel_qty w WHERE w.ref_no = s.ref_no AND w.pid = s.pid AND w.tid = s.tid AND w.is_active = 1 AND w.is_delete = 0 LIMIT 1), 0) AS qty_workorder_registered, " + + "COALESCE((SELECT SUM(CAST(mr.qty_requested AS SIGNED)) FROM workorder_model_request_details mr WHERE mr.ref_no = s.ref_no AND mr.pid = s.pid AND mr.tid = s.tid AND mr.is_active = 1 AND mr.is_delete = 0), 0) AS qty_workorder_requested " + + "FROM stock_register_details s " + + "LEFT JOIN printer_model_list p ON CAST(s.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(s.tid AS SIGNED) = t.id " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(s.updated_by AS SIGNED) = u.usr_id " + + "WHERE s.is_active = 1 AND s.is_delete = 0 " + + "GROUP BY s.ref_no, s.pid, s.tid, s.company_name, p.printer_name, t.model_name " + + "ORDER BY MAX(s.id) DESC"; try { return jdbcTemplate.queryForList(sql); } catch (Exception e) { @@ -241,14 +258,16 @@ public class TonerService { } public List> getAllUserRequests() { - String sql = "SELECT r.id, r.req_no, r.itcell_ref_no, r.dept_id, r.qty_requested, r.qty_delivered, " + - "r.user_request_upload, r.cdate, r.updated_date, r.updated_by, " + - "p.printer_name, t.model_name " + - "FROM department_requested_details r " + - "LEFT JOIN printer_model_list p ON CAST(r.pid AS SIGNED) = p.id " + - "LEFT JOIN toner_model_list t ON CAST(r.tid AS SIGNED) = t.id " + - "WHERE r.is_active = 1 AND r.is_delete = 0 " + - "ORDER BY r.id DESC"; + String sql = "SELECT r.id, r.pid, r.tid, r.req_no, r.itcell_ref_no, COALESCE(d.dept_name, r.dept_id) AS dept_id, r.qty_requested, r.qty_delivered, " + + "r.user_request_upload, r.cdate, r.updated_date, COALESCE(u.usr_name, r.updated_by) AS updated_by, " + + "p.printer_name, t.model_name " + + "FROM department_requested_details r " + + "LEFT JOIN printer_model_list p ON CAST(r.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(r.tid AS SIGNED) = t.id " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(r.updated_by AS SIGNED) = u.usr_id " + + "LEFT JOIN department_list d ON CAST(r.dept_id AS SIGNED) = d.id " + + "WHERE r.is_active = 1 AND r.is_delete = 0 " + + "ORDER BY r.id DESC"; try { return jdbcTemplate.queryForList(sql); } catch (Exception e) { @@ -258,20 +277,223 @@ public class TonerService { } public List> getOutwardHistory() { - String sql = "SELECT r.id, r.req_no, r.itcell_ref_no, r.dept_id, r.qty_requested, r.qty_delivered, r.final_delivered_upload, r.user_request_upload, r.cdate, r.updated_date, " + + String sql = "SELECT r.id, r.pid, r.tid, r.req_no, r.itcell_ref_no, COALESCE(d.dept_name, r.dept_id) AS dept_id, r.qty_requested, r.qty_delivered, r.final_delivered_upload, r.user_request_upload, r.cdate, r.updated_date, " + + "p.printer_name, t.model_name " + "FROM department_requested_details r " + "LEFT JOIN printer_model_list p ON CAST(r.pid AS SIGNED) = p.id " + "LEFT JOIN toner_model_list t ON CAST(r.tid AS SIGNED) = t.id " + + "LEFT JOIN department_list d ON CAST(r.dept_id AS SIGNED) = d.id " + "WHERE r.is_active = 1 AND r.is_delete = 0 " + "AND r.qty_delivered IS NOT NULL AND CAST(r.qty_delivered AS SIGNED) > 0 " + "ORDER BY r.updated_date DESC"; try { return jdbcTemplate.queryForList(sql); } catch (Exception e) { - System.err.println("Error fetching outward history: " + e.getMessage()); return new ArrayList<>(); } } -} + public boolean saveWorkorder(String refNo, String fileNumber, String vendorName, + String startDate, String endDate, String dcUpload, + String totalQty, List> items, String username) { + java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis()); + + String sqlMain = "INSERT INTO workorder_register_details " + + "(ref_no, file_number, vendor_name, workorder_start_date, workorder_end_date, pid, tid, total_qty_registered, dc_upload, cdate, updated_date, updated_by, is_active, is_delete) " + + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; + + String firstPid = null; + String firstTid = null; + if (items != null && !items.isEmpty()) { + Map firstItem = items.get(0); + if (firstItem.get("pid") != null) + firstPid = String.valueOf(firstItem.get("pid")); + if (firstItem.get("tid") != null) + firstTid = String.valueOf(firstItem.get("tid")); + } + + try { + int mainRows = jdbcTemplate.update(sqlMain, + refNo, fileNumber, vendorName, startDate, endDate, + firstPid, firstTid, totalQty, dcUpload, now, now, username); + + if (mainRows <= 0) { + return false; + } + + String sqlSub = "INSERT INTO workorder_printermodel_qty " + + "(ref_no, pid, tid, qty_registered, cdate, updated_date, updated_by, is_active, is_delete) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, 1, 0)"; + + for (Map item : items) { + String pid = String.valueOf(item.get("pid")); + String tid = String.valueOf(item.get("tid")); + String qty = String.valueOf(item.get("qty")); + + jdbcTemplate.update(sqlSub, refNo, pid, tid, qty, now, now, username); + } + + return true; + } catch (Exception e) { + System.err.println("Error saving workorder: " + e.getMessage()); + e.printStackTrace(); + throw new RuntimeException("Rollback saveWorkorder due to: " + e.getMessage()); + } + } + + @PostConstruct + public void initDatabase() { + try { + jdbcTemplate.execute("ALTER TABLE stock_register_details ADD COLUMN request_id INT DEFAULT NULL"); + } catch (Exception e) { + // Ignore + } + try { + jdbcTemplate.execute("ALTER TABLE workorder_register_details DROP COLUMN order_by"); + } catch (Exception e) { + // Ignore + } + try { + jdbcTemplate + .execute("ALTER TABLE workorder_printermodel_qty ADD COLUMN updated_by VARCHAR(255) DEFAULT NULL"); + } catch (Exception e) { + // Ignore + } + try { + jdbcTemplate.execute("ALTER TABLE workorder_printermodel_qty DROP COLUMN order_by"); + } catch (Exception e) { + // Ignore + } + } + + public List getActiveWorkorderRefNos() { + String sql = "SELECT ref_no FROM workorder_register_details WHERE is_active = 1 AND is_delete = 0 ORDER BY id DESC"; + try { + return jdbcTemplate.queryForList(sql, String.class); + } catch (Exception e) { + System.err.println("Error fetching workorder ref nos: " + e.getMessage()); + return new ArrayList<>(); + } + } + + public boolean saveWorkorderModelRequest(String refNo, String companyName, String pid, String tid, + String qtyRequested, String emailCopyUpload, String username) { + String sql = "INSERT INTO workorder_model_request_details " + + "(ref_no, company_name, pid, tid, qty_requested, email_copy_upload, cdate, updated_date, updated_by, is_active, is_delete) " + + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0)"; + java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis()); + try { + int rows = jdbcTemplate.update(sql, refNo, companyName, pid, tid, qtyRequested, emailCopyUpload, now, now, + username); + return rows > 0; + } catch (Exception e) { + System.err.println("Error saving workorder model request: " + e.getMessage()); + e.printStackTrace(); + return false; + } + } + + public List> getWorkorderRegisteredItems(String refNo) { + String sql = "SELECT w.pid, w.tid, w.qty_registered, p.printer_name, t.model_name, t.part_code, COALESCE(vl.vendor_name, r.vendor_name) AS vendor_name, " + + + "COALESCE((SELECT SUM(CAST(mr.qty_requested AS SIGNED)) FROM workorder_model_request_details mr " + + "WHERE mr.ref_no = w.ref_no AND mr.pid = w.pid AND mr.tid = w.tid AND mr.is_active = 1 AND mr.is_delete = 0), 0) AS qty_already_requested " + + + "FROM workorder_printermodel_qty w " + + "LEFT JOIN workorder_register_details r ON w.ref_no = r.ref_no " + + "LEFT JOIN gccpayment_processing_tracker.vendors_list vl ON CAST(r.vendor_name AS SIGNED) = vl.id " + + "LEFT JOIN printer_model_list p ON CAST(w.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(w.tid AS SIGNED) = t.id " + + "WHERE w.ref_no = ? AND w.is_active = 1 AND w.is_delete = 0"; + try { + return jdbcTemplate.queryForList(sql, refNo); + } catch (Exception e) { + System.err.println("Error fetching workorder registered items for ref " + refNo + ": " + e.getMessage()); + return new ArrayList<>(); + } + } + + public List getActiveWorkorderRequestRefNos() { + String sql = "SELECT ref_no FROM workorder_model_request_details WHERE is_active = 1 AND is_delete = 0 GROUP BY ref_no ORDER BY MAX(id) DESC"; + try { + return jdbcTemplate.queryForList(sql, String.class); + } catch (Exception e) { + System.err.println("Error fetching workorder request ref nos: " + e.getMessage()); + return new ArrayList<>(); + } + } + + public List> getWorkorderRequests(String refNo) { + String sql = "SELECT r.id, r.pid, r.tid, r.qty_requested, r.company_name AS vendor_id, r.cdate, " + + "COALESCE(u.usr_name, r.updated_by) AS updated_by, r.email_copy_upload, p.printer_name, t.model_name, t.part_code, " + + "COALESCE((SELECT SUM(CAST(sr.qty_registered AS SIGNED)) FROM stock_register_details sr " + + "WHERE ((sr.request_id = r.id) OR (sr.request_id IS NULL AND sr.ref_no = r.ref_no AND sr.pid = r.pid AND sr.tid = r.tid)) " + + "AND sr.is_active = 1 AND sr.is_delete = 0), 0) AS qty_inward_received " + + "FROM workorder_model_request_details r " + + "LEFT JOIN printer_model_list p ON CAST(r.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(r.tid AS SIGNED) = t.id " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(r.updated_by AS SIGNED) = u.usr_id " + + "WHERE r.ref_no = ? AND r.is_active = 1 AND r.is_delete = 0"; + try { + return jdbcTemplate.queryForList(sql, refNo); + } catch (Exception e) { + System.err.println("Error fetching workorder requests for ref " + refNo + ": " + e.getMessage()); + return new ArrayList<>(); + } + } + + public List> getWorkorderRegisterHistory() { + String sql = "SELECT w.id, w.ref_no, w.pid, w.tid, w.qty_registered AS total_qty_registered, " + + "r.file_number, COALESCE(vl.vendor_name, r.vendor_name) AS vendor_name, r.workorder_start_date, r.workorder_end_date, " + + + "r.dc_upload, r.cdate, COALESCE(u.usr_name, r.updated_by) AS updated_by, " + + "p.printer_name, t.model_name " + + "FROM workorder_printermodel_qty w " + + "LEFT JOIN workorder_register_details r ON w.ref_no = r.ref_no " + + "LEFT JOIN gccpayment_processing_tracker.vendors_list vl ON CAST(r.vendor_name AS SIGNED) = vl.id " + + "LEFT JOIN printer_model_list p ON CAST(w.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(w.tid AS SIGNED) = t.id " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(r.updated_by AS SIGNED) = u.usr_id " + + "WHERE w.is_active = 1 AND w.is_delete = 0 AND r.is_active = 1 AND r.is_delete = 0 " + + "ORDER BY w.id DESC"; + try { + return jdbcTemplate.queryForList(sql); + } catch (Exception e) { + System.err.println("Error fetching workorder register history: " + e.getMessage()); + return new ArrayList<>(); + } + } + + public List> getWorkorderModelRequestHistory() { + String sql = "SELECT MAX(mr.id) AS id, mr.ref_no, mr.pid, mr.tid, mr.company_name AS vendor_id, " + + "SUM(CAST(mr.qty_requested AS SIGNED)) AS qty_requested, MAX(mr.email_copy_upload) AS email_copy_upload, " + + "MAX(mr.cdate) AS cdate, COALESCE(MAX(u.usr_name), MAX(mr.updated_by)) AS order_by, p.printer_name, t.model_name, " + + "COALESCE((SELECT w.qty_registered FROM workorder_printermodel_qty w WHERE w.ref_no = mr.ref_no AND w.pid = mr.pid AND w.tid = mr.tid AND w.is_active = 1 AND w.is_delete = 0 LIMIT 1), 0) AS qty_registered " + + "FROM workorder_model_request_details mr " + + "LEFT JOIN printer_model_list p ON CAST(mr.pid AS SIGNED) = p.id " + + "LEFT JOIN toner_model_list t ON CAST(mr.tid AS SIGNED) = t.id " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(mr.updated_by AS SIGNED) = u.usr_id " + + "WHERE mr.is_active = 1 AND mr.is_delete = 0 " + + "GROUP BY mr.ref_no, mr.pid, mr.tid, mr.company_name, p.printer_name, t.model_name " + + "ORDER BY MAX(mr.id) DESC"; + try { + return jdbcTemplate.queryForList(sql); + } catch (Exception e) { + System.err.println("Error fetching workorder model request history: " + e.getMessage()); + return new ArrayList<>(); + } + } + + public List> getActiveDepartments() { + String sql = "SELECT id, dept_name FROM department_list WHERE is_active = 1 AND is_delete = 0 ORDER BY dept_name ASC"; + try { + return jdbcTemplate.queryForList(sql); + } catch (Exception e) { + System.err.println("Error fetching active departments: " + e.getMessage()); + return new ArrayList<>(); + } + } +} diff --git a/src/main/java/com/gcc_manpower/service/AppUserService.java b/src/main/java/com/gcc_manpower/service/AppUserService.java index bc2151d..92202e4 100644 --- a/src/main/java/com/gcc_manpower/service/AppUserService.java +++ b/src/main/java/com/gcc_manpower/service/AppUserService.java @@ -967,4 +967,22 @@ public class AppUserService { return new ArrayList<>(); } } + + public List> getRecentEmployeeUpdates() { + String sql = "SELECT e.emp_code, e.name, e.updated_at, e.isactive, e.isdelete, e.cdate, " + + "COALESCE(u.usr_name, e.updated_by) AS updated_by_name, " + + "COALESCE(ew.designation, e.designation) AS designation_name, " + + "COALESCE(v.vendor_name, e.vendor_id) AS vendor_name " + + "FROM employee_details e " + + "LEFT JOIN gcc_manpower.app_user u ON CAST(e.updated_by AS SIGNED) = u.usr_id " + + "LEFT JOIN employee_workorder_details ew ON CAST(e.designation AS SIGNED) = ew.id " + + "LEFT JOIN vendor_details v ON CAST(e.vendor_id AS SIGNED) = v.id " + + "ORDER BY e.updated_at DESC LIMIT 20"; + try { + return jdbcManpowerTemplate.queryForList(sql); + } catch (Exception e) { + System.err.println("Error fetching recent employee updates: " + e.getMessage()); + return new ArrayList<>(); + } + } } diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index 5d2a223..1bf4f93 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -75,6 +75,11 @@