package in.gov.chennaicorporation.gccoffice.callcenter.controller; import org.apache.poi.ss.usermodel.*; import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import in.gov.chennaicorporation.gccoffice.callcenter.service.AddcategoryServices; import in.gov.chennaicorporation.gccoffice.callcenter.service.AgentAssignService; import in.gov.chennaicorporation.gccoffice.callcenter.service.CampaignService; @RestController("callcenterapicontroller") @RequestMapping("gcc/api/campaign") public class CampaignAPIController { @Autowired private CampaignService campaignService; @Autowired private AddcategoryServices addCategoryServices; // Injecting the service @Autowired private AgentAssignService agentsAssignService; @Autowired private JdbcTemplate jdbcTemplate; @Autowired private Environment environment; @GetMapping("/getCampaignDetails") public ResponseEntity> getCampaignDetails() { Map response = new HashMap<>(); List> data = campaignService.getCampaignDetails(); response.put("data", data); return ResponseEntity.ok(response); } // Endpoint to get campaign details by ID @GetMapping("/getCampaignDetailsById") public @ResponseBody List> getCampaignDetailsById(@RequestParam("campaign_id") Long campaignId) { return campaignService.getCampaignDetailsById(campaignId); } @PostMapping("/updateCampaign") public ResponseEntity updateCampaign( @RequestBody Map requestData) { Long campaign_id = ((Number) requestData.get("campaign_id")).longValue(); String end_date = (String) requestData.get("end_date"); List> questionsData = (List>) requestData.get("questionsData"); if (campaign_id == null) { return ResponseEntity.badRequest().body("Campaign ID is required."); } try { // Update campaign details campaignService.updateCampaign(campaign_id, end_date); // Save questions and answers for (Map questionMap : questionsData) { String category = (String) questionMap.get("category"); String question = (String) questionMap.get("question"); String answerType = (String) questionMap.get("answerType"); List answers = (List) questionMap.get("answers"); if (category != null && question != null && answerType != null) { campaignService.saveQuestionsAndAnswers( category, String.valueOf(campaign_id), // Corrected data type question, answerType, answers ); } } return ResponseEntity.ok("Campaign updated successfully."); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Error updating campaign: " + e.getMessage()); } } //save question and ansewers for campaign @PostMapping("/saveQuestionsAndAnswers") public ResponseEntity saveQuestions(@RequestBody List> requestData) { String response = campaignService.saveQuestionsAnswers(requestData); return ResponseEntity.ok(response); } //save file and get path private String saveFile(MultipartFile file) throws IOException { String uploadDirectory = environment.getProperty("file.upload.directory"); String folderName = environment.getProperty("campaign.foldername"); String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + "_" + file.getOriginalFilename(); String folderPath = uploadDirectory + "/" + folderName + "/excel/"; Path dirPath = Paths.get(folderPath); if (!Files.exists(dirPath)) { Files.createDirectories(dirPath); } Path filePath = dirPath.resolve(fileName); Files.write(filePath, file.getBytes()); return filePath.toAbsolutePath().toString(); } //read uploaded excel data and make condition for each category uploading same excel columns are other some other? private List> readExcelData(InputStream inputStream, List categoryColumns) throws IOException { List> dataList = new ArrayList<>(); try (Workbook workbook = new XSSFWorkbook(inputStream)) { Sheet sheet = workbook.getSheetAt(0); FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); // Read header row from Excel Row headerRow = sheet.getRow(0); List excelHeaders = new ArrayList<>(); for (Cell cell : headerRow) { excelHeaders.add(cell.getStringCellValue().trim()); } // Compare Excel headers with category columns if (!excelHeaders.containsAll(categoryColumns)) { // throw new IllegalArgumentException("Excel data does not match the category columns."); } // Proceed with reading data only if headers match for (Row row : sheet) { if (row.getRowNum() == 0) continue; // Skip header row Map dataMap = new HashMap<>(); for (Cell cell : row) { String cellValue = ""; switch (formulaEvaluator.evaluateInCell(cell).getCellType()) { case STRING: cellValue = cell.getStringCellValue(); break; case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { cellValue = new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue()); } else { // Check if value is an integer (whole number) if (cell.getNumericCellValue() % 1 == 0) { cellValue = String.valueOf((long) cell.getNumericCellValue()); // Format as integer } else { cellValue = String.valueOf(cell.getNumericCellValue()); // Keep decimal values as they are } } break; case BOOLEAN: cellValue = String.valueOf(cell.getBooleanCellValue()); break; default: cellValue = "Unknown"; break; } // Map cell data to correct column name dataMap.put(excelHeaders.get(cell.getColumnIndex()), cellValue); } if (!dataMap.isEmpty()) { dataList.add(dataMap); } } } return dataList; } @GetMapping("/getExcelData") public ResponseEntity>> getExcelData(@RequestParam("filePath") String filePath) { try { // Read data from the uploaded Excel file List> excelData = readExcelData(new FileInputStream(filePath), null); // Return data as JSON return ResponseEntity.ok(excelData); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } @GetMapping("/getlastCampaignid") public List> getLastRow() { return campaignService.getLastRow(); } @GetMapping("/startcampaign") public List> getDataforAgents(@RequestParam int campaign_id,@RequestParam int calls_per_agent) { return campaignService.getDataforAgents(campaign_id, calls_per_agent); } @GetMapping("/viewcampaignstatus") public List> viewcampaignstatus(@RequestParam int campaign_id) { return campaignService.viewcampaignstatus(campaign_id); } @GetMapping("/viewcompletedby") public List> viewcompletedby(@RequestParam int campaign_id,@RequestParam int agent_id) { return campaignService.viewcompletedby(campaign_id,agent_id); } @PostMapping(value = "/savecampaign", consumes = {"multipart/form-data"}) public ResponseEntity> saveCampaign( @RequestParam String campaignId, @RequestParam String categoryId, @RequestParam String eventStartDate, @RequestParam String eventEndDate, @RequestParam int noOfCalls, @RequestParam String description, @RequestParam(required = false) String questionsData, // JSON as String @RequestParam(required = false) String selectedAgents // JSON string ) { // Convert JSON strings to List objects List> questionsDataList = new ArrayList<>(); List selectedAgentsList = new ArrayList<>(); try { if (questionsData != null) { questionsDataList = new ObjectMapper().readValue(questionsData, new TypeReference>>() {}); } if (selectedAgents != null) { selectedAgentsList = new ObjectMapper().readValue(selectedAgents, new TypeReference>() {}); } } catch (JsonProcessingException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(Map.of("status", "error", "message", "Invalid JSON format in request data")); } // Campaign Details Mapping Map campaignDetails = new HashMap<>(); campaignDetails.put("campaign_id", campaignId); campaignDetails.put("category_id", categoryId); campaignDetails.put("start_date", eventStartDate); campaignDetails.put("end_date", eventEndDate); campaignDetails.put("calls_per_agent", noOfCalls); campaignDetails.put("description", description); try { campaignService.saveCampaignDetails(campaignDetails); // Step 3: Assign Agents for the Campaign if (!selectedAgentsList.isEmpty()) { int parsedCampaignId = Integer.parseInt(campaignId); int parsedCategoryId = Integer.parseInt(categoryId); System.out.println("selectedAgentsList====== " + selectedAgentsList); int calls_assign = noOfCalls * selectedAgentsList.size(); System.out.println("calls_assign== " + calls_assign); List DataIds=agentsAssignService.getDataIdForInitialAssign(parsedCategoryId, parsedCampaignId); for (String agentId : selectedAgentsList) { int selectedAgentId = Integer.parseInt(agentId); agentsAssignService.addAgentsForCampaign(selectedAgentId, parsedCategoryId, parsedCampaignId); } //System.out.println("dataids=== " + DataIds); if (!DataIds.isEmpty()) { int dataIndex = 0; // Initialize data index pointer for (String agentId : selectedAgentsList) { int selectedAgentId = Integer.parseInt(agentId); // Iterate for noOfCalls times and assign data IDs to the current agent for (int i = 0; i < noOfCalls && dataIndex < DataIds.size(); i++, dataIndex++) { int DataId = DataIds.get(dataIndex); agentsAssignService.updateAgentForCampaign( selectedAgentId, parsedCategoryId, parsedCampaignId, DataId ); } } // Update campaign status to 'ONGOING' after successful assignment campaignService.updateCampaignStatus(parsedCampaignId, parsedCategoryId); } else { return ResponseEntity.status(HttpStatus.NOT_FOUND) .body(Map.of("status", "error", "message", "No data available for initial assignment.")); } } // Step 4: Save Questions and Answers if (!questionsDataList.isEmpty()) { for (Map questionMap : questionsDataList) { String question = (String) questionMap.get("question"); String answerType = (String) questionMap.get("answerType"); List answers = (List) questionMap.get("answers"); if (question != null && answerType != null) { campaignService.saveQuestionsAndAnswers( categoryId, campaignId, question, answerType, answers ); } else { System.out.println("Skipping invalid question data: " + questionMap); } } } } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(Map.of("status", "error", "message", "Failed to save campaign details: " + e.getMessage())); } return ResponseEntity.ok(Map.of("status", "success", "message", "Campaign details saved successfully")); } //save excel data separate method @PostMapping(value = "/saveexcelcampaign" ,consumes = {"multipart/form-data"}) public Map saveExcelCampaign( @RequestParam String name, @RequestParam String category, @RequestPart MultipartFile file) { //System.out.println("Received campaign data:"); //System.out.println("Name: " + name); //System.out.println("Category: " + category); //System.out.println("File Name: " + file.getOriginalFilename()); Map campaignDetails = new HashMap<>(); campaignDetails.put("campaign_name", name); campaignDetails.put("category_id", category); try { // Get category-specific columns List> categoryColumns = addCategoryServices.getCategoryColumns(Integer.parseInt(category)); //System.out.println("categorycolmns: " + categoryColumns); List expectedHeaders = categoryColumns.stream() .map(column -> column.get("column_name").toString()) .collect(Collectors.toList()); // System.out.println("expectedheaders: " + expectedHeaders); // Fetch field_ columns from upload_data table List fieldColumns = campaignService.getUploadDataFieldColumns(); //System.out.println("fieldColumns: " + fieldColumns); // Read uploaded Excel data and extract headers List> excelData = readExcelData(file.getInputStream(), expectedHeaders); // System.out.println("excedata: " + excelData ); List uploadedHeaders = new ArrayList<>(excelData.get(0).keySet()); // Extract headers from first row //System.out.println("uploadeddata : " + uploadedHeaders); // Check column count mismatch with field_ columns if (uploadedHeaders.size() > fieldColumns.size()) { Map response = new HashMap<>(); response.put("status", "column_mismatch"); // Changed status to differentiate response.put("message", "Extend the columns in Database, Inform Admin."); return response; } // Validate headers if (!new HashSet<>(expectedHeaders).equals(new HashSet<>(uploadedHeaders))) { Map response = new HashMap<>(); response.put("status", "header_mismatch"); // Changed status to differentiate response.put("message", "Excel data does not match the category columns."); return response; } String fileUrl = saveFile(file); campaignDetails.put("excel_url", fileUrl); //System.out.println("Campaign Details: " + campaignDetails); //System.out.println("Excel Data: " + excelData); campaignService.saveCampaignDetailsExcel(campaignDetails); int lastId = campaignService.getLastInsertedCampaignId(); String excelUrl = campaignService.getExcelUrlByCampaignId(lastId); //List> excelDatas = readExcelDataupdated(new FileInputStream(excelUrl)); List> excelDatas = readExcelData(new FileInputStream(excelUrl), uploadedHeaders); //System.out.println("excelDatas:" + excelDatas); for (Map row : excelDatas) { campaignService.saveUploadData(category, lastId, row,expectedHeaders); //System.out.println("exceldatas:" + excelDatas); } Map response = new HashMap<>(); response.put("status", "success"); response.put("message", "Campaign and Excel saved successfully"); return response; } catch (IOException e) { e.printStackTrace(); Map response = new HashMap<>(); response.put("status", "error"); response.put("message", "Failed to save campaign details: "+ e.getMessage()); return response; } } @GetMapping("/availableAgents") public ResponseEntity>> getAvailableAgents() { // Query 1: Fetch OUTBOUND agents String outboundAgentsQuery = "SELECT agent_name, agent_id, calling_type " + "FROM gcc_1913_qaqc.agents_list " + "WHERE calling_type='OUTBOUND'"; List> outboundAgents = jdbcTemplate.queryForList(outboundAgentsQuery); //System.out.println("outboundagents" + outboundAgents); // Query 2: Fetch agents from ongoing campaigns String ongoingCampaignAgentsQuery = "SELECT ca.agent_id " + "FROM gcc_1913_campaign.campaign_request cr " + "JOIN gcc_1913_campaign.agent_assign ca " + "ON ca.campaign_id = cr.campaign_id " + "WHERE cr.campaign_status = 'ONGOING'"; List> ongoingAgents = jdbcTemplate.queryForList(ongoingCampaignAgentsQuery); //System.out.println("ongoingAgents" + ongoingAgents); // Extract agent IDs from both lists Set ongoingAgentIds = ongoingAgents.stream() .map(agent -> (Integer) agent.get("agent_id")) .collect(Collectors.toSet()); // Filter OUTBOUND agents who are NOT in ongoing agents List> availableAgents = outboundAgents.stream() .filter(agent -> !ongoingAgentIds.contains(agent.get("agent_id"))) .collect(Collectors.toList()); return ResponseEntity.ok(availableAgents); } private Object getCellValue(Cell cell) { switch (cell.getCellType()) { case STRING: return cell.getStringCellValue().trim(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue(); // Return Date for date-formatted cells } double numericValue = cell.getNumericCellValue(); // ✅ Convert numeric values that are likely mobile numbers to string if (String.valueOf((long) numericValue).length() >= 10) { // Assuming mobile numbers are at least 10 digits return String.valueOf((long) numericValue); } // ✅ Convert to int if no decimal part, else keep as double return (numericValue % 1 == 0) ? (int) numericValue : numericValue; case BOOLEAN: return cell.getBooleanCellValue(); case FORMULA: return cell.getCellFormula(); // Return formula as string case BLANK: return ""; default: return ""; } } //question and answers report page api @GetMapping("/question-answers") public ResponseEntity getQuestionAnswers(@RequestParam int campaignId) { List> response = campaignService.getQuestionAnswers(campaignId); return ResponseEntity.ok(response); } //dizo campaignlist apicontroller // Query Parameter Approach @GetMapping("/statistics") public ResponseEntity> getCampaignStatisticsByQuery(@RequestParam int campaignId) { Map statistics = campaignService.getCampaignStatistics(campaignId); return ResponseEntity.ok(statistics); } @GetMapping("/assignagentid") public ResponseEntity>> getAllAgents() { List> assignAgentId = campaignService.getAllAgents(); return ResponseEntity.ok(assignAgentId); } @PostMapping("/close") public ResponseEntity closeCampaign(@RequestParam("campaignId") int campaignId) { if (campaignId <= 0) { return ResponseEntity.badRequest().body("Invalid Campaign ID"); } System.out.println("Received request to close campaign ID: " + campaignId); // Debugging log int rowsUpdated = campaignService.closeCampaign(campaignId); if (rowsUpdated > 0) { return ResponseEntity.ok("Campaign closed successfully"); } else { return ResponseEntity.status(400).body("Failed to close campaign. Campaign ID " + campaignId + " may not exist."); } } @PostMapping("/auto-close") public ResponseEntity autoCloseExpiredCampaigns() { int rowsUpdated = campaignService.autoCloseExpiredCampaigns(); if (rowsUpdated > 0) { return ResponseEntity.ok(rowsUpdated + " expired campaigns closed successfully."); } else { return ResponseEntity.ok("No expired campaigns found."); } } }