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