All GCC vendors and employee details for IT department management
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

530 lines
28 KiB

package com.gcc_manpower.gccservicepaymenttracker.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import com.gcc_manpower.service.AppUserService;
import javax.sql.DataSource;
import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class GccServicePaymentTrackerService {
private JdbcTemplate jdbcTemplate;
@Autowired
private AppUserService appUserService;
@Autowired
public void setDataSource(@Qualifier("mysqlItcellManagementDataSource") DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public Map<String, Integer> getCountsByCategory() {
Map<String, Integer> counts = new HashMap<>();
counts.put("sd", 0);
counts.put("tax invoice", 0);
counts.put("emd", 0);
counts.put("bank guarantee", 0);
counts.put("delivery chellan", 0);
counts.put("asd", 0);
counts.put("agreement", 0);
counts.put("total", 0);
counts.put("status_not_updated", 0);
String sql = "SELECT "
+ "CASE WHEN p.type REGEXP '^[0-9]+$' THEN t.type_name ELSE p.type END as type_resolved, "
+ "COUNT(*) as cnt "
+ "FROM payment_tracking_details p "
+ "LEFT JOIN payment_type_list t ON p.type REGEXP '^[0-9]+$' AND t.id = p.type "
+ "WHERE p.is_active = 1 AND p.is_delete = 0 "
+ "GROUP BY type_resolved";
try {
// Count total active records
String sqlTotal = "SELECT COUNT(*) FROM payment_tracking_details WHERE is_active = 1 AND is_delete = 0";
Integer totalCount = jdbcTemplate.queryForObject(sqlTotal, Integer.class);
counts.put("total", totalCount != null ? totalCount : 0);
// Count records where type is missing
String sqlMissingType = "SELECT COUNT(*) FROM payment_tracking_details WHERE is_active = 1 AND is_delete = 0 AND (type IS NULL OR TRIM(type) = '')";
Integer missingTypeCount = jdbcTemplate.queryForObject(sqlMissingType, Integer.class);
counts.put("status_not_updated", missingTypeCount != null ? missingTypeCount : 0);
} catch (Exception e) {
System.err.println("Error getting total or missing type counts: " + e.getMessage());
}
try {
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
for (Map<String, Object> row : rows) {
String type = String.valueOf(row.get("type_resolved")).toLowerCase().trim();
Number countNum = (Number) row.get("cnt");
int count = countNum != null ? countNum.intValue() : 0;
// Map database values back to categories
if (type.equals("asd") || type.contains("asd") || type.contains("additional security")) {
counts.put("asd", counts.getOrDefault("asd", 0) + count);
} else if (type.equals("agreement") || type.contains("agreement")) {
counts.put("agreement", counts.getOrDefault("agreement", 0) + count);
} else if (type.equals("sd") || type.contains("security")) {
counts.put("sd", counts.getOrDefault("sd", 0) + count);
} else if (type.contains("invoice") || type.contains("bill")) {
counts.put("tax invoice", counts.getOrDefault("tax invoice", 0) + count);
} else if (type.equals("emd")) {
counts.put("emd", counts.getOrDefault("emd", 0) + count);
} else if (type.contains("guarantee") || type.contains("bg")) {
counts.put("bank guarantee", counts.getOrDefault("bank guarantee", 0) + count);
} else if (type.contains("chellan") || type.contains("challan") || type.contains("dc")) {
counts.put("delivery chellan", counts.getOrDefault("delivery chellan", 0) + count);
}
}
} catch (Exception e) {
System.err.println("Error getting category counts: " + e.getMessage());
}
return counts;
}
public List<Map<String, Object>> searchDetails(String type, String fromDate, String toDate, String status) {
StringBuilder sql = new StringBuilder(
"SELECT p.*, "
+ "t.type_name as resolved_type, "
+ "v.vendor_name as resolved_vendor, "
+ "s.status_name as resolved_status, "
+ "u.usr_name as updated_by_name "
+ "FROM payment_tracking_details p "
+ "LEFT JOIN payment_type_list t ON TRIM(p.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(p.type) AS UNSIGNED) "
+ "LEFT JOIN payment_vendors_list v ON TRIM(p.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(p.vendor_name) AS UNSIGNED) "
+ "LEFT JOIN payment_status_list s ON TRIM(p.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(p.status) AS UNSIGNED) "
+ "LEFT JOIN app_user u ON (p.updated_by = CAST(u.usr_id AS CHAR) OR p.updated_by = u.usr_name) "
+ "WHERE p.is_active = 1 AND p.is_delete = 0");
List<Object> params = new ArrayList<>();
if (type != null && !type.trim().isEmpty()) {
String category = type.trim().toLowerCase();
if (category.equals("status_not_updated")) {
sql.append(" AND (p.type IS NULL OR TRIM(p.type) = '')");
} else if (category.equals("asd")) {
sql.append(
" AND (LOWER(p.type) = 'asd' OR LOWER(p.type) LIKE '%asd%' OR LOWER(t.type_name) LIKE '%asd%' OR LOWER(t.type_name) LIKE '%additional security%')");
} else if (category.equals("agreement")) {
sql.append(" AND (LOWER(p.type) LIKE '%agreement%' OR LOWER(t.type_name) LIKE '%agreement%')");
} else if (category.equals("sd")) {
sql.append(
" AND ((LOWER(p.type) = 'sd' OR LOWER(p.type) LIKE '%security%' OR LOWER(t.type_name) LIKE '%security%') "
+ "AND LOWER(p.type) NOT LIKE '%additional security%' AND LOWER(p.type) NOT LIKE '%asd%' "
+ "AND (t.type_name IS NULL OR (LOWER(t.type_name) NOT LIKE '%additional security%' AND LOWER(t.type_name) NOT LIKE '%asd%')))");
} else if (category.equals("tax invoice")) {
sql.append(
" AND (LOWER(p.type) LIKE '%invoice%' OR LOWER(p.type) LIKE '%bill%' OR LOWER(t.type_name) LIKE '%invoice%' OR LOWER(t.type_name) LIKE '%bill%')");
} else if (category.equals("emd")) {
sql.append(
" AND (LOWER(p.type) = 'emd' OR LOWER(p.type) LIKE '%earnest%' OR LOWER(t.type_name) LIKE '%emd%' OR LOWER(t.type_name) LIKE '%earnest%')");
} else if (category.equals("bank guarantee")) {
sql.append(
" AND (LOWER(p.type) LIKE '%guarantee%' OR LOWER(p.type) = 'bg' OR LOWER(t.type_name) LIKE '%guarantee%' OR LOWER(t.type_name) = 'bg')");
} else if (category.equals("delivery chellan")) {
sql.append(
" AND (LOWER(p.type) LIKE '%chellan%' OR LOWER(p.type) LIKE '%challan%' OR LOWER(p.type) = 'dc' "
+ "OR LOWER(t.type_name) LIKE '%chellan%' OR LOWER(t.type_name) LIKE '%challan%' OR LOWER(t.type_name) = 'dc')");
} else {
sql.append(" AND (LOWER(p.type) = ? OR LOWER(t.type_name) = ?)");
params.add(category);
params.add(category);
}
}
if (fromDate != null && !fromDate.trim().isEmpty()) {
sql.append(" AND p.received_date >= ?");
params.add(parseDate(fromDate));
}
if (toDate != null && !toDate.trim().isEmpty()) {
sql.append(" AND p.received_date <= ?");
params.add(parseDate(toDate));
}
if (status != null && !status.trim().isEmpty()) {
if (status.trim().matches("^[0-9]+$")) {
sql.append(
" AND (p.status = ? OR (NOT p.status REGEXP '^[0-9]+$' AND p.status = (SELECT status_name FROM payment_status_list WHERE id = ? LIMIT 1)))");
params.add(status.trim());
params.add(status.trim());
} else {
sql.append(" AND (LOWER(p.status) = ? OR (p.status REGEXP '^[0-9]+$' AND LOWER(s.status_name) = ?))");
params.add(status.trim().toLowerCase());
params.add(status.trim().toLowerCase());
}
}
sql.append(" ORDER BY p.order_by ASC, p.received_date DESC, p.id DESC");
try {
return jdbcTemplate.queryForList(sql.toString(), params.toArray());
} catch (Exception e) {
System.err.println("Error searching payment tracking details: " + e.getMessage());
return new ArrayList<>();
}
}
public Map<String, Object> getDetailById(int id) {
String sql = "SELECT * FROM payment_tracking_details WHERE id = ? AND is_active = 1 AND is_delete = 0";
try {
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, id);
if (list != null && !list.isEmpty()) {
return list.get(0);
}
} catch (Exception e) {
System.err.println("Error fetching payment tracking detail ID " + id + ": " + e.getMessage());
}
return null;
}
public boolean saveOrUpdateDetail(Map<String, Object> payload, String updatedByUsername) {
String userId = appUserService.getUserIdByName(updatedByUsername);
if (userId == null) {
userId = updatedByUsername;
}
Object idObj = payload.get("id");
java.sql.Date receivedDate = parseDate(payload.get("received_date"));
String vendorName = (String) payload.get("vendor_name");
if (vendorName != null && !vendorName.trim().isEmpty() && !vendorName.trim().matches("^[0-9]+$")) {
String trimmedVendorName = vendorName.trim();
String checkSql = "SELECT id FROM payment_vendors_list WHERE TRIM(LOWER(vendor_name)) = ? AND is_active = 1 AND is_delete = 0 LIMIT 1";
List<Integer> existingIds = jdbcTemplate.query(checkSql, (rs, rowNum) -> rs.getInt("id"),
trimmedVendorName.toLowerCase());
if (existingIds != null && !existingIds.isEmpty()) {
vendorName = String.valueOf(existingIds.get(0));
} else {
try {
org.springframework.jdbc.support.GeneratedKeyHolder keyHolder = new org.springframework.jdbc.support.GeneratedKeyHolder();
final String finalVendorName = trimmedVendorName;
jdbcTemplate.update(connection -> {
java.sql.PreparedStatement ps = connection.prepareStatement(
"INSERT INTO payment_vendors_list (vendor_name, is_active, is_delete, order_by, cdate) VALUES (?, 1, 0, '0', NOW())",
java.sql.Statement.RETURN_GENERATED_KEYS);
ps.setString(1, finalVendorName);
return ps;
}, keyHolder);
Number key = keyHolder.getKey();
if (key != null) {
vendorName = String.valueOf(key.intValue());
}
} catch (Exception e) {
System.err.println("Error inserting custom vendor '" + trimmedVendorName + "': " + e.getMessage());
}
}
}
String subject = (String) payload.get("subject");
String amount = (String) payload.get("amount");
String invoiceNo = (String) payload.get("invoice_no");
String receiptNo = payload.get("receiptno") != null ? String.valueOf(payload.get("receiptno")) : null;
java.sql.Date invoiceDate = parseDate(payload.get("invoice_date"));
String type = (String) payload.get("type");
String physicalFileNo = (String) payload.get("physical_file_no");
String remarks = (String) payload.get("remarks");
String tat = (String) payload.get("tat");
String status = (String) payload.get("status");
String followup = (String) payload.get("followup");
String myfollowup = (String) payload.get("myfollowup");
String orderBy = (String) payload.get("order_by");
String filePath = (String) payload.get("file_path");
String paymentReview = (String) payload.get("payment_review");
if (idObj != null && !String.valueOf(idObj).trim().isEmpty()) {
// Update
int id = Integer.parseInt(String.valueOf(idObj).trim());
// Insert old record into history before update
try {
Map<String, Object> old = getDetailById(id);
if (old != null) {
String insertHistorySql = "INSERT INTO payment_tracking_details_history ("
+ "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
+ "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
+ "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(insertHistorySql,
old.get("id"),
old.get("received_date"),
old.get("vendor_name"),
old.get("subject"),
old.get("amount"),
old.get("invoice_no"),
old.get("receiptno"),
old.get("invoice_date"),
old.get("type"),
old.get("physical_file_no"),
old.get("remarks"),
old.get("tat"),
old.get("status"),
old.get("followup"),
old.get("myfollowup"),
old.get("is_active"),
old.get("is_delete"),
old.get("order_by"),
old.get("file_path"),
old.get("payment_review"),
old.get("cdate"),
new java.sql.Timestamp(System.currentTimeMillis()),
userId);
}
} catch (Exception e) {
System.err.println("Error saving history for payment tracking detail ID " + id + ": " + e.getMessage());
}
String sql = "UPDATE payment_tracking_details SET "
+ "received_date = ?, vendor_name = ?, subject = ?, amount = ?, invoice_no = ?, "
+ "receiptno = ?, invoice_date = ?, type = ?, physical_file_no = ?, remarks = ?, "
+ "tat = ?, status = ?, followup = ?, myfollowup = ?, order_by = ?, file_path = ?, "
+ "payment_review = ?, updated_by = ?, updated_date = ? "
+ "WHERE id = ? AND is_active = 1 AND is_delete = 0";
try {
int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo,
receiptNo, invoiceDate, type, physicalFileNo, remarks,
tat, status, followup, myfollowup, orderBy, filePath,
paymentReview, userId, new java.sql.Timestamp(System.currentTimeMillis()), id);
return rows > 0;
} catch (Exception e) {
System.err.println("Error updating payment tracking detail ID " + id + ": " + e.getMessage());
return false;
}
} else {
// Insert
String sql = "INSERT INTO payment_tracking_details ("
+ "received_date, vendor_name, subject, amount, invoice_no, receiptno, "
+ "invoice_date, type, physical_file_no, remarks, tat, status, "
+ "followup, myfollowup, is_active, is_delete, order_by, file_path, "
+ "payment_review, updated_by, updated_date, cdate"
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?, ?, ?, ?, ?, ?)";
try {
java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis());
int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo,
receiptNo, invoiceDate, type, physicalFileNo, remarks,
tat, status, followup, myfollowup, orderBy, filePath,
paymentReview, userId, now, now);
return rows > 0;
} catch (Exception e) {
System.err.println("Error saving payment tracking detail: " + e.getMessage());
return false;
}
}
}
public boolean deleteDetail(int id, String remarks, String updatedBy) {
String sql = "UPDATE payment_tracking_details SET is_active = 0, is_delete = 1, remarks = ?, updated_by = ?, updated_date = ? WHERE id = ?";
try {
// Retrieve old record first to populate history
Map<String, Object> old = null;
try {
old = jdbcTemplate.queryForMap("SELECT * FROM payment_tracking_details WHERE id = ?", id);
} catch (Exception e) {
System.err.println("Could not find old record for history before delete: " + e.getMessage());
}
int rows = jdbcTemplate.update(sql, remarks, updatedBy, new java.sql.Timestamp(System.currentTimeMillis()),
id);
if (rows > 0 && old != null) {
try {
String histSql = "INSERT INTO payment_tracking_details_history ("
+ "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
+ "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
+ "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(histSql,
id,
old.get("received_date"),
old.get("vendor_name"),
old.get("subject"),
old.get("amount"),
old.get("invoice_no"),
old.get("receiptno"),
old.get("invoice_date"),
old.get("type"),
old.get("physical_file_no"),
remarks,
old.get("tat"),
old.get("status"),
old.get("followup"),
old.get("myfollowup"),
0, // is_active = 0
1, // is_delete = 1
old.get("order_by"),
old.get("file_path"),
old.get("payment_review"),
old.get("cdate"),
new java.sql.Timestamp(System.currentTimeMillis()),
updatedBy);
} catch (Exception he) {
System.err.println("Error saving history during delete: " + he.getMessage());
}
}
return rows > 0;
} catch (Exception e) {
System.err.println("Error soft-deleting payment tracking detail ID " + id + ": " + e.getMessage());
return false;
}
}
private java.sql.Date parseDate(Object obj) {
if (obj == null || String.valueOf(obj).trim().isEmpty()) {
return null;
}
String str = String.valueOf(obj).trim();
try {
// Support both yyyy-MM-dd and dd/MM/yyyy
if (str.contains("/")) {
String[] parts = str.split("/");
if (parts.length == 3) {
// Convert dd/MM/yyyy to yyyy-MM-dd
str = parts[2] + "-" + parts[1] + "-" + parts[0];
}
}
return java.sql.Date.valueOf(str);
} catch (Exception e) {
System.err.println("Error parsing date '" + obj + "': " + e.getMessage());
return null;
}
}
public List<Map<String, Object>> getActiveTypes() {
String sql = "SELECT id, type_name FROM payment_type_list "
+ "WHERE is_active = 1 AND is_delete = 0 "
+ "ORDER BY order_by ASC, type_name ASC";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception e) {
System.err.println("Error fetching active types: " + e.getMessage());
return new ArrayList<>();
}
}
public List<Map<String, Object>> getActiveVendors() {
String sql = "SELECT id, vendor_name FROM payment_vendors_list "
+ "WHERE is_active = 1 AND is_delete = 0 "
+ "ORDER BY order_by ASC, vendor_name ASC";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception e) {
System.err.println("Error fetching active vendors: " + e.getMessage());
return new ArrayList<>();
}
}
public List<Map<String, Object>> getStatusList() {
String sql = "SELECT id, status_name FROM payment_status_list "
+ "WHERE is_active = 1 AND is_delete = 0 "
+ "ORDER BY id ASC, status_name ASC";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception e) {
System.err.println("Error fetching active vendors: " + e.getMessage());
return new ArrayList<>();
}
}
public List<Map<String, Object>> getHistory(int detailId) {
String sql = "SELECT h.*, "
+ "t.type_name as resolved_type, "
+ "v.vendor_name as resolved_vendor, "
+ "s.status_name as resolved_status, "
+ "u.usr_name as updated_by_name "
+ "FROM payment_tracking_details_history h "
+ "LEFT JOIN payment_type_list t ON TRIM(h.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(h.type) AS UNSIGNED) "
+ "LEFT JOIN payment_vendors_list v ON TRIM(h.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(h.vendor_name) AS UNSIGNED) "
+ "LEFT JOIN payment_status_list s ON TRIM(h.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(h.status) AS UNSIGNED) "
+ "LEFT JOIN app_user u ON (h.updated_by = CAST(u.usr_id AS CHAR) OR h.updated_by = u.usr_name) "
+ "WHERE h.detail_id = ? "
+ "ORDER BY h.updated_at DESC";
try {
return jdbcTemplate.queryForList(sql, detailId);
} catch (Exception e) {
System.err.println(
"Error fetching payment tracking history for detail ID " + detailId + ": " + e.getMessage());
return new ArrayList<>();
}
}
public List<Map<String, Object>> getDeletedDetails() {
String sql = "SELECT p.*, "
+ "t.type_name as resolved_type, "
+ "v.vendor_name as resolved_vendor, "
+ "s.status_name as resolved_status, "
+ "u.usr_name as updated_by_name "
+ "FROM payment_tracking_details p "
+ "LEFT JOIN payment_type_list t ON TRIM(p.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(p.type) AS UNSIGNED) "
+ "LEFT JOIN payment_vendors_list v ON TRIM(p.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(p.vendor_name) AS UNSIGNED) "
+ "LEFT JOIN payment_status_list s ON TRIM(p.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(p.status) AS UNSIGNED) "
+ "LEFT JOIN app_user u ON (p.updated_by = CAST(u.usr_id AS CHAR) OR p.updated_by = u.usr_name) "
+ "WHERE p.is_active = 0 AND p.is_delete = 1 "
+ "ORDER BY p.updated_date DESC";
try {
return jdbcTemplate.queryForList(sql);
} catch (Exception e) {
System.err.println("Error fetching deleted payment tracking details: " + e.getMessage());
return new ArrayList<>();
}
}
public boolean restoreDetail(int id, String updatedBy) {
String sql = "UPDATE payment_tracking_details SET is_active = 1, is_delete = 0, remarks = 'Record restored', updated_by = ?, updated_date = ? WHERE id = ?";
try {
// Retrieve old record first to populate history
Map<String, Object> old = null;
try {
old = jdbcTemplate.queryForMap("SELECT * FROM payment_tracking_details WHERE id = ?", id);
} catch (Exception e) {
System.err.println("Could not find old record for history before restore: " + e.getMessage());
}
int rows = jdbcTemplate.update(sql, updatedBy, new java.sql.Timestamp(System.currentTimeMillis()), id);
if (rows > 0 && old != null) {
try {
String histSql = "INSERT INTO payment_tracking_details_history ("
+ "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
+ "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
+ "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(histSql,
id,
old.get("received_date"),
old.get("vendor_name"),
old.get("subject"),
old.get("amount"),
old.get("invoice_no"),
old.get("receiptno"),
old.get("invoice_date"),
old.get("type"),
old.get("physical_file_no"),
"Record restored", // remarks
old.get("tat"),
old.get("status"),
old.get("followup"),
old.get("myfollowup"),
1, // is_active = 1
0, // is_delete = 0
old.get("order_by"),
old.get("file_path"),
old.get("payment_review"),
old.get("cdate"),
new java.sql.Timestamp(System.currentTimeMillis()),
updatedBy);
} catch (Exception he) {
System.err.println("Error saving history during restore: " + he.getMessage());
}
}
return rows > 0;
} catch (Exception e) {
System.err.println("Error restoring payment tracking detail ID " + id + ": " + e.getMessage());
return false;
}
}
}