From 63a60b2522d0a8693f36c0dd25abfadde2eff96d Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 5 Mar 2025 15:03:51 +0530 Subject: [PATCH] Done ticket GEPAFINBE-181 --- .../constants/GepafinConstant.java | 5 + .../gepafin/tendermanagement/dao/CallDao.java | 137 +++++++++++++++++- .../request/CallPageableRequestBean.java | 3 + 3 files changed, 141 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 8f29a46f..ff6ac233 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -485,6 +485,11 @@ public class GepafinConstant { public static final String USAGE="usage"; public static final String LIMIT="limit"; public static final String DATA="data"; + + public static final String PREFERRED_CALL_ID="preferredCallId"; + + public static final String REGION_ID="regionId"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index c34b32aa..bef8c76f 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -4,17 +4,18 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; +import java.sql.Timestamp; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.Predicate; -import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.*; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.*; @@ -1058,10 +1059,14 @@ public class CallDao { Integer year = null; String search = null; + Map filters = new HashMap<>(); if (callPageableRequestBean.getGlobalFilters() != null) { year = callPageableRequestBean.getGlobalFilters().getYear(); search = callPageableRequestBean.getGlobalFilters().getSearch(); } + if (callPageableRequestBean.getFilters() != null) { + filters = callPageableRequestBean.getFilters(); + } List predicates = new ArrayList<>(); if (year != null && year > 0) { int filterYear = callPageableRequestBean.getGlobalFilters().getYear(); @@ -1104,7 +1109,7 @@ public class CallDao { .toList(); predicates.add(root.get(GepafinConstant.STATUS).in(statusValues)); } - + applyFilters(root, criteriaBuilder, predicates, filters); predicates.add(criteriaBuilder.equal(root.get(GepafinConstant.HUB).get(GepafinConstant.ID), userEntity.getHub().getId())); @@ -1112,6 +1117,130 @@ public class CallDao { } + private void applyFilters(Root root, CriteriaBuilder criteriaBuilder, List predicates, Map filters) { + if (Boolean.FALSE.equals(filters.isEmpty())) { + for (Map.Entry entry : filters.entrySet()) { + String fieldName = entry.getKey(); + FilterCriteria filterCriteria = entry.getValue(); + Object value = filterCriteria.getValue(); + MatchModeEnum matchMode = filterCriteria.getMatchMode(); + + if (value != null && matchMode != null) { + Path fieldPath = getFieldPath(root, fieldName); + if (fieldPath != null) { + applyStringFilter(fieldPath, criteriaBuilder, predicates, value, matchMode); + applyNumberFilter(fieldPath, criteriaBuilder, predicates, value, matchMode); + applyDateFilter(fieldPath, criteriaBuilder, predicates, value, matchMode,root); + } + } + } + } + } + + private void applyStringFilter(Path fieldPath, CriteriaBuilder criteriaBuilder, List predicates, Object value, MatchModeEnum matchMode) { + if (value instanceof String) { + String valueStr = (String) value; + if (fieldPath.getJavaType().equals(String.class)) { + MatchModeEnum mode = MatchModeEnum.fromObject(matchMode.getValue()); + switch (mode) { + case CONTAINS -> + predicates.add(criteriaBuilder.like(criteriaBuilder.lower(fieldPath.as(String.class)), "%" + valueStr.toLowerCase() + "%")); + case EQUALS -> predicates.add(criteriaBuilder.equal(fieldPath, valueStr)); + case STARTSWITH -> + predicates.add(criteriaBuilder.like(criteriaBuilder.lower(fieldPath.as(String.class)), valueStr.toLowerCase() + "%")); + case ENDSWITH -> + predicates.add(criteriaBuilder.like(criteriaBuilder.lower(fieldPath.as(String.class)), "%" + valueStr.toLowerCase())); + } + } + } + } + + private void applyNumberFilter(Path fieldPath, CriteriaBuilder criteriaBuilder, List predicates, Object value, MatchModeEnum matchMode) { + if (Number.class.isAssignableFrom(fieldPath.getJavaType())) { + Number numberValue = null; + if (value instanceof Number) { + numberValue = (Number) value; + } + MatchModeEnum mode = MatchModeEnum.fromObject(matchMode.getValue()); + switch (mode) { + case EQUALS -> predicates.add(criteriaBuilder.equal(fieldPath, numberValue)); + } + } + } + + + + + private void applyDateFilter(Path fieldPath, CriteriaBuilder criteriaBuilder, List predicates, Object value, MatchModeEnum matchMode, Root root) { + if (fieldPath.getJavaType().equals(LocalDateTime.class)) { + // Convert input string: Replace 'T' with space + String formattedValue = value.toString().replace("T", " "); + + // Handle timezones and UTC (`Z` or `+HH:mm`) + if (formattedValue.contains("Z") || formattedValue.matches(".*[+-]\\d{2}:\\d{2}$")) { + OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME); + formattedValue = offsetDateTime.toLocalDateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")); + } + + // Check if more than 3 decimal places exist + if (formattedValue.contains(".")) { + int dotIndex = formattedValue.indexOf("."); + if (formattedValue.length() > dotIndex + 4) { + formattedValue = formattedValue.substring(0, dotIndex + 4); // Keep only 3 decimals + } + } else { + formattedValue += ".000"; // Ensure 3 decimals + } + + // Define correct date-time format + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + // Parse the formatted value into LocalDateTime + LocalDateTime dateTimeValue = LocalDateTime.parse(formattedValue, formatter); + + // Extract only the date portion + LocalDate dateValue = dateTimeValue.toLocalDate(); + + // Convert database field to LocalDate for date-only comparison + Expression dateField = criteriaBuilder.function("DATE", LocalDate.class, fieldPath); + + MatchModeEnum mode = MatchModeEnum.fromObject(matchMode.getValue()); + + switch (mode) { + case DATEIS -> predicates.add(criteriaBuilder.equal(dateField, dateValue)); + case DATEISNOT -> predicates.add(criteriaBuilder.notEqual(dateField, dateValue)); + case BEFORE -> predicates.add(criteriaBuilder.lessThan(fieldPath.as(Timestamp.class), Timestamp.valueOf(dateTimeValue))); + case AFTER -> predicates.add(criteriaBuilder.greaterThan(fieldPath.as(Timestamp.class), Timestamp.valueOf(dateTimeValue))); + } + } + } + + + + + private Path getFieldPath(Root root, String fieldName) { + try { + return switch (fieldName) { + + case GepafinConstant.REGION_ID -> { + // Ensure join is only created if not already present + Join regionJoin = root.getJoins().stream() + .filter(j -> j.getAttribute().getName().equals("region")) + .findFirst() + .map(j -> (Join) j) + .orElseGet(() -> root.join("region", JoinType.LEFT)); + + yield regionJoin.get("id"); + } + + default -> root.get(fieldName); + }; + } catch (IllegalArgumentException e) { + return null; + } + } + + public CallResponse createCallStep2EvaluationV2(CallEntity callEntity, CreateCallRequestStep2EvaluationV2 createCallRequest, UserEntity user) { convertToDocumentEntities(createCallRequest.getDocs(), callEntity.getId(), DocumentTypeEnum.DOCUMENT); diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CallPageableRequestBean.java b/src/main/java/net/gepafin/tendermanagement/model/request/CallPageableRequestBean.java index 8b848c85..260a45e5 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/CallPageableRequestBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CallPageableRequestBean.java @@ -4,6 +4,7 @@ import lombok.Data; import net.gepafin.tendermanagement.enums.CallStatusEnum; import java.util.List; +import java.util.Map; @Data public class CallPageableRequestBean { @@ -11,4 +12,6 @@ public class CallPageableRequestBean { private GlobalFilters globalFilters; private List status; + + private Map filters; }