Merge pull request #280 from Kitzanos/manage-pec-errors

Enhance PEC Email Error Handling and Response Saving
This commit is contained in:
Rinaldo
2025-05-08 21:12:02 +02:00
committed by GitHub
20 changed files with 296 additions and 36 deletions

View File

@@ -1,5 +1,6 @@
package net.gepafin.tendermanagement.dao; package net.gepafin.tendermanagement.dao;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaBuilder;
@@ -308,6 +309,7 @@ public class ApplicationAmendmentRequestDao {
emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(applicationAmendmentRequestEntity); emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(applicationAmendmentRequestEntity);
EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request); EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request);
applicationAmendmentRequestResponse.setEmailSendResponse(emailSendResponse); applicationAmendmentRequestResponse.setEmailSendResponse(emailSendResponse);
saveEmailSendResponse(emailSendResponse, applicationAmendmentRequestEntity);
} }
return applicationAmendmentRequestResponse; return applicationAmendmentRequestResponse;
} }
@@ -1197,6 +1199,7 @@ public class ApplicationAmendmentRequestDao {
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email), emailLogRequest); emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email), emailLogRequest);
EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request); EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request);
emailReminderResponse.setEmailSendResponse(emailSendResponse); emailReminderResponse.setEmailSendResponse(emailSendResponse);
saveEmailSendResponse(emailSendResponse, amendment);
} else { } else {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.BENEFICIARY_EMAIL_NOT_FOUND_MSG)); throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.BENEFICIARY_EMAIL_NOT_FOUND_MSG));
} }
@@ -1551,8 +1554,14 @@ public class ApplicationAmendmentRequestDao {
applicationAmendmentRequestViewResponse.setExpirationDate(applicationAmendmentRequestView.getExpirationDate()); applicationAmendmentRequestViewResponse.setExpirationDate(applicationAmendmentRequestView.getExpirationDate());
applicationAmendmentRequestViewResponse.setAssigendUserName(applicationAmendmentRequestView.getAssigendUserName()); applicationAmendmentRequestViewResponse.setAssigendUserName(applicationAmendmentRequestView.getAssigendUserName());
applicationAmendmentRequestViewResponse.setStatus(applicationAmendmentRequestView.getStatus()); applicationAmendmentRequestViewResponse.setStatus(applicationAmendmentRequestView.getStatus());
applicationAmendmentRequestViewResponse.setEmailSendResponse(applicationAmendmentRequestView.getEmailSendResponse());
return applicationAmendmentRequestViewResponse; return applicationAmendmentRequestViewResponse;
} }
private void saveEmailSendResponse(EmailSendResponse newResponses, ApplicationAmendmentRequestEntity amendment) {
List<EmailSendResponse> mergedResponses = Utils.mergeEmailSendResponses(amendment.getEmailSendResponse(), newResponses);
amendment.setEmailSendResponse(mergedResponses);
applicationAmendmentRequestRepository.save(amendment);
}
} }

View File

@@ -1892,7 +1892,7 @@ public class ApplicationEvaluationDao {
log.info("Status updated to ADMISSIBLE for applicationId: " + application.getId()); log.info("Status updated to ADMISSIBLE for applicationId: " + application.getId());
emailNotificationDao.sendAdmissibilityNotificationEmailForAdmissibleApplication(application); emailNotificationDao.sendAdmissibilityNotificationEmailForAdmissibleApplication(application);
emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request); emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request);
saveEmailSendResponseToEvaluation(emailSendResponse,existingEntity);
} }
if(newStatus.equals(ApplicationStatusForEvaluation.TECHNICAL_EVALUATION) && Boolean.TRUE.equals(application.getStatus().equals(ApplicationStatusTypeEnum.ADMISSIBLE.getValue()))){ if(newStatus.equals(ApplicationStatusForEvaluation.TECHNICAL_EVALUATION) && Boolean.TRUE.equals(application.getStatus().equals(ApplicationStatusTypeEnum.ADMISSIBLE.getValue()))){
@@ -1950,6 +1950,7 @@ public class ApplicationEvaluationDao {
application = applicationRepository.save(application); application = applicationRepository.save(application);
emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(application,existingEntity); emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(application,existingEntity);
emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request); emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request);
saveEmailSendResponseToEvaluation(emailSendResponse,existingEntity);
} }
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_RESULT); Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_RESULT);
@@ -1963,6 +1964,14 @@ public class ApplicationEvaluationDao {
return null; return null;
} }
private void saveEmailSendResponseToEvaluation(EmailSendResponse newResponse, ApplicationEvaluationEntity evaluationEntity) {
List<EmailSendResponse> mergedResponses = Utils.mergeEmailSendResponses(
evaluationEntity.getEmailSendResponse(), newResponse
);
evaluationEntity.setEmailSendResponse(mergedResponses);
applicationEvaluationRepository.save(evaluationEntity);
}
public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) { public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) {
return applicationEvaluationRepository return applicationEvaluationRepository
.findByApplicationIdAndIsDeletedFalse(applicationId) .findByApplicationIdAndIsDeletedFalse(applicationId)

View File

@@ -470,6 +470,7 @@ public class AssignedApplicationsDao {
response.setCompanyName(view.getCompanyName()); response.setCompanyName(view.getCompanyName());
response.setCreatedDate(view.getCreatedDate()); response.setCreatedDate(view.getCreatedDate());
response.setUpdatedDate(view.getUpdatedDate()); response.setUpdatedDate(view.getUpdatedDate());
response.setEmailSendResponse(view.getEmailSendResponse());
return response; return response;
} }

View File

@@ -20,8 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List; import java.util.*;
import java.util.Set;
@Component @Component
@Log4j2 @Log4j2
@@ -36,21 +35,25 @@ public class EmailDao {
@Autowired @Autowired
private CallService callService; private CallService callService;
@Autowired
private EmailLogDao emailLogDao;
public EmailResendResponseBean resendEmail(HttpServletRequest request , Long userActionId){ public EmailResendResponseBean resendEmail(HttpServletRequest request , Long userActionId){
List<EmailLogEntity> emailLogs = emailLogRepository.findByUserActionIdAndEmailServiceType(userActionId,EmailServiceTypeEnum.PEC_SERVICE.getValue()); List<EmailLogEntity> emailLogs = emailLogRepository.findByUserActionIdAndEmailServiceTypeAndSendStatus(userActionId,EmailServiceTypeEnum.PEC_SERVICE.getValue(),StatusTypeEnum.FAILED.getValue());
if (emailLogs.isEmpty()) { if (emailLogs.isEmpty()) {
log.info("No emails found for given userActionId."); log.info("No emails found for given userActionId.");
} }
EmailResendResponseBean emailResendResponseBean = new EmailResendResponseBean(); EmailResendResponseBean emailResendResponseBean = new EmailResendResponseBean();
for (EmailLogEntity log : emailLogs){ for (EmailLogEntity log : emailLogs){
EmailLogRequest emailLogRequest = new EmailLogRequest(); EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(EmailScenarioTypeEnum.valueOf(log.getEmailType()),
emailLogRequest.setEmailType(EmailScenarioTypeEnum.valueOf(log.getEmailType())); RecipientTypeEnum.valueOf(log.getRecipientType()),
emailLogRequest.setRecipientType(RecipientTypeEnum.valueOf(log.getRecipientType())); log.getRecipientId(),
emailLogRequest.setRecipientId(log.getRecipientId()); log.getRecipientEmails(),
emailLogRequest.setUserId(log.getUserId()); log.getUserId(),
emailLogRequest.setApplicatioId(log.getApplicationId()); log.getApplicationId(),
emailLogRequest.setCallId(log.getCallId()); log.getAmendmentId(),
emailLogRequest.setAmendmentId(log.getAmendmentId()); log.getCallId()
);
List<String> recipients = Utils.commaSeparatedStringToList(log.getRecipientEmails()); List<String> recipients = Utils.commaSeparatedStringToList(log.getRecipientEmails());
CallEntity call = callService.validateCall(log.getCallId()); CallEntity call = callService.validateCall(log.getCallId());
@@ -69,23 +72,37 @@ public class EmailDao {
public EmailSendResponse buildEmailSendResponseFromRequest(HttpServletRequest request) { public EmailSendResponse buildEmailSendResponseFromRequest(HttpServletRequest request) {
Long userActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID); Long userActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID);
boolean isEmailSendSuccess = isEmailSentSuccessfully(userActionId);
EmailSendResponse emailSendResponse = new EmailSendResponse();
emailSendResponse.setIsEmailSend(isEmailSendSuccess);
emailSendResponse.setUserActionId(userActionId);
return emailSendResponse;
}
public boolean isEmailSentSuccessfully(Long userActionId) {
List<EmailLogEntity> emailLogs = emailLogRepository.findByUserActionId(userActionId); List<EmailLogEntity> emailLogs = emailLogRepository.findByUserActionId(userActionId);
boolean allSuccess = true;
String emailScenario = null;
for (EmailLogEntity log : emailLogs) { for (EmailLogEntity log : emailLogs) {
if (EmailServiceTypeEnum.PEC_SERVICE.getValue().equals(log.getEmailServiceType()) && if (emailScenario == null) {
StatusTypeEnum.SUCCESS.getValue().equals(log.getSendStatus())) { emailScenario = log.getEmailType();
return true;
} }
boolean isSuccess = EmailServiceTypeEnum.PEC_SERVICE.getValue().equals(log.getEmailServiceType()) &&
StatusTypeEnum.SUCCESS.getValue().equals(log.getSendStatus());
if (!isSuccess) {
allSuccess = false;
break;
} }
return false;
} }
return buildResponse(userActionId, allSuccess, emailScenario);
}
private EmailSendResponse buildResponse(Long userActionId, boolean allSuccess, String emailScenario) {
EmailSendResponse response = new EmailSendResponse();
response.setUserActionId(userActionId);
response.setIsEmailSend(allSuccess);
response.setEmailScenario(emailScenario != null ? EmailScenarioTypeEnum.valueOf(emailScenario) : null);
return response;
}
} }

View File

@@ -43,6 +43,7 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated;
@@ -155,6 +156,8 @@ public class UserDao {
emailSendResponse.setIsEmailSend(isEmailSendSuccess); emailSendResponse.setIsEmailSend(isEmailSendSuccess);
Long userActionId =(Long)request.getAttribute(GepafinConstant.USER_ACTION_ID); Long userActionId =(Long)request.getAttribute(GepafinConstant.USER_ACTION_ID);
emailSendResponse.setUserActionId(userActionId); emailSendResponse.setUserActionId(userActionId);
emailSendResponse.setEmailScenario(EmailScenarioTypeEnum.USER_CREATION);
saveEmailSendResponseToUser(emailSendResponse,userEntity);
} }
JWTToken token = authService.getJWTTokenBean(userEntity, Boolean.TRUE, loginAttemptEntity.getId(),emailSendResponse); JWTToken token = authService.getJWTTokenBean(userEntity, Boolean.TRUE, loginAttemptEntity.getId(),emailSendResponse);
return token; return token;
@@ -406,6 +409,7 @@ public class UserDao {
RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity()); RoleResponseBean roleResponseBean = roleDao.convertRoleEntityToRoleResponse(userEntity.getRoleEntity());
userResponseBean.setRole(roleResponseBean); userResponseBean.setRole(roleResponseBean);
userResponseBean.setLastLogin(userEntity.getLastLogin()); userResponseBean.setLastLogin(userEntity.getLastLogin());
userResponseBean.setEmailSendResponse(userEntity.getEmailSendResponse());
List<CompanyResponse> companyResponseBeans = companyDao.getCompanyByUserId(userEntity.getId()); List<CompanyResponse> companyResponseBeans = companyDao.getCompanyByUserId(userEntity.getId());
userResponseBean.setCompanies(companyResponseBeans); userResponseBean.setCompanies(companyResponseBeans);
if (userEntity.getBeneficiary() == null) { if (userEntity.getBeneficiary() == null) {
@@ -506,8 +510,18 @@ public class UserDao {
InitiatePasswordResetResponse initiatePasswordResetResponse = new InitiatePasswordResetResponse(); InitiatePasswordResetResponse initiatePasswordResetResponse = new InitiatePasswordResetResponse();
EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request); EmailSendResponse emailSendResponse = emailDao.buildEmailSendResponseFromRequest(request);
initiatePasswordResetResponse.setEmailSendResponse(emailSendResponse); initiatePasswordResetResponse.setEmailSendResponse(emailSendResponse);
saveEmailSendResponseToUser(emailSendResponse,user);
return initiatePasswordResetResponse; return initiatePasswordResetResponse;
} }
private void saveEmailSendResponseToUser(EmailSendResponse newResponse, UserEntity user) {
List<EmailSendResponse> mergedResponses = Utils.mergeEmailSendResponses(
user.getEmailSendResponse(), newResponse
);
user.setEmailSendResponse(mergedResponses);
userRepository.save(user);
}
public void sendResetPasswordTokenEmail(UserEntity user, String token) { public void sendResetPasswordTokenEmail(UserEntity user, String token) {
SystemEmailTemplateResponse emailTemplate = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( SystemEmailTemplateResponse emailTemplate = systemEmailTemplatesService.retrieveTemplateByTypeAndCall(

View File

@@ -2,7 +2,10 @@ package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Entity @Entity
@Table(name="application_amendment_request") @Table(name="application_amendment_request")
@@ -53,7 +56,10 @@ public class ApplicationAmendmentRequestEntity extends BaseEntity {
@Column(name = "amendment_document") @Column(name = "amendment_document")
private String amendmentDocument; private String amendmentDocument;
@Column(name = "CLOSING_DATE") @Column(name = "CLOSING_DATE")
private LocalDateTime closingDate; private LocalDateTime closingDate;
@Convert(converter = EmailSendResponseConverter.class)
@Column(name = "EMAIL_SEND_RESPONSE", columnDefinition = "TEXT")
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -3,9 +3,12 @@ package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.gepafin.tendermanagement.model.BaseBean;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Immutable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Entity @Entity
@Immutable @Immutable
@@ -13,12 +16,12 @@ import java.time.LocalDateTime;
@Getter @Getter
@Setter @Setter
@IdClass(ApplicationAmendmentRequestViewId.class) @IdClass(ApplicationAmendmentRequestViewId.class)
public class ApplicationAmendmentRequestView { public class ApplicationAmendmentRequestView extends BaseEntity {
@Id // @Id
@Column(name = "ID") // @Column(name = "ID")
private Long id; // private Long id;
@Column(name = "APPLICATION_ID") @Column(name = "APPLICATION_ID")
private Long applicationId; private Long applicationId;
@@ -56,12 +59,17 @@ public class ApplicationAmendmentRequestView {
@Column(name = "APPLICATION_USER_ID") @Column(name = "APPLICATION_USER_ID")
private Long applicationUserId; private Long applicationUserId;
@Column(name = "CREATED_DATE") // @Column(name = "CREATED_DATE")
private String createdDate; // private String createdDate;
//
@Column(name = "UPDATED_DATE") // @Column(name = "UPDATED_DATE")
private String updatedDate; // private String updatedDate;
@Column(name = "IS_DELETED") @Column(name = "IS_DELETED")
private Boolean isDeleted; private Boolean isDeleted;
@Convert(converter = EmailSendResponseConverter.class)
@Column(name = "EMAIL_SEND_RESPONSE", columnDefinition = "TEXT")
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -2,8 +2,10 @@ package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Data @Data
@Entity @Entity
@@ -71,4 +73,7 @@ public class ApplicationEvaluationEntity extends BaseEntity{
@Column(name = "evaluationVersion") @Column(name = "evaluationVersion")
private String evaluationVersion; private String evaluationVersion;
@Convert(converter = EmailSendResponseConverter.class)
@Column(name = "EMAIL_SEND_RESPONSE", columnDefinition = "TEXT")
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -2,9 +2,11 @@ package net.gepafin.tendermanagement.entities;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.Data; import lombok.Data;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Immutable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Entity @Entity
@Immutable @Immutable
@@ -58,4 +60,8 @@ public class AssignedApplicationsView{
@Column(name = "IS_DELETED") @Column(name = "IS_DELETED")
private Boolean isDeleted; private Boolean isDeleted;
@Convert(converter = EmailSendResponseConverter.class)
@Column(name = "EMAIL_SEND_RESPONSE", columnDefinition = "TEXT")
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -0,0 +1,40 @@
package net.gepafin.tendermanagement.entities;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import java.io.IOException;
import java.util.List;
@Converter
public class EmailSendResponseConverter implements AttributeConverter<List<EmailSendResponse>, String> {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public String convertToDatabaseColumn(List<EmailSendResponse> attribute) {
try {
return objectMapper.writeValueAsString(attribute);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Error converting list to JSON", e);
}
}
@Override
public List<EmailSendResponse> convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isBlank()) {
return List.of(); // or null if you prefer
}
try {
return objectMapper.readValue(dbData, new TypeReference<List<EmailSendResponse>>() {});
} catch (IOException e) {
throw new IllegalArgumentException("Error reading JSON from database", e);
}
}
}

View File

@@ -7,8 +7,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Entity @Entity
@Table(name = "GEPAFIN_USER") @Table(name = "GEPAFIN_USER")
@@ -69,4 +71,9 @@ public class UserEntity extends BaseEntity {
@ManyToOne @ManyToOne
@JoinColumn(name = "HUB_ID") @JoinColumn(name = "HUB_ID")
private HubEntity hub; private HubEntity hub;
@Convert(converter = EmailSendResponseConverter.class)
@Column(name = "EMAIL_SEND_RESPONSE", columnDefinition = "TEXT")
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.model.response;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Data @Data
public class ApplicationAmendmentRequestViewResponse { public class ApplicationAmendmentRequestViewResponse {
@@ -24,4 +25,6 @@ public class ApplicationAmendmentRequestViewResponse {
private String assigendUserName; private String assigendUserName;
private String status; private String status;
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -6,6 +6,7 @@ import net.gepafin.tendermanagement.enums.AssignedApplicationEnum;
import net.gepafin.tendermanagement.model.BaseBean; import net.gepafin.tendermanagement.model.BaseBean;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
@Data @Data
public class AssignedApplicationViewResponse extends BaseBean { public class AssignedApplicationViewResponse extends BaseBean {
@@ -20,5 +21,7 @@ public class AssignedApplicationViewResponse extends BaseBean {
private Long protocolNumber; private Long protocolNumber;
private String callName; private String callName;
private String companyName; private String companyName;
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -1,9 +1,11 @@
package net.gepafin.tendermanagement.model.response; package net.gepafin.tendermanagement.model.response;
import lombok.Data; import lombok.Data;
import net.gepafin.tendermanagement.enums.EmailScenarioTypeEnum;
@Data @Data
public class EmailSendResponse { public class EmailSendResponse {
private Boolean isEmailSend; private Boolean isEmailSend;
private Long userActionId; private Long userActionId;
private EmailScenarioTypeEnum emailScenario;
} }

View File

@@ -48,4 +48,5 @@ public class UserResponseBean extends BaseBean {
private Boolean thirdParty; private Boolean thirdParty;
private String emailPec; private String emailPec;
private List<EmailSendResponse> emailSendResponse;
} }

View File

@@ -11,8 +11,8 @@ public interface EmailLogRepository extends JpaRepository<EmailLogEntity,Long> {
List<EmailLogEntity> findByUserIdAndAmendmentIdAndIsDeletedFalse(Long userId,Long amendmentId); List<EmailLogEntity> findByUserIdAndAmendmentIdAndIsDeletedFalse(Long userId,Long amendmentId);
List<EmailLogEntity> findByUserActionId(Long userActionId); List<EmailLogEntity> findByUserActionId(Long userActionId);
List<EmailLogEntity> findByUserActionIdAndEmailServiceType(Long userActionId, String emailServiceType); List<EmailLogEntity> findByUserActionIdAndEmailServiceTypeAndSendStatus(
Long userActionId, String emailServiceType, String sendStatus);
Optional<EmailLogEntity> findTopByUserIdAndEmailTypeAndIsDeletedFalseOrderByCreatedDateDesc(Long userId, String emailType); Optional<EmailLogEntity> findTopByUserIdAndEmailTypeAndIsDeletedFalseOrderByCreatedDateDesc(Long userId, String emailType);
} }

View File

@@ -15,6 +15,7 @@ import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -36,9 +37,11 @@ import jakarta.persistence.criteria.Root;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.enums.EmailScenarioTypeEnum;
import net.gepafin.tendermanagement.enums.MatchModeEnum; import net.gepafin.tendermanagement.enums.MatchModeEnum;
import net.gepafin.tendermanagement.model.request.FilterCriteria; import net.gepafin.tendermanagement.model.request.FilterCriteria;
import net.gepafin.tendermanagement.model.request.GlobalFilters; import net.gepafin.tendermanagement.model.request.GlobalFilters;
import net.gepafin.tendermanagement.model.response.EmailSendResponse;
import net.gepafin.tendermanagement.web.rest.api.errors.*; import net.gepafin.tendermanagement.web.rest.api.errors.*;
import net.objecthunter.exp4j.Expression; import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder; import net.objecthunter.exp4j.ExpressionBuilder;
@@ -1021,5 +1024,21 @@ public class Utils {
} }
public static List<EmailSendResponse> mergeEmailSendResponses(List<EmailSendResponse> existingResponses, EmailSendResponse newResponse) {
Map<EmailScenarioTypeEnum, EmailSendResponse> responseMap = Optional.ofNullable(existingResponses)
.orElse(new ArrayList<>())
.stream()
.collect(Collectors.toMap(
EmailSendResponse::getEmailScenario,
Function.identity(),
(oldVal, newVal) -> newVal,
LinkedHashMap::new
));
responseMap.put(newResponse.getEmailScenario(), newResponse);
return new ArrayList<>(responseMap.values());
}
} }

View File

@@ -2765,4 +2765,34 @@
path="db/dump/insert_system_email_template_for_application_submission_failure_30_04_2025.sql"/> path="db/dump/insert_system_email_template_for_application_submission_failure_30_04_2025.sql"/>
</changeSet> </changeSet>
<changeSet id="06-05-2025_PK_193412" author="Piyush Kag">
<addColumn tableName="application_amendment_request">
<column name="email_send_response" type="TEXT">
<constraints nullable="true"/>
</column>
</addColumn>
<addColumn tableName="application_evaluation">
<column name="email_send_response" type="TEXT">
<constraints nullable="true"/>
</column>
</addColumn>
<addColumn tableName="gepafin_user">
<column name="email_send_response" type="TEXT">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
<changeSet id="07-05-2025_PK_195815" author="Piyush Kag">
<sqlFile dbms="postgresql"
path="db/dump/update_application_amendment_request_view.sql"/>
</changeSet>
<changeSet id="07-05-2025_PK_201518" author="Piyush Kag">
<sqlFile dbms="postgresql"
path="db/dump/update_assigned_application_view.sql"/>
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View File

@@ -0,0 +1,27 @@
CREATE OR REPLACE VIEW application_amendment_request_view AS
SELECT a.id,
a.application_id,
p.protocol_number,
cl.name AS call_name,
c.company_name,
a.start_date,
a.end_date AS expiration_date,
COALESCE(NULLIF(TRIM(BOTH FROM concat(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, ''))), ''), '') AS assigned_user_name,
aa.user_id AS assigned_user_id,
a.status,
a.note,
a.internal_note,
app.user_id AS application_user_id,
a.created_date,
a.updated_date,
a.is_deleted,
a.email_send_response
FROM gepafin_schema.application_amendment_request a
LEFT JOIN gepafin_schema.application app ON a.application_id = app.id AND (app.is_deleted IS FALSE OR app.is_deleted IS NULL)
LEFT JOIN gepafin_schema.call cl ON app.call_id = cl.id
LEFT JOIN gepafin_schema.company c ON app.company_id = c.id
LEFT JOIN gepafin_schema.protocol p ON a.protocol_id = p.id
LEFT JOIN gepafin_schema.assigned_applications aa ON app.id = aa.application_id AND (aa.is_deleted IS FALSE OR aa.is_deleted IS NULL)
LEFT JOIN gepafin_schema.gepafin_user u ON aa.user_id = u.id
WHERE a.is_deleted IS FALSE OR a.is_deleted IS NULL ORDER BY id;

View File

@@ -0,0 +1,53 @@
CREATE OR REPLACE VIEW assigned_applications_view AS
SELECT
-- From assigned_applications
aa.id AS id,
aa.user_id AS user_id,
aa.status AS status,
aa.created_date AS created_date,
aa.updated_date AS updated_date,
aa.is_deleted AS is_deleted,
-- From application
a.id AS application_id,
a.status AS application_status,
a.submission_date AS submission_date,
ae.end_date AS evaluation_end_date,
a.ndg AS ndg,
a.appointment_id AS appointment_id,
-- From protocol (OneToOne)
p.protocol_number AS protocol_number,
-- From call (ManyToOne)
cl.name AS call_name,
-- From company (ManyToOne)
c.company_name AS company_name,
ae.email_send_response AS email_send_response
FROM gepafin_schema.assigned_applications aa
-- Join application (ManyToOne from assigned_applications)
LEFT JOIN gepafin_schema.application a
ON aa.application_id = a.id
AND (a.is_deleted IS FALSE OR a.is_deleted IS NULL)
-- Join application_evaluation (application_id matches + not deleted)
LEFT JOIN gepafin_schema.application_evaluation ae
ON ae.application_id = a.id
AND (ae.is_deleted IS FALSE OR ae.is_deleted IS NULL)
-- Join protocol (OneToOne from application)
LEFT JOIN gepafin_schema.protocol p
ON a.protocol_number = p.id
-- Join call (ManyToOne from application)
LEFT JOIN gepafin_schema.call cl
ON a.call_id = cl.id
-- Join company (ManyToOne from application)
LEFT JOIN gepafin_schema.company c
ON a.company_id = c.id
WHERE aa.is_deleted IS FALSE OR aa.is_deleted IS NULL;