Updated amendment rejection email flow and handled for special amendment

This commit is contained in:
rajesh
2026-03-16 16:38:53 +05:30
parent 3410f6b45f
commit 94c86ebacd
6 changed files with 62 additions and 36 deletions

View File

@@ -786,10 +786,6 @@ public class ApplicationAmendmentRequestDao {
log.warn("Permission denied: Beneficiary tried to update amendment ID {} with status RESPONSE_RECEIVED", id);
throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
}
if(Boolean.TRUE.equals(isBeneficiary) && existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.DRAFT.getValue())){
log.warn("Permission denied: Beneficiary tried to update amendment ID {} with status DRAFT (only instructor can update)", id);
throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
}
if(Boolean.FALSE.equals(isBeneficiary) && existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())){
log.warn("Permission denied: Non-beneficiary tried to update amendment ID {} with status AWAITING", id);
throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
@@ -1283,26 +1279,7 @@ public class ApplicationAmendmentRequestDao {
ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id);
ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(existingApplicationAmendment);
if (ApplicationAmendmentRequestEnum.AWAITING.equals(statusTypeEnum)) {
// Only instructor can set status to AWAITING (e.g. after finishing edits post email rejection); beneficiary must not be allowed
if (Boolean.TRUE.equals(validator.checkIsBeneficiary()) || Boolean.TRUE.equals(validator.checkIsConfidi())) {
log.warn("Permission denied: Beneficiary/Confidi tried to set amendment ID {} status to AWAITING", id);
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
}
validator.validatePreInstructor(request, existingApplicationAmendment.getApplicationEvaluationEntity().getUserId());
// Allow transition to AWAITING only from DRAFT (e.g. after instructor finished edits post email rejection)
if (!ApplicationAmendmentRequestEnum.DRAFT.getValue().equals(existingApplicationAmendment.getStatus())) {
log.warn("Invalid status transition: amendment ID {} is not in DRAFT (current: {})", id, existingApplicationAmendment.getStatus());
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_APPROPIATE_STATUS));
}
log.info("Updating amendment ID {} status from DRAFT to AWAITING", id);
existingApplicationAmendment.setStatus(ApplicationAmendmentRequestEnum.AWAITING.getValue());
existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
applicationAmendmentRequestRepository.save(existingApplicationAmendment);
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationAmendmentEntity).newData(existingApplicationAmendment).build());
// Send the same mail as when (normal) amendment was created; only normal amendments can be in DRAFT (special amendment emails are sent at creation, not held)
emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(existingApplicationAmendment);
} else if (Boolean.TRUE.equals(existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())) && Boolean.TRUE.equals(statusTypeEnum.equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED))) {
if (Boolean.TRUE.equals(existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())) && Boolean.TRUE.equals(statusTypeEnum.equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED))) {
log.info("Updating amendment ID {} status from {} to {}", id, existingApplicationAmendment.getStatus(), statusTypeEnum);
existingApplicationAmendment.setStatus(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue());
existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));

View File

@@ -427,7 +427,9 @@ public class EmailNotificationDao {
if(Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.APPLICATION_TECHNICAL_EVALUATION_REJECTED.getValue()))
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.APPLICATION_ADMISSIBLE.getValue()))
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.APPLICATION_REJECTED.getValue()))
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.APPLICATION_AMENDMENT_REQUESTED.getValue()))) {
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.APPLICATION_AMENDMENT_REQUESTED.getValue()))
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.SPECIAL_APPLICATION_AMENDMENT_REQUESTED.getValue()))
|| Boolean.TRUE.equals(emailLogEntity.getEmailType().equals(EmailScenarioTypeEnum.SPECIAL_APPLICATION_AMENDMENT_REQUESTED_BLUE_TONGUE.getValue()))) {
isSendEmail = Boolean.FALSE;
}
}

View File

@@ -7,6 +7,7 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.AssignedApplicationEnum;
import net.gepafin.tendermanagement.enums.EmailScenarioTypeEnum;
import net.gepafin.tendermanagement.enums.EmailServiceTypeEnum;
@@ -133,16 +134,39 @@ public class PecMailDao {
String scenario = firstLog.getEmailType();
Long applicationId = firstLog.getApplicationId();
// Only normal amendment emails are rejectable in PEC flow; set amendment to DRAFT so only instructor can update
if (EmailScenarioTypeEnum.APPLICATION_AMENDMENT_REQUESTED.getValue().equals(scenario)) {
Long amendmentId = firstLog.getAmendmentId();
if (amendmentId != null) {
applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentId).ifPresent(amendment -> {
amendment.setStatus(ApplicationAmendmentRequestEnum.DRAFT.getValue());
applicationAmendmentRequestRepository.save(amendment);
log.info("Set amendment id={} to DRAFT after email rejected (userActionId={})", amendmentId, userActionId);
});
// Amendment email rejected (normal or special): revert application, then mark amendment REJECTED and soft-deleted
boolean isNormalAmendment = EmailScenarioTypeEnum.APPLICATION_AMENDMENT_REQUESTED.getValue().equals(scenario);
boolean isSpecialAmendment = EmailScenarioTypeEnum.SPECIAL_APPLICATION_AMENDMENT_REQUESTED.getValue().equals(scenario)
|| EmailScenarioTypeEnum.SPECIAL_APPLICATION_AMENDMENT_REQUESTED_BLUE_TONGUE.getValue().equals(scenario);
if (isNormalAmendment || isSpecialAmendment) {
ApplicationEntity applicationEntity = applicationService.validateApplication(applicationId);
if (isNormalAmendment) {
List<VersionHistoryEntity> appHistory = versionHistoryRepository.findVersionHistoryByUserActionIdAndTableName(userActionId, TABLE_APPLICATION);
Optional<VersionHistoryEntity> applicationVersion = appHistory.stream()
.filter(v -> applicationId.equals(v.getRecordId()) && v.getOldData() != null && !v.getOldData().isEmpty())
.findFirst();
if (applicationVersion.isPresent()) {
Map<String, Object> oldDataMap = Utils.convertJsonStringToMap(applicationVersion.get().getOldData());
if (oldDataMap != null) {
String previousStatus = Utils.extractString(oldDataMap, "status");
if (previousStatus != null) {
applicationEntity.setStatus(previousStatus);
}
applicationRepository.save(applicationEntity);
log.info("Rolled back application id={} from version history after amendment email rejected (userActionId={})", applicationId, userActionId);
}
} else {
log.warn("No APPLICATION version history with oldData found for userActionId={}, applicationId={}; skipping application rollback", userActionId, applicationId);
}
} else {
applicationEntity.setStatus(ApplicationStatusTypeEnum.ADMISSIBLE.getValue());
applicationEntity.setDateRejected(null);
applicationRepository.save(applicationEntity);
log.info("Set application id={} to ADMISSIBLE after special amendment email rejected (userActionId={})", applicationId, userActionId);
}
markAmendmentRejectedAndDeleted(firstLog.getAmendmentId(), userActionId);
return;
}
@@ -197,6 +221,18 @@ public class PecMailDao {
});
}
private void markAmendmentRejectedAndDeleted(Long amendmentId, Long userActionId) {
if (amendmentId == null) {
return;
}
applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentId).ifPresent(amendment -> {
amendment.setStatus(ApplicationAmendmentRequestEnum.REJECTED.getValue());
amendment.setIsDeleted(true);
applicationAmendmentRequestRepository.save(amendment);
log.info("Set amendment id={} to REJECTED and is_deleted=true after amendment email rejected (userActionId={})", amendmentId, userActionId);
});
}
private static LocalDateTime parseLocalDateTimeFromAudit(Object value) {
if (value == null) {
return null;

View File

@@ -7,8 +7,8 @@ public enum ApplicationAmendmentRequestEnum {
RESPONSE_RECEIVED("RESPONSE_RECEIVED"),
CLOSE("CLOSE"),
EXPIRED("EXPIRED"),
/** Amendment PEC email was rejected; only instructor can update until status is set back to AWAITING. */
DRAFT("DRAFT");
/** Special amendment PEC email was rejected; amendment status set to REJECTED. */
REJECTED("REJECTED");
private String value;

View File

@@ -3205,4 +3205,8 @@
</addColumn>
</changeSet>
<changeSet id="16-03-2026_RK_153512" author="Rajesh Khore">
<sqlFile dbms="postgresql" path="db/dump/update_system_email_template_special_amendment_16_03_2026.sql"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,7 @@
UPDATE gepafin_schema.system_email_template
SET subject='Comunicazione esito valutazione tecnica ed economico-finanziaria Avviso {{call_name}} '
WHERE email_scenario='SPECIAL_APPLICATION_AMENDMENT_REQUESTED';
UPDATE gepafin_schema.system_email_template
SET subject='Comunicazione esito valutazione tecnica ed economico-finanziaria Avviso {{call_name}} '
WHERE email_scenario='SPECIAL_APPLICATION_AMENDMENT_REQUESTED_BLUE_TONGUE';