From 39846150dec0da833790cfdd5ec3b0e59a7e1dff Mon Sep 17 00:00:00 2001 From: Ibrahim Elsanosi Date: Thu, 25 Jun 2026 22:28:57 +0100 Subject: [PATCH 1/5] FACT-2610 update counter service API --- .../CourtOpeningHoursControllerTest.java | 16 ++++++--- .../CourtOpeningHoursController.java | 34 ++++++++++++++---- ...tCounterServiceOpeningHoursRepository.java | 5 +-- .../services/CourtOpeningHoursService.java | 36 ++++++++++++------- .../CourtOpeningHoursControllerTest.java | 16 +++++---- .../CourtOpeningHoursServiceTest.java | 7 ++-- 6 files changed, 80 insertions(+), 34 deletions(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java index 3a187f95..d058581d 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.reform.fact.data.api.controllers; +import org.springframework.web.bind.annotation.GetMapping; import tools.jackson.databind.ObjectMapper; import io.qameta.allure.Feature; import org.junit.jupiter.api.Assertions; @@ -54,6 +55,7 @@ class CourtOpeningHoursControllerTest { private UUID courtId; private UUID nonExistentCourtId; + private UUID nonExistentCourterServiceId; private UUID openingHourTypeId; private Court court; private OpeningHourType openingHourType; @@ -64,6 +66,7 @@ class CourtOpeningHoursControllerTest { @BeforeEach public void setup() { nonExistentCourtId = UUID.randomUUID(); + nonExistentCourterServiceId = UUID.randomUUID(); openingHourTypeId = UUID.randomUUID(); courtId = UUID.randomUUID(); openingHourType = new OpeningHourType(); @@ -225,12 +228,17 @@ void getOpeningHoursByIdInvalidUUID() throws Exception { } @Test - @DisplayName("GET /courts/{courtId}/v1/opening-hours/counter-service returns opening hours successfully") + @DisplayName("GET /courts/{courtId}/v1/opening-hours/counter-service/{counterServiceOpeningHoursId}" + + "returns counter service opening hours successfully") void getCounterServiceOpeningHoursReturnsSuccessfully() throws Exception { - when(courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(courtId)) + when(courtOpeningHoursService.getCounterServiceOpeningHoursById(courtId, counterServiceOpeningHours.getId())) .thenReturn(counterServiceOpeningHours); - mockMvc.perform(get("/courts/{courtId}/v1/opening-hours/counter-service", courtId)) + mockMvc.perform( + get( + "/courts/{courtId}/v1/opening-hours/counter-service/{counterServiceOpeningHoursId}", + courtId, + counterServiceOpeningHours.getId())) .andExpect(status().isOk()) .andExpect(jsonPath("$.openingTimesDetails[0].dayOfWeek") .value(counterServiceOpeningHours @@ -573,7 +581,7 @@ void deleteCounterServiceOpeningHoursDeletesSuccessfully() throws Exception { void deleteCounterServiceOpeningHoursNonExistentCourtReturnsNotFound() throws Exception { doThrow(new NotFoundException("Court not found")) .when(courtOpeningHoursService) - .deleteCourtCounterServiceOpeningHours(nonExistentCourtId); + .deleteCourtCounterServiceOpeningHours(nonExistentCourtId, nonExistentCourterServiceId); mockMvc.perform(delete( "/courts/{courtId}/v1/opening-hours/counter-service", diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java index 72450007..40e5eb58 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java @@ -87,10 +87,30 @@ public ResponseEntity getOpeningHoursById( @ApiResponse(responseCode = "400", description = "Invalid court ID supplied"), @ApiResponse(responseCode = "404", description = "Court not found") }) - public ResponseEntity getCounterServiceOpeningHoursByCourtId( + public ResponseEntity> getCounterServiceOpeningHoursByCourtId( @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId) { + return ResponseEntity.ok(courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(UUID.fromString(courtId))); + } + + @GetMapping("/v1/opening-hours/counter-service/{counterServiceId}") + @Operation( + summary = "Get court counter service opening hours by court ID and opening hours ID", + description = "Fetch counter service opening hours for a given court." + + "Returns 204 if no opening hours exist for the court with this ID." + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully retrieved court counter service opening hours"), + @ApiResponse(responseCode = "204", description = "No court counter service opening hours found for the court with this ID"), + @ApiResponse(responseCode = "400", description = "Invalid court ID or court counter service opening hours ID supplied"), + @ApiResponse(responseCode = "404", description = "Court or court counter service opening hours not found") + }) + public ResponseEntity getCounterServiceOpeningHoursById( + @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId, + @Parameter(description = "UUID of the counter service opening hours", required = true) + @ValidUUID @PathVariable String counterServiceId) { return ResponseEntity.ok( - courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(UUID.fromString(courtId))); + courtOpeningHoursService + .getCounterServiceOpeningHoursById(UUID.fromString(courtId), UUID.fromString(counterServiceId))); } @PutMapping("/v1/opening-hours") @@ -120,7 +140,7 @@ public ResponseEntity setOpeningHours( description = "Creates a opening hours for a court or updates the existing one." ) @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Successfully created/updated opening hours"), + @ApiResponse(responseCode = "200", description = "Successfully created/updated counter service opening hours"), @ApiResponse(responseCode = "204", description = "No Content"), @ApiResponse(responseCode = "400", description = "Invalid court ID or request body"), @ApiResponse(responseCode = "404", description = "Court or court type not found") @@ -154,7 +174,7 @@ public ResponseEntity deleteOpeningHours( return ResponseEntity.ok().body(null); } - @DeleteMapping("/v1/opening-hours/counter-service") + @DeleteMapping("/v1/opening-hours/counter-service/{counterServiceId}") @Operation( summary = "Delete counter service opening hours for a court", description = "Deletes counter service opening hours for a court." @@ -166,8 +186,10 @@ public ResponseEntity deleteOpeningHours( }) @PreAuthorize("@authService.isAdmin()") public ResponseEntity deleteCounterServiceOpeningHours( - @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId) { - courtOpeningHoursService.deleteCourtCounterServiceOpeningHours(UUID.fromString(courtId)); + @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId, + @Parameter(description = "UUID of the counter service", required = true) + @ValidUUID @PathVariable String counterServiceId) { + courtOpeningHoursService.deleteCourtCounterServiceOpeningHours(UUID.fromString(courtId), UUID.fromString(counterServiceId)); return ResponseEntity.ok().body(null); } } diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java index 49066c8f..da920afa 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java @@ -2,6 +2,7 @@ import uk.gov.hmcts.reform.fact.data.api.entities.CourtCounterServiceOpeningHours; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -12,7 +13,7 @@ public interface CourtCounterServiceOpeningHoursRepository extends JpaRepository { - Optional findByCourtId(UUID courtId); + Optional> findByCourtId(UUID courtId); - void deleteByCourtId(UUID courtId); + Optional findByCourtIdAndId(UUID courtId, UUID counterServiceOpeningHourId); } diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java index f292ae2a..9c85879e 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java @@ -12,10 +12,7 @@ import uk.gov.hmcts.reform.fact.data.api.repositories.CourtCounterServiceOpeningHoursRepository; import uk.gov.hmcts.reform.fact.data.api.repositories.CourtOpeningHoursRepository; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; @Service @Slf4j @@ -71,21 +68,35 @@ public CourtOpeningHours getOpeningHoursById(UUID courtId, UUID openingHoursId) "No opening hour found for court ID: " + courtId + " with ID: " + openingHoursId)); } + /** + * Get a list of counter service opening hours by court ID. + * + * @param courtId The court ID to find the counter service opening hours for. + * @return The list of counter service opening hours. + * @throws CourtResourceNotFoundException if no counter service opening hours record exists for the court or the list is empty. + */ + public List getCounterServiceOpeningHoursByCourtId(UUID courtId) { + return courtCounterServiceOpeningHoursRepository + .findByCourtId(courtService.getCourtById(courtId).getId()) + .filter(list -> !list.isEmpty()) + .orElseThrow(() -> new CourtResourceNotFoundException( + "No counter service opening hours found for court ID: " + courtId)); + } /** * Get counter-service opening hours by court ID. - * A court will only ever have zero or one counter-service opening hours record. * * @param courtId The court ID to find the counter-service opening hours for. + * @param counterServiceOpeningHoursId The ID for the counter service opening hours to find. * @return The counter-service opening hours record. * @throws CourtResourceNotFoundException if no counter-service opening hours record exists for the court. */ - public CourtCounterServiceOpeningHours getCounterServiceOpeningHoursByCourtId(UUID courtId) { + public CourtCounterServiceOpeningHours getCounterServiceOpeningHoursById(final UUID courtId, final UUID counterServiceOpeningHoursId) { return courtCounterServiceOpeningHoursRepository - .findByCourtId(courtService.getCourtById(courtId).getId()) + .findByCourtIdAndId(courtService.getCourtById(courtId).getId(), counterServiceOpeningHoursId) .orElseThrow( () -> new CourtResourceNotFoundException( - "No counter service opening hours found for court ID: " + courtId)); + "No counter service opening hours found for court ID: " + courtId + " with ID: " + counterServiceOpeningHoursId)); } /** @@ -147,7 +158,7 @@ public CourtCounterServiceOpeningHours setCounterServiceOpeningHours( .map(this::validateCourtTypeIds) .ifPresent(courtCounterServiceOpeningHours::setCourtTypes); - courtCounterServiceOpeningHoursRepository.findByCourtId(courtId) + courtCounterServiceOpeningHoursRepository.findByCourtIdAndId(courtId, courtCounterServiceOpeningHours.getId()) .ifPresent(existing -> courtCounterServiceOpeningHours.setId(existing.getId())); return courtCounterServiceOpeningHoursRepository.save(courtCounterServiceOpeningHours); @@ -165,11 +176,12 @@ public void deleteCourtOpeningHours(UUID courtId, UUID openingHoursId) { /** * Delete court counter service opening hours. - * @param courtId The ID of the court to delete counter service opening hours for. + * @param counterServiceId The ID of the counter service to delete counter service opening hours for court courtId. */ @Transactional - public void deleteCourtCounterServiceOpeningHours(UUID courtId) { - courtCounterServiceOpeningHoursRepository.deleteByCourtId(courtService.getCourtById(courtId).getId()); + public void deleteCourtCounterServiceOpeningHours(final UUID courtId, final UUID counterServiceId) { + log.info("Deleting court counter service opening hours for court ID: {} and counter service ID: {}", courtId, counterServiceId); + courtCounterServiceOpeningHoursRepository.deleteById(counterServiceId); } /** diff --git a/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java b/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java index 0160810b..08d202ca 100644 --- a/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java @@ -203,9 +203,9 @@ void getOpeningHoursByIdThrowsIllegalArgumentExceptionForInvalidUUID() { @Test void getCounterServiceOpeningHoursByCourtIdReturns200() { when(courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(COURT_ID)) - .thenReturn(counterServiceOpeningHours); + .thenReturn(List.of(counterServiceOpeningHours)); - ResponseEntity response + ResponseEntity> response = courtOpeningHoursController.getCounterServiceOpeningHoursByCourtId(COURT_ID.toString()); assertThat(response.getStatusCode()).as(RESPONSE_STATUS_MESSAGE).isEqualTo(HttpStatus.OK); @@ -238,7 +238,7 @@ void getCounterServiceOpeningHoursThrowsCourtNotFoundException() { void getCounterServiceOpeningHoursThrowsIllegalArgumentExceptionForInvalidUUID() { assertThrows( IllegalArgumentException.class, () -> - courtOpeningHoursController.getCounterServiceOpeningHoursByCourtId(INVALID_UUID) + courtOpeningHoursController.getCounterServiceOpeningHoursById(INVALID_UUID, INVALID_UUID) ); } @@ -351,7 +351,8 @@ void deleteOpeningHoursByTypeIdThrowsIllegalArgumentException() { @Test void deleteCourtCounterServiceOpeningHoursReturns200() { ResponseEntity response = courtOpeningHoursController.deleteCounterServiceOpeningHours( - COURT_ID.toString() + COURT_ID.toString(), + counterServiceOpeningHours.getId().toString() ); assertThat(response.getStatusCode()).as(RESPONSE_STATUS_MESSAGE).isEqualTo(HttpStatus.OK); } @@ -360,12 +361,13 @@ void deleteCourtCounterServiceOpeningHoursReturns200() { void deleteCourtCounterServiceOpeningHoursThrowsNotFoundException() { doThrow(new NotFoundException(COURT_NOT_FOUND_MESSAGE)) .when(courtOpeningHoursService) - .deleteCourtCounterServiceOpeningHours(UNKNOWN_COURT_ID); + .deleteCourtCounterServiceOpeningHours(UNKNOWN_COURT_ID, UNKNOWN_ID); assertThrows( NotFoundException.class, () -> courtOpeningHoursController.deleteCounterServiceOpeningHours( - UNKNOWN_COURT_ID.toString() + UNKNOWN_COURT_ID.toString(), + UNKNOWN_ID.toString() ) ); } @@ -375,7 +377,7 @@ void deleteCounterServiceOpeningHoursThrowsIllegalArgumentException() { assertThrows( IllegalArgumentException.class, () -> courtOpeningHoursController - .deleteCounterServiceOpeningHours(INVALID_UUID) + .deleteCounterServiceOpeningHours(INVALID_UUID, INVALID_UUID) ); } } diff --git a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java index d1deb84a..ec194483 100644 --- a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java @@ -202,12 +202,13 @@ void getOpeningHoursThrowsExceptionWhenOpeningHourTypeDoesNotExist() { void getCounterServiceOpeningHoursByCourtIdReturnsOpeningHoursWhenFound() { when(courtService.getCourtById(courtId)).thenReturn(court); when(courtCounterServiceOpeningHoursRepository.findByCourtId(courtId)) - .thenReturn(Optional.of(counterServiceOpeningHours)); + .thenReturn(Optional.of(List.of(counterServiceOpeningHours))); - CourtCounterServiceOpeningHours result = + + List result = courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(courtId); - assertThat(result).isEqualTo(counterServiceOpeningHours); + assertThat(result).isEqualTo(List.of(counterServiceOpeningHours)); } @Test From 1d04ae27a1537b344f419bb85122dc9abe72ed73 Mon Sep 17 00:00:00 2001 From: Ibrahim Elsanosi Date: Mon, 6 Jul 2026 14:05:32 +0100 Subject: [PATCH 2/5] FACT-2610 Fix unit test --- .../CourtOpeningHoursControllerTest.java | 20 ++++++++--------- .../CourtOpeningHoursController.java | 18 +++++++++------ .../services/CourtOpeningHoursService.java | 22 ++++++++++++------- .../CourtOpeningHoursControllerTest.java | 2 +- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java index d058581d..e4c9c259 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java @@ -1,6 +1,5 @@ package uk.gov.hmcts.reform.fact.data.api.controllers; -import org.springframework.web.bind.annotation.GetMapping; import tools.jackson.databind.ObjectMapper; import io.qameta.allure.Feature; import org.junit.jupiter.api.Assertions; @@ -55,7 +54,6 @@ class CourtOpeningHoursControllerTest { private UUID courtId; private UUID nonExistentCourtId; - private UUID nonExistentCourterServiceId; private UUID openingHourTypeId; private Court court; private OpeningHourType openingHourType; @@ -66,7 +64,6 @@ class CourtOpeningHoursControllerTest { @BeforeEach public void setup() { nonExistentCourtId = UUID.randomUUID(); - nonExistentCourterServiceId = UUID.randomUUID(); openingHourTypeId = UUID.randomUUID(); courtId = UUID.randomUUID(); openingHourType = new OpeningHourType(); @@ -570,8 +567,9 @@ void deleteOpeningHoursInvalidUUID() throws Exception { @DisplayName("DELETE /courts/{courtId}/v1/opening-hours/counter-service deletes opening hours successfully") void deleteCounterServiceOpeningHoursDeletesSuccessfully() throws Exception { mockMvc.perform(delete( - "/courts/{courtId}/v1/opening-hours/counter-service", - courtId + "/courts/{courtId}/v1/opening-hours/counter-service/{counterServiceId}", + courtId, + counterServiceOpeningHours.getId() )) .andExpect(status().isOk()); } @@ -581,11 +579,12 @@ void deleteCounterServiceOpeningHoursDeletesSuccessfully() throws Exception { void deleteCounterServiceOpeningHoursNonExistentCourtReturnsNotFound() throws Exception { doThrow(new NotFoundException("Court not found")) .when(courtOpeningHoursService) - .deleteCourtCounterServiceOpeningHours(nonExistentCourtId, nonExistentCourterServiceId); + .deleteCourtCounterServiceOpeningHours(nonExistentCourtId, counterServiceOpeningHours.getId()); mockMvc.perform(delete( - "/courts/{courtId}/v1/opening-hours/counter-service", - nonExistentCourtId + "/courts/{courtId}/v1/opening-hours/counter-service/{counterServiceId}", + nonExistentCourtId, + counterServiceOpeningHours.getId() )) .andExpect(status().isNotFound()); } @@ -594,8 +593,9 @@ void deleteCounterServiceOpeningHoursNonExistentCourtReturnsNotFound() throws Ex @DisplayName("DELETE /courts/{courtId}/v1/opening-hours/counter-service returns 400 for invalid UUID") void deleteCounterServiceOpeningHoursInvalidUUID() throws Exception { mockMvc.perform(delete( - "/courts/{courtId}/v1/opening-hours/counter-service", - "invalid-uuid" + "/courts/{courtId}/v1/opening-hours/counter-service/{counterServiceId}", + "invalid-uuid", + counterServiceOpeningHours.getId() )) .andExpect(status().isBadRequest()); } diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java index 40e5eb58..17996092 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursController.java @@ -89,20 +89,22 @@ public ResponseEntity getOpeningHoursById( }) public ResponseEntity> getCounterServiceOpeningHoursByCourtId( @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId) { - return ResponseEntity.ok(courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(UUID.fromString(courtId))); + return ResponseEntity.ok(courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId( + UUID.fromString(courtId)) + ); } @GetMapping("/v1/opening-hours/counter-service/{counterServiceId}") @Operation( - summary = "Get court counter service opening hours by court ID and opening hours ID", + summary = "Get court counter service opening hours by court ID and counter service ID", description = "Fetch counter service opening hours for a given court." - + "Returns 204 if no opening hours exist for the court with this ID." + + "Returns 204 if no counter service opening hours exist for the court with this ID." ) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Successfully retrieved court counter service opening hours"), - @ApiResponse(responseCode = "204", description = "No court counter service opening hours found for the court with this ID"), - @ApiResponse(responseCode = "400", description = "Invalid court ID or court counter service opening hours ID supplied"), - @ApiResponse(responseCode = "404", description = "Court or court counter service opening hours not found") + @ApiResponse(responseCode = "204", description = "No counter service found for the court with this ID"), + @ApiResponse(responseCode = "400", description = "Invalid court ID or court counter service ID supplied"), + @ApiResponse(responseCode = "404", description = "Court or counter service opening hours not found") }) public ResponseEntity getCounterServiceOpeningHoursById( @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId, @@ -189,7 +191,9 @@ public ResponseEntity deleteCounterServiceOpeningHours( @Parameter(description = "UUID of the court", required = true) @ValidUUID @PathVariable String courtId, @Parameter(description = "UUID of the counter service", required = true) @ValidUUID @PathVariable String counterServiceId) { - courtOpeningHoursService.deleteCourtCounterServiceOpeningHours(UUID.fromString(courtId), UUID.fromString(counterServiceId)); + courtOpeningHoursService.deleteCourtCounterServiceOpeningHours( + UUID.fromString(courtId), UUID.fromString(counterServiceId) + ); return ResponseEntity.ok().body(null); } } diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java index 9c85879e..ce8ca3ef 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java @@ -12,7 +12,10 @@ import uk.gov.hmcts.reform.fact.data.api.repositories.CourtCounterServiceOpeningHoursRepository; import uk.gov.hmcts.reform.fact.data.api.repositories.CourtOpeningHoursRepository; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; @Service @Slf4j @@ -73,7 +76,7 @@ public CourtOpeningHours getOpeningHoursById(UUID courtId, UUID openingHoursId) * * @param courtId The court ID to find the counter service opening hours for. * @return The list of counter service opening hours. - * @throws CourtResourceNotFoundException if no counter service opening hours record exists for the court or the list is empty. + * @throws CourtResourceNotFoundException if no counter service record exists for the court or the list is empty. */ public List getCounterServiceOpeningHoursByCourtId(UUID courtId) { return courtCounterServiceOpeningHoursRepository @@ -84,19 +87,21 @@ public List getCounterServiceOpeningHoursByCour } /** - * Get counter-service opening hours by court ID. + * Get counter-service opening hours by court ID and counter service ID. * * @param courtId The court ID to find the counter-service opening hours for. - * @param counterServiceOpeningHoursId The ID for the counter service opening hours to find. + * @param counterServiceId The ID for the counter service opening hours to find. * @return The counter-service opening hours record. * @throws CourtResourceNotFoundException if no counter-service opening hours record exists for the court. */ - public CourtCounterServiceOpeningHours getCounterServiceOpeningHoursById(final UUID courtId, final UUID counterServiceOpeningHoursId) { + public CourtCounterServiceOpeningHours getCounterServiceOpeningHoursById( + final UUID courtId, final UUID counterServiceId) { return courtCounterServiceOpeningHoursRepository - .findByCourtIdAndId(courtService.getCourtById(courtId).getId(), counterServiceOpeningHoursId) + .findByCourtIdAndId(courtService.getCourtById(courtId).getId(), counterServiceId) .orElseThrow( () -> new CourtResourceNotFoundException( - "No counter service opening hours found for court ID: " + courtId + " with ID: " + counterServiceOpeningHoursId)); + "No counter service opening hours found for court ID: " + courtId + " with ID: " + + counterServiceId)); } /** @@ -180,7 +185,8 @@ public void deleteCourtOpeningHours(UUID courtId, UUID openingHoursId) { */ @Transactional public void deleteCourtCounterServiceOpeningHours(final UUID courtId, final UUID counterServiceId) { - log.info("Deleting court counter service opening hours for court ID: {} and counter service ID: {}", courtId, counterServiceId); + log.info("Deleting court counter service opening hours for court ID: {} and counter service ID: {}", + courtId, counterServiceId); courtCounterServiceOpeningHoursRepository.deleteById(counterServiceId); } diff --git a/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java b/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java index 08d202ca..5da61eb5 100644 --- a/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/fact/data/api/controllers/CourtOpeningHoursControllerTest.java @@ -209,7 +209,7 @@ void getCounterServiceOpeningHoursByCourtIdReturns200() { = courtOpeningHoursController.getCounterServiceOpeningHoursByCourtId(COURT_ID.toString()); assertThat(response.getStatusCode()).as(RESPONSE_STATUS_MESSAGE).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).as(RESPONSE_BODY_MESSAGE).isEqualTo(counterServiceOpeningHours); + assertThat(response.getBody()).as(RESPONSE_BODY_MESSAGE).isEqualTo(List.of(counterServiceOpeningHours)); } @Test From 604456dac396e7c618085cb9b305b05775439b1c Mon Sep 17 00:00:00 2001 From: Ibrahim Elsanosi Date: Mon, 6 Jul 2026 16:42:29 +0100 Subject: [PATCH 3/5] FACT-2610 Add unit test for Counter service APIs --- .../CourtOpeningHoursServiceTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java index ec194483..81b4ea80 100644 --- a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java @@ -231,6 +231,40 @@ void getCounterServiceOpeningHoursThrowsExceptionWhenCourtDoesNotExist() { ); } + @Test + void getCounterServiceOpeningHoursByIdReturnsCounterServiceOpeningHoursWhenFound() { + when(courtService.getCourtById(courtId)).thenReturn(court); + when(courtCounterServiceOpeningHoursRepository.findByCourtIdAndId(courtId, counterServiceOpeningHours.getId())) + .thenReturn(Optional.of(counterServiceOpeningHours)); + + CourtCounterServiceOpeningHours result = courtOpeningHoursService + .getCounterServiceOpeningHoursById(courtId, counterServiceOpeningHours.getId()); + + assertThat(result).isEqualTo(counterServiceOpeningHours); + } + + @Test + void getCounterServiceOpeningHoursThrowsExceptionWhenNotFound() { + when(courtService.getCourtById(courtId)).thenReturn(court); + when(courtCounterServiceOpeningHoursRepository.findByCourtIdAndId(courtId, counterServiceOpeningHours.getId())) + .thenReturn(Optional.empty()); + + assertThrows( + CourtResourceNotFoundException.class, + () -> courtOpeningHoursService.getCounterServiceOpeningHoursById( + courtId, counterServiceOpeningHours.getId()) + ); + } + + @Test + void getCounterServiceOpeningHoursByIdThrowsExceptionWhenCourtDoesNotExist() { + when(courtService.getCourtById(courtId)).thenThrow(new NotFoundException(COURT_NOT_FOUND_MESSAGE)); + + assertThrows(NotFoundException.class, () -> + courtOpeningHoursService.getCounterServiceOpeningHoursById(courtId, counterServiceOpeningHours.getId()) + ); + } + @Test void setOpeningHoursSuccessfullyCreatesNewOpeningHours() { when(courtService.getCourtById(courtId)).thenReturn(court); @@ -475,5 +509,12 @@ void deleteCourtOpeningHoursSuccessfullyDeletesHours() { verify(courtOpeningHoursRepository).deleteById(openingHours.getId()); } + + @Test + void deleteCounterServiceOpeningHoursSuccessfullyDeletesHours() { + courtOpeningHoursService.deleteCourtCounterServiceOpeningHours(courtId, counterServiceOpeningHours.getId()); + + verify(courtCounterServiceOpeningHoursRepository).deleteById(counterServiceOpeningHours.getId()); + } } From cfb2058602a261527e427808d67b80e4b285ce1b Mon Sep 17 00:00:00 2001 From: Ibrahim Elsanosi Date: Mon, 6 Jul 2026 19:48:37 +0100 Subject: [PATCH 4/5] FACT-2610 Fix functional test --- .../CourtOpeningHoursControllerFunctionalTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/functionalTest/java/uk/gov/hmcts/reform/fact/functional/controllers/CourtOpeningHoursControllerFunctionalTest.java b/src/functionalTest/java/uk/gov/hmcts/reform/fact/functional/controllers/CourtOpeningHoursControllerFunctionalTest.java index 2f824014..1b0d4798 100644 --- a/src/functionalTest/java/uk/gov/hmcts/reform/fact/functional/controllers/CourtOpeningHoursControllerFunctionalTest.java +++ b/src/functionalTest/java/uk/gov/hmcts/reform/fact/functional/controllers/CourtOpeningHoursControllerFunctionalTest.java @@ -162,11 +162,14 @@ void shouldGetCounterServiceOpeningHours() throws Exception { final Response getResponse = http.doGet("/courts/" + courtId + "/v1/opening-hours/counter-service"); assertThat(getResponse.statusCode()).isEqualTo(OK.value()); - final CourtCounterServiceOpeningHours retrievedHours = mapper.readValue( + final List retrievedHoursList = mapper.readValue( getResponse.asString(), - CourtCounterServiceOpeningHours.class + mapper.getTypeFactory().constructCollectionType(List.class, CourtCounterServiceOpeningHours.class) ); + assertThat((retrievedHoursList)).hasSize(1); + final CourtCounterServiceOpeningHours retrievedHours = retrievedHoursList.getFirst(); + assertThat(retrievedHours.getOpeningTimesDetails()).hasSize(5); assertThat(retrievedHours.getOpeningTimesDetails().getFirst().getOpeningTime()) .isEqualTo(LocalTime.of(9, 0)); From e42b6c091126496c7e47b88cfc068feabe8ede31 Mon Sep 17 00:00:00 2001 From: Ibrahim Elsanosi Date: Fri, 10 Jul 2026 17:33:44 +0100 Subject: [PATCH 5/5] FACT-2610 address PR feedback --- ...CourtCounterServiceOpeningHoursRepository.java | 2 +- .../api/services/CourtOpeningHoursService.java | 12 +++++++----- .../services/CourtOpeningHoursServiceTest.java | 15 +++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java index da920afa..f058487f 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/repositories/CourtCounterServiceOpeningHoursRepository.java @@ -13,7 +13,7 @@ public interface CourtCounterServiceOpeningHoursRepository extends JpaRepository { - Optional> findByCourtId(UUID courtId); + List findByCourtId(UUID courtId); Optional findByCourtIdAndId(UUID courtId, UUID counterServiceOpeningHourId); } diff --git a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java index ce8ca3ef..4f7573dd 100644 --- a/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java +++ b/src/main/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursService.java @@ -79,11 +79,13 @@ public CourtOpeningHours getOpeningHoursById(UUID courtId, UUID openingHoursId) * @throws CourtResourceNotFoundException if no counter service record exists for the court or the list is empty. */ public List getCounterServiceOpeningHoursByCourtId(UUID courtId) { - return courtCounterServiceOpeningHoursRepository - .findByCourtId(courtService.getCourtById(courtId).getId()) - .filter(list -> !list.isEmpty()) - .orElseThrow(() -> new CourtResourceNotFoundException( - "No counter service opening hours found for court ID: " + courtId)); + List result = + courtCounterServiceOpeningHoursRepository.findByCourtId(courtService.getCourtById(courtId).getId()); + if (result.isEmpty()) { + throw new CourtResourceNotFoundException( + "No counter service opening hours found for court ID: " + courtId); + } + return result; } /** diff --git a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java index 81b4ea80..81a755ef 100644 --- a/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/fact/data/api/services/CourtOpeningHoursServiceTest.java @@ -202,8 +202,7 @@ void getOpeningHoursThrowsExceptionWhenOpeningHourTypeDoesNotExist() { void getCounterServiceOpeningHoursByCourtIdReturnsOpeningHoursWhenFound() { when(courtService.getCourtById(courtId)).thenReturn(court); when(courtCounterServiceOpeningHoursRepository.findByCourtId(courtId)) - .thenReturn(Optional.of(List.of(counterServiceOpeningHours))); - + .thenReturn(List.of(counterServiceOpeningHours)); List result = courtOpeningHoursService.getCounterServiceOpeningHoursByCourtId(courtId); @@ -214,7 +213,7 @@ void getCounterServiceOpeningHoursByCourtIdReturnsOpeningHoursWhenFound() { @Test void getCounterServiceOpeningHoursByCourtIdThrowsExceptionWhenNotFound() { when(courtService.getCourtById(courtId)).thenReturn(court); - when(courtCounterServiceOpeningHoursRepository.findByCourtId(courtId)).thenReturn(Optional.empty()); + when(courtCounterServiceOpeningHoursRepository.findByCourtId(courtId)).thenReturn(List.of()); assertThrows( CourtResourceNotFoundException.class, @@ -244,24 +243,24 @@ void getCounterServiceOpeningHoursByIdReturnsCounterServiceOpeningHoursWhenFound } @Test - void getCounterServiceOpeningHoursThrowsExceptionWhenNotFound() { + void getCounterServiceOpeningHoursByIdThrowsExceptionWhenNotFound() { when(courtService.getCourtById(courtId)).thenReturn(court); when(courtCounterServiceOpeningHoursRepository.findByCourtIdAndId(courtId, counterServiceOpeningHours.getId())) .thenReturn(Optional.empty()); + final UUID counterServiceId = counterServiceOpeningHours.getId(); assertThrows( CourtResourceNotFoundException.class, - () -> courtOpeningHoursService.getCounterServiceOpeningHoursById( - courtId, counterServiceOpeningHours.getId()) - ); + () -> courtOpeningHoursService.getCounterServiceOpeningHoursById(courtId, counterServiceId)); } @Test void getCounterServiceOpeningHoursByIdThrowsExceptionWhenCourtDoesNotExist() { when(courtService.getCourtById(courtId)).thenThrow(new NotFoundException(COURT_NOT_FOUND_MESSAGE)); + final UUID counterServiceId = counterServiceOpeningHours.getId(); assertThrows(NotFoundException.class, () -> - courtOpeningHoursService.getCounterServiceOpeningHoursById(courtId, counterServiceOpeningHours.getId()) + courtOpeningHoursService.getCounterServiceOpeningHoursById(courtId, counterServiceId) ); }