diff --git a/pointtils/pom.xml b/pointtils/pom.xml
index 63bdaa44..55616bbc 100644
--- a/pointtils/pom.xml
+++ b/pointtils/pom.xml
@@ -76,7 +76,7 @@
h2
test
-
+
org.springframework.boot
spring-boot-starter-security
diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/InterpreterService.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/InterpreterService.java
index ad7a67d7..5f08f721 100644
--- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/InterpreterService.java
+++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/InterpreterService.java
@@ -9,7 +9,6 @@
import com.pointtils.pointtils.src.application.mapper.InterpreterResponseMapper;
import com.pointtils.pointtils.src.application.mapper.LocationMapper;
import com.pointtils.pointtils.src.core.domain.entities.Interpreter;
-import com.pointtils.pointtils.src.core.domain.entities.enums.DayOfWeek;
import com.pointtils.pointtils.src.core.domain.entities.enums.Gender;
import com.pointtils.pointtils.src.core.domain.entities.enums.InterpreterModality;
import com.pointtils.pointtils.src.core.domain.entities.enums.UserStatus;
@@ -24,7 +23,6 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
-import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
@@ -77,16 +75,14 @@ public void delete(UUID id) {
repository.save(interpreter);
}
- public List findAll(
- String modality,
- String gender,
- String city,
- String uf,
- String neighborhood,
- String specialty,
- String availableDate,
- String name) {
-
+ public List findAll(String modality,
+ String gender,
+ String city,
+ String uf,
+ String neighborhood,
+ String specialty,
+ String availableDate,
+ String name) {
InterpreterModality modalityEnum = null;
if (modality != null) {
modalityEnum = InterpreterModality.valueOf(modality.toUpperCase());
@@ -97,16 +93,9 @@ public List findAll(
genderEnum = Gender.valueOf(gender.toUpperCase());
}
- DayOfWeek dayOfWeek = null;
- LocalTime requestedStart = null;
- LocalTime requestedEnd = null;
-
+ LocalDateTime dateTime = null;
if (availableDate != null) {
- LocalDateTime dateTime = LocalDateTime.parse(availableDate,
- DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
- dayOfWeek = DayOfWeek.valueOf(dateTime.getDayOfWeek().name().substring(0, 3));
- requestedStart = dateTime.toLocalTime();
- requestedEnd = requestedStart.plusHours(1);
+ dateTime = LocalDateTime.parse(availableDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
}
List specialtyList = null;
@@ -116,9 +105,8 @@ public List findAll(
.toList();
}
- return repository.findAll(
- InterpreterSpecification.filter(modalityEnum, uf, city, neighborhood, specialtyList, genderEnum, dayOfWeek,
- requestedStart, requestedEnd, name))
+ return repository.findAll(InterpreterSpecification.filter(modalityEnum, uf, city, neighborhood, specialtyList,
+ genderEnum, dateTime, name))
.stream()
.map(responseMapper::toListResponseDTO)
.toList();
diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecification.java b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecification.java
index a64cbbb2..0e942a49 100644
--- a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecification.java
+++ b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecification.java
@@ -1,9 +1,11 @@
package com.pointtils.pointtils.src.infrastructure.repositories.spec;
+import com.pointtils.pointtils.src.core.domain.entities.Appointment;
import com.pointtils.pointtils.src.core.domain.entities.Interpreter;
import com.pointtils.pointtils.src.core.domain.entities.Location;
import com.pointtils.pointtils.src.core.domain.entities.Schedule;
import com.pointtils.pointtils.src.core.domain.entities.UserSpecialty;
+import com.pointtils.pointtils.src.core.domain.entities.enums.AppointmentStatus;
import com.pointtils.pointtils.src.core.domain.entities.enums.DayOfWeek;
import com.pointtils.pointtils.src.core.domain.entities.enums.Gender;
import com.pointtils.pointtils.src.core.domain.entities.enums.InterpreterModality;
@@ -13,17 +15,24 @@
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import lombok.experimental.UtilityClass;
import org.springframework.data.jpa.domain.Specification;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
+import java.util.Objects;
import java.util.UUID;
@UtilityClass
public class InterpreterSpecification {
+ private static final String START_TIME_FIELD = "startTime";
+ private static final String END_TIME_FIELD = "endTime";
+
@SuppressWarnings("null")
public static Specification filter(
InterpreterModality modality,
@@ -32,50 +41,139 @@ public static Specification filter(
String neighborhood,
List specialties,
Gender gender,
- DayOfWeek dayOfWeek,
- LocalTime requestedStart,
- LocalTime requestedEnd,
+ LocalDateTime availableDate,
String name
) {
return (root, query, cb) -> {
query.distinct(true);
- Join location = root.join("locations", JoinType.LEFT);
- Join schedule = root.join("schedules", JoinType.LEFT);
-
Predicate predicate = cb.conjunction();
- if (modality == InterpreterModality.ALL) {
- predicate = cb.and(predicate, root.get("modality").in(InterpreterModality.ALL, InterpreterModality.ONLINE, InterpreterModality.PERSONALLY));
- } else if (modality != null) {
- predicate = cb.and(predicate, root.get("modality").in(InterpreterModality.ALL, modality));
- }
- if (name != null) predicate = cb.and(predicate, cb.like(cb.lower(root.get("name")), "%" + name.toLowerCase() + "%"));
- if (gender != null) predicate = cb.and(predicate, cb.equal(root.get("gender"), gender));
- if (uf != null) predicate = cb.and(predicate, cb.equal(location.get("uf"), uf));
- if (city != null) predicate = cb.and(predicate, cb.like(cb.lower(location.get("city")), "%" + city.toLowerCase() + "%"));
- if (neighborhood != null) predicate = cb.and(predicate, cb.like(cb.lower(location.get("neighborhood")), "%" + neighborhood.toLowerCase() + "%"));
- if (!Collections.isEmpty(specialties)) {
- Subquery subquery = buildSpecialtiesSubquery(query, specialties, cb);
- predicate = cb.and(predicate, root.get("id").in(subquery));
+ if (name != null) {
+ predicate = cb.and(predicate, cb.like(cb.lower(root.get("name")), "%" + name.toLowerCase() + "%"));
}
- if (dayOfWeek != null && requestedStart != null && requestedEnd != null) {
- predicate = cb.and(predicate, cb.equal(schedule.get("day"), dayOfWeek));
- predicate = cb.and(predicate, cb.lessThanOrEqualTo(schedule.get("startTime"), requestedStart));
- predicate = cb.and(predicate, cb.greaterThanOrEqualTo(schedule.get("endTime"), requestedEnd));
+ if (gender != null) {
+ predicate = cb.and(predicate, cb.equal(root.get("gender"), gender));
}
-
+ predicate = checkIfInterpreterHasModality(predicate, cb, root, modality);
+ predicate = checkIfInterpreterHasLocation(predicate, cb, root, uf, city, neighborhood);
+ predicate = checkIfInterpreterHasSpecialties(predicate, query, cb, root, specialties);
+ predicate = checkIfInterpreterIsAvailableOnRequestedDate(predicate, query, cb, root, availableDate);
return predicate;
};
}
- private static Subquery buildSpecialtiesSubquery(CriteriaQuery> query, List specialties,
- CriteriaBuilder criteriaBuilder) {
+ private static Predicate checkIfInterpreterHasModality(Predicate predicate,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ InterpreterModality modality) {
+ if (modality == InterpreterModality.ALL) {
+ predicate = criteriaBuilder.and(predicate, root.get("modality")
+ .in(InterpreterModality.ALL, InterpreterModality.ONLINE, InterpreterModality.PERSONALLY));
+ } else if (Objects.nonNull(modality)) {
+ predicate = criteriaBuilder.and(predicate, root.get("modality").in(InterpreterModality.ALL, modality));
+ }
+ return predicate;
+ }
+
+ private static Predicate checkIfInterpreterHasLocation(Predicate predicate,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ String uf,
+ String city,
+ String neighborhood) {
+
+ Join location = root.join("locations", JoinType.LEFT);
+ if (Objects.nonNull(uf)) {
+ predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(location.get("uf"), uf));
+ }
+ if (Objects.nonNull(city)) {
+ predicate = criteriaBuilder.and(predicate, criteriaBuilder
+ .like(criteriaBuilder.lower(location.get("city")), "%" + city.toLowerCase() + "%"));
+ }
+ if (Objects.nonNull(neighborhood)) {
+ predicate = criteriaBuilder.and(predicate, criteriaBuilder
+ .like(criteriaBuilder.lower(location.get("neighborhood")), "%" + neighborhood.toLowerCase() + "%"));
+ }
+ return predicate;
+ }
+
+ private static Predicate checkIfInterpreterHasSpecialties(Predicate predicate,
+ CriteriaQuery> query,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ List specialties) {
+ if (Collections.isEmpty(specialties)) {
+ return predicate;
+ }
Subquery subquery = query.subquery(UUID.class);
var subRoot = subquery.from(UserSpecialty.class);
subquery.select(subRoot.get("user").get("id"))
.where(subRoot.get("specialty").get("id").in(specialties))
.groupBy(subRoot.get("user").get("id"))
.having(criteriaBuilder.equal(criteriaBuilder.countDistinct(subRoot.get("specialty").get("id")), specialties.size()));
- return subquery;
+ return criteriaBuilder.and(predicate, root.get("id").in(subquery));
+ }
+
+ private static Predicate checkIfInterpreterIsAvailableOnRequestedDate(Predicate predicate,
+ CriteriaQuery> query,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ LocalDateTime availableDate) {
+ if (Objects.isNull(availableDate)) {
+ return predicate;
+ }
+
+ LocalDate requestedDate = availableDate.toLocalDate();
+ DayOfWeek dayOfWeek = DayOfWeek.valueOf(availableDate.getDayOfWeek().name().substring(0, 3));
+ LocalTime requestedStart = availableDate.toLocalTime();
+ LocalTime requestedEnd = requestedStart.plusHours(1);
+
+ predicate = checkIfInterpreterHasScheduleOnRequestedDate(predicate, criteriaBuilder, root, dayOfWeek, requestedStart, requestedEnd);
+ return checkIfInterpreterHasNoAppointmentOnRequestDate(predicate, query, criteriaBuilder, root, requestedDate, requestedStart, requestedEnd);
+ }
+
+ private static Predicate checkIfInterpreterHasScheduleOnRequestedDate(Predicate predicate,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ DayOfWeek dayOfWeek,
+ LocalTime requestedStart,
+ LocalTime requestedEnd) {
+ Join schedule = root.join("schedules", JoinType.LEFT);
+ predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(schedule.get("day"), dayOfWeek));
+ predicate = criteriaBuilder.and(predicate, criteriaBuilder
+ .lessThanOrEqualTo(schedule.get(START_TIME_FIELD), requestedStart));
+ return criteriaBuilder.and(predicate, criteriaBuilder
+ .greaterThanOrEqualTo(schedule.get(END_TIME_FIELD), requestedEnd));
+ }
+
+ private static Predicate checkIfInterpreterHasNoAppointmentOnRequestDate(Predicate predicate,
+ CriteriaQuery> query,
+ CriteriaBuilder criteriaBuilder,
+ Root root,
+ LocalDate requestedDate,
+ LocalTime requestedStart,
+ LocalTime requestedEnd) {
+ Subquery subquery = query.subquery(UUID.class);
+ var subRoot = subquery.from(Appointment.class);
+ subquery.select(subRoot.get("interpreter").get("id"))
+ .where(criteriaBuilder.and(
+ subRoot.get("status").in(AppointmentStatus.ACCEPTED, AppointmentStatus.COMPLETED),
+ criteriaBuilder.equal(subRoot.get("date"), requestedDate),
+ criteriaBuilder.or(
+ criteriaBuilder.and(
+ criteriaBuilder.greaterThan(subRoot.get(START_TIME_FIELD), requestedStart),
+ criteriaBuilder.lessThan(subRoot.get(START_TIME_FIELD), requestedEnd)
+ ),
+ criteriaBuilder.and(
+ criteriaBuilder.greaterThan(subRoot.get(END_TIME_FIELD), requestedStart),
+ criteriaBuilder.lessThan(subRoot.get(END_TIME_FIELD), requestedEnd)
+ ),
+ criteriaBuilder.and(
+ criteriaBuilder.lessThanOrEqualTo(subRoot.get(START_TIME_FIELD), requestedStart),
+ criteriaBuilder.greaterThanOrEqualTo(subRoot.get(END_TIME_FIELD), requestedEnd)
+ )
+ )
+ ));
+ return criteriaBuilder.and(predicate, criteriaBuilder.not(root.get("id").in(subquery)));
}
}
\ No newline at end of file
diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecificationTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecificationTest.java
index 810f10c9..935dedde 100644
--- a/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecificationTest.java
+++ b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/repositories/spec/InterpreterSpecificationTest.java
@@ -1,9 +1,12 @@
package com.pointtils.pointtils.src.infrastructure.repositories.spec;
+import com.pointtils.pointtils.src.core.domain.entities.Appointment;
import com.pointtils.pointtils.src.core.domain.entities.Interpreter;
import com.pointtils.pointtils.src.core.domain.entities.Schedule;
+import com.pointtils.pointtils.src.core.domain.entities.enums.AppointmentStatus;
import com.pointtils.pointtils.src.core.domain.entities.enums.DayOfWeek;
import com.pointtils.pointtils.src.core.domain.entities.enums.Gender;
+import com.pointtils.pointtils.src.core.domain.entities.enums.InterpreterModality;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
@@ -12,12 +15,20 @@
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
+import jakarta.persistence.criteria.Subquery;
import org.junit.jupiter.api.Test;
import org.springframework.data.jpa.domain.Specification;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.time.LocalTime;
+import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -38,7 +49,7 @@ void shouldBuildPredicateWithGender() {
when(cb.and(basePredicate, genderPredicate)).thenReturn(genderPredicate);
Specification spec = InterpreterSpecification.filter(null, null, null, null,
- null, Gender.MALE, null, null, null, null);
+ null, Gender.MALE, null, null);
Predicate result = spec.toPredicate(root, query, cb);
@@ -46,6 +57,54 @@ void shouldBuildPredicateWithGender() {
verify(cb).equal(root.get("gender"), Gender.MALE);
}
+ @Test
+ void shouldBuildPredicateWithAllModality() {
+ Root root = mock(Root.class);
+ CriteriaQuery> query = mock(CriteriaQuery.class);
+ CriteriaBuilder cb = mock(CriteriaBuilder.class);
+ Predicate basePredicate = mock(Predicate.class);
+ when(cb.conjunction()).thenReturn(basePredicate);
+
+ Predicate modalityPredicate = mock(Predicate.class);
+ Path modalityPath = mock(Path.class);
+ when(root.get("modality")).thenReturn(modalityPath);
+ when(modalityPath.in(InterpreterModality.ALL, InterpreterModality.ONLINE, InterpreterModality.PERSONALLY))
+ .thenReturn(modalityPredicate);
+
+ Predicate resultPredicate = mock(Predicate.class);
+ when(cb.and(basePredicate, modalityPredicate)).thenReturn(resultPredicate);
+
+ Specification spec = InterpreterSpecification.filter(InterpreterModality.ALL, null, null,
+ null, null, null, null, null);
+
+ Predicate result = spec.toPredicate(root, query, cb);
+ assertEquals(resultPredicate, result);
+ }
+
+ @Test
+ void shouldBuildPredicateWithOnlineModality() {
+ Root root = mock(Root.class);
+ CriteriaQuery> query = mock(CriteriaQuery.class);
+ CriteriaBuilder cb = mock(CriteriaBuilder.class);
+ Predicate basePredicate = mock(Predicate.class);
+ when(cb.conjunction()).thenReturn(basePredicate);
+
+ Predicate modalityPredicate = mock(Predicate.class);
+ Path modalityPath = mock(Path.class);
+ when(root.get("modality")).thenReturn(modalityPath);
+ when(modalityPath.in(InterpreterModality.ALL, InterpreterModality.ONLINE))
+ .thenReturn(modalityPredicate);
+
+ Predicate resultPredicate = mock(Predicate.class);
+ when(cb.and(basePredicate, modalityPredicate)).thenReturn(resultPredicate);
+
+ Specification spec = InterpreterSpecification.filter(InterpreterModality.ONLINE, null, null,
+ null, null, null, null, null);
+
+ Predicate result = spec.toPredicate(root, query, cb);
+ assertEquals(resultPredicate, result);
+ }
+
@Test
void shouldBuildPredicateWithCity() {
Root root = mock(Root.class);
@@ -67,7 +126,7 @@ void shouldBuildPredicateWithCity() {
when(cb.conjunction()).thenReturn(basePredicate);
Specification spec = InterpreterSpecification.filter(null, null, "São Paulo",
- null, null, null, null, null, null, null);
+ null, null, null, null, null);
Predicate result = spec.toPredicate(root, query, cb);
@@ -94,7 +153,7 @@ void shouldBuildPredicateWithUF() {
when(cb.conjunction()).thenReturn(basePredicate);
Specification spec = InterpreterSpecification.filter(null, "RS", null,
- null, null, null, null, null, null, null);
+ null, null, null, null, null);
Predicate result = spec.toPredicate(root, query, cb);
@@ -103,40 +162,86 @@ void shouldBuildPredicateWithUF() {
}
@Test
- void shouldBuildPredicateWithScheduleAndTime() {
+ void shouldBuildPredicateWithAvailableDate() {
Root root = mock(Root.class);
CriteriaQuery> query = mock(CriteriaQuery.class);
CriteriaBuilder cb = mock(CriteriaBuilder.class);
Predicate basePredicate = mock(Predicate.class);
- Predicate dayPredicate = mock(Predicate.class);
- Predicate startPredicate = mock(Predicate.class);
- Predicate endPredicate = mock(Predicate.class);
Join scheduleJoin = (Join) (Join, ?>) mock(Join.class);
-
- when(root.join("schedules", JoinType.LEFT)).thenReturn((Join) scheduleJoin);
when(cb.conjunction()).thenReturn(basePredicate);
- LocalTime requestedStart = LocalTime.of(10, 0);
+ LocalDateTime availableDate = LocalDateTime.of(2025, 10, 6, 10, 0);
+ LocalTime requestedStart = availableDate.toLocalTime();
LocalTime requestedEnd = requestedStart.plusHours(1);
- when(cb.equal(scheduleJoin.get("day"), DayOfWeek.MON)).thenReturn(dayPredicate);
- when(cb.lessThanOrEqualTo(scheduleJoin.get("startTime"), requestedStart)).thenReturn(startPredicate);
- when(cb.greaterThanOrEqualTo(scheduleJoin.get("endTime"), requestedEnd)).thenReturn(endPredicate);
+ // Mock schedule predicates
+ Predicate schedulePredicate = mock(Predicate.class);
+ Path scheduleStartTimePath = mock(Path.class);
+ Path scheduleEndTimePath = mock(Path.class);
+ when(scheduleJoin.get("startTime")).thenReturn(scheduleStartTimePath);
+ when(scheduleJoin.get("endTime")).thenReturn(scheduleEndTimePath);
- when(cb.and(basePredicate, dayPredicate)).thenReturn(dayPredicate);
- when(cb.and(dayPredicate, startPredicate)).thenReturn(startPredicate);
- when(cb.and(startPredicate, endPredicate)).thenReturn(endPredicate);
+ when(root.join("schedules", JoinType.LEFT)).thenReturn((Join) scheduleJoin);
+ when(cb.equal(scheduleJoin.get("day"), DayOfWeek.MON)).thenReturn(schedulePredicate);
+ when(cb.lessThanOrEqualTo(scheduleStartTimePath, requestedStart)).thenReturn(schedulePredicate);
+ when(cb.greaterThanOrEqualTo(scheduleEndTimePath, requestedEnd)).thenReturn(schedulePredicate);
+ when(cb.and(basePredicate, schedulePredicate)).thenReturn(schedulePredicate);
+
+ // Mock subquery for appointments
+ Subquery subquery = mock(Subquery.class);
+ Root appointmentSubRoot = mock(Root.class);
+ when(query.subquery(UUID.class)).thenReturn(subquery);
+ when(subquery.from(Appointment.class)).thenReturn(appointmentSubRoot);
+
+ Path interpreterPath = mock(Path.class);
+ Path idPath = mock(Path.class);
+ when(appointmentSubRoot.get("interpreter")).thenReturn(interpreterPath);
+ when(interpreterPath.get("id")).thenReturn(idPath);
+ when(subquery.select(idPath)).thenReturn(subquery);
+
+ Predicate subqueryAndPredicate = mock(Predicate.class);
+ Predicate firstConditionPredicate = mock(Predicate.class);
+ Predicate secondConditionPredicate = mock(Predicate.class);
+ Predicate thirdConditionPredicate = mock(Predicate.class);
+ when(cb.and(firstConditionPredicate, secondConditionPredicate, thirdConditionPredicate)).thenReturn(subqueryAndPredicate);
+
+ Path statusPath = mock(Path.class);
+ when(appointmentSubRoot.get("status")).thenReturn(statusPath);
+ when(statusPath.in(AppointmentStatus.ACCEPTED, AppointmentStatus.COMPLETED)).thenReturn(firstConditionPredicate);
+
+ Path datePath = mock(Path.class);
+ when(appointmentSubRoot.get("date")).thenReturn(datePath);
+ when(cb.equal(datePath, LocalDate.of(2025, 10, 6))).thenReturn(secondConditionPredicate);
+
+ Predicate greaterThanPredicate = mock(Predicate.class);
+ Predicate lessThanPredicate = mock(Predicate.class);
+ Predicate joinGreaterThanLessThanPredicate = mock(Predicate.class);
+ when(cb.greaterThan(any(), eq(requestedStart))).thenReturn(greaterThanPredicate);
+ when(cb.lessThan(any(), eq(requestedEnd))).thenReturn(lessThanPredicate);
+ when(cb.and(greaterThanPredicate, lessThanPredicate)).thenReturn(joinGreaterThanLessThanPredicate);
+ when(cb.lessThanOrEqualTo(any(), eq(requestedStart))).thenReturn(lessThanPredicate);
+ when(cb.greaterThanOrEqualTo(any(), eq(requestedEnd))).thenReturn(greaterThanPredicate);
+ when(cb.and(lessThanPredicate, greaterThanPredicate)).thenReturn(joinGreaterThanLessThanPredicate);
+ when(cb.or(joinGreaterThanLessThanPredicate, joinGreaterThanLessThanPredicate, joinGreaterThanLessThanPredicate))
+ .thenReturn(thirdConditionPredicate);
+
+ when(subquery.where(subqueryAndPredicate)).thenReturn(subquery);
+
+ Predicate inSubqueryPredicate = mock(Predicate.class);
+ when(root.get("id")).thenReturn(idPath);
+ when(idPath.in(subquery)).thenReturn(inSubqueryPredicate);
+
+ when(cb.not(idPath.in(subquery))).thenReturn(inSubqueryPredicate);
+ when(cb.and(schedulePredicate, inSubqueryPredicate)).thenReturn(inSubqueryPredicate);
Specification spec = InterpreterSpecification.filter(null, null, null, null,
- null, null, DayOfWeek.MON, requestedStart, requestedEnd, null);
-
- Predicate result = spec.toPredicate(root, query, cb);
+ null, null, availableDate, null);
- assertThat(result).isEqualTo(endPredicate);
+ assertDoesNotThrow(() -> spec.toPredicate(root, query, cb));
verify(cb).equal(scheduleJoin.get("day"), DayOfWeek.MON);
- verify(cb).lessThanOrEqualTo(scheduleJoin.get("startTime"), requestedStart);
- verify(cb).greaterThanOrEqualTo(scheduleJoin.get("endTime"), requestedEnd);
+ verify(cb).lessThanOrEqualTo(scheduleStartTimePath, requestedStart);
+ verify(cb).greaterThanOrEqualTo(scheduleEndTimePath, requestedEnd);
}
@Test
@@ -157,11 +262,11 @@ void shouldBuildPredicateWithName() {
when(cb.and(basePredicate, namePredicate)).thenReturn(namePredicate);
Specification spec = InterpreterSpecification.filter(null, null, null, null,
- null, null, null, null, null, "SOUZA");
+ null, null, null, "SOUZA");
Predicate result = spec.toPredicate(root, query, cb);
assertThat(result).isEqualTo(namePredicate);
verify(cb).like(lowerNameExpression, "%souza%");
}
-}
+}
\ No newline at end of file