// language: java package com.billpaymentservice.bbps.serviceImpl; import java.util.List; import java.util.Map; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClient; import com.billpaymentservice.bbps.dto.GeneralResp; import com.billpaymentservice.bbps.dto.ResponseModel; import com.billpaymentservice.bbps.dto.request.AllMasterOptionsRequest; import com.billpaymentservice.bbps.dto.request.ComplainStatusRequest; import com.billpaymentservice.bbps.dto.request.ComplaintRequestDTO; import com.billpaymentservice.bbps.dto.request.GetTicketLatestStausRequest; import com.billpaymentservice.bbps.dto.request.TxnStatusRequest; import com.billpaymentservice.bbps.dto.request.ViewAllComplaintsTicketsRequest; import com.billpaymentservice.bbps.dto.response.ComplaintHistoryStatusResponse; import com.billpaymentservice.bbps.dto.response.ComplaintResponse; import com.billpaymentservice.bbps.dto.response.TicketCheckStatusResponse; import com.billpaymentservice.bbps.dto.response.TxnStatusResponse; import com.billpaymentservice.bbps.dto.response.ViewAllComplaintsTicketsResponse; import com.billpaymentservice.bbps.dto.response.ViewComplainByIdResponse; import com.billpaymentservice.bbps.dto.sentRequest.FetchComplaintForwardRequest; import com.billpaymentservice.bbps.dto.sentRequest.FetchTicketLatestStatusRequest; import com.billpaymentservice.bbps.entites.BharatConnectMaster; import com.billpaymentservice.bbps.entites.ComplaintResponseEntity; import com.billpaymentservice.bbps.entites.ComplaintStatusOptionsMaster; import com.billpaymentservice.bbps.entites.InboundTraceLog; import com.billpaymentservice.bbps.entites.OutboundTraceLog; import com.billpaymentservice.bbps.entites.TransactionMaster; import com.billpaymentservice.bbps.exception.CustomException; import com.billpaymentservice.bbps.repository.BharatConnectMasterRepository; import com.billpaymentservice.bbps.repository.ComplainRepository; import com.billpaymentservice.bbps.repository.ComplaintOptionsStatusMasterRepository; import com.billpaymentservice.bbps.repository.ComplaintResponseRepository; import com.billpaymentservice.bbps.repository.TransactionMasterRepository; import com.billpaymentservice.bbps.service.ComplainService; import com.billpaymentservice.bbps.util.BBPSConstant; import com.billpaymentservice.bbps.util.BillerMapperHelper; import com.billpaymentservice.bbps.util.Helper; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @Service public class ComplainServiceImpl implements ComplainService { @Value("${agent.data.url}") private String agentDtaUrl; @Value("${complaint.data.url}") private String complainDataUrl; private final RestClient restClient; private final HttpService httpService; private final Helper helper; private final BharatConnectMasterRepository beneficiaryDetailsRepository; private final BillerMapperHelper mapperHelper; private final ComplainRepository complainRepository; private final ComplaintOptionsStatusMasterRepository complaintStatusMasterRepository; private final TransactionMasterRepository transactionMasterRepository; private final ComplaintResponseRepository complaintResponseRepository; // moved to class-level private final ObjectMapper objectMapper; private static final Logger LOGGER = LoggerFactory.getLogger(ComplainServiceImpl.class); public ComplainServiceImpl(RestClient restClient, HttpService httpService, Helper helper, BharatConnectMasterRepository beneficiaryDetailsRepository, BillerMapperHelper mapperHelper, ComplainRepository complainRepository, ComplaintOptionsStatusMasterRepository complaintStatusMasterRepository, TransactionMasterRepository transactionMasterRepository, ComplaintResponseRepository complaintResponseRepository) { this.restClient = restClient; this.httpService = httpService; this.helper = helper; this.beneficiaryDetailsRepository = beneficiaryDetailsRepository; this.mapperHelper = mapperHelper; this.complainRepository = complainRepository; this.complaintStatusMasterRepository = complaintStatusMasterRepository; this.transactionMasterRepository = transactionMasterRepository; // initialize shared ObjectMapper once this.objectMapper = new ObjectMapper(); this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); this.complaintResponseRepository = complaintResponseRepository; } @Override public ResponseModel addComplain(ComplaintRequestDTO complainRequestDTO) { String apiName = BBPSConstant.API_ADD_COMPLAIN; String requestId = complainRequestDTO.getReqId(); String mid = complainRequestDTO.getMid(); String userId = complainRequestDTO.getClientUserId(); String requestTxnId=complainRequestDTO.getTxnId(); LOGGER.info("[{}] START | reqId={} | mid={} | clientUserId={}", apiName, requestId, mid, userId); String txnId = helper.generateTxnId(15); String fullUrl = complainDataUrl + BBPSConstant.ADD_COMPLAIN_ENDPOINT; LOGGER.info("[{}] Full URL={}", apiName, fullUrl); // Fetch tenant & agent from DB FetchComplaintForwardRequest forwardReq = mapperHelper.fetchComplaintForwardRequestMap(complainRequestDTO); String forwardJson = helper.convertObjectToJson(forwardReq); String requestJson = helper.convertObjectToJson(complainRequestDTO); InboundTraceLog inboundLog = helper.createInboundLog(requestId, txnId, apiName, complainRequestDTO.getMid(), BBPSConstant.HTTP_POST, requestJson); helper.validateMerchant(mid); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, fullUrl, BBPSConstant.HTTP_POST, null); try { Optional dataById = transactionMasterRepository.findById(complainRequestDTO.getTxnId()); if (dataById == null || dataById.isEmpty()) { LOGGER.warn("Txn Data Not Found This Txn Id is null"); throw new CustomException(BBPSConstant.USER_Txn_IS_NOT_FOUND, "FAILED", BBPSConstant.BADREQUEST, null); } TransactionMaster transData = dataById.get(); // Inject tenantId + agentId into request JSON String transactionCreatedDateString = transData.getCreationDate(); LOGGER.info("Date is coming -:" + transactionCreatedDateString); LOGGER.info("Return Date Time After 24 Hours" + BillerMapperHelper.isComplaintAllowed(transactionCreatedDateString)); if (!BillerMapperHelper.isComplaintAllowed(transactionCreatedDateString)) { LOGGER.warn("Complaint cannot be raised after 24 hours for txnId: {}", complainRequestDTO.getTxnId()); String responseData = "Complaint cannot be raised after 24 hours for txnId: " + complainRequestDTO.getTxnId(); helper.updateOutboundLogResponse(outboundLog, responseData); return ResponseModel.builder().message("Complaint cannot be raised after 24 hours of transaction.") .status("Failure").statusCode(400) // Bad request .data(null).build(); } ObjectNode root = (ObjectNode) objectMapper.readTree(forwardJson); root.put("tenantId", headersData.getTenantId()); root.put("agentId", headersData.getAgentId()); root.put("billerId", transData.getBillerId()); root.put("billerName", transData.getBillerName()); String finalJson = root.toString(); LOGGER.info("[{}] Final Request Sent to API | reqId={} | payload={}", apiName, requestId, finalJson); // IMPORTANT: Send finalJson, not requestJson Map responseMap = httpService.postRequest(fullUrl, finalJson, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.debug("[{}] Response Received | reqId={} | data={}", apiName, requestId, responseData); helper.updateOutboundLogResponse(outboundLog, responseData); // Handle HttpService error wrapper if (responseData.startsWith(BBPSConstant.HTTP_SERVICE_ERROR_PREFIX)) { int start = responseData.indexOf("{"); int end = responseData.lastIndexOf("}"); if (start != -1 && end != -1) { responseData = responseData.substring(start, end + 1); } LOGGER.warn("[{}] Extracted JSON from error wrapper | data={}", apiName, responseData); } // Parse JSON into Map Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); int statusCode = Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))); // Throw exception for non-200 if (statusCode != BBPSConstant.HTTP_OK_INT) { LOGGER.warn("[{}] Failure Response | reqId={} | statusCode={}", apiName, requestId, statusCode); throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), statusCode, String.valueOf(dataMap.get(BBPSConstant.RESPONSE_REMARKS_KEY))); } // Convert to response wrapper ComplaintResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintResponse.class); String saveComplaintResponseEntity = mapperHelper.saveComplaintResponseEntity(responseWrapper, requestId, txnId, userId,requestTxnId); LOGGER.info("Save Complaint Response Count" + saveComplaintResponseEntity); ResponseModel responseModel = new ResponseModel(responseWrapper.getMessage(), responseWrapper.getStatus(), Integer.parseInt(responseWrapper.getStatusCode()), responseWrapper); helper.updateInboundLogSuccess(inboundLog, responseData, responseWrapper.getStatus()); LOGGER.info("[{}] SUCCESS | reqId={} | status={}", apiName, requestId, responseWrapper.getStatus()); return responseModel; } catch (JsonProcessingException e) { LOGGER.error("JSON Parsing Error: {}", e.getMessage()); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel getComplaintStatus(GetTicketLatestStausRequest request) { String apiName = BBPSConstant.API_COMPLAINT_STATUS; String reqId = request.getReqId(); String complaintId = request.getTicketId(); String mid = request.getMid(); String ticketId = request.getTicketId(); String userId = request.getClientUserId(); LOGGER.info("[{}] START | reqId={} | mid={} | ticketId={} | userId={}", apiName, reqId, mid, ticketId, userId); String fullUrl = agentDtaUrl + BBPSConstant.COMPALINT_STATUS; String txnId = helper.generateTxnId(15); FetchTicketLatestStatusRequest forwardReq = mapperHelper.fetchTicketLatestStatusRequestMap(request); String forwardJson = helper.convertObjectToJson(forwardReq); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_POST, requestJson); helper.validateMerchant(request.getMid()); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); // Convert request to JSON ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_POST, complaintId); try { ObjectNode root = (ObjectNode) objectMapper.readTree(forwardJson); root.put("tenantId", headersData.getTenantId()); // root.put("agentId", headersData.getAgentId()); String finalJson = root.toString(); LOGGER.info("[{}] Final API Payload | reqId={} | payload={}", apiName, reqId, finalJson); Map responseMap = httpService.postRequest(fullUrl, finalJson, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.debug("[{}] Raw Response | reqId={} | data={}", apiName, reqId, responseData); helper.updateOutboundLogResponse(outboundLog, responseData); // Handle HttpService error wrapper if (responseData.startsWith(BBPSConstant.HTTP_SERVICE_ERROR_PREFIX)) { int start = responseData.indexOf("{"); int end = responseData.lastIndexOf("}"); if (start != -1 && end != -1) { responseData = responseData.substring(start, end + 1); } LOGGER.info("Extracted pure JSON from error: {}", responseData); } Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); int statusCode = Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))); if (statusCode != BBPSConstant.HTTP_OK_INT) { throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), statusCode, String.valueOf(dataMap.get(BBPSConstant.RESPONSE_REMARKS_KEY))); } TicketCheckStatusResponse responseWrapper = objectMapper.convertValue(dataMap, TicketCheckStatusResponse.class); String saveComplaintStatus = mapperHelper.saveComplaintStatus(responseWrapper, reqId, txnId, userId); LOGGER.info("[{}] Save Status | ticketId={} | status={}", apiName, ticketId, saveComplaintStatus); helper.updateInboundLogSuccess(inboundLog, responseData, responseWrapper.getStatus()); return new ResponseModel(responseWrapper.getMessage(), responseWrapper.getStatus(), Integer.parseInt(responseWrapper.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { LOGGER.error("Error parsing JSON in complaint status API: {}", e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel viewComplaintHistory(ComplainStatusRequest request) { String apiName = BBPSConstant.API_VIEW_COMPLAINT_HISTORY; String reqId = request.getReqId(); String ticketId = request.getTicketId(); String mid = request.getMid(); String userId = request.getClientUserId(); LOGGER.info("[{}] START | reqId={} | mid={} | ticketId={} | userId={}", apiName, reqId, mid, ticketId, userId); String fullUrl = agentDtaUrl + BBPSConstant.COMPLAINT_HISTORY + request.getTicketId(); String txnId = helper.generateTxnId(15); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_GET, requestJson); helper.validateMerchant(request.getMid()); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_GET, ticketId); LOGGER.debug("Outbound log created successfully for Complaint : {}", fullUrl); try { LOGGER.info("[{}] Calling external API | URL={} | reqId={}", apiName, fullUrl, reqId); Map responseMap = httpService.getRequest(fullUrl, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.debug("[{}] Raw Response | reqId={} | data={}", apiName, reqId, responseData); helper.updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) { LOGGER.warn("[{}] Invalid response structure | reqId={} | data={}", apiName, reqId, responseData); helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE); LOGGER.warn("Invalid response structure for txnId: {}", txnId); throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))), String.valueOf("")); } ComplaintHistoryStatusResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintHistoryStatusResponse.class); GeneralResp generalResp = responseWrapper.getGeneralResp(); String status = generalResp.getStatus(); LOGGER.info("Current Complaint ReOpen Status: {}", status); helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); String saveComplaintHistory = mapperHelper.saveComplaintHistory(responseWrapper, reqId, txnId, userId); LOGGER.info("[{}] Complaint history saved | ticketId={} | entryId={}", apiName, ticketId, saveComplaintHistory); return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { LOGGER.error("Error parsing Complaint Id JSON: {}", e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel viewComplaintById(ComplainStatusRequest request) { String apiName = BBPSConstant.API_VIEW_COMPLAINT_BY_ID; String reqId = request.getReqId(); String ticketId = request.getTicketId(); String mid = request.getMid(); String userId = request.getClientUserId(); LOGGER.info("[{}] START | reqId={} | mid={} | ticketId={} | userId={}", apiName, reqId, mid, ticketId, userId); String txnId = helper.generateTxnId(15); String fullUrl = agentDtaUrl + BBPSConstant.VIEW_COMPLAINT_BY_ID + request.getTicketId(); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_GET, requestJson); helper.validateMerchant(request.getMid()); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_GET, ticketId); LOGGER.debug("Outbound log created successfully for Complaint : {}", fullUrl); try { LOGGER.info("[{}] Calling external API | reqId={} | URL={}", apiName, reqId, fullUrl); Map responseMap = httpService.getRequest(fullUrl, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.info("Complaint History Complaint FetchById Response: {}", responseData); helper.updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) { helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE); LOGGER.warn("Invalid response structure for txnId: {}", txnId); throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))), String.valueOf("")); } ViewComplainByIdResponse responseWrapper = objectMapper.convertValue(dataMap, ViewComplainByIdResponse.class); GeneralResp generalResp = responseWrapper.getGeneralResp(); String status = generalResp.getStatus(); LOGGER.info("Current Complaint ReOpen Status: {}", status); helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); String saveComplaint = mapperHelper.saveComplainStatusDetail(responseWrapper, reqId, txnId, userId); LOGGER.info("[{}] Complaint details saved | ticketId={} | id={}", apiName, ticketId, saveComplaint); return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { LOGGER.error("Error parsing Complaint Id JSON: {}", e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel getAllActiveStatuses(AllMasterOptionsRequest request) { try { LOGGER.info("Fetch All Master Options - MID: {}", request.getMid()); String apiName = BBPSConstant.API_GET_ALL_MASTER_OPTIONS; String txnId = helper.generateTxnId(15); String reqId = request.getReqId(); String fullUrl = BBPSConstant.DB_OPTIONS; String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_GET, requestJson); // Validate merchant helper.validateMerchant(request.getMid()); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_GET, null); LOGGER.debug("Outbound log created successfully for Complaint : {}", fullUrl); // Fetch data from DB List allActiveStatuses = complaintStatusMasterRepository .findAllActiveStatuses(); LOGGER.info("Total Master Records Found: {}", allActiveStatuses != null ? allActiveStatuses.size() : 0); // Check empty or null if (allActiveStatuses == null || allActiveStatuses.isEmpty()) { helper.updateInboundLogFailure(inboundLog, String.valueOf(allActiveStatuses), BBPSConstant.NULL_DATA_FROM_DB); return new ResponseModel(BBPSConstant.NO_MASTER_FIELDS_FOUND, BBPSConstant.FAILED_STATUS, BBPSConstant.HTTP_NOT_FOUND, null, 0); } helper.updateInboundLogSuccess(inboundLog, String.valueOf(allActiveStatuses), String.valueOf(BBPSConstant.HTTP_OK_INT)); // SUCCESS RESPONSE return new ResponseModel(BBPSConstant.ALL_MASTER_FIELDS_FETCH, BBPSConstant.SUCCESS_RESPONSE, BBPSConstant.HTTP_OK_INT, allActiveStatuses, allActiveStatuses.size()); } catch (Exception e) { LOGGER.error("Error while fetching master options", e); return new ResponseModel(BBPSConstant.SOMETHING_WENT_WRONG, BBPSConstant.FAILED_STATUS, BBPSConstant.HTTP_INTERNAL_SERVER_ERROR, null, 0); } } public ResponseModel checkTxnStatus(TxnStatusRequest request) { String apiName = BBPSConstant.API_CHECK_TXN_STATUS; String reqId = request.getReqId(); String ID = request.getId(); String mid = request.getMid(); String transactionId = request.getId(); LOGGER.info("[{}] START | reqId={} | mid={} | txnId={}", apiName, reqId, mid, transactionId); String txnId = helper.generateTxnId(15); String fullUrl = agentDtaUrl + BBPSConstant.CHECK_TRANSACTION_URL + request.getId(); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_GET, requestJson); helper.validateMerchant(request.getMid()); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_GET, ID); LOGGER.debug("Outbound log created successfully for Complaint : {}", fullUrl); try { LOGGER.info("[{}] Calling external BBPS API | URL={}", apiName, fullUrl); Map responseMap = httpService.getRequest(fullUrl, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.info("checkTxnStatus: {}", responseData); helper.updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) { helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE); LOGGER.warn("Invalid response structure for txnId: {}", txnId); throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))), String.valueOf("")); } TxnStatusResponse responseWrapper = objectMapper.convertValue(dataMap, TxnStatusResponse.class); GeneralResp generalResp = responseWrapper.getGeneralResp(); String status = generalResp.getStatus(); LOGGER.info("Current Complaint ReOpen Status: {}", status); helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); LOGGER.info("[{}] End Txn Status: {}", apiName, generalResp.getStatus()); return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { LOGGER.error("Error parsing Complaint Id JSON: {}", e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel ViewAllComplaints(ViewAllComplaintsTicketsRequest request) { String apiName = BBPSConstant.API_VIEW_ALL_COMPLAINTS_BY_STATUS; String reqId = request.getReqId(); String mid = request.getMid(); String statusType = request.getStatusType(); String userId = request.getClientUserId(); LOGGER.info("[{}] START | reqId={} | mid={} | statusType={} | userId={}", apiName, reqId, mid, statusType, userId); String txnId = helper.generateTxnId(15); String fullUrl = complainDataUrl + BBPSConstant.VIEW_ALL_COMPLAINTS_BASE + "?pageNo=" + request.getPageNo() + "&pageSize=" + request.getPageSize() + "&statusType=" + request.getStatusType() + "&ticketType=" + request.getTicketType(); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, request.getMid(), BBPSConstant.HTTP_GET, requestJson); helper.validateMerchant(request.getMid()); BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, BBPSConstant.HTTP_GET, request.getStatusType()); LOGGER.debug("Outbound log created successfully for Complaint : {}", fullUrl); try { LOGGER.info("[{}] Calling external API | URL={}", apiName, fullUrl); Map responseMap = httpService.getRequest(fullUrl, headers); String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY); LOGGER.info("Response: {}", responseData); helper.updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) { helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE); LOGGER.warn("Invalid response structure for txnId: {}", txnId); throw new CustomException(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_MESSAGE_KEY)), String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)), Integer.parseInt(String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUSCODE_KEY))), String.valueOf("")); } ViewAllComplaintsTicketsResponse responseWrapper = objectMapper.convertValue(dataMap, ViewAllComplaintsTicketsResponse.class); GeneralResp generalResp = responseWrapper.getGeneralResp(); String status = generalResp.getStatus(); LOGGER.info("Current Complaint ReOpen Status: {}", status); String saveComplaint = mapperHelper.saveAllComplaints(responseWrapper, reqId, txnId, userId); LOGGER.info("[{}] Complaint records saved into DB | count={}", apiName, saveComplaint); return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { LOGGER.error("Error parsing Complaint Id JSON: {}", e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel viewAllComplaintsByUserId(AllMasterOptionsRequest request) { String apiName = BBPSConstant.API_VIEW_ALL_COMPLAINTS_BY_USER_ID; String reqId = request.getReqId(); String mid = request.getMid(); String userId = request.getClientUserId(); LOGGER.info("[{}] START | reqId={} | mid={} | userId={}", apiName, reqId, mid, userId); String txnId = helper.generateTxnId(15); String requestJson = helper.convertObjectToJson(request); InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, mid, BBPSConstant.HTTP_GET, requestJson); helper.validateMerchant(mid); // Validate merchant before continuing BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID); HttpHeaders headers = helper.buildHeaders(headersData); OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, apiName, BBPSConstant.HTTP_GET, requestJson); LOGGER.debug("Outbound log created successfully for Complaint: {}", apiName); try { // Validate userId if (userId.isEmpty() || userId == null) { helper.updateOutboundLogResponse(outboundLog, BBPSConstant.USER_ID_IS_EMPTY); return new ResponseModel(BBPSConstant.USER_ID_IS_EMPTY, "User ID cannot be null or empty", // Provide a BBPSConstant.BADREQUEST, null, 0 // Return 0 as the size when no complaints ); } // Log the call to external API LOGGER.info("[{}] Calling external API | URL={}", apiName, apiName); // List complaintUserData = // complaintResponseRepository.findByUserIdCustom(userId); Pageable pageable = PageRequest.of(request.getPageNo(), request.getPageSize()); Page complaintUserData = complaintResponseRepository.findByUserIdCustom(userId, pageable); // Check if complaints were found if (complaintUserData == null || complaintUserData.isEmpty()) { LOGGER.info("[{}] No complaints found for userId={}", apiName, userId); throw new CustomException("No complaints found for this User ID", "FAILED", BBPSConstant.BADREQUEST, null); } // Log the number of complaints fetched LOGGER.info("[{}] Complaints found for userId={} | count={}", apiName, userId, complaintUserData.getContent().size()); // Update outbound log with the count String count = String.valueOf(complaintUserData.getContent().size()); helper.updateOutboundLogResponse(outboundLog, count); // Return successful response with complaints data return new ResponseModel(BBPSConstant.ALL_COMPLAINT_FIELDS_FETCH, BBPSConstant.SUCCESS_RESPONSE, BBPSConstant.HTTP_OK_INT, complaintUserData.getContent(), // Only the list of complaints (data) complaintUserData.getContent().size()); } catch (CustomException e) { // Rethrow custom exception for handling at the controller level throw e; } catch (Exception e) { // Log generic exception and create inbound log failure LOGGER.error("[{}] Error: {}", apiName, e.getMessage(), e); helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR); throw new CustomException("An error occurred while processing the request"); } } }