From aefe8fb38b8ad066ae74c6dc17c73ea26550d290 Mon Sep 17 00:00:00 2001 From: Piyush Date: Fri, 9 May 2025 18:27:17 +0530 Subject: [PATCH 1/9] updated code --- .../java/net/gepafin/tendermanagement/dao/EmailDao.java | 8 ++++---- .../tendermanagement/repositories/EmailLogRepository.java | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java index 66b20b77..df5566e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java @@ -72,18 +72,18 @@ public class EmailDao { public EmailSendResponse buildEmailSendResponseFromRequest(HttpServletRequest request) { Long userActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID); - List emailLogs = emailLogRepository.findByUserActionId(userActionId); + List emailLogs = emailLogRepository.findByUserActionIdAndEmailServiceType(userActionId,EmailServiceTypeEnum.PEC_SERVICE.getValue()); boolean allSuccess = true; String emailScenario = null; for (EmailLogEntity log : emailLogs) { + if (emailScenario == null) { emailScenario = log.getEmailType(); } - boolean isSuccess = EmailServiceTypeEnum.PEC_SERVICE.getValue().equals(log.getEmailServiceType()) && - StatusTypeEnum.SUCCESS.getValue().equals(log.getSendStatus()); - if (!isSuccess) { + boolean isSuccess = StatusTypeEnum.SUCCESS.getValue().equals(log.getSendStatus()); + if (Boolean.FALSE.equals(isSuccess)) { allSuccess = false; break; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/EmailLogRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/EmailLogRepository.java index f12d0e3b..669c4b69 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/EmailLogRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/EmailLogRepository.java @@ -14,5 +14,8 @@ public interface EmailLogRepository extends JpaRepository { List findByUserActionIdAndEmailServiceTypeAndSendStatus( Long userActionId, String emailServiceType, String sendStatus); Optional findTopByUserIdAndEmailTypeAndIsDeletedFalseOrderByCreatedDateDesc(Long userId, String emailType); + List findByUserActionIdAndEmailServiceType( + Long userActionId, String emailServiceType); + } From 43da0472813ff38873e6b1fd0e6782ca7b9acc07 Mon Sep 17 00:00:00 2001 From: Piyush Date: Fri, 9 May 2025 19:12:32 +0530 Subject: [PATCH 2/9] Updated code --- .../constants/GepafinConstant.java | 2 ++ .../gepafin/tendermanagement/dao/EmailDao.java | 17 ++++++++++++++++- src/main/resources/message_en.properties | 4 +++- src/main/resources/message_it.properties | 4 +++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index d0fb0136..7e165dc3 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -541,6 +541,8 @@ public class GepafinConstant { public static final String RESEND_EMAIL_SENT_FAILED_MSG = "resend.email.sent.failed.msg"; public static final String REMINDER_EMAIL_FAILED_MSG = "reminder.email.sent.failed.msg"; + public static final String NO_EMAIL_LOG_FOUND = "no.email.log.msg"; + public static final String USER_ACTION_ID_NOT_FOUND = "user.action.id.not.found"; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java index df5566e0..6e46d475 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java @@ -3,9 +3,11 @@ package net.gepafin.tendermanagement.dao; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; +import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.EmailLogEntity; +import net.gepafin.tendermanagement.entities.UserActionEntity; import net.gepafin.tendermanagement.enums.EmailScenarioTypeEnum; import net.gepafin.tendermanagement.enums.EmailServiceTypeEnum; import net.gepafin.tendermanagement.enums.RecipientTypeEnum; @@ -14,8 +16,12 @@ import net.gepafin.tendermanagement.model.request.EmailLogRequest; import net.gepafin.tendermanagement.model.response.EmailResendResponseBean; import net.gepafin.tendermanagement.model.response.EmailSendResponse; import net.gepafin.tendermanagement.repositories.EmailLogRepository; +import net.gepafin.tendermanagement.repositories.UserActionsRepository; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -38,10 +44,19 @@ public class EmailDao { @Autowired private EmailLogDao emailLogDao; + @Autowired + private UserActionsRepository userActionsRepository; + public EmailResendResponseBean resendEmail(HttpServletRequest request , Long userActionId){ + UserActionEntity userActionEntity = userActionsRepository.findUserActionByIdAndIsDeletedFalse(userActionId); + if(userActionEntity == null){ + throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_ACTION_ID_NOT_FOUND)); + } List emailLogs = emailLogRepository.findByUserActionIdAndEmailServiceTypeAndSendStatus(userActionId,EmailServiceTypeEnum.PEC_SERVICE.getValue(),StatusTypeEnum.FAILED.getValue()); + if (emailLogs.isEmpty()) { - log.info("No emails found for given userActionId."); + log.info("No emails found for given userActionId: {}",userActionId); + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.NO_EMAIL_LOG_FOUND)); } EmailResendResponseBean emailResendResponseBean = new EmailResendResponseBean(); for (EmailLogEntity log : emailLogs){ diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index b09c8d62..ddd71c3e 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -403,4 +403,6 @@ invalid.user=Invalid user. reminder.email.sent.failed.msg = Failed to send reminder email resend.email.sent.success.msg = Email resend successfully -resend.email.sent.failed.msg = Failed to resend the email. \ No newline at end of file +resend.email.sent.failed.msg = Failed to resend the email. +no.email.log.msg = No failed emails found for given userActionId. +user.action.id.not.found = User Action id not found. \ No newline at end of file diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index faafb940..09ec0e49 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -394,4 +394,6 @@ invalid.user=Utente non valido. reminder.email.sent.failed.msg = Impossibile inviare l'e-mail di promemoria resend.email.sent.success.msg = Email reinviata con successo -resend.email.sent.failed.msg = Impossibile inviare nuovamente l'e-mail. \ No newline at end of file +resend.email.sent.failed.msg = Impossibile inviare nuovamente l'e-mail. +no.email.log.msg = Nessuna email trovata per userActionId specificato. +user.action.id.not.found = ID azione utente non trovato. \ No newline at end of file From d1dcc5cf7bf9d65aec96cc34840cbb7e194c6aea Mon Sep 17 00:00:00 2001 From: Piyush Date: Mon, 12 May 2025 15:55:22 +0530 Subject: [PATCH 3/9] Added emailSendResponse in get Amendment Api --- .../dao/ApplicationAmendmentRequestDao.java | 15 +++++--- ...plicationAmendmentRequestResponseBean.java | 36 +++++++++++++++++++ .../ApplicationAmendmentRequestService.java | 2 +- ...pplicationAmendmentRequestServiceImpl.java | 2 +- .../api/ApplicationAmendmentRequestApi.java | 2 +- ...ApplicationAmendmentRequestController.java | 4 +-- 6 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponseBean.java diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java index a0d0ff7f..59004619 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java @@ -654,12 +654,19 @@ public class ApplicationAmendmentRequestDao { log.info(" Application amendment deleted with ID: {}", id); } - public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(Long id) { + public ApplicationAmendmentRequestResponseBean getApplicationAmendmentRequestById(Long id) { log.info("Fetching application amendment with ID: {}", id); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id); - ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity,true); - log.info("Application Amendment fetched successfully by ID: {}", response); - return response; + ApplicationAmendmentRequestResponse sourceResponse = convertEntityToResponse(applicationAmendmentRequestEntity,true); + ApplicationAmendmentRequestResponseBean targetResponse = Utils.convertSourceObjectToDestinationObject( + sourceResponse, ApplicationAmendmentRequestResponseBean.class + ); + + if (targetResponse != null) { + targetResponse.setEmailSendResponse(applicationAmendmentRequestEntity.getEmailSendResponse()); + } + log.info("Application Amendment fetched successfully by ID: {}", targetResponse); + return targetResponse; } public List getAllApplicationAmendmentRequest(HttpServletRequest request, Long userId) { diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponseBean.java new file mode 100644 index 00000000..9bbddfeb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponseBean.java @@ -0,0 +1,36 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class ApplicationAmendmentRequestResponseBean { + private Long id; + private String callEmail; + private String note; + private Long responseDays; + private LocalDateTime startDate; + private Boolean isSendNotification; + private Boolean isSendEmail; + private Long protocolNumber; + private String callName; + private String beneficiaryName; + private String companyName; + private List formFields; + private List applicationFormFields; + private List amendmentDocuments; + private String amendmentNotes; + private Boolean valid; + private Long applicationId; + private Long applicationEvaluationId; + private LocalDateTime evaluationEndDate; + private LocalDateTime expirationDate; + private List commentsList; + private String internalNote; + private ApplicationAmendmentRequestEnum status; + private String emailTemplate; + private List emailSendResponse; +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java index b19f77c4..9b4b63ed 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationAmendmentRequestService.java @@ -16,7 +16,7 @@ public interface ApplicationAmendmentRequestService { public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(HttpServletRequest request,Long applicationEvaluationId); public ApplicationAmendmentRequestResponse createApplicationAmendmentRequest(HttpServletRequest request, Long applicationEvaluationId , ApplicationAmendmentRequest applicationAmendmentRequest); void deleteApplicationAmendmentRequest(HttpServletRequest request, Long id); - ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(HttpServletRequest request,Long id); + ApplicationAmendmentRequestResponseBean getApplicationAmendmentRequestById(HttpServletRequest request,Long id); List getAllApplicationAmendmentRequest(HttpServletRequest request, Long userId); ApplicationAmendmentRequestResponse updateApplicationAmendment(HttpServletRequest request, Long id, ApplicationAmendmentRequestBean applicationAmendmentRequestBean); ApplicationAmendmentRequestEntity validateApplicationAmendmentRequest(Long applicationAmendmentId); diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java index a680ec1b..20a1e455 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java @@ -75,7 +75,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override - public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { + public ApplicationAmendmentRequestResponseBean getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java index 5d81ce7e..25b53b3c 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationAmendmentRequestApi.java @@ -72,7 +72,7 @@ public interface ApplicationAmendmentRequestApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "", produces = "application/json") - ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,@Parameter(description = "The application amendment id", required = true) @RequestParam(value = "id", required = true) Long id); + ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,@Parameter(description = "The application amendment id", required = true) @RequestParam(value = "id", required = true) Long id); @Operation(summary = "Api to get all applications amendment request by preInstructor user Id (deprecated)", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java index c92a060b..739c2802 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationAmendmentRequestController.java @@ -69,14 +69,14 @@ public class ApplicationAmendmentRequestController implements ApplicationAmendme } @Override - public ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { + public ResponseEntity> getApplicationAmendmentRequestById(HttpServletRequest request,Long id) { log.info("Get Application Amendment Request By Id"); /** This code is responsible for creating user action logs for the "get application amendment by id" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW) .actionContext(UserActionContextEnum.GET_AMENDMENT).build()); - ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = applicationAmendmentRequestService.getApplicationAmendmentRequestById(request,id); + ApplicationAmendmentRequestResponseBean applicationAmendmentRequestResponse = applicationAmendmentRequestService.getApplicationAmendmentRequestById(request,id); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applicationAmendmentRequestResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_APPLICATION_AMENDMENT_SUCCESS_MSG))); } From 5e3b0025d9c9b1c93d9d103683d268276c13d64a Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 13 May 2025 18:02:43 +0530 Subject: [PATCH 4/9] Done ticket GEPAFINBE-216 Handled error for appointment creation failed, now returning the error description getting from third party API. --- .../constants/GepafinConstant.java | 4 ++- .../tendermanagement/dao/AppointmentDao.java | 29 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 7e165dc3..5ecfa9b5 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -544,7 +544,9 @@ public class GepafinConstant { public static final String NO_EMAIL_LOG_FOUND = "no.email.log.msg"; public static final String USER_ACTION_ID_NOT_FOUND = "user.action.id.not.found"; - + public static final String CAUSE_STRING = "cause" ; + public static final String ERROR_DESCRIPTION_STRING = "errorDescription" ; + public static final String ERROR_STRING = "errors"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java index cb83406e..43c8cfdc 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -758,12 +758,31 @@ public class AppointmentDao { if (appointmentResponse.getBody() != null) { log.info("Appointment API Response : {}", appointmentResponse.getBody()); - Map responseBody = (Map) appointmentResponse.getBody(); - if (responseBody.containsKey(GepafinConstant.DATA_STRING)) { - Map data = (Map) responseBody.get(GepafinConstant.DATA_STRING); - if (data != null && data.containsKey(GepafinConstant.ID_STRING)) { - return data.get(GepafinConstant.ID_STRING).toString(); + try { + Map responseBody = (Map) appointmentResponse.getBody(); + // 1. Try to get appointment ID from data.id + if (responseBody.containsKey(GepafinConstant.DATA_STRING)) { + Map data = (Map) responseBody.get(GepafinConstant.DATA_STRING); + if (data != null && data.containsKey(GepafinConstant.ID_STRING)) { + return data.get(GepafinConstant.ID_STRING).toString(); + } } + // 2. If ID not present, check errors[0].cause.errorDescription + if (responseBody.containsKey(GepafinConstant.ERROR_STRING)) { + List> errors = (List>) responseBody.get(GepafinConstant.ERROR_STRING); + if (errors != null && !errors.isEmpty()) { + Map firstError = errors.get(0); + if (firstError.containsKey(GepafinConstant.CAUSE_STRING)) { + Map cause = (Map) firstError.get(GepafinConstant.CAUSE_STRING); + if (cause != null && cause.containsKey(GepafinConstant.ERROR_DESCRIPTION_STRING)) { + String errorDescription = cause.get(GepafinConstant.ERROR_DESCRIPTION_STRING).toString(); + log.warn("Appointment creation failed: {}", errorDescription); + } + } + } + } + } catch (Exception e) { + log.error("Error while extracting appointment ID or parsing error message", e); } } return null; From 5a055923300906f33410adf8dcdf14e0ecdc05d5 Mon Sep 17 00:00:00 2001 From: Piyush Date: Tue, 13 May 2025 18:18:46 +0530 Subject: [PATCH 5/9] Fixed Issue with Resend Email API --- .../tendermanagement/dao/EmailDao.java | 97 ++++++++++++++++++- .../ApplicationEvaluationRepository.java | 5 + .../repositories/EmailLogRepository.java | 7 ++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java index 6e46d475..9b99facb 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailDao.java @@ -5,9 +5,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.extern.log4j.Log4j2; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; -import net.gepafin.tendermanagement.entities.CallEntity; -import net.gepafin.tendermanagement.entities.EmailLogEntity; -import net.gepafin.tendermanagement.entities.UserActionEntity; +import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.EmailScenarioTypeEnum; import net.gepafin.tendermanagement.enums.EmailServiceTypeEnum; import net.gepafin.tendermanagement.enums.RecipientTypeEnum; @@ -15,8 +13,7 @@ import net.gepafin.tendermanagement.enums.StatusTypeEnum; import net.gepafin.tendermanagement.model.request.EmailLogRequest; import net.gepafin.tendermanagement.model.response.EmailResendResponseBean; import net.gepafin.tendermanagement.model.response.EmailSendResponse; -import net.gepafin.tendermanagement.repositories.EmailLogRepository; -import net.gepafin.tendermanagement.repositories.UserActionsRepository; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; @@ -47,6 +44,15 @@ public class EmailDao { @Autowired private UserActionsRepository userActionsRepository; + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + public EmailResendResponseBean resendEmail(HttpServletRequest request , Long userActionId){ UserActionEntity userActionEntity = userActionsRepository.findUserActionByIdAndIsDeletedFalse(userActionId); if(userActionEntity == null){ @@ -82,9 +88,90 @@ public class EmailDao { } EmailSendResponse emailSendResponse = buildEmailSendResponseFromRequest(request); emailResendResponseBean.setEmailSendResponse(emailSendResponse); + + if (Boolean.TRUE.equals(emailSendResponse.getIsEmailSend())){ + updateEmailSendStatusIfSuccessful(emailSendResponse); + } return emailResendResponseBean; } + private void updateEmailSendStatusIfSuccessful(EmailSendResponse emailSendResponse){ + Long actionId = emailSendResponse.getUserActionId(); + + EmailLogEntity emailLog = emailLogRepository.findTopByUserActionIdAndEmailServiceTypeAndSendStatusOrderByIdDesc( + actionId, + EmailServiceTypeEnum.PEC_SERVICE.getValue(), + StatusTypeEnum.SUCCESS.getValue() + ); + if (emailLog != null) { + switch (emailSendResponse.getEmailScenario()) { + case APPLICATION_AMENDMENT_REQUESTED: + case APPLICATION_AMENDMENT_REMINDER: + updateApplicationAmendmentStatus(emailLog, emailSendResponse.getEmailScenario().getValue()); + break; + + case USER_CREATION: + case PASSWORD_RESET_REQUEST: + updateUserEmailStatus(emailLog, emailSendResponse.getEmailScenario().getValue()); + break; + + case APPLICATION_ADMISSIBLE: + case APPLICATION_REJECTED: + updateApplicationEvaluationStatus(emailLog, emailSendResponse.getEmailScenario().getValue()); + break; + + default: + log.warn("Unhandled email scenario: {}", emailSendResponse.getEmailScenario()); + } + } + } + + private void updateApplicationAmendmentStatus(EmailLogEntity log, String scenario) { + if (log.getAmendmentId() != null) { + applicationAmendmentRequestRepository.findById(log.getAmendmentId()).ifPresent(amendment -> { + if (updateEmailSendResponse(amendment.getEmailSendResponse(), scenario)) { + applicationAmendmentRequestRepository.save(amendment); + } + }); + } + } + + private void updateApplicationEvaluationStatus(EmailLogEntity log, String scenario) { + if (log.getApplicationId() != null) { + ApplicationEvaluationEntity evaluation = applicationEvaluationRepository.findByApplicationId(log.getApplicationId()); + if (evaluation != null && updateEmailSendResponse(evaluation.getEmailSendResponse(), scenario)) { + applicationEvaluationRepository.save(evaluation); + } + } + } + + private void updateUserEmailStatus(EmailLogEntity log, String scenario) { + if (log.getUserId() != null) { + userRepository.findById(log.getUserId()).ifPresent(user -> { + if (updateEmailSendResponse(user.getEmailSendResponse(), scenario)) { + userRepository.save(user); + } + }); + } + } + + + + + private boolean updateEmailSendResponse(List responses, String scenario) { + if (responses == null || responses.isEmpty()) return false; + + for (EmailSendResponse response : responses) { + if (scenario.equals(response.getEmailScenario().getValue())) { + response.setIsEmailSend(true); + return true; + } + } + return false; + } + + + public EmailSendResponse buildEmailSendResponseFromRequest(HttpServletRequest request) { Long userActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID); List emailLogs = emailLogRepository.findByUserActionIdAndEmailServiceType(userActionId,EmailServiceTypeEnum.PEC_SERVICE.getValue()); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java index 9019aad4..a231d3c6 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java @@ -76,5 +76,10 @@ public interface ApplicationEvaluationRepository extends JpaRepository { List findByUserActionIdAndEmailServiceType( Long userActionId, String emailServiceType); + EmailLogEntity findTopByUserActionIdAndEmailServiceTypeAndSendStatusOrderByIdDesc( + Long userActionId, + String emailServiceType, + String sendStatus + ); + + } From 43ff10e7b685c53d3b00b05f0849e1a2c540e3fd Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 13 May 2025 19:39:11 +0530 Subject: [PATCH 6/9] Updated code for maximum retries on login to odessa. --- .../tendermanagement/dao/AppointmentDao.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java index 43c8cfdc..23f9784d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -176,6 +176,11 @@ public class AppointmentDao { } private HubEntity loginToOdessa(HubEntity hub, ApplicationEntity application) { + + int maxRetries = 3; + int attempt = 0; + boolean success = false; + while (attempt < maxRetries && !success) { try { //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); @@ -195,15 +200,16 @@ public class AppointmentDao { hub.setAreaCode(parsedResponse.getAreaCode()); hubRepository.save(hub); log.info("Saved new authToken and areaCode for Hub."); + success = true; return hub; } else { throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again."); } } throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); - } - catch (FeignException.Forbidden forbiddenException) { - logForbiddenError(); + } catch (FeignException.Forbidden forbiddenException) { + attempt++; + log.error("Failed to login to odessa due to some error"); // Extract raw response body String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response @@ -239,15 +245,17 @@ public class AppointmentDao { } catch (IOException e) { log.error("Error parsing JSON response: {}", e.getMessage()); } - - // Regenerate the token and retry - loginToOdessa(hub, application); - } - catch (Exception e) { + if (attempt >= maxRetries) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); + } else { + loginToOdessa(hub, application); + } + } catch (Exception e) { log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); throw new RuntimeException("Authentication failed on Odessa. try again", e); } - return null; + } + return null; } private void startAsyncNdgProcessing(Long applicationId) { From b137c9b3ec0946166955517dc482238ee674a375 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 13 May 2025 19:48:48 +0530 Subject: [PATCH 7/9] Updated code for retry authentication for login to odessa. --- .../tendermanagement/dao/AppointmentDao.java | 132 ++++++++++-------- 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java index 23f9784d..079addee 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -430,77 +430,85 @@ public class AppointmentDao { } private HubEntity authenticateAndSaveToken(HubEntity hub) { - - try { - //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call - String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); - log.info("Got the auth for login to odessa {}", authJwtToken); - hub.setAuthToken(authJwtToken); - hubRepository.save(hub); - // Prepare the request body (adjust if necessary for login API) - Map body = Collections.emptyMap(); - // Perform login API call - ResponseEntity responseLogin = appointmentApiService.loginWithOdessa(authJwtToken, source, context, user, password, body); - - // Handle successful login - if (responseLogin.getStatusCode() == HttpStatus.OK) { - log.info("Login successful to odessa. Parsing response."); - String loginResponseJson = Utils.convertObjectToJson(responseLogin.getBody()); - AppointmentLoginResponse parsedResponse = parseLoginResponse(loginResponseJson); - - // Validate and save token - if (parsedResponse.getTokenId() != null) { - hub.setAppointmentAuthTokenId(parsedResponse.getTokenId()); - hub.setAreaCode(parsedResponse.getAreaCode()); - hubRepository.save(hub); - - log.info("Saved new authToken and areaCode for Hub."); - return hub; - } else { - throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again."); - } - } - // Handle non-OK response - throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); - } catch (FeignException.Forbidden forbiddenException) { - logForbiddenError(); - - // Extract raw response body - String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response - - // Parse JSON to check for "PasswordExpired" + int maxRetries = 3; + int attempt = 0; + boolean success = false; + while (attempt < maxRetries && !success) { try { - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode rootNode = objectMapper.readTree(responseBody); - JsonNode errorsNode = rootNode.path("errors"); + //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call + String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); + log.info("Got the auth for login to odessa {}", authJwtToken); + hub.setAuthToken(authJwtToken); + hubRepository.save(hub); + // Prepare the request body (adjust if necessary for login API) + Map body = Collections.emptyMap(); + // Perform login API call + ResponseEntity responseLogin = appointmentApiService.loginWithOdessa(authJwtToken, source, context, user, password, body); - if (errorsNode.isArray()) { - for (JsonNode error : errorsNode) { - // Check the main errorCode - if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) { - throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA)); - } + // Handle successful login + if (responseLogin.getStatusCode() == HttpStatus.OK) { + log.info("Login successful to odessa. Parsing response."); + String loginResponseJson = Utils.convertObjectToJson(responseLogin.getBody()); + AppointmentLoginResponse parsedResponse = parseLoginResponse(loginResponseJson); - // Check inside "subErrors" - JsonNode subErrorsNode = error.path("subErrors"); - if (subErrorsNode.isArray()) { - for (JsonNode subError : subErrorsNode) { - if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) { - throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA)); + // Validate and save token + if (parsedResponse.getTokenId() != null) { + hub.setAppointmentAuthTokenId(parsedResponse.getTokenId()); + hub.setAreaCode(parsedResponse.getAreaCode()); + hubRepository.save(hub); + + log.info("Saved new authToken and areaCode for Hub."); + success = true; + return hub; + } else { + throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again."); + } + } + // Handle non-OK response + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); + } catch (FeignException.Forbidden forbiddenException) { + attempt++; + log.error("Failed to login to odessa due to some error occurred."); + + // Extract raw response body + String responseBody = forbiddenException.contentUTF8(); // Extract raw JSON response + + // Parse JSON to check for "PasswordExpired" + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(responseBody); + JsonNode errorsNode = rootNode.path("errors"); + + if (errorsNode.isArray()) { + for (JsonNode error : errorsNode) { + // Check the main errorCode + if (GepafinConstant.PASSWORD_EXPIRED.equals(error.path("errorCode").asText())) { + throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA)); + } + + // Check inside "subErrors" + JsonNode subErrorsNode = error.path("subErrors"); + if (subErrorsNode.isArray()) { + for (JsonNode subError : subErrorsNode) { + if (GepafinConstant.PASSWORD_EXPIRED.equals(subError.path("errorCode").asText())) { + throw new CustomValidationException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PASSWORD_EXPIRED_LOGIN_TO_ODESSA)); + } } } } } + } catch (IOException e) { + log.error("Error parsing JSON response: {}", e.getMessage()); } - } catch (IOException e) { - log.error("Error parsing JSON response: {}", e.getMessage()); + if (attempt >= maxRetries) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); + } else { + regenerateTokenAndSave(hub); + } + } catch (Exception e) { + log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); + throw new RuntimeException("Authentication failed on Odessa. try again", e); } - - // Regenerate the token and retry - regenerateTokenAndSave(hub); - } catch (Exception e) { - log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); - throw new RuntimeException("Authentication failed on Odessa. try again", e); } return null; } From 42fd20adc7758b285126786aa0e0963488974a8a Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 13 May 2025 20:09:12 +0530 Subject: [PATCH 8/9] Updated code fix. --- .../tendermanagement/dao/AppointmentDao.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java index 079addee..5cfa0fe3 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -208,7 +208,6 @@ public class AppointmentDao { } throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); } catch (FeignException.Forbidden forbiddenException) { - attempt++; log.error("Failed to login to odessa due to some error"); // Extract raw response body @@ -245,14 +244,16 @@ public class AppointmentDao { } catch (IOException e) { log.error("Error parsing JSON response: {}", e.getMessage()); } - if (attempt >= maxRetries) { - throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); + if (attempt + 1 < maxRetries) { + regenerateTokenAndSave(hub); } else { - loginToOdessa(hub, application); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); } } catch (Exception e) { log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); throw new RuntimeException("Authentication failed on Odessa. try again", e); + } finally { + attempt++; } } return null; @@ -430,6 +431,7 @@ public class AppointmentDao { } private HubEntity authenticateAndSaveToken(HubEntity hub) { + int maxRetries = 3; int attempt = 0; boolean success = false; @@ -467,7 +469,6 @@ public class AppointmentDao { // Handle non-OK response throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); } catch (FeignException.Forbidden forbiddenException) { - attempt++; log.error("Failed to login to odessa due to some error occurred."); // Extract raw response body @@ -500,14 +501,16 @@ public class AppointmentDao { } catch (IOException e) { log.error("Error parsing JSON response: {}", e.getMessage()); } - if (attempt >= maxRetries) { - throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); - } else { + if (attempt + 1 < maxRetries) { regenerateTokenAndSave(hub); + } else { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); } } catch (Exception e) { log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); throw new RuntimeException("Authentication failed on Odessa. try again", e); + } finally { + attempt++; } } return null; From a836864faceaa34e95e0d6338703797dbf192d9e Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 13 May 2025 20:19:43 +0530 Subject: [PATCH 9/9] Code Fix. --- .../tendermanagement/dao/AppointmentDao.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java index 5cfa0fe3..609ab87d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -181,6 +181,7 @@ public class AppointmentDao { int attempt = 0; boolean success = false; while (attempt < maxRetries && !success) { + attempt++; try { //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); @@ -244,16 +245,9 @@ public class AppointmentDao { } catch (IOException e) { log.error("Error parsing JSON response: {}", e.getMessage()); } - if (attempt + 1 < maxRetries) { - regenerateTokenAndSave(hub); - } else { - throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); - } } catch (Exception e) { log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); throw new RuntimeException("Authentication failed on Odessa. try again", e); - } finally { - attempt++; } } return null; @@ -436,6 +430,7 @@ public class AppointmentDao { int attempt = 0; boolean success = false; while (attempt < maxRetries && !success) { + attempt++; try { //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); @@ -501,16 +496,9 @@ public class AppointmentDao { } catch (IOException e) { log.error("Error parsing JSON response: {}", e.getMessage()); } - if (attempt + 1 < maxRetries) { - regenerateTokenAndSave(hub); - } else { - throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale("Maximum retry attempts reached while trying to login to Odessa.")); - } } catch (Exception e) { log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); throw new RuntimeException("Authentication failed on Odessa. try again", e); - } finally { - attempt++; } } return null;