Done ticket GEPAFINBE-6326 Ranking Management
This commit is contained in:
@@ -108,6 +108,12 @@ public class GepafinConstant {
|
||||
public static final String INVALID_STATUS_CHANGE_FROM_PUBLISH_TO_DRAFT = "invalid.status.change.from.publish.to.draft";
|
||||
public static final String STATUS_CANNOT_BE_CHANGED = "status.cannot.be.changed";
|
||||
public static final String PUBLISHED_CALL_NOT_UPDATE = "published.call.not.update";
|
||||
public static final String PUBLISHED_CALL_STEP1_ONLY_RANKING_TYPE_ALLOWED = "published.call.step1.only.ranking.type.allowed";
|
||||
public static final String CALL_RANKING_TYPE_UPDATED_SUCCESSFULLY = "call.ranking.type.updated.successfully";
|
||||
public static final String APPLICATION_RANKING_ACTION_UPDATED_SUCCESSFULLY = "application.ranking.action.updated.successfully";
|
||||
public static final String APPLICATION_RANKING_FETCHED_SUCCESSFULLY = "application.ranking.fetched.successfully";
|
||||
public static final String CALL_MUST_BE_CLOSED_FOR_RANKING_ACTION = "call.must.be.closed.for.ranking.action";
|
||||
public static final String APPLICATION_RANKING_ACTION_INVALID = "application.ranking.action.invalid";
|
||||
public static final String INVALID_USER = "invalid_user";
|
||||
public static final String FLOW_CREATED_SUCCESSFULLY = "flow.created.successfully";
|
||||
public static final String FLOW_FETCHED_SUCCESSFULLY = "flow.fetched.successfully";
|
||||
|
||||
@@ -72,6 +72,7 @@ import java.time.OffsetDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -215,6 +216,9 @@ public class ApplicationDao {
|
||||
@Autowired
|
||||
private ApplicationFormViewRepository applicationFormViewRepository;
|
||||
|
||||
@Autowired
|
||||
private ApplicationRankingViewRepository applicationRankingViewRepository;
|
||||
|
||||
@Autowired
|
||||
private FormRepository formRepository;
|
||||
|
||||
@@ -509,6 +513,11 @@ public class ApplicationDao {
|
||||
responseBean.setDateAccepted(applicationEntity.getDateAccepted());
|
||||
responseBean.setDateRejected(applicationEntity.getDateRejected());
|
||||
responseBean.setNdg(applicationEntity.getNdg());
|
||||
if (applicationEntity.getRankingActionType() != null && !applicationEntity.getRankingActionType().isBlank()) {
|
||||
responseBean.setRankingActionType(
|
||||
ApplicationRankingActionTypeEnum.valueOf(applicationEntity.getRankingActionType().trim()));
|
||||
}
|
||||
responseBean.setManualRanking(applicationEntity.getManualRanking());
|
||||
return responseBean;
|
||||
}
|
||||
|
||||
@@ -1152,6 +1161,114 @@ public class ApplicationDao {
|
||||
return getApplicationResponse(applicationEntity);
|
||||
}
|
||||
|
||||
public ApplicationResponse updateApplicationRankingAction(HttpServletRequest request, Long applicationId,
|
||||
ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking) {
|
||||
ApplicationEntity applicationEntity = validateApplication(applicationId);
|
||||
validator.validateRequest(request, RoleStatusEnum.ROLE_SUPER_ADMIN);
|
||||
validateCallClosedForRankingAction(applicationEntity.getCall());
|
||||
if (!ApplicationStatusTypeEnum.APPROVED.getValue().equals(applicationEntity.getStatus())) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST,
|
||||
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
|
||||
}
|
||||
validateRankingActionRequest(rankingActionType, manualRanking);
|
||||
ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity);
|
||||
if (rankingActionType == null) {
|
||||
applicationEntity.setRankingActionType(null);
|
||||
applicationEntity.setManualRanking(null);
|
||||
} else {
|
||||
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION
|
||||
&& applicationRepository.existsByCallIdAndManualRankingAndIsDeletedFalseAndIdNot(
|
||||
applicationEntity.getCall().getId(), manualRanking, applicationEntity.getId())) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST,
|
||||
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
|
||||
}
|
||||
applicationEntity.setRankingActionType(rankingActionType.getValue());
|
||||
applicationEntity.setManualRanking(
|
||||
rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION ? manualRanking : null);
|
||||
}
|
||||
applicationEntity = applicationRepository.save(applicationEntity);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE)
|
||||
.oldData(oldApplicationEntity).newData(applicationEntity).build());
|
||||
return getApplicationResponse(applicationEntity);
|
||||
}
|
||||
|
||||
public CallRankingSummaryResponse getApplicationRanking(Long callId,
|
||||
List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
|
||||
CallEntity call = callRepository.findById(callId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
|
||||
Translator.toLocale(GepafinConstant.CALL_NOT_FOUND)));
|
||||
|
||||
Specification<ApplicationRankingView> spec = (root, query, criteriaBuilder) -> {
|
||||
List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();
|
||||
predicates.add(criteriaBuilder.equal(root.get("callId"), callId));
|
||||
if (rankingActionTypes != null && !rankingActionTypes.isEmpty()) {
|
||||
List<String> types = rankingActionTypes.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(ApplicationRankingActionTypeEnum::getValue)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (!types.isEmpty()) {
|
||||
predicates.add(root.get("rankingActionType").in(types));
|
||||
}
|
||||
}
|
||||
query.orderBy(criteriaBuilder.asc(root.get("rank")));
|
||||
return criteriaBuilder.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
|
||||
};
|
||||
List<ApplicationRankingView> rows = applicationRankingViewRepository.findAll(spec);
|
||||
|
||||
CallRankingSummaryResponse summary = new CallRankingSummaryResponse();
|
||||
summary.setCallId(call.getId());
|
||||
summary.setCallName(call.getName());
|
||||
summary.setAmount(call.getAmount());
|
||||
if (call.getRankingType() != null && !call.getRankingType().isBlank()) {
|
||||
summary.setRankingType(CallRankingTypeEnum.valueOf(call.getRankingType().trim()));
|
||||
}
|
||||
summary.setApplications(rows.stream()
|
||||
.map(this::convertToApplicationRankingResponse)
|
||||
.collect(Collectors.toList()));
|
||||
return summary;
|
||||
}
|
||||
|
||||
private ApplicationRankingResponse convertToApplicationRankingResponse(ApplicationRankingView entity) {
|
||||
ApplicationRankingResponse response = new ApplicationRankingResponse();
|
||||
response.setApplicationId(entity.getApplicationId());
|
||||
response.setCallId(entity.getCallId());
|
||||
response.setUserId(entity.getUserId());
|
||||
response.setStatus(entity.getStatus());
|
||||
response.setSubmissionDate(entity.getSubmissionDate());
|
||||
response.setProtocolDatetime(entity.getProtocolDatetime());
|
||||
response.setProtocolNumber(entity.getProtocolNumber());
|
||||
response.setNdg(entity.getNdg());
|
||||
response.setAmountAccepted(entity.getAmountAccepted());
|
||||
response.setPecEmail(entity.getPecEmail());
|
||||
response.setManualRanking(entity.getManualRanking());
|
||||
response.setRank(entity.getRank());
|
||||
response.setTotalScore(entity.getTotalScore());
|
||||
if (entity.getRankingActionType() != null && !entity.getRankingActionType().isBlank()) {
|
||||
response.setRankingActionType(ApplicationRankingActionTypeEnum.valueOf(entity.getRankingActionType().trim()));
|
||||
}
|
||||
if (entity.getRankingType() != null && !entity.getRankingType().isBlank()) {
|
||||
response.setRankingType(CallRankingTypeEnum.valueOf(entity.getRankingType().trim()));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private void validateCallClosedForRankingAction(CallEntity callEntity) {
|
||||
if (!CallStatusEnum.EXPIRED.getValue().equals(callEntity.getStatus())) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST,
|
||||
Translator.toLocale(GepafinConstant.CALL_MUST_BE_CLOSED_FOR_RANKING_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateRankingActionRequest(ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking) {
|
||||
if (rankingActionType == ApplicationRankingActionTypeEnum.REPOSITION
|
||||
&& (manualRanking == null || manualRanking <= 0)) {
|
||||
throw new CustomValidationException(Status.BAD_REQUEST,
|
||||
Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all non-terminal amendments, the application evaluation (if any), and the assigned application row to CLOSE.
|
||||
*/
|
||||
|
||||
@@ -228,6 +228,9 @@ public class CallDao {
|
||||
if (createCallRequest.getAllowMultipleApplications() != null) {
|
||||
callEntity.setAllowMultipleApplications(createCallRequest.getAllowMultipleApplications());
|
||||
}
|
||||
if (createCallRequest.getRankingType() != null) {
|
||||
callEntity.setRankingType(createCallRequest.getRankingType().getValue());
|
||||
}
|
||||
callEntity = callRepository.save(callEntity);
|
||||
log.info("CallEntity saved with ID: {} for call name: '{}'", callEntity.getId(), callEntity.getName());
|
||||
|
||||
@@ -418,6 +421,9 @@ public class CallDao {
|
||||
createCallResponseBean.setEmail(callEntity.getEmail());
|
||||
createCallResponseBean.setCreatedDate(callEntity.getCreatedDate());
|
||||
createCallResponseBean.setUpdatedDate(callEntity.getUpdatedDate());
|
||||
if (callEntity.getRankingType() != null && !callEntity.getRankingType().isBlank()) {
|
||||
createCallResponseBean.setRankingType(CallRankingTypeEnum.valueOf(callEntity.getRankingType().trim()));
|
||||
}
|
||||
return createCallResponseBean;
|
||||
}
|
||||
|
||||
@@ -583,6 +589,41 @@ public class CallDao {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNonRankingStep1Field(UpdateCallRequestStep1 r) {
|
||||
return r.getName() != null
|
||||
|| r.getDescriptionShort() != null
|
||||
|| r.getDescriptionLong() != null
|
||||
|| r.getDates() != null
|
||||
|| r.getAmount() != null
|
||||
|| r.getAmountMax() != null
|
||||
|| r.getAimedTo() != null
|
||||
|| r.getDocumentationRequested() != null
|
||||
|| r.getAmountMin() != null
|
||||
|| r.getEmail() != null
|
||||
|| r.getPhoneNumber() != null
|
||||
|| r.getStartTime() != null
|
||||
|| r.getEndTime() != null
|
||||
|| r.getConfidi() != null
|
||||
|| r.getAllowMultipleApplications() != null
|
||||
|| r.getFaq() != null
|
||||
|| r.getNumberOfCheck() != null
|
||||
|| r.getAppointmentTemplateId() != null
|
||||
|| r.getEvaluationVersion() != null;
|
||||
}
|
||||
|
||||
private CallResponse updatePublishedCallStep1RankingTypeOnly(HttpServletRequest request, CallEntity callEntity,
|
||||
CallEntity oldCallEntity, UpdateCallRequestStep1 updateCallRequest) {
|
||||
setIfUpdated(callEntity::getRankingType, callEntity::setRankingType,
|
||||
updateCallRequest.getRankingType() != null ? updateCallRequest.getRankingType().getValue() : null);
|
||||
callEntity = callRepository.save(callEntity);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCallEntity).newData(callEntity).build());
|
||||
CallResponse response = getCallResponseBean(callEntity);
|
||||
response.setCurrentStep(GepafinConstant.STEP_1);
|
||||
log.info("Published call step 1: ranking type only | callId={}", callEntity.getId());
|
||||
return response;
|
||||
}
|
||||
|
||||
public void isValidDateRange(UpdateCallRequestStep1 updateCallRequest, CallEntity callEntity) {
|
||||
List<LocalDateTime> dates = updateCallRequest.getDates();
|
||||
|
||||
@@ -615,6 +656,18 @@ public class CallDao {
|
||||
public CallResponse updateCallStep1(HttpServletRequest request,CallEntity callEntity, UpdateCallRequestStep1 updateCallRequest, UserEntity userEntity) {
|
||||
log.info("Updating Call ID: {}, by User ID: {}", callEntity.getId(),userEntity.getId() );
|
||||
CallEntity oldCallEntity = Utils.getClonedEntityForData(callEntity);
|
||||
if (CallStatusEnum.PUBLISH.getValue().equals(callEntity.getStatus())) {
|
||||
if (hasNonRankingStep1Field(updateCallRequest)) {
|
||||
throw new CustomValidationException(Status.VALIDATION_ERROR,
|
||||
Translator.toLocale(GepafinConstant.PUBLISHED_CALL_STEP1_ONLY_RANKING_TYPE_ALLOWED));
|
||||
}
|
||||
if (updateCallRequest.getRankingType() != null) {
|
||||
return updatePublishedCallStep1RankingTypeOnly(request, callEntity, oldCallEntity, updateCallRequest);
|
||||
}
|
||||
CallResponse unchanged = getCallResponseBean(callEntity);
|
||||
unchanged.setCurrentStep(GepafinConstant.STEP_1);
|
||||
return unchanged;
|
||||
}
|
||||
isValidDateRange(updateCallRequest, callEntity);
|
||||
setIfUpdated(callEntity::getName, callEntity::setName, updateCallRequest.getName());
|
||||
setIfUpdated(callEntity::getDescriptionShort, callEntity::setDescriptionShort,
|
||||
@@ -648,8 +701,6 @@ public class CallDao {
|
||||
|
||||
if (!requestEndTime.equals(storedEndTime)) {
|
||||
setIfUpdated(callEntity::getEndTime, callEntity::setEndTime, DateTimeUtil.parseTime(updateCallRequest.getEndTime()));
|
||||
// callEntity.setStatus(CallStatusEnum.PUBLISH.getValue());
|
||||
// callRepository.save(callEntity);
|
||||
isEndTimeUpdated = true;
|
||||
}
|
||||
}
|
||||
@@ -708,10 +759,15 @@ public class CallDao {
|
||||
setIfUpdated(callEntity::getPhoneNumber, callEntity::setPhoneNumber, updateCallRequest.getPhoneNumber());
|
||||
setIfUpdated(callEntity::getStartTime, callEntity::setStartTime, DateTimeUtil.parseTime(updateCallRequest.getStartTime()));
|
||||
setIfUpdated(callEntity::getConfidi, callEntity::setConfidi, updateCallRequest.getConfidi());
|
||||
setIfUpdated(callEntity::getEvaluationVersion, callEntity::setEvaluationVersion, updateCallRequest.getEvaluationVersion().getValue());
|
||||
if (updateCallRequest.getEvaluationVersion() != null) {
|
||||
setIfUpdated(callEntity::getEvaluationVersion, callEntity::setEvaluationVersion,
|
||||
updateCallRequest.getEvaluationVersion().getValue());
|
||||
}
|
||||
setIfUpdated(callEntity::getNumberOfCheck, callEntity::setNumberOfCheck, updateCallRequest.getNumberOfCheck());
|
||||
setIfUpdated(callEntity::getAppointmentTemplateId, callEntity::setAppointmentTemplateId, updateCallRequest.getAppointmentTemplateId());
|
||||
setIfUpdated(callEntity::getAllowMultipleApplications, callEntity::setAllowMultipleApplications, updateCallRequest.getAllowMultipleApplications());
|
||||
setIfUpdated(callEntity::getRankingType, callEntity::setRankingType,
|
||||
updateCallRequest.getRankingType() != null ? updateCallRequest.getRankingType().getValue() : null);
|
||||
callEntity = callRepository.save(callEntity);
|
||||
|
||||
/** This code is responsible for adding a version history log for the "update call step 1" operation **/
|
||||
@@ -725,6 +781,15 @@ public class CallDao {
|
||||
return createCallResponseBean;
|
||||
}
|
||||
|
||||
public CallResponse updateCallRankingType(HttpServletRequest request, CallEntity callEntity, CallRankingTypeEnum rankingType) {
|
||||
CallEntity oldCallEntity = Utils.getClonedEntityForData(callEntity);
|
||||
callEntity.setRankingType(rankingType != null ? rankingType.getValue() : null);
|
||||
callEntity = callRepository.save(callEntity);
|
||||
loggingUtil.addVersionHistory(
|
||||
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCallEntity).newData(callEntity).build());
|
||||
return getCallResponseBean(callEntity);
|
||||
}
|
||||
|
||||
private void softDeleteFaq(FaqEntity faqEntity) {
|
||||
|
||||
FaqEntity oldFaqEntity = Utils.getClonedEntityForData(faqEntity);
|
||||
|
||||
@@ -90,4 +90,10 @@ public class ApplicationEntity extends BaseEntity {
|
||||
|
||||
@Column(name = "COMPANY_DOCUMENT")
|
||||
private String companyDocument;
|
||||
|
||||
@Column(name = "ranking_action_type")
|
||||
private String rankingActionType;
|
||||
|
||||
@Column(name = "manual_ranking")
|
||||
private Long manualRanking;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.gepafin.tendermanagement.entities;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.Immutable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Maps {@code application_ranking_view} (read-only).
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Immutable
|
||||
@Table(name = "application_ranking_view")
|
||||
public class ApplicationRankingView implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "application_id")
|
||||
private Long applicationId;
|
||||
|
||||
@Column(name = "listing_rank")
|
||||
private Long rank;
|
||||
|
||||
@Column(name = "call_id")
|
||||
private Long callId;
|
||||
|
||||
@Column(name = "ranking_action_type")
|
||||
private String rankingActionType;
|
||||
|
||||
@Column(name = "total_score")
|
||||
private BigDecimal totalScore;
|
||||
|
||||
@Column(name = "user_id")
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "status")
|
||||
private String status;
|
||||
|
||||
@Column(name = "submission_date")
|
||||
private LocalDateTime submissionDate;
|
||||
|
||||
@Column(name = "protocol_datetime")
|
||||
private LocalDateTime protocolDatetime;
|
||||
|
||||
@Column(name = "protocol_number")
|
||||
private Long protocolNumber;
|
||||
|
||||
@Column(name = "ndg")
|
||||
private String ndg;
|
||||
|
||||
@Column(name = "amount_accepted")
|
||||
private BigDecimal amountAccepted;
|
||||
|
||||
@Column(name = "pec_email")
|
||||
private String pecEmail;
|
||||
|
||||
@Column(name = "manual_ranking")
|
||||
private Long manualRanking;
|
||||
|
||||
@Column(name = "ranking_type")
|
||||
private String rankingType;
|
||||
}
|
||||
@@ -102,5 +102,8 @@ public class CallEntity extends BaseEntity {
|
||||
|
||||
@Column(name = "allow_multiple_applications")
|
||||
private Boolean allowMultipleApplications;
|
||||
|
||||
@Column(name = "ranking_type")
|
||||
private String rankingType;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.gepafin.tendermanagement.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum ApplicationRankingActionTypeEnum {
|
||||
|
||||
REMOVE("REMOVE"),
|
||||
REPOSITION("REPOSITION");
|
||||
|
||||
private final String value;
|
||||
|
||||
ApplicationRankingActionTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.gepafin.tendermanagement.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
public enum CallRankingTypeEnum {
|
||||
|
||||
SCORE("SCORE"),
|
||||
PROTOCOL_DATE_TIME("PROTOCOL_DATE_TIME");
|
||||
|
||||
private final String value;
|
||||
|
||||
CallRankingTypeEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -236,7 +236,10 @@ public enum UserActionContextEnum {
|
||||
REJECT_PEC_MAIL("REJECT_PEC_MAIL"),
|
||||
FETCH_EMAIL_LOG("FETCH_EMAIL_LOG"),
|
||||
FETCH_ALL_EMAIL_LOG("FETCH_ALL_EMAIL_LOG"),
|
||||
UPLOAD_COMPANY_DOCUMENT_TO_APPLICATION("UPLOAD_COMPANY_DOCUMENT_TO_APPLICATION");
|
||||
UPLOAD_COMPANY_DOCUMENT_TO_APPLICATION("UPLOAD_COMPANY_DOCUMENT_TO_APPLICATION"),
|
||||
UPDATE_CALL_RANKING_TYPE("UPDATE_CALL_RANKING_TYPE"),
|
||||
UPDATE_APPLICATION_RANKING_ACTION("UPDATE_APPLICATION_RANKING_ACTION"),
|
||||
GET_APPLICATION_RANKING("GET_APPLICATION_RANKING");
|
||||
|
||||
|
||||
private final String value;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package net.gepafin.tendermanagement.model.request;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
|
||||
@Data
|
||||
public class ApplicationRankingActionRequest {
|
||||
|
||||
private ApplicationRankingActionTypeEnum rankingActionType;
|
||||
|
||||
/** Required when {@code rankingActionType} is {@link ApplicationRankingActionTypeEnum#REPOSITION}. */
|
||||
private Long manualRanking;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
|
||||
@Data
|
||||
@@ -49,4 +50,6 @@ public class CreateCallRequestStep1 {
|
||||
private List<FaqReq> faq;
|
||||
|
||||
private EvaluationVersionEnum evaluationVersion;
|
||||
|
||||
private CallRankingTypeEnum rankingType;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
|
||||
@Data
|
||||
@@ -46,6 +47,8 @@ public class UpdateCallRequestStep1 {
|
||||
|
||||
private Long appointmentTemplateId;
|
||||
|
||||
private EvaluationVersionEnum evaluationVersion;
|
||||
private EvaluationVersionEnum evaluationVersion;
|
||||
|
||||
private CallRankingTypeEnum rankingType;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.gepafin.tendermanagement.model.response;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class ApplicationRankingResponse {
|
||||
|
||||
private Long rank;
|
||||
private Long applicationId;
|
||||
private Long callId;
|
||||
private ApplicationRankingActionTypeEnum rankingActionType;
|
||||
private BigDecimal totalScore;
|
||||
private Long userId;
|
||||
private String status;
|
||||
private LocalDateTime submissionDate;
|
||||
private LocalDateTime protocolDatetime;
|
||||
private Long protocolNumber;
|
||||
private String ndg;
|
||||
private BigDecimal amountAccepted;
|
||||
private String pecEmail;
|
||||
private Long manualRanking;
|
||||
private CallRankingTypeEnum rankingType;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.gepafin.tendermanagement.model.response;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
import net.gepafin.tendermanagement.model.response.ApplicationFormFieldResponseBean;
|
||||
|
||||
@@ -54,4 +55,8 @@ public class ApplicationResponse{
|
||||
|
||||
private String ndg;
|
||||
|
||||
private ApplicationRankingActionTypeEnum rankingActionType;
|
||||
|
||||
private Long manualRanking;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.gepafin.tendermanagement.model.response;
|
||||
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Call-level ranking payload: tender info plus ordered ranked applications. */
|
||||
@Data
|
||||
public class CallRankingSummaryResponse {
|
||||
|
||||
private Long callId;
|
||||
private String callName;
|
||||
private BigDecimal amount;
|
||||
private CallRankingTypeEnum rankingType;
|
||||
private List<ApplicationRankingResponse> applications;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import lombok.Data;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallStatusEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
import net.gepafin.tendermanagement.util.DynamicLocalTimeSerializer;
|
||||
@@ -83,6 +84,8 @@ public class CallResponse {
|
||||
private Long preferredCallId;
|
||||
|
||||
private EvaluationVersionEnum evaluationVersion;
|
||||
|
||||
private CallRankingTypeEnum rankingType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.gepafin.tendermanagement.repositories;
|
||||
|
||||
import net.gepafin.tendermanagement.entities.ApplicationRankingView;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ApplicationRankingViewRepository extends JpaRepository<ApplicationRankingView, Long>,
|
||||
JpaSpecificationExecutor<ApplicationRankingView> {
|
||||
}
|
||||
@@ -183,5 +183,6 @@ public interface ApplicationRepository extends JpaRepository<ApplicationEntity,
|
||||
|
||||
public List<ApplicationEntity> findByCallIdAndIsDeletedFalseAndStatusIn(Long callId,List<String> status);
|
||||
|
||||
boolean existsByCallIdAndManualRankingAndIsDeletedFalseAndIdNot(Long callId, Long manualRanking, Long id);
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.gepafin.tendermanagement.entities.ApplicationEntity;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationPageableRequestBean;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.FormActionEnum;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
|
||||
@@ -57,4 +58,10 @@ public interface ApplicationService {
|
||||
public byte[] downloadRankingCsv(HttpServletRequest request, Long callId);
|
||||
|
||||
public void uploadCompanyDocumentsToApplication(HttpServletRequest request, Long applicationId, List<Long> companyDocumentIds);
|
||||
|
||||
ApplicationResponse updateApplicationRankingAction(HttpServletRequest request, Long applicationId,
|
||||
ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking);
|
||||
|
||||
CallRankingSummaryResponse getApplicationRanking(HttpServletRequest request, Long callId,
|
||||
List<ApplicationRankingActionTypeEnum> rankingActionTypes);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import net.gepafin.tendermanagement.entities.CallEntity;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallStatusEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
import net.gepafin.tendermanagement.model.request.*;
|
||||
@@ -37,4 +38,6 @@ public interface CallService {
|
||||
|
||||
CallResponse createCallStep2EvaluationV2(HttpServletRequest request, Long callId, CreateCallRequestStep2EvaluationV2 createCallRequest);
|
||||
|
||||
CallResponse updateCallRankingType(HttpServletRequest request, Long callId, CallRankingTypeEnum rankingType);
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.gepafin.tendermanagement.entities.CompanyEntity;
|
||||
import net.gepafin.tendermanagement.entities.UserEntity;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationPageableRequestBean;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.FormActionEnum;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
|
||||
@@ -195,4 +196,20 @@ public class ApplicationServiceImpl implements ApplicationService {
|
||||
UserEntity userEntity = validator.validateUser(request);
|
||||
applicationDao.uploadCompanyDocumentsToApplication(applicationId,companyDocumentIds,userEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ApplicationResponse updateApplicationRankingAction(HttpServletRequest request, Long applicationId,
|
||||
ApplicationRankingActionTypeEnum rankingActionType, Long manualRanking) {
|
||||
return applicationDao.updateApplicationRankingAction(request, applicationId, rankingActionType, manualRanking);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public CallRankingSummaryResponse getApplicationRanking(HttpServletRequest request, Long callId,
|
||||
List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
|
||||
validator.validateUser(request);
|
||||
validator.validateSuperAdminOrDirector();
|
||||
return applicationDao.getApplicationRanking(callId, rankingActionTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package net.gepafin.tendermanagement.service.impl;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import net.gepafin.tendermanagement.config.Translator;
|
||||
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||
import net.gepafin.tendermanagement.dao.CallDao;
|
||||
import net.gepafin.tendermanagement.entities.CallEntity;
|
||||
import net.gepafin.tendermanagement.entities.UserEntity;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallStatusEnum;
|
||||
import net.gepafin.tendermanagement.enums.EvaluationVersionEnum;
|
||||
import net.gepafin.tendermanagement.model.request.*;
|
||||
@@ -12,6 +15,8 @@ import net.gepafin.tendermanagement.model.response.CallResponse;
|
||||
import net.gepafin.tendermanagement.model.response.PageableResponseBean;
|
||||
import net.gepafin.tendermanagement.service.CallService;
|
||||
import net.gepafin.tendermanagement.util.Validator;
|
||||
import net.gepafin.tendermanagement.web.rest.api.errors.ForbiddenAccessException;
|
||||
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -116,4 +121,15 @@ public class CallServiceImpl implements CallService {
|
||||
CallEntity call = validator.validateUserWithCall(user, callId);
|
||||
return callDao.createCallStep2EvaluationV2(call, createCallRequest, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CallResponse updateCallRankingType(HttpServletRequest request, Long callId, CallRankingTypeEnum rankingType) {
|
||||
validator.validateUser(request);
|
||||
if (Boolean.FALSE.equals(validator.checkIsSuperAdmin())) {
|
||||
throw new ForbiddenAccessException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PERMISSION_DENIED));
|
||||
}
|
||||
CallEntity call = callDao.validateCall(callId);
|
||||
return callDao.updateCallRankingType(request, call, rankingType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.gepafin.tendermanagement.web.rest.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRankingActionRequest;
|
||||
import net.gepafin.tendermanagement.model.response.CallRankingSummaryResponse;
|
||||
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
|
||||
import net.gepafin.tendermanagement.model.response.CallResponse;
|
||||
import net.gepafin.tendermanagement.model.util.Response;
|
||||
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Validated
|
||||
public interface RankingApi {
|
||||
|
||||
@Operation(summary = "API to update call ranking type",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
|
||||
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
|
||||
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))
|
||||
})
|
||||
@PutMapping(value = "/call/{callId}/type", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN')")
|
||||
ResponseEntity<Response<CallResponse>> updateCallRankingType(HttpServletRequest request,
|
||||
@PathVariable("callId") Long callId,
|
||||
@RequestParam("rankingType") CallRankingTypeEnum rankingType);
|
||||
|
||||
@Operation(summary = "API to update application ranking action type in application",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
|
||||
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
|
||||
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))
|
||||
})
|
||||
@PatchMapping(value = "/application/{applicationId}/action", produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN')")
|
||||
ResponseEntity<Response<ApplicationResponse>> updateApplicationRankingAction(HttpServletRequest request,
|
||||
@PathVariable("applicationId") Long applicationId,
|
||||
@Valid @RequestBody ApplicationRankingActionRequest rankingActionRequest);
|
||||
|
||||
@Operation(summary = "API to get ranking list with callId",
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
|
||||
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
|
||||
@io.swagger.v3.oas.annotations.media.ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)}))
|
||||
})
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN') || hasRole('ROLE_DIRECTOR')")
|
||||
ResponseEntity<Response<CallRankingSummaryResponse>> getApplicationRanking(HttpServletRequest request,
|
||||
@Parameter(description = "Call id", required = true)
|
||||
@RequestParam("callId") Long callId,
|
||||
@Parameter(description = "ranking action types", required = false,
|
||||
array = @ArraySchema(schema = @Schema(implementation = ApplicationRankingActionTypeEnum.class)))
|
||||
@RequestParam(value = "rankingActionType", required = false) List<ApplicationRankingActionTypeEnum> rankingActionTypes);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.gepafin.tendermanagement.web.rest.api.impl;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import net.gepafin.tendermanagement.config.Translator;
|
||||
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||
import net.gepafin.tendermanagement.enums.ApplicationRankingActionTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.CallRankingTypeEnum;
|
||||
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
|
||||
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
|
||||
import net.gepafin.tendermanagement.model.request.ApplicationRankingActionRequest;
|
||||
import net.gepafin.tendermanagement.model.request.UserActionRequest;
|
||||
import net.gepafin.tendermanagement.model.response.CallRankingSummaryResponse;
|
||||
import net.gepafin.tendermanagement.model.response.ApplicationResponse;
|
||||
import net.gepafin.tendermanagement.model.response.CallResponse;
|
||||
import net.gepafin.tendermanagement.model.util.Response;
|
||||
import net.gepafin.tendermanagement.service.ApplicationService;
|
||||
import net.gepafin.tendermanagement.service.CallService;
|
||||
import net.gepafin.tendermanagement.util.LoggingUtil;
|
||||
import net.gepafin.tendermanagement.web.rest.api.RankingApi;
|
||||
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/v1/ranking")
|
||||
public class RankingApiController implements RankingApi {
|
||||
|
||||
@Autowired
|
||||
private CallService callService;
|
||||
|
||||
@Autowired
|
||||
private ApplicationService applicationService;
|
||||
|
||||
@Autowired
|
||||
private LoggingUtil loggingUtil;
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Response<CallResponse>> updateCallRankingType(HttpServletRequest request, Long callId,
|
||||
CallRankingTypeEnum rankingType) {
|
||||
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE)
|
||||
.actionContext(UserActionContextEnum.UPDATE_CALL_RANKING_TYPE).build());
|
||||
CallResponse updated = callService.updateCallRankingType(request, callId, rankingType);
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.body(new Response<>(updated, Status.SUCCESS, Translator.toLocale(GepafinConstant.CALL_RANKING_TYPE_UPDATED_SUCCESSFULLY)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Response<ApplicationResponse>> updateApplicationRankingAction(HttpServletRequest request,
|
||||
Long applicationId, @Valid @RequestBody ApplicationRankingActionRequest rankingActionRequest) {
|
||||
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE)
|
||||
.actionContext(UserActionContextEnum.UPDATE_APPLICATION_RANKING_ACTION).build());
|
||||
ApplicationResponse body = applicationService.updateApplicationRankingAction(request, applicationId,
|
||||
rankingActionRequest.getRankingActionType(), rankingActionRequest.getManualRanking());
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.body(new Response<>(body, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_RANKING_ACTION_UPDATED_SUCCESSFULLY)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Response<CallRankingSummaryResponse>> getApplicationRanking(HttpServletRequest request,
|
||||
Long callId, List<ApplicationRankingActionTypeEnum> rankingActionTypes) {
|
||||
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW)
|
||||
.actionContext(UserActionContextEnum.GET_APPLICATION_RANKING).build());
|
||||
CallRankingSummaryResponse ranking = applicationService.getApplicationRanking(request, callId, rankingActionTypes);
|
||||
return ResponseEntity.status(HttpStatus.OK)
|
||||
.body(new Response<>(ranking, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_RANKING_FETCHED_SUCCESSFULLY)));
|
||||
}
|
||||
}
|
||||
@@ -3223,4 +3223,22 @@
|
||||
<changeSet id="25-03-2026_NK_170536" author="Rajesh Khore">
|
||||
<sqlFile dbms="postgresql" path="db/dump/insert_form_field_25_03_2026.sql"/>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="07-04-2026_ranking_columns" author="GEPAFIN">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<columnExists tableName="call" columnName="ranking_type"/>
|
||||
</not>
|
||||
</preConditions>
|
||||
<addColumn tableName="call">
|
||||
<column name="ranking_type" type="VARCHAR(64)"/>
|
||||
</addColumn>
|
||||
<addColumn tableName="application">
|
||||
<column name="ranking_action_type" type="VARCHAR(64)"/>
|
||||
<column name="manual_ranking" type="BIGINT"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
<changeSet id="07-04-2026_RK_145623" author="Rajesh Khore">
|
||||
<sqlFile path="db/dump/create_application_ranking_view_07_04_2026.sql"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
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
|
||||
),
|
||||
manual_repositioned AS (
|
||||
SELECT *
|
||||
FROM natural_ranked
|
||||
WHERE COALESCE(ranking_action_type, '') = 'REPOSITION'
|
||||
AND manual_ranking IS NOT NULL
|
||||
),
|
||||
non_manual AS (
|
||||
SELECT *
|
||||
FROM natural_ranked
|
||||
WHERE COALESCE(ranking_action_type, '') <> 'REPOSITION'
|
||||
OR manual_ranking IS NULL
|
||||
),
|
||||
manual_slots AS (
|
||||
SELECT
|
||||
mr.call_id,
|
||||
mr.application_id,
|
||||
mr.company_id,
|
||||
mr.user_id,
|
||||
mr.status,
|
||||
mr.submission_date,
|
||||
mr.amount_requested,
|
||||
mr.amount_accepted,
|
||||
mr.amount,
|
||||
mr.ranking_type,
|
||||
mr.protocol_datetime,
|
||||
mr.protocol_number,
|
||||
mr.total_score,
|
||||
mr.ranking_action_type,
|
||||
mr.manual_ranking,
|
||||
mr.ndg,
|
||||
mr.pec_email,
|
||||
mr.natural_rank,
|
||||
mr.manual_ranking AS effective_rank_slot
|
||||
FROM manual_repositioned mr
|
||||
),
|
||||
non_manual_shifted AS (
|
||||
SELECT
|
||||
nm.call_id,
|
||||
nm.application_id,
|
||||
nm.company_id,
|
||||
nm.user_id,
|
||||
nm.status,
|
||||
nm.submission_date,
|
||||
nm.amount_requested,
|
||||
nm.amount_accepted,
|
||||
nm.amount,
|
||||
nm.ranking_type,
|
||||
nm.protocol_datetime,
|
||||
nm.protocol_number,
|
||||
nm.total_score,
|
||||
nm.ranking_action_type,
|
||||
nm.manual_ranking,
|
||||
nm.ndg,
|
||||
nm.pec_email,
|
||||
nm.natural_rank,
|
||||
nm.natural_rank
|
||||
+ COALESCE((
|
||||
SELECT COUNT(*)::bigint
|
||||
FROM manual_repositioned mr
|
||||
WHERE mr.call_id = nm.call_id
|
||||
AND mr.manual_ranking <= nm.natural_rank
|
||||
), 0) AS effective_rank_slot
|
||||
FROM non_manual nm
|
||||
),
|
||||
combined AS (
|
||||
SELECT * FROM manual_slots
|
||||
UNION ALL
|
||||
SELECT * FROM non_manual_shifted
|
||||
),
|
||||
max_slot_by_call AS (
|
||||
SELECT call_id, MAX(effective_rank_slot) AS max_slot
|
||||
FROM combined
|
||||
GROUP BY call_id
|
||||
),
|
||||
remove_placed AS (
|
||||
SELECT
|
||||
ra.call_id,
|
||||
ra.application_id,
|
||||
ra.company_id,
|
||||
ra.user_id,
|
||||
ra.status,
|
||||
ra.submission_date,
|
||||
ra.amount_requested,
|
||||
ra.amount_accepted,
|
||||
ra.amount,
|
||||
ra.ranking_type,
|
||||
ra.protocol_datetime,
|
||||
ra.protocol_number,
|
||||
ra.total_score,
|
||||
ra.ranking_action_type,
|
||||
ra.manual_ranking,
|
||||
ra.ndg,
|
||||
ra.pec_email,
|
||||
NULL::bigint AS natural_rank,
|
||||
COALESCE(ms.max_slot, 0)
|
||||
+ ROW_NUMBER() OVER (
|
||||
PARTITION BY ra.call_id
|
||||
ORDER BY ra.protocol_datetime ASC NULLS LAST, ra.application_id
|
||||
) AS effective_rank_slot
|
||||
FROM remove_apps ra
|
||||
LEFT JOIN max_slot_by_call ms ON ms.call_id = ra.call_id
|
||||
),
|
||||
final_rows AS (
|
||||
SELECT * FROM combined
|
||||
UNION ALL
|
||||
SELECT * FROM remove_placed
|
||||
)
|
||||
SELECT
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY fr.call_id
|
||||
ORDER BY fr.effective_rank_slot, fr.protocol_datetime ASC NULLS LAST, fr.application_id
|
||||
) AS listing_rank,
|
||||
fr.application_id,
|
||||
fr.call_id,
|
||||
fr.ranking_action_type,
|
||||
fr.total_score,
|
||||
fr.user_id,
|
||||
fr.status,
|
||||
fr.submission_date,
|
||||
fr.protocol_datetime,
|
||||
fr.protocol_number,
|
||||
fr.ndg,
|
||||
fr.amount_accepted,
|
||||
fr.pec_email,
|
||||
fr.manual_ranking,
|
||||
fr.ranking_type
|
||||
FROM final_rows fr;
|
||||
@@ -61,6 +61,12 @@ status.same.error=Status is already set.
|
||||
invalid.status.change.from.draft=Status cannot be changed to READY_TO_PUBLISH or PUBLISH from DRAFT.
|
||||
status.cannot.be.changed=Status cannot be changed.
|
||||
published.call.not.update=Published call cannot be updated.
|
||||
published.call.step1.only.ranking.type.allowed=For a published call, this step accepts only ranking type.
|
||||
call.ranking.type.updated.successfully=Call ranking type updated successfully.
|
||||
application.ranking.action.updated.successfully=Application ranking action updated successfully.
|
||||
application.ranking.fetched.successfully=Application ranking fetched successfully.
|
||||
call.must.be.closed.for.ranking.action=Ranking action is allowed only when the call is closed.
|
||||
application.ranking.action.invalid=Invalid application ranking action request.
|
||||
invalid.status.change.from.publish=Status cannot be changed to READY_TO_PUBLISH from PUBLISH.
|
||||
invalid.status.change.from.publish.to.draft=Status cannot be changed to DRAFT from PUBLISH as Applications are already created for this CALL.
|
||||
validation.table.message=Data for field {0} is not present.
|
||||
|
||||
@@ -61,6 +61,12 @@ status.same.error=Lo stato ? gi? impostato.
|
||||
invalid.status.change.from.draft=Lo stato non pu? essere cambiato in READY_TO_PUBLISH o PUBLISH da DRAFT.
|
||||
status.cannot.be.changed=Lo stato non pu? essere cambiato.
|
||||
published.call.not.update=Il bando pubblicato non pu? essere aggiornato.
|
||||
published.call.step1.only.ranking.type.allowed=Per un bando pubblicato, questo passaggio accetta solo il tipo di graduatoria; omettere tutti gli altri campi.
|
||||
call.ranking.type.updated.successfully=Tipo di graduatoria del bando aggiornato correttamente.
|
||||
application.ranking.action.updated.successfully=Azione di graduatoria sulla domanda aggiornata correttamente.
|
||||
application.ranking.fetched.successfully=Graduatoria recuperata correttamente.
|
||||
call.must.be.closed.for.ranking.action=L'azione di graduatoria <20> consentita solo se il bando <20> chiuso (scaduto).
|
||||
application.ranking.action.invalid=Richiesta di azione sulla graduatoria non valida.
|
||||
invalid.status.change.from.publish=Lo stato non pu? essere modificato in READY_TO_PUBLISH da PUBLISH.
|
||||
invalid.status.change.from.publish.to.draft=Lo stato non pu essere modificato da PUBLISH a DRAFT poich sono gi state create applicazioni per questa CALL.
|
||||
|
||||
@@ -71,7 +77,7 @@ email.already.exists=Esiste gi? un utente con questa email.
|
||||
invalid_user=Validazione utente fallita. Controlla le informazioni, lo stato dell'account e la scadenza del token.
|
||||
|
||||
#Global messages
|
||||
common_message=Qualcosa è andato storto. Riprova.
|
||||
common_message=Qualcosa <EFBFBD> andato storto. Riprova.
|
||||
invalid_signature=Gettone non valido.
|
||||
invalid_login=Nome utente o password errati
|
||||
req_validation_er=Errore di convalida
|
||||
@@ -425,7 +431,7 @@ amendment.must.be.approved.first=L'emendamento deve essere approvato dal diretto
|
||||
upload.company.document.to.application=Documento aziendale caricato correttamente nell'applicazione.
|
||||
company.document.not.found.with.ids=Documento aziendale non trovato. ID mancanti: {0}
|
||||
amount.field.not.provided= Si prega di fornire i campi obbligatori per l'importo.
|
||||
vat.or.tax.code.required=È obbligatorio il numero di partita IVA o il codice fiscale.
|
||||
vat.or.tax.code.required=<EFBFBD> obbligatorio il numero di partita IVA o il codice fiscale.
|
||||
provide.valid.vat.number=Inserisci un numero di partita IVA valido per procedere con NDG.
|
||||
application.status.transition.restricted=Questa modifica di stato non è disponibile tramite questa operazione.
|
||||
application.status.transition.restricted=Questa modifica di stato non <EFBFBD> disponibile tramite questa operazione.
|
||||
application.registry.segment.invalid=Valore del segmento non valido.
|
||||
Reference in New Issue
Block a user