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

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. package com.gcc_manpower.gccservicepaymenttracker.service;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Qualifier;
  4. import org.springframework.jdbc.core.JdbcTemplate;
  5. import org.springframework.stereotype.Service;
  6. import com.gcc_manpower.service.AppUserService;
  7. import javax.sql.DataSource;
  8. import jakarta.annotation.PostConstruct;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.List;
  12. import java.util.Map;
  13. @Service
  14. public class GccServicePaymentTrackerService {
  15. private JdbcTemplate jdbcTemplate;
  16. @Autowired
  17. private AppUserService appUserService;
  18. @Autowired
  19. public void setDataSource(@Qualifier("mysqlItcellManagementDataSource") DataSource dataSource) {
  20. this.jdbcTemplate = new JdbcTemplate(dataSource);
  21. }
  22. public Map<String, Integer> getCountsByCategory() {
  23. Map<String, Integer> counts = new HashMap<>();
  24. counts.put("sd", 0);
  25. counts.put("tax invoice", 0);
  26. counts.put("emd", 0);
  27. counts.put("bank guarantee", 0);
  28. counts.put("delivery chellan", 0);
  29. counts.put("asd", 0);
  30. counts.put("agreement", 0);
  31. counts.put("total", 0);
  32. counts.put("status_not_updated", 0);
  33. String sql = "SELECT "
  34. + "CASE WHEN p.type REGEXP '^[0-9]+$' THEN t.type_name ELSE p.type END as type_resolved, "
  35. + "COUNT(*) as cnt "
  36. + "FROM payment_tracking_details p "
  37. + "LEFT JOIN payment_type_list t ON p.type REGEXP '^[0-9]+$' AND t.id = p.type "
  38. + "WHERE p.is_active = 1 AND p.is_delete = 0 "
  39. + "GROUP BY type_resolved";
  40. try {
  41. // Count total active records
  42. String sqlTotal = "SELECT COUNT(*) FROM payment_tracking_details WHERE is_active = 1 AND is_delete = 0";
  43. Integer totalCount = jdbcTemplate.queryForObject(sqlTotal, Integer.class);
  44. counts.put("total", totalCount != null ? totalCount : 0);
  45. // Count records where type is missing
  46. String sqlMissingType = "SELECT COUNT(*) FROM payment_tracking_details WHERE is_active = 1 AND is_delete = 0 AND (type IS NULL OR TRIM(type) = '')";
  47. Integer missingTypeCount = jdbcTemplate.queryForObject(sqlMissingType, Integer.class);
  48. counts.put("status_not_updated", missingTypeCount != null ? missingTypeCount : 0);
  49. } catch (Exception e) {
  50. System.err.println("Error getting total or missing type counts: " + e.getMessage());
  51. }
  52. try {
  53. List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
  54. for (Map<String, Object> row : rows) {
  55. String type = String.valueOf(row.get("type_resolved")).toLowerCase().trim();
  56. Number countNum = (Number) row.get("cnt");
  57. int count = countNum != null ? countNum.intValue() : 0;
  58. // Map database values back to categories
  59. if (type.equals("asd") || type.contains("asd") || type.contains("additional security")) {
  60. counts.put("asd", counts.getOrDefault("asd", 0) + count);
  61. } else if (type.equals("agreement") || type.contains("agreement")) {
  62. counts.put("agreement", counts.getOrDefault("agreement", 0) + count);
  63. } else if (type.equals("sd") || type.contains("security")) {
  64. counts.put("sd", counts.getOrDefault("sd", 0) + count);
  65. } else if (type.contains("invoice") || type.contains("bill")) {
  66. counts.put("tax invoice", counts.getOrDefault("tax invoice", 0) + count);
  67. } else if (type.equals("emd")) {
  68. counts.put("emd", counts.getOrDefault("emd", 0) + count);
  69. } else if (type.contains("guarantee") || type.contains("bg")) {
  70. counts.put("bank guarantee", counts.getOrDefault("bank guarantee", 0) + count);
  71. } else if (type.contains("chellan") || type.contains("challan") || type.contains("dc")) {
  72. counts.put("delivery chellan", counts.getOrDefault("delivery chellan", 0) + count);
  73. }
  74. }
  75. } catch (Exception e) {
  76. System.err.println("Error getting category counts: " + e.getMessage());
  77. }
  78. return counts;
  79. }
  80. public List<Map<String, Object>> searchDetails(String type, String fromDate, String toDate, String status) {
  81. StringBuilder sql = new StringBuilder(
  82. "SELECT p.*, "
  83. + "t.type_name as resolved_type, "
  84. + "v.vendor_name as resolved_vendor, "
  85. + "s.status_name as resolved_status, "
  86. + "u.usr_name as updated_by_name "
  87. + "FROM payment_tracking_details p "
  88. + "LEFT JOIN payment_type_list t ON TRIM(p.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(p.type) AS UNSIGNED) "
  89. + "LEFT JOIN payment_vendors_list v ON TRIM(p.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(p.vendor_name) AS UNSIGNED) "
  90. + "LEFT JOIN payment_status_list s ON TRIM(p.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(p.status) AS UNSIGNED) "
  91. + "LEFT JOIN app_user u ON (p.updated_by = CAST(u.usr_id AS CHAR) OR p.updated_by = u.usr_name) "
  92. + "WHERE p.is_active = 1 AND p.is_delete = 0");
  93. List<Object> params = new ArrayList<>();
  94. if (type != null && !type.trim().isEmpty()) {
  95. String category = type.trim().toLowerCase();
  96. if (category.equals("status_not_updated")) {
  97. sql.append(" AND (p.type IS NULL OR TRIM(p.type) = '')");
  98. } else if (category.equals("asd")) {
  99. sql.append(
  100. " 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%')");
  101. } else if (category.equals("agreement")) {
  102. sql.append(" AND (LOWER(p.type) LIKE '%agreement%' OR LOWER(t.type_name) LIKE '%agreement%')");
  103. } else if (category.equals("sd")) {
  104. sql.append(
  105. " AND ((LOWER(p.type) = 'sd' OR LOWER(p.type) LIKE '%security%' OR LOWER(t.type_name) LIKE '%security%') "
  106. + "AND LOWER(p.type) NOT LIKE '%additional security%' AND LOWER(p.type) NOT LIKE '%asd%' "
  107. + "AND (t.type_name IS NULL OR (LOWER(t.type_name) NOT LIKE '%additional security%' AND LOWER(t.type_name) NOT LIKE '%asd%')))");
  108. } else if (category.equals("tax invoice")) {
  109. sql.append(
  110. " 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%')");
  111. } else if (category.equals("emd")) {
  112. sql.append(
  113. " 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%')");
  114. } else if (category.equals("bank guarantee")) {
  115. sql.append(
  116. " AND (LOWER(p.type) LIKE '%guarantee%' OR LOWER(p.type) = 'bg' OR LOWER(t.type_name) LIKE '%guarantee%' OR LOWER(t.type_name) = 'bg')");
  117. } else if (category.equals("delivery chellan")) {
  118. sql.append(
  119. " AND (LOWER(p.type) LIKE '%chellan%' OR LOWER(p.type) LIKE '%challan%' OR LOWER(p.type) = 'dc' "
  120. + "OR LOWER(t.type_name) LIKE '%chellan%' OR LOWER(t.type_name) LIKE '%challan%' OR LOWER(t.type_name) = 'dc')");
  121. } else {
  122. sql.append(" AND (LOWER(p.type) = ? OR LOWER(t.type_name) = ?)");
  123. params.add(category);
  124. params.add(category);
  125. }
  126. }
  127. if (fromDate != null && !fromDate.trim().isEmpty()) {
  128. sql.append(" AND p.received_date >= ?");
  129. params.add(parseDate(fromDate));
  130. }
  131. if (toDate != null && !toDate.trim().isEmpty()) {
  132. sql.append(" AND p.received_date <= ?");
  133. params.add(parseDate(toDate));
  134. }
  135. if (status != null && !status.trim().isEmpty()) {
  136. if (status.trim().matches("^[0-9]+$")) {
  137. sql.append(
  138. " AND (p.status = ? OR (NOT p.status REGEXP '^[0-9]+$' AND p.status = (SELECT status_name FROM payment_status_list WHERE id = ? LIMIT 1)))");
  139. params.add(status.trim());
  140. params.add(status.trim());
  141. } else {
  142. sql.append(" AND (LOWER(p.status) = ? OR (p.status REGEXP '^[0-9]+$' AND LOWER(s.status_name) = ?))");
  143. params.add(status.trim().toLowerCase());
  144. params.add(status.trim().toLowerCase());
  145. }
  146. }
  147. sql.append(" ORDER BY p.order_by ASC, p.received_date DESC, p.id DESC");
  148. try {
  149. return jdbcTemplate.queryForList(sql.toString(), params.toArray());
  150. } catch (Exception e) {
  151. System.err.println("Error searching payment tracking details: " + e.getMessage());
  152. return new ArrayList<>();
  153. }
  154. }
  155. public Map<String, Object> getDetailById(int id) {
  156. String sql = "SELECT * FROM payment_tracking_details WHERE id = ? AND is_active = 1 AND is_delete = 0";
  157. try {
  158. List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, id);
  159. if (list != null && !list.isEmpty()) {
  160. return list.get(0);
  161. }
  162. } catch (Exception e) {
  163. System.err.println("Error fetching payment tracking detail ID " + id + ": " + e.getMessage());
  164. }
  165. return null;
  166. }
  167. public boolean saveOrUpdateDetail(Map<String, Object> payload, String updatedByUsername) {
  168. String userId = appUserService.getUserIdByName(updatedByUsername);
  169. if (userId == null) {
  170. userId = updatedByUsername;
  171. }
  172. Object idObj = payload.get("id");
  173. java.sql.Date receivedDate = parseDate(payload.get("received_date"));
  174. String vendorName = (String) payload.get("vendor_name");
  175. if (vendorName != null && !vendorName.trim().isEmpty() && !vendorName.trim().matches("^[0-9]+$")) {
  176. String trimmedVendorName = vendorName.trim();
  177. String checkSql = "SELECT id FROM payment_vendors_list WHERE TRIM(LOWER(vendor_name)) = ? AND is_active = 1 AND is_delete = 0 LIMIT 1";
  178. List<Integer> existingIds = jdbcTemplate.query(checkSql, (rs, rowNum) -> rs.getInt("id"),
  179. trimmedVendorName.toLowerCase());
  180. if (existingIds != null && !existingIds.isEmpty()) {
  181. vendorName = String.valueOf(existingIds.get(0));
  182. } else {
  183. try {
  184. org.springframework.jdbc.support.GeneratedKeyHolder keyHolder = new org.springframework.jdbc.support.GeneratedKeyHolder();
  185. final String finalVendorName = trimmedVendorName;
  186. jdbcTemplate.update(connection -> {
  187. java.sql.PreparedStatement ps = connection.prepareStatement(
  188. "INSERT INTO payment_vendors_list (vendor_name, is_active, is_delete, order_by, cdate) VALUES (?, 1, 0, '0', NOW())",
  189. java.sql.Statement.RETURN_GENERATED_KEYS);
  190. ps.setString(1, finalVendorName);
  191. return ps;
  192. }, keyHolder);
  193. Number key = keyHolder.getKey();
  194. if (key != null) {
  195. vendorName = String.valueOf(key.intValue());
  196. }
  197. } catch (Exception e) {
  198. System.err.println("Error inserting custom vendor '" + trimmedVendorName + "': " + e.getMessage());
  199. }
  200. }
  201. }
  202. String subject = (String) payload.get("subject");
  203. String amount = (String) payload.get("amount");
  204. String invoiceNo = (String) payload.get("invoice_no");
  205. String receiptNo = payload.get("receiptno") != null ? String.valueOf(payload.get("receiptno")) : null;
  206. java.sql.Date invoiceDate = parseDate(payload.get("invoice_date"));
  207. String type = (String) payload.get("type");
  208. String physicalFileNo = (String) payload.get("physical_file_no");
  209. String remarks = (String) payload.get("remarks");
  210. String tat = (String) payload.get("tat");
  211. String status = (String) payload.get("status");
  212. String followup = (String) payload.get("followup");
  213. String myfollowup = (String) payload.get("myfollowup");
  214. String orderBy = (String) payload.get("order_by");
  215. String filePath = (String) payload.get("file_path");
  216. String paymentReview = (String) payload.get("payment_review");
  217. if (idObj != null && !String.valueOf(idObj).trim().isEmpty()) {
  218. // Update
  219. int id = Integer.parseInt(String.valueOf(idObj).trim());
  220. // Insert old record into history before update
  221. try {
  222. Map<String, Object> old = getDetailById(id);
  223. if (old != null) {
  224. String insertHistorySql = "INSERT INTO payment_tracking_details_history ("
  225. + "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
  226. + "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
  227. + "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
  228. + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
  229. jdbcTemplate.update(insertHistorySql,
  230. old.get("id"),
  231. old.get("received_date"),
  232. old.get("vendor_name"),
  233. old.get("subject"),
  234. old.get("amount"),
  235. old.get("invoice_no"),
  236. old.get("receiptno"),
  237. old.get("invoice_date"),
  238. old.get("type"),
  239. old.get("physical_file_no"),
  240. old.get("remarks"),
  241. old.get("tat"),
  242. old.get("status"),
  243. old.get("followup"),
  244. old.get("myfollowup"),
  245. old.get("is_active"),
  246. old.get("is_delete"),
  247. old.get("order_by"),
  248. old.get("file_path"),
  249. old.get("payment_review"),
  250. old.get("cdate"),
  251. new java.sql.Timestamp(System.currentTimeMillis()),
  252. userId);
  253. }
  254. } catch (Exception e) {
  255. System.err.println("Error saving history for payment tracking detail ID " + id + ": " + e.getMessage());
  256. }
  257. String sql = "UPDATE payment_tracking_details SET "
  258. + "received_date = ?, vendor_name = ?, subject = ?, amount = ?, invoice_no = ?, "
  259. + "receiptno = ?, invoice_date = ?, type = ?, physical_file_no = ?, remarks = ?, "
  260. + "tat = ?, status = ?, followup = ?, myfollowup = ?, order_by = ?, file_path = ?, "
  261. + "payment_review = ?, updated_by = ?, updated_date = ? "
  262. + "WHERE id = ? AND is_active = 1 AND is_delete = 0";
  263. try {
  264. int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo,
  265. receiptNo, invoiceDate, type, physicalFileNo, remarks,
  266. tat, status, followup, myfollowup, orderBy, filePath,
  267. paymentReview, userId, new java.sql.Timestamp(System.currentTimeMillis()), id);
  268. return rows > 0;
  269. } catch (Exception e) {
  270. System.err.println("Error updating payment tracking detail ID " + id + ": " + e.getMessage());
  271. return false;
  272. }
  273. } else {
  274. // Insert
  275. String sql = "INSERT INTO payment_tracking_details ("
  276. + "received_date, vendor_name, subject, amount, invoice_no, receiptno, "
  277. + "invoice_date, type, physical_file_no, remarks, tat, status, "
  278. + "followup, myfollowup, is_active, is_delete, order_by, file_path, "
  279. + "payment_review, updated_by, updated_date, cdate"
  280. + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, ?, ?, ?, ?, ?, ?)";
  281. try {
  282. java.sql.Timestamp now = new java.sql.Timestamp(System.currentTimeMillis());
  283. int rows = jdbcTemplate.update(sql, receivedDate, vendorName, subject, amount, invoiceNo,
  284. receiptNo, invoiceDate, type, physicalFileNo, remarks,
  285. tat, status, followup, myfollowup, orderBy, filePath,
  286. paymentReview, userId, now, now);
  287. return rows > 0;
  288. } catch (Exception e) {
  289. System.err.println("Error saving payment tracking detail: " + e.getMessage());
  290. return false;
  291. }
  292. }
  293. }
  294. public boolean deleteDetail(int id, String remarks, String updatedBy) {
  295. String sql = "UPDATE payment_tracking_details SET is_active = 0, is_delete = 1, remarks = ?, updated_by = ?, updated_date = ? WHERE id = ?";
  296. try {
  297. // Retrieve old record first to populate history
  298. Map<String, Object> old = null;
  299. try {
  300. old = jdbcTemplate.queryForMap("SELECT * FROM payment_tracking_details WHERE id = ?", id);
  301. } catch (Exception e) {
  302. System.err.println("Could not find old record for history before delete: " + e.getMessage());
  303. }
  304. int rows = jdbcTemplate.update(sql, remarks, updatedBy, new java.sql.Timestamp(System.currentTimeMillis()),
  305. id);
  306. if (rows > 0 && old != null) {
  307. try {
  308. String histSql = "INSERT INTO payment_tracking_details_history ("
  309. + "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
  310. + "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
  311. + "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
  312. + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
  313. jdbcTemplate.update(histSql,
  314. id,
  315. old.get("received_date"),
  316. old.get("vendor_name"),
  317. old.get("subject"),
  318. old.get("amount"),
  319. old.get("invoice_no"),
  320. old.get("receiptno"),
  321. old.get("invoice_date"),
  322. old.get("type"),
  323. old.get("physical_file_no"),
  324. remarks,
  325. old.get("tat"),
  326. old.get("status"),
  327. old.get("followup"),
  328. old.get("myfollowup"),
  329. 0, // is_active = 0
  330. 1, // is_delete = 1
  331. old.get("order_by"),
  332. old.get("file_path"),
  333. old.get("payment_review"),
  334. old.get("cdate"),
  335. new java.sql.Timestamp(System.currentTimeMillis()),
  336. updatedBy);
  337. } catch (Exception he) {
  338. System.err.println("Error saving history during delete: " + he.getMessage());
  339. }
  340. }
  341. return rows > 0;
  342. } catch (Exception e) {
  343. System.err.println("Error soft-deleting payment tracking detail ID " + id + ": " + e.getMessage());
  344. return false;
  345. }
  346. }
  347. private java.sql.Date parseDate(Object obj) {
  348. if (obj == null || String.valueOf(obj).trim().isEmpty()) {
  349. return null;
  350. }
  351. String str = String.valueOf(obj).trim();
  352. try {
  353. // Support both yyyy-MM-dd and dd/MM/yyyy
  354. if (str.contains("/")) {
  355. String[] parts = str.split("/");
  356. if (parts.length == 3) {
  357. // Convert dd/MM/yyyy to yyyy-MM-dd
  358. str = parts[2] + "-" + parts[1] + "-" + parts[0];
  359. }
  360. }
  361. return java.sql.Date.valueOf(str);
  362. } catch (Exception e) {
  363. System.err.println("Error parsing date '" + obj + "': " + e.getMessage());
  364. return null;
  365. }
  366. }
  367. public List<Map<String, Object>> getActiveTypes() {
  368. String sql = "SELECT id, type_name FROM payment_type_list "
  369. + "WHERE is_active = 1 AND is_delete = 0 "
  370. + "ORDER BY order_by ASC, type_name ASC";
  371. try {
  372. return jdbcTemplate.queryForList(sql);
  373. } catch (Exception e) {
  374. System.err.println("Error fetching active types: " + e.getMessage());
  375. return new ArrayList<>();
  376. }
  377. }
  378. public List<Map<String, Object>> getActiveVendors() {
  379. String sql = "SELECT id, vendor_name FROM payment_vendors_list "
  380. + "WHERE is_active = 1 AND is_delete = 0 "
  381. + "ORDER BY order_by ASC, vendor_name ASC";
  382. try {
  383. return jdbcTemplate.queryForList(sql);
  384. } catch (Exception e) {
  385. System.err.println("Error fetching active vendors: " + e.getMessage());
  386. return new ArrayList<>();
  387. }
  388. }
  389. public List<Map<String, Object>> getStatusList() {
  390. String sql = "SELECT id, status_name FROM payment_status_list "
  391. + "WHERE is_active = 1 AND is_delete = 0 "
  392. + "ORDER BY id ASC, status_name ASC";
  393. try {
  394. return jdbcTemplate.queryForList(sql);
  395. } catch (Exception e) {
  396. System.err.println("Error fetching active vendors: " + e.getMessage());
  397. return new ArrayList<>();
  398. }
  399. }
  400. public List<Map<String, Object>> getHistory(int detailId) {
  401. String sql = "SELECT h.*, "
  402. + "t.type_name as resolved_type, "
  403. + "v.vendor_name as resolved_vendor, "
  404. + "s.status_name as resolved_status, "
  405. + "u.usr_name as updated_by_name "
  406. + "FROM payment_tracking_details_history h "
  407. + "LEFT JOIN payment_type_list t ON TRIM(h.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(h.type) AS UNSIGNED) "
  408. + "LEFT JOIN payment_vendors_list v ON TRIM(h.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(h.vendor_name) AS UNSIGNED) "
  409. + "LEFT JOIN payment_status_list s ON TRIM(h.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(h.status) AS UNSIGNED) "
  410. + "LEFT JOIN app_user u ON (h.updated_by = CAST(u.usr_id AS CHAR) OR h.updated_by = u.usr_name) "
  411. + "WHERE h.detail_id = ? "
  412. + "ORDER BY h.updated_at DESC";
  413. try {
  414. return jdbcTemplate.queryForList(sql, detailId);
  415. } catch (Exception e) {
  416. System.err.println(
  417. "Error fetching payment tracking history for detail ID " + detailId + ": " + e.getMessage());
  418. return new ArrayList<>();
  419. }
  420. }
  421. public List<Map<String, Object>> getDeletedDetails() {
  422. String sql = "SELECT p.*, "
  423. + "t.type_name as resolved_type, "
  424. + "v.vendor_name as resolved_vendor, "
  425. + "s.status_name as resolved_status, "
  426. + "u.usr_name as updated_by_name "
  427. + "FROM payment_tracking_details p "
  428. + "LEFT JOIN payment_type_list t ON TRIM(p.type) REGEXP '^[0-9]+$' AND t.id = CAST(TRIM(p.type) AS UNSIGNED) "
  429. + "LEFT JOIN payment_vendors_list v ON TRIM(p.vendor_name) REGEXP '^[0-9]+$' AND v.id = CAST(TRIM(p.vendor_name) AS UNSIGNED) "
  430. + "LEFT JOIN payment_status_list s ON TRIM(p.status) REGEXP '^[0-9]+$' AND s.id = CAST(TRIM(p.status) AS UNSIGNED) "
  431. + "LEFT JOIN app_user u ON (p.updated_by = CAST(u.usr_id AS CHAR) OR p.updated_by = u.usr_name) "
  432. + "WHERE p.is_active = 0 AND p.is_delete = 1 "
  433. + "ORDER BY p.updated_date DESC";
  434. try {
  435. return jdbcTemplate.queryForList(sql);
  436. } catch (Exception e) {
  437. System.err.println("Error fetching deleted payment tracking details: " + e.getMessage());
  438. return new ArrayList<>();
  439. }
  440. }
  441. public boolean restoreDetail(int id, String updatedBy) {
  442. String sql = "UPDATE payment_tracking_details SET is_active = 1, is_delete = 0, remarks = 'Record restored', updated_by = ?, updated_date = ? WHERE id = ?";
  443. try {
  444. // Retrieve old record first to populate history
  445. Map<String, Object> old = null;
  446. try {
  447. old = jdbcTemplate.queryForMap("SELECT * FROM payment_tracking_details WHERE id = ?", id);
  448. } catch (Exception e) {
  449. System.err.println("Could not find old record for history before restore: " + e.getMessage());
  450. }
  451. int rows = jdbcTemplate.update(sql, updatedBy, new java.sql.Timestamp(System.currentTimeMillis()), id);
  452. if (rows > 0 && old != null) {
  453. try {
  454. String histSql = "INSERT INTO payment_tracking_details_history ("
  455. + "detail_id, received_date, vendor_name, subject, amount, invoice_no, receiptno, "
  456. + "invoice_date, type, physical_file_no, remarks, tat, status, followup, myfollowup, "
  457. + "is_active, is_delete, order_by, file_path, payment_review, cdate, updated_at, updated_by"
  458. + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
  459. jdbcTemplate.update(histSql,
  460. id,
  461. old.get("received_date"),
  462. old.get("vendor_name"),
  463. old.get("subject"),
  464. old.get("amount"),
  465. old.get("invoice_no"),
  466. old.get("receiptno"),
  467. old.get("invoice_date"),
  468. old.get("type"),
  469. old.get("physical_file_no"),
  470. "Record restored", // remarks
  471. old.get("tat"),
  472. old.get("status"),
  473. old.get("followup"),
  474. old.get("myfollowup"),
  475. 1, // is_active = 1
  476. 0, // is_delete = 0
  477. old.get("order_by"),
  478. old.get("file_path"),
  479. old.get("payment_review"),
  480. old.get("cdate"),
  481. new java.sql.Timestamp(System.currentTimeMillis()),
  482. updatedBy);
  483. } catch (Exception he) {
  484. System.err.println("Error saving history during restore: " + he.getMessage());
  485. }
  486. }
  487. return rows > 0;
  488. } catch (Exception e) {
  489. System.err.println("Error restoring payment tracking detail ID " + id + ": " + e.getMessage());
  490. return false;
  491. }
  492. }
  493. }