Compare commits
64 Commits
b934665570
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2530030a8 | ||
|
|
c9534187af | ||
|
|
5e849d76d1 | ||
|
|
5a24549de3 | ||
|
|
9b321e700d | ||
|
|
7176ec27eb | ||
|
|
5aa342bd05 | ||
|
|
eef2d621f8 | ||
|
|
a5606c1018 | ||
|
|
67bf81e5ae | ||
|
|
3c8f2b0c84 | ||
|
|
b644707f85 | ||
|
|
acf2e4f73c | ||
|
|
63f8bd4a85 | ||
|
|
b225b9f042 | ||
|
|
1e703e4a40 | ||
|
|
d0b05aae11 | ||
|
|
94c86ebacd | ||
|
|
3410f6b45f | ||
|
|
9536935d02 | ||
|
|
bdb7b7d885 | ||
|
|
00080d6a6c | ||
|
|
5fe2291a3e | ||
|
|
e2c73db9f7 | ||
|
|
f0f904dabe | ||
|
|
7c564f999e | ||
|
|
2c6a64f408 | ||
|
|
78b15a0ea0 | ||
|
|
0669d2c928 | ||
|
|
43047b5cc9 | ||
|
|
aa34bf698e | ||
|
|
eb5e0f73e2 | ||
|
|
aa7ac4fef2 | ||
|
|
cadc4639c5 | ||
|
|
255ee536e1 | ||
|
|
6d21d46523 | ||
|
|
ccc6ac2c8f | ||
|
|
b65b3eb47c | ||
|
|
f0c15b928e | ||
|
|
8b72e372a1 | ||
|
|
05f74b3728 | ||
|
|
3347624d1d | ||
|
|
7a1f3dd1e8 | ||
|
|
3671d83d25 | ||
|
|
ce0320ced6 | ||
|
|
b69b4ace36 | ||
|
|
c56ff7658c | ||
|
|
158e48a2f2 | ||
|
|
b75dcf6532 | ||
|
|
0d0aafe31b | ||
|
|
6f3d3ac4b2 | ||
|
|
551c4b04df | ||
|
|
6d1b8dc041 | ||
|
|
97a992083b | ||
|
|
26e7430f93 | ||
|
|
bf086741f7 | ||
|
|
763aa8ab09 | ||
|
|
26d9cf46bb | ||
|
|
e69c6ba8e0 | ||
|
|
b52b82d8de | ||
|
|
d8538b0b35 | ||
|
|
feca1e86bf | ||
|
|
e8a59ce277 | ||
|
|
277663639d |
@@ -1164,15 +1164,12 @@ public class ApplicationAmendmentRequestDao {
|
|||||||
applicationEvaluationRepository.save(existingApplicationAmendment.getApplicationEvaluationEntity());
|
applicationEvaluationRepository.save(existingApplicationAmendment.getApplicationEvaluationEntity());
|
||||||
log.info("Updated ApplicationEvaluation status to OPEN for ID: {}", existingApplicationEvaluationEntity.getId());
|
log.info("Updated ApplicationEvaluation status to OPEN for ID: {}", existingApplicationEvaluationEntity.getId());
|
||||||
|
|
||||||
String previousApplicationStatus = application.getPreviousStatus();
|
if(Boolean.FALSE.equals(existingApplicationAmendment.getType().equals(ApplicationAmendmentRequestTypeEnum.SPECIAL.getValue()))){
|
||||||
if (previousApplicationStatus != null) {
|
application.setStatus(application.getPreviousStatus());
|
||||||
application.setStatus(previousApplicationStatus);
|
|
||||||
} else if (ApplicationAmendmentRequestTypeEnum.SPECIAL.getValue().equals(existingApplicationAmendment.getType())) {
|
|
||||||
application.setStatus(ApplicationStatusTypeEnum.ADMISSIBLE.getValue());
|
|
||||||
log.warn("Special amendment close: previousStatus was null for applicationId={}, defaulting to ADMISSIBLE", application.getId());
|
|
||||||
}
|
|
||||||
applicationRepository.save(application);
|
applicationRepository.save(application);
|
||||||
log.info("Updated Application status to previous state for Application ID: {}", application.getId());
|
loggingUtil.addVersionHistory(
|
||||||
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntityData).newData(application).build());
|
||||||
|
}
|
||||||
|
|
||||||
existingApplicationAmendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity().setStatus(AssignedApplicationEnum.OPEN.getValue());
|
existingApplicationAmendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity().setStatus(AssignedApplicationEnum.OPEN.getValue());
|
||||||
|
|
||||||
@@ -1193,9 +1190,6 @@ public class ApplicationAmendmentRequestDao {
|
|||||||
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity)
|
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity)
|
||||||
.newData(existingApplicationEvaluationEntity).build());
|
.newData(existingApplicationEvaluationEntity).build());
|
||||||
|
|
||||||
/** This code is responsible for adding a version history log for the "Update Application status" operation. **/
|
|
||||||
loggingUtil.addVersionHistory(
|
|
||||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntityData).newData(application).build());
|
|
||||||
|
|
||||||
/** This code is responsible for adding a version history log for the "Update assigned application " operation. **/
|
/** This code is responsible for adding a version history log for the "Update assigned application " operation. **/
|
||||||
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplicationData)
|
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplicationData)
|
||||||
|
|||||||
@@ -1173,26 +1173,57 @@ public class ApplicationDao {
|
|||||||
validateRankingActionRequest(rankingActionType, manualRanking);
|
validateRankingActionRequest(rankingActionType, manualRanking);
|
||||||
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
|
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
|
||||||
if (rankingActionType == null) {
|
if (rankingActionType == null) {
|
||||||
|
compactManualRanksAfterLeavingReposition(applicationEntity);
|
||||||
applicationEntity.setRankingActionType(null);
|
applicationEntity.setRankingActionType(null);
|
||||||
applicationEntity.setManualRanking(null);
|
applicationEntity.setManualRanking(null);
|
||||||
} else {
|
} else {
|
||||||
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION
|
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION) {
|
||||||
&& applicationRepository.existsByCallIdAndManualRankingAndIsDeletedFalseAndIdNot(
|
shiftOtherManualRanksForReposition(applicationEntity, manualRanking);
|
||||||
applicationEntity.getCall().getId(), manualRanking, applicationEntity.getId())) {
|
} else if (rankingActionType == ApplicationRankingActionTypeEnum.REMOVE) {
|
||||||
throw new CustomValidationException(Status.BAD_REQUEST,
|
compactManualRanksAfterLeavingReposition(applicationEntity);
|
||||||
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
|
|
||||||
}
|
}
|
||||||
applicationEntity.setRankingActionType(rankingActionType.getValue());
|
applicationEntity.setRankingActionType(rankingActionType.getValue());
|
||||||
applicationEntity.setManualRanking(
|
applicationEntity.setManualRanking(
|
||||||
rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION ? manualRanking : null);
|
rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION ? manualRanking : null);
|
||||||
}
|
}
|
||||||
applicationEntity = applicationRepository.save(applicationEntity);
|
applicationEntity = applicationRepository.save(applicationEntity);
|
||||||
|
normalizeDenseManualRanksForCall(applicationEntity.getCall().getId());
|
||||||
|
applicationEntity = applicationRepository.findById(applicationEntity.getId()).orElse(applicationEntity);
|
||||||
loggingUtil.addVersionHistory(
|
loggingUtil.addVersionHistory(
|
||||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE)
|
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE)
|
||||||
.oldData(oldApplicationEntity).newData(applicationEntity).build());
|
.oldData(oldApplicationEntity).newData(applicationEntity).build());
|
||||||
return getApplicationResponse(applicationEntity);
|
return getApplicationResponse(applicationEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps stored manual ranks in {@code 1..N} for the call (same count as repositioned rows with a manual value),
|
||||||
|
* preserving relative order. Prevents gaps or values above the pool size (e.g. 2,3,4,5 with four apps → 1,2,3,4).
|
||||||
|
*/
|
||||||
|
private void normalizeDenseManualRanksForCall(Long callId) {
|
||||||
|
String reposition = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
|
||||||
|
List<ApplicationEntity> repositioned = applicationRepository.findByCallIdAndIsDeletedFalse(callId).stream()
|
||||||
|
.filter(a -> ApplicationStatusTypeEnum.APPROVED.getValue().equals(a.getStatus()))
|
||||||
|
.filter(a -> reposition.equalsIgnoreCase(StringUtils.trimToEmpty(a.getRankingActionType())))
|
||||||
|
.filter(a -> a.getManualRanking() != null)
|
||||||
|
.sorted(Comparator.comparing(ApplicationEntity::getManualRanking).thenComparing(ApplicationEntity::getId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (repositioned.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean changed = false;
|
||||||
|
long slot = 1L;
|
||||||
|
for (ApplicationEntity a : repositioned) {
|
||||||
|
if (!Objects.equals(a.getManualRanking(), slot)) {
|
||||||
|
a.setManualRanking(slot);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
slot++;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
applicationRepository.saveAll(repositioned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public CallRankingSummaryResponse getApplicationRanking(Long callId,
|
public CallRankingSummaryResponse getApplicationRanking(Long callId,
|
||||||
List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
|
List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
|
||||||
CallEntity call = callRepository.findById(callId)
|
CallEntity call = callRepository.findById(callId)
|
||||||
@@ -1269,6 +1300,48 @@ public class ApplicationDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an application stops using manual REPOSITION (cleared or REMOVE), every other manual rank above its
|
||||||
|
* old slot shifts down by one so ranks stay dense (e.g. after removing rank 1, 2 and 3 become 1 and 2).
|
||||||
|
*/
|
||||||
|
private void compactManualRanksAfterLeavingReposition(ApplicationEntity applicationEntity) {
|
||||||
|
String repositionType = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
|
||||||
|
if (!repositionType.equalsIgnoreCase(StringUtils.trimToEmpty(applicationEntity.getRankingActionType()))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Long releasedRank = applicationEntity.getManualRanking();
|
||||||
|
if (releasedRank == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applicationRepository.compactRepositionedManualRankingAfterSlotFreed(
|
||||||
|
applicationEntity.getCall().getId(),
|
||||||
|
applicationEntity.getId(),
|
||||||
|
releasedRank,
|
||||||
|
repositionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shiftOtherManualRanksForReposition(ApplicationEntity applicationEntity, Long newRank) {
|
||||||
|
Long callId = applicationEntity.getCall().getId();
|
||||||
|
Long applicationId = applicationEntity.getId();
|
||||||
|
String repositionType = ApplicationRankingActionTypeEnum.REPOSITION.getValue();
|
||||||
|
Long oldRank = applicationEntity.getManualRanking();
|
||||||
|
if (Objects.equals(oldRank, newRank)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (oldRank == null) {
|
||||||
|
applicationRepository.bumpRepositionedManualRankingFromRankInclusive(callId, applicationId, newRank,
|
||||||
|
repositionType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newRank < oldRank) {
|
||||||
|
applicationRepository.bumpRepositionedManualRankingUpInHalfOpenInterval(callId, applicationId, newRank,
|
||||||
|
oldRank, repositionType);
|
||||||
|
} else {
|
||||||
|
applicationRepository.bumpRepositionedManualRankingDownInHalfOpenInterval(callId, applicationId, oldRank,
|
||||||
|
newRank, repositionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets all non-terminal amendments, the application evaluation (if any), and the assigned application row to CLOSE.
|
* Sets all non-terminal amendments, the application evaluation (if any), and the assigned application row to CLOSE.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ public class PdfDao {
|
|||||||
try {
|
try {
|
||||||
if (Boolean.FALSE.equals(StringUtils.isEmpty(fieldValue))) {
|
if (Boolean.FALSE.equals(StringUtils.isEmpty(fieldValue))) {
|
||||||
// Use Locale.ITALY to parse the number with the Italian format (comma as decimal separator)
|
// Use Locale.ITALY to parse the number with the Italian format (comma as decimal separator)
|
||||||
NumberFormat format = NumberFormat.getInstance(Locale.ENGLISH);
|
NumberFormat format = NumberFormat.getInstance(Locale.ITALY);
|
||||||
Number number = format.parse(fieldValue); // Parse the fieldValue as a number
|
Number number = format.parse(fieldValue); // Parse the fieldValue as a number
|
||||||
double numericValue = number.doubleValue(); // Convert the parsed number to double
|
double numericValue = number.doubleValue(); // Convert the parsed number to double
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import net.gepafin.tendermanagement.enums.StatusTypeEnum;
|
|||||||
import net.gepafin.tendermanagement.model.response.EmailLogResponse;
|
import net.gepafin.tendermanagement.model.response.EmailLogResponse;
|
||||||
import net.gepafin.tendermanagement.model.response.PecEmailLogResponse;
|
import net.gepafin.tendermanagement.model.response.PecEmailLogResponse;
|
||||||
import net.gepafin.tendermanagement.model.response.PecMailResponse;
|
import net.gepafin.tendermanagement.model.response.PecMailResponse;
|
||||||
|
import net.gepafin.tendermanagement.repositories.*;
|
||||||
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
|
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
|
||||||
import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository;
|
import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository;
|
||||||
import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository;
|
import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository;
|
||||||
|
|||||||
@@ -185,4 +185,67 @@ public interface ApplicationRepository extends JpaRepository<ApplicationEntity,
|
|||||||
|
|
||||||
boolean existsByCallIdAndManualRankingAndIsDeletedFalseAndIdNot(Long callId, Long manualRanking, Long id);
|
boolean existsByCallIdAndManualRankingAndIsDeletedFalseAndIdNot(Long callId, Long manualRanking, Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments manual_ranking by 1 for other REPOSITION rows in the call with rank >= fromRank (insert / move up).
|
||||||
|
*/
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
@Query("UPDATE ApplicationEntity a SET a.manualRanking = a.manualRanking + 1 "
|
||||||
|
+ "WHERE a.call.id = :callId AND a.isDeleted = false "
|
||||||
|
+ "AND a.rankingActionType = :repositionType "
|
||||||
|
+ "AND a.manualRanking IS NOT NULL AND a.id <> :applicationId "
|
||||||
|
+ "AND a.manualRanking >= :fromRank")
|
||||||
|
int bumpRepositionedManualRankingFromRankInclusive(@Param("callId") Long callId,
|
||||||
|
@Param("applicationId") Long applicationId,
|
||||||
|
@Param("fromRank") Long fromRank,
|
||||||
|
@Param("repositionType") String repositionType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments manual_ranking by 1 for ranks in [lowRank, highRank) — used when moving this application to a better (smaller) rank.
|
||||||
|
*/
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
@Query("UPDATE ApplicationEntity a SET a.manualRanking = a.manualRanking + 1 "
|
||||||
|
+ "WHERE a.call.id = :callId AND a.isDeleted = false "
|
||||||
|
+ "AND a.rankingActionType = :repositionType "
|
||||||
|
+ "AND a.manualRanking IS NOT NULL AND a.id <> :applicationId "
|
||||||
|
+ "AND a.manualRanking >= :lowRank AND a.manualRanking < :highRank")
|
||||||
|
int bumpRepositionedManualRankingUpInHalfOpenInterval(@Param("callId") Long callId,
|
||||||
|
@Param("applicationId") Long applicationId,
|
||||||
|
@Param("lowRank") Long lowRank,
|
||||||
|
@Param("highRank") Long highRank,
|
||||||
|
@Param("repositionType") String repositionType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements manual_ranking by 1 for ranks in (lowRank, highRank] — used when moving this application to a worse (larger) rank.
|
||||||
|
*/
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
@Query("UPDATE ApplicationEntity a SET a.manualRanking = a.manualRanking - 1 "
|
||||||
|
+ "WHERE a.call.id = :callId AND a.isDeleted = false "
|
||||||
|
+ "AND a.rankingActionType = :repositionType "
|
||||||
|
+ "AND a.manualRanking IS NOT NULL AND a.id <> :applicationId "
|
||||||
|
+ "AND a.manualRanking > :lowRank AND a.manualRanking <= :highRank")
|
||||||
|
int bumpRepositionedManualRankingDownInHalfOpenInterval(@Param("callId") Long callId,
|
||||||
|
@Param("applicationId") Long applicationId,
|
||||||
|
@Param("lowRank") Long lowRank,
|
||||||
|
@Param("highRank") Long highRank,
|
||||||
|
@Param("repositionType") String repositionType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After this application leaves manual REPOSITION, closes the gap: every other REPOSITION row with rank
|
||||||
|
* strictly greater than {@code releasedRank} moves down by 1.
|
||||||
|
*/
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
@Query("UPDATE ApplicationEntity a SET a.manualRanking = a.manualRanking - 1 "
|
||||||
|
+ "WHERE a.call.id = :callId AND a.isDeleted = false "
|
||||||
|
+ "AND a.rankingActionType = :repositionType "
|
||||||
|
+ "AND a.manualRanking IS NOT NULL AND a.id <> :applicationId "
|
||||||
|
+ "AND a.manualRanking > :releasedRank")
|
||||||
|
int compactRepositionedManualRankingAfterSlotFreed(@Param("callId") Long callId,
|
||||||
|
@Param("applicationId") Long applicationId,
|
||||||
|
@Param("releasedRank") Long releasedRank,
|
||||||
|
@Param("repositionType") String repositionType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import org.springframework.stereotype.Component;
|
|||||||
import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity;
|
import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity;
|
||||||
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
|
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
|
||||||
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
|
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
|
||||||
|
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestTypeEnum;
|
||||||
import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum;
|
import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum;
|
||||||
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
|
|
||||||
import net.gepafin.tendermanagement.enums.AssignedApplicationEnum;
|
import net.gepafin.tendermanagement.enums.AssignedApplicationEnum;
|
||||||
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
|
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
|
||||||
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
|
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
|
||||||
@@ -129,9 +129,22 @@ public class ApplicationAmendmentScheduler {
|
|||||||
// Update AssignedApplicationsEntity status
|
// Update AssignedApplicationsEntity status
|
||||||
updateAssignedApplicationStatus(evaluation.getAssignedApplicationsEntity());
|
updateAssignedApplicationStatus(evaluation.getAssignedApplicationsEntity());
|
||||||
|
|
||||||
// Update ApplicationEntity status
|
// Skip application status restore only when every amendment expired *in this run* for this
|
||||||
|
// evaluation is SPECIAL. (Do not use all amendments on the eval — a closed non-SPECIAL
|
||||||
|
// record from the past would wrongly force a previousStatus restore after special expiry.)
|
||||||
|
List<ApplicationAmendmentRequestEntity> expiredThisRunForEval = amendmentRequests.stream()
|
||||||
|
.filter(req -> req.getApplicationEvaluationEntity().getId().equals(evaluation.getId()))
|
||||||
|
.toList();
|
||||||
|
boolean skipApplicationStatusRestore = !expiredThisRunForEval.isEmpty()
|
||||||
|
&& expiredThisRunForEval.stream()
|
||||||
|
.allMatch(req -> ApplicationAmendmentRequestTypeEnum.SPECIAL.getValue().equals(req.getType()));
|
||||||
|
if (!skipApplicationStatusRestore) {
|
||||||
updateApplicationStatus(evaluation.getAssignedApplicationsEntity().getApplication());
|
updateApplicationStatus(evaluation.getAssignedApplicationsEntity().getApplication());
|
||||||
|
} else {
|
||||||
|
log.info(
|
||||||
|
"Amendment expiration: skipping Application status restore (all amendments expired this run are SPECIAL), evaluationId={}",
|
||||||
|
evaluation.getId());
|
||||||
|
}
|
||||||
|
|
||||||
log.info("Updated EndDate and suspension days for ApplicationEvaluation with ID: {}",
|
log.info("Updated EndDate and suspension days for ApplicationEvaluation with ID: {}",
|
||||||
evaluation.getId());
|
evaluation.getId());
|
||||||
|
|||||||
@@ -3240,4 +3240,49 @@
|
|||||||
<changeSet id="09-04-2026_RK_115923" author="Rajesh Khore">
|
<changeSet id="09-04-2026_RK_115923" author="Rajesh Khore">
|
||||||
<sqlFile dbms="postgresql" path="db/dump/update_email_config_for_mailgun_09_04_2026.sql" />
|
<sqlFile dbms="postgresql" path="db/dump/update_email_config_for_mailgun_09_04_2026.sql" />
|
||||||
</changeSet>
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="09-04-2026_RK_143457" author="Rajesh Khore">
|
||||||
|
<sqlFile dbms="postgresql" path="db/dump/update_system_email_template_09_04_2026.sql" />
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="09-04-2026_RK_174653" author="Rajesh Khore">
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="MANAGE_SUBSEQUENT_PHASES"/>
|
||||||
|
<where>role_type='ROLE_GEPAFIN_OPERATOR'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="VIEW_CALLS,APPLY_CALLS"/>
|
||||||
|
<where>role_type='ROLE_BENEFICIARY'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="EVALUATE_APPLICATIONS,MANAGE_PRELIMINARY_RELIEF"/>
|
||||||
|
<where>role_type='ROLE_PRE_INSTRUCTOR'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="EVALUATE_APPLICATIONS,MANAGE_PRELIMINARY_RELIEF,ASSIGED_APPLICATION"/>
|
||||||
|
<where>role_type='ROLE_INSTRUCTOR_MANAGER'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="VIEW_CONFIDI_CALLS,APPLY_CONFIDI_CALLS"/>
|
||||||
|
<where>role_type='ROLE_CONFIDI'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="ROOT_MANAGE_APPL_VIEW_DELETED,ROOT_MANAGE_APPL_DELETE_CONFIRM"/>
|
||||||
|
<where>role_type='ROLE_DIRECTOR'</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update tableName="role">
|
||||||
|
<column name="permissions" value="MANAGE_TENDERS,MANAGE_USERS,ROOT_MANAGE_NDG,ROOT_MANAGE_APPL_STATUS,ROOT_MANAGE_AMENDMENT_REOPEN,ROOT_MANAGE_AMENDMENT_EXTEND,ROOT_MANAGE_APPL_VIEW_DELETED,ROOT_MANAGE_APPL_DELETE,ROOT_MANAGE_PEC_SEND,ROOT_MANAGE_VIEW_LOG,ROOT_MANAGE_EMAIL_TEMPLATES,ROOT_MANAGE_CALL_COPY"/>
|
||||||
|
<where>role_type='ROLE_SUPER_ADMIN'</where>
|
||||||
|
</update>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="15-04-2026_RK_153423" author="Rajesh Khore">
|
||||||
|
<sqlFile dbms="postgresql" path="db/dump/update_application_ranking_view_15_04_2026.sql"/>
|
||||||
|
</changeSet>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
DROP VIEW IF EXISTS application_ranking_view;
|
||||||
|
|
||||||
|
CREATE OR REPLACE VIEW application_ranking_view AS
|
||||||
|
WITH evaluation_scores AS (
|
||||||
|
SELECT
|
||||||
|
ae.application_id,
|
||||||
|
COALESCE(
|
||||||
|
SUM(
|
||||||
|
COALESCE(NULLIF(TRIM(score_item ->> 'score'), ''), '0')::numeric
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS total_score
|
||||||
|
FROM application_evaluation ae
|
||||||
|
LEFT JOIN LATERAL jsonb_array_elements(
|
||||||
|
CASE
|
||||||
|
WHEN ae.criteria IS NULL OR BTRIM(ae.criteria) = '' THEN '[]'::jsonb
|
||||||
|
ELSE ae.criteria::jsonb
|
||||||
|
END
|
||||||
|
) score_item ON TRUE
|
||||||
|
WHERE ae.is_deleted = false
|
||||||
|
GROUP BY ae.application_id
|
||||||
|
),
|
||||||
|
approved_applications AS (
|
||||||
|
SELECT
|
||||||
|
a.id AS application_id,
|
||||||
|
a.call_id,
|
||||||
|
a.company_id,
|
||||||
|
a.user_id,
|
||||||
|
a.status AS status,
|
||||||
|
a.submission_date,
|
||||||
|
a.amount_requested,
|
||||||
|
a.amount_accepted,
|
||||||
|
a.manual_ranking,
|
||||||
|
a.ranking_action_type,
|
||||||
|
a.ndg,
|
||||||
|
a.pec_email,
|
||||||
|
c.ranking_type,
|
||||||
|
p.created_date AS protocol_datetime,
|
||||||
|
p.protocol_number AS protocol_number,
|
||||||
|
COALESCE(a.amount_accepted, a.amount_requested, 0) AS amount,
|
||||||
|
COALESCE(es.total_score, 0) AS total_score
|
||||||
|
FROM application a
|
||||||
|
JOIN call c ON c.id = a.call_id
|
||||||
|
AND (c.is_deleted = false OR c.is_deleted IS NULL)
|
||||||
|
AND NULLIF(BTRIM(c.ranking_type), '') IS NOT NULL
|
||||||
|
LEFT JOIN protocol p ON p.id = a.protocol_number
|
||||||
|
LEFT JOIN evaluation_scores es ON es.application_id = a.id
|
||||||
|
WHERE (a.is_deleted = false OR a.is_deleted IS NULL)
|
||||||
|
AND a.status = 'APPROVED'
|
||||||
|
AND COALESCE(a.ranking_action_type, '') <> 'EXCLUDE'
|
||||||
|
),
|
||||||
|
ranking_core AS (
|
||||||
|
SELECT *
|
||||||
|
FROM approved_applications
|
||||||
|
WHERE COALESCE(ranking_action_type, '') <> 'REMOVE'
|
||||||
|
),
|
||||||
|
remove_apps AS (
|
||||||
|
SELECT *
|
||||||
|
FROM approved_applications
|
||||||
|
WHERE COALESCE(ranking_action_type, '') = 'REMOVE'
|
||||||
|
),
|
||||||
|
natural_ranked AS (
|
||||||
|
SELECT
|
||||||
|
rc.*,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY rc.call_id
|
||||||
|
ORDER BY
|
||||||
|
CASE WHEN rc.ranking_type = 'SCORE' THEN rc.total_score END DESC NULLS LAST,
|
||||||
|
CASE WHEN rc.ranking_type = 'PROTOCOL_DATE_TIME' THEN rc.protocol_datetime END ASC NULLS LAST,
|
||||||
|
rc.protocol_datetime ASC NULLS LAST,
|
||||||
|
rc.application_id ASC
|
||||||
|
) AS natural_rank
|
||||||
|
FROM ranking_core rc
|
||||||
|
),
|
||||||
|
call_limits AS (
|
||||||
|
SELECT
|
||||||
|
nr.call_id,
|
||||||
|
COUNT(*)::bigint AS app_cnt,
|
||||||
|
COALESCE(
|
||||||
|
MAX(
|
||||||
|
CASE
|
||||||
|
WHEN COALESCE(nr.ranking_action_type, '') = 'REPOSITION'
|
||||||
|
AND nr.manual_ranking IS NOT NULL
|
||||||
|
THEN nr.manual_ranking
|
||||||
|
END
|
||||||
|
),
|
||||||
|
0
|
||||||
|
) AS max_manual
|
||||||
|
FROM natural_ranked nr
|
||||||
|
GROUP BY nr.call_id
|
||||||
|
),
|
||||||
|
free_ranks AS (
|
||||||
|
SELECT
|
||||||
|
cl.call_id,
|
||||||
|
gs.slot::bigint AS listing_rank,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY cl.call_id ORDER BY gs.slot) AS fill_order
|
||||||
|
FROM call_limits cl
|
||||||
|
CROSS JOIN LATERAL generate_series(
|
||||||
|
1,
|
||||||
|
GREATEST(cl.app_cnt::int, cl.max_manual::int)
|
||||||
|
) AS gs(slot)
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM natural_ranked mr
|
||||||
|
WHERE mr.call_id = cl.call_id
|
||||||
|
AND COALESCE(mr.ranking_action_type, '') = 'REPOSITION'
|
||||||
|
AND mr.manual_ranking IS NOT NULL
|
||||||
|
AND mr.manual_ranking = gs.slot
|
||||||
|
)
|
||||||
|
),
|
||||||
|
non_manual_ordered AS (
|
||||||
|
SELECT
|
||||||
|
nr.*,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY nr.call_id
|
||||||
|
ORDER BY
|
||||||
|
CASE WHEN nr.ranking_type = 'SCORE' THEN nr.total_score END DESC NULLS LAST,
|
||||||
|
CASE WHEN nr.ranking_type = 'PROTOCOL_DATE_TIME' THEN nr.protocol_datetime END ASC NULLS LAST,
|
||||||
|
nr.protocol_datetime ASC NULLS LAST,
|
||||||
|
nr.application_id ASC
|
||||||
|
) AS fill_order
|
||||||
|
FROM natural_ranked nr
|
||||||
|
WHERE COALESCE(nr.ranking_action_type, '') <> 'REPOSITION'
|
||||||
|
OR nr.manual_ranking IS NULL
|
||||||
|
),
|
||||||
|
manual_part AS (
|
||||||
|
SELECT
|
||||||
|
mr.call_id,
|
||||||
|
mr.application_id,
|
||||||
|
mr.ranking_action_type,
|
||||||
|
mr.total_score,
|
||||||
|
mr.user_id,
|
||||||
|
mr.status,
|
||||||
|
mr.submission_date,
|
||||||
|
mr.protocol_datetime,
|
||||||
|
mr.protocol_number,
|
||||||
|
mr.ndg,
|
||||||
|
mr.amount_accepted,
|
||||||
|
mr.pec_email,
|
||||||
|
mr.manual_ranking,
|
||||||
|
mr.ranking_type,
|
||||||
|
mr.manual_ranking AS listing_rank
|
||||||
|
FROM natural_ranked mr
|
||||||
|
WHERE COALESCE(mr.ranking_action_type, '') = 'REPOSITION'
|
||||||
|
AND mr.manual_ranking IS NOT NULL
|
||||||
|
),
|
||||||
|
non_manual_part AS (
|
||||||
|
SELECT
|
||||||
|
nmo.call_id,
|
||||||
|
nmo.application_id,
|
||||||
|
nmo.ranking_action_type,
|
||||||
|
nmo.total_score,
|
||||||
|
nmo.user_id,
|
||||||
|
nmo.status,
|
||||||
|
nmo.submission_date,
|
||||||
|
nmo.protocol_datetime,
|
||||||
|
nmo.protocol_number,
|
||||||
|
nmo.ndg,
|
||||||
|
nmo.amount_accepted,
|
||||||
|
nmo.pec_email,
|
||||||
|
nmo.manual_ranking,
|
||||||
|
nmo.ranking_type,
|
||||||
|
fr.listing_rank
|
||||||
|
FROM non_manual_ordered nmo
|
||||||
|
JOIN free_ranks fr
|
||||||
|
ON fr.call_id = nmo.call_id
|
||||||
|
AND fr.fill_order = nmo.fill_order
|
||||||
|
),
|
||||||
|
ranked_pool AS (
|
||||||
|
SELECT * FROM manual_part
|
||||||
|
UNION ALL
|
||||||
|
SELECT * FROM non_manual_part
|
||||||
|
),
|
||||||
|
pool_max AS (
|
||||||
|
SELECT call_id, COALESCE(MAX(listing_rank), 0) AS max_lr
|
||||||
|
FROM ranked_pool
|
||||||
|
GROUP BY call_id
|
||||||
|
),
|
||||||
|
remove_part AS (
|
||||||
|
SELECT
|
||||||
|
ra.call_id,
|
||||||
|
ra.application_id,
|
||||||
|
ra.ranking_action_type,
|
||||||
|
ra.total_score,
|
||||||
|
ra.user_id,
|
||||||
|
ra.status,
|
||||||
|
ra.submission_date,
|
||||||
|
ra.protocol_datetime,
|
||||||
|
ra.protocol_number,
|
||||||
|
ra.ndg,
|
||||||
|
ra.amount_accepted,
|
||||||
|
ra.pec_email,
|
||||||
|
ra.manual_ranking,
|
||||||
|
ra.ranking_type,
|
||||||
|
COALESCE(pm.max_lr, 0)
|
||||||
|
+ ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY ra.call_id
|
||||||
|
ORDER BY ra.protocol_datetime ASC NULLS LAST, ra.application_id
|
||||||
|
) AS listing_rank
|
||||||
|
FROM remove_apps ra
|
||||||
|
LEFT JOIN pool_max pm ON pm.call_id = ra.call_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
rp.listing_rank,
|
||||||
|
rp.application_id,
|
||||||
|
rp.call_id,
|
||||||
|
rp.ranking_action_type,
|
||||||
|
rp.total_score,
|
||||||
|
rp.user_id,
|
||||||
|
rp.status,
|
||||||
|
rp.submission_date,
|
||||||
|
rp.protocol_datetime,
|
||||||
|
rp.protocol_number,
|
||||||
|
rp.ndg,
|
||||||
|
rp.amount_accepted,
|
||||||
|
rp.pec_email,
|
||||||
|
rp.manual_ranking,
|
||||||
|
rp.ranking_type
|
||||||
|
FROM ranked_pool rp
|
||||||
|
UNION ALL
|
||||||
|
SELECT
|
||||||
|
rv.listing_rank,
|
||||||
|
rv.application_id,
|
||||||
|
rv.call_id,
|
||||||
|
rv.ranking_action_type,
|
||||||
|
rv.total_score,
|
||||||
|
rv.user_id,
|
||||||
|
rv.status,
|
||||||
|
rv.submission_date,
|
||||||
|
rv.protocol_datetime,
|
||||||
|
rv.protocol_number,
|
||||||
|
rv.ndg,
|
||||||
|
rv.amount_accepted,
|
||||||
|
rv.pec_email,
|
||||||
|
rv.manual_ranking,
|
||||||
|
rv.ranking_type
|
||||||
|
FROM remove_part rv order by listing_rank asc;
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
-- 1
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name = 'Application submission template to beneficiary and company',
|
||||||
|
"type" = 'APPLICATION_SUBMISSION_TO_USER_AND_COMPANY',
|
||||||
|
html_content = '<html>
|
||||||
|
<body style="font-family: Arial, sans-serif; color: #333; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p>Buongiorno,</p>
|
||||||
|
<p>
|
||||||
|
Si comunica che, in riferimento alla domanda di concessione di
|
||||||
|
Finanziamento agevolato a valere sul Fondo prestiti
|
||||||
|
<strong>{{call_name}}</strong> di cui all''oggetto, la stessa è stata
|
||||||
|
regolarmente acquisita ed è stata registrata con Protocollo n.
|
||||||
|
<strong>{{protocol_number}}</strong> del <strong>{{date}}</strong> alle
|
||||||
|
<strong>{{time}}</strong>.
|
||||||
|
</p>
|
||||||
|
<p>Distinti Saluti,</p>
|
||||||
|
<p>
|
||||||
|
<strong>{{email_signature}}</strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>',
|
||||||
|
subject = 'BANDO {{call_name}} - Domanda di concessione di finanziamento agevolato {{company_name}}'
|
||||||
|
WHERE email_scenario = 'APPLICATION_SUBMITTED'
|
||||||
|
AND type = 'APPLICATION_SUBMISSION_TO_USER_AND_COMPANY'
|
||||||
|
AND hub_id IS NULL;
|
||||||
|
|
||||||
|
-- 2
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name='Application submission template to gepafin',
|
||||||
|
"type"='APPLICATION_SUBMISSION_TO_GEPAFIN',
|
||||||
|
html_content='<html>
|
||||||
|
<body style="font-family: Arial, sans-serif; color: #333; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p>
|
||||||
|
In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti
|
||||||
|
<strong>{{call_name}}</strong> di cui all''oggetto, la stessa è stata regolarmente acquisita ed è stata
|
||||||
|
registrata con Protocollo n. <strong>{{protocol_number}}</strong> del <strong>{{date}}</strong> alle <strong>{{time}}</strong>.
|
||||||
|
</p>
|
||||||
|
<p>Distinti Saluti,</p>
|
||||||
|
<p>
|
||||||
|
<strong>{{email_signature}}</strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>',
|
||||||
|
subject='BANDO {{call_name}} - Domanda di concessione di finanziamento agevolato {{company_name}}'
|
||||||
|
WHERE email_scenario='APPLICATION_SUBMITTED'
|
||||||
|
AND type='APPLICATION_SUBMISSION_TO_GEPAFIN'
|
||||||
|
AND hub_id IS NULL;
|
||||||
|
|
||||||
|
-- 3
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET html_content='<html>
|
||||||
|
<body style="font-family: Arial, sans-serif; color: #000; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p><strong>RICHIESTA INTEGRAZIONE DOCUMENTALE</strong></p>
|
||||||
|
<p>Buongiorno,</p>
|
||||||
|
<p>In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti
|
||||||
|
<strong>{{call_name}}</strong> di cui al <strong>Protocollo n. {{protocol_number}} del
|
||||||
|
{{protocol_date}} e {{protocol_time}}</strong>, alla luce dell''attività istruttoria svolta,
|
||||||
|
segnaliamo quanto segue:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
{{form_dataInput}}
|
||||||
|
</ul>
|
||||||
|
<p>{{note}}</p>
|
||||||
|
<p>Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all''interno dello sportello
|
||||||
|
online <a href="{{platform_link}}">{{platform_link}}</a> che inviandola a mezzo PEC all''indirizzo
|
||||||
|
bandi.gepafin@legalmail.it entro e <strong>non oltre {{response_days}} giorni</strong> dal ricevimento della presente comunicazione,
|
||||||
|
precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.
|
||||||
|
</p>
|
||||||
|
<p>Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito
|
||||||
|
dell''invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.
|
||||||
|
</p>
|
||||||
|
<p>Distinti Saluti,</p>
|
||||||
|
<p><strong>{{email_signature}}</strong></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>'
|
||||||
|
WHERE email_scenario='APPLICATION_AMENDMENT_REQUESTED'
|
||||||
|
AND hub_id IS NULL;
|
||||||
|
|
||||||
|
-- 4
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET subject='BANDO {{call_name}} - Domanda di finanziamento non ammessa {{company_name}}'
|
||||||
|
WHERE email_scenario='APPLICATION_AMENDMENT_EXPIRED';
|
||||||
|
|
||||||
|
-- 5
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET subject='BANDO {{call_name}} – Esito positivo istruttoria di ammissibilità {{company_name}}'
|
||||||
|
WHERE email_scenario='APPLICATION_ADMISSIBLE';
|
||||||
|
|
||||||
|
-- 6
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET html_content='<html> <body style="font-family: Arial, sans-serif; color: #000; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p>Buongiorno,</p>
|
||||||
|
<p>Si comunica che, in riferimento alla domanda a valere sul bando “<strong>{{call_name}}</strong>” di cui al
|
||||||
|
<strong>Protocollo n. {{protocol_number}} del {{protocol_date}} alle {{protocol_time}}</strong>,
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{tipo_inammissibilita}}.</p>
|
||||||
|
<p>Le motivazioni sono le seguenti: <strong>{{form_text}}</strong></p>
|
||||||
|
<p>Vi ricordiamo che i Beneficiari che hanno presentato richieste valutate non ammissibili entro 10 giorni dalla data di ricevimento della presente potranno finoltrare richiesta di chiarimenti e/o osservazioni alla scrivente Società ai sensi e per gli effetti dell''art.10 bis della L.241/1990 e s.m.i.</p>
|
||||||
|
<p>Distinti Saluti,</p>
|
||||||
|
<p><strong>{{email_signature}}</strong></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>'
|
||||||
|
WHERE email_scenario='APPLICATION_REJECTED'
|
||||||
|
AND hub_id IS NULL;
|
||||||
|
|
||||||
|
|
||||||
|
-- 7
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET html_content='<html>
|
||||||
|
<body style="font-family: Arial, sans-serif; color: #000; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p><strong>PROMEMORIA PER LA PRESENTAZIONE DELL''Soccorso Istruttorio</strong></p>
|
||||||
|
<p>Buongiorno,</p>
|
||||||
|
<p>Questo è un promemoria per completare la presentazione dell''Soccorso Istruttorio entro il termine specificato. Di seguito i dettagli:</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Amendment ID:</strong> {{amendment_id}}</li>
|
||||||
|
<li><strong>Data di Scadenza:</strong> {{amendment_due_date}}</li>
|
||||||
|
</ul>
|
||||||
|
<p>Si prega di assicurarsi che l''Soccorso Istruttorio venga presentato entro la data di scadenza per evitare ritardi. Inviare l''Soccorso Istruttorio tramite la piattaforma online <a href="{{platform_link}}">{{platform_link}}</a> </p>
|
||||||
|
<p>Distinti saluti,</p>
|
||||||
|
<p><strong>{{email_signature}}</strong></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>'
|
||||||
|
WHERE email_scenario='APPLICATION_AMENDMENT_REMINDER';
|
||||||
|
|
||||||
|
-- 8
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name='Welcome Email for New Confidi User'
|
||||||
|
WHERE email_scenario='USER_CREATION' AND type='USER_ONBOARDING_CONFIDI';
|
||||||
|
|
||||||
|
-- 9
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name='Password Reset Link Email (Italian)'
|
||||||
|
WHERE email_scenario='PASSWORD_RESET_REQUEST';
|
||||||
|
|
||||||
|
-- 10 (hub specific)
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET html_content='<html>
|
||||||
|
<body style="font-family: Arial, sans-serif; color: #000; line-height: 1.6;">
|
||||||
|
<div style="padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;">
|
||||||
|
<p><strong>RICHIESTA INTEGRAZIONE DOCUMENTALE</strong></p>
|
||||||
|
<p>Buongiorno,</p>
|
||||||
|
<p>In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Bando
|
||||||
|
"<strong>{{call_name}}</strong>" di cui al <strong>Protocollo n. {{protocol_number}} del
|
||||||
|
{{protocol_date}} e {{protocol_time}}</strong>, alla luce dell''attività istruttoria svolta,
|
||||||
|
segnaliamo quanto segue:
|
||||||
|
</p>
|
||||||
|
{{note}}
|
||||||
|
<p>Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione caricandola all''interno dello sportello
|
||||||
|
online <a href="{{platform_link}}">{{platform_link}}</a> entro e <strong>non oltre {{response_days}} giorni</strong> dal ricevimento della presente comunicazione,
|
||||||
|
precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.
|
||||||
|
</p>
|
||||||
|
<p>La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.
|
||||||
|
</p>
|
||||||
|
<p>Distinti Saluti,</p>
|
||||||
|
<p><strong>{{email_signature}}</strong></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>'
|
||||||
|
WHERE email_scenario='APPLICATION_AMENDMENT_REQUESTED' AND hub_id=2;
|
||||||
|
|
||||||
|
-- 11 (hub specific reject)
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET subject='BANDO {{call_name}} – Esito negativo istruttoria di ammissibilità {{company_name}}'
|
||||||
|
WHERE email_scenario='APPLICATION_REJECTED' AND hub_id=2;
|
||||||
|
|
||||||
|
-- 12
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name='Welcome Email for New Bandi User'
|
||||||
|
WHERE email_scenario='USER_CREATION' AND type='USER_ONBOARDING_BANDI';
|
||||||
|
|
||||||
|
-- 13
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET template_name='Application submission failure notification'
|
||||||
|
WHERE email_scenario='APPLICATION_SUBMISSION_FAILURE';
|
||||||
|
|
||||||
|
-- 14
|
||||||
|
UPDATE gepafin_schema.system_email_template
|
||||||
|
SET subject='BANDO – "{{call_name}}" – Esito negativo della valutazione tecnica – {{company_name}}'
|
||||||
|
WHERE email_scenario='APPLICATION_TECHNICAL_EVALUATION_REJECTED';
|
||||||
|
|
||||||
|
-- 15
|
||||||
|
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';
|
||||||
|
|
||||||
|
-- 16
|
||||||
|
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';
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user