diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java new file mode 100644 index 0000000..987d647 --- /dev/null +++ b/src/integrationTest/java/uk/gov/hmcts/cp/config/TestConfig.java @@ -0,0 +1,15 @@ +package uk.gov.hmcts.cp.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepositoryImpl; + +import java.net.http.HttpClient; + +import static org.mockito.Mockito.mock; + +@Configuration +public class TestConfig { + +} \ No newline at end of file diff --git a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java index cd106d1..4a11e10 100644 --- a/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerIT.java @@ -7,11 +7,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; +import uk.gov.hmcts.cp.config.TestConfig; +import uk.gov.hmcts.cp.repositories.CourtScheduleRepository; import java.util.UUID; @@ -24,12 +28,23 @@ @ExtendWith(SpringExtension.class) @SpringBootTest @AutoConfigureMockMvc +@Import(TestConfig.class) class CourtScheduleControllerIT { private static final Logger log = LoggerFactory.getLogger(CourtScheduleControllerIT.class); @Autowired private MockMvc mockMvc; + @Autowired + @Qualifier("inMemoryCourtScheduleRepositoryImpl") + private CourtScheduleRepository courtScheduleRepository; + + /*@BeforeEach + void setUp() { + inMemoryCaseUrnMapper.clearAllMappings(); + inMemoryCaseUrnMapper.saveCaseUrnMapping("test-case-urn", "test-case-id"); + } + */ @Test void shouldReturnOkWhenValidUrnIsProvided() throws Exception { String caseUrn = "test-case-urn"; diff --git a/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java new file mode 100644 index 0000000..035dd14 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImpl.java @@ -0,0 +1,112 @@ +package uk.gov.hmcts.cp.repositories; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Primary; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.cp.openapi.model.CourtSchedule; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; +import uk.gov.hmcts.cp.openapi.model.CourtSitting; +import uk.gov.hmcts.cp.openapi.model.Hearing; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Primary +public class CourtScheduleRepositoryImpl implements CourtScheduleRepository { + private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleRepositoryImpl.class); + + private final Map courtScheduleResponseMap = new ConcurrentHashMap<>(); + + + public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse courtScheduleResponse) { + courtScheduleResponseMap.put(caseUrn, courtScheduleResponse); + } + + public CourtScheduleResponse getCourtScheduleByCaseId(final String caseUrn) { + if (!courtScheduleResponseMap.containsKey(caseUrn)) { + saveCourtSchedule(caseUrn, createCourtScheduleResponse()); + } + return courtScheduleResponseMap.get(caseUrn); + } + + public void clearAll() { + courtScheduleResponseMap.clear(); + } + + private CourtScheduleResponse createCourtScheduleResponse() { + + String res = getHearingData(); + LOG.info("infunction createCourtScheduleResponse Response Body: {} " + res); + + + final OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC) + .truncatedTo(ChronoUnit.SECONDS); + + final Hearing hearing = Hearing.builder() + .hearingId(UUID.randomUUID().toString()) + .listNote("Requires interpreter") + .hearingDescription("Sentencing for theft case") + .hearingType("Trial") + .courtSittings(List.of( + CourtSitting.builder() + .courtHouse("Central Criminal Court") + .sittingStart(sittingStartTime) + .sittingEnd(sittingStartTime.plusMinutes(60)) + .judiciaryId(UUID.randomUUID().toString()) + .build()) + ).build(); + + return CourtScheduleResponse.builder() + .courtSchedule(List.of( + CourtSchedule.builder() + .hearings(List.of(hearing) + ).build() + ) + ).build(); + } + + private String getHearingData(){ + HttpResponse response = null; + try { + // Create HttpClient instance + HttpClient client = HttpClient.newHttpClient(); + + // Build the request + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://steccm64.ingress01.dev.nl.cjscp.org.uk/listing-query-api/query/api/rest/listing/hearings/allocated-and-unallocated?caseId=f552dee6-f092-415b-839c-5e5b5f46635e")) + .GET() + .header("Accept", "application/vnd.listing.search.hearings+json") + .header("CJSCPPUID", "d7c91866-646a-462c-9203-46678e8cddef") + .build(); + + // Send the request + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // Check response status + if (response.statusCode() != HttpStatus.OK.value()) { + LOG.error("Failed to fetch hearing data. HTTP Status: {}", response.statusCode()); + return null; + } + + // Print response status and body + LOG.info("Response Code: {} " + response.statusCode()); + LOG.info("Response Body: {} " + response.body()); + return response.body(); + } catch (Exception e) { + LOG.error("Exception occurred while fetching hearing data: {}", e.getMessage(), e); + } + return null; + } +} diff --git a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java index 1a5d8c4..ad067fb 100644 --- a/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java +++ b/src/main/java/uk/gov/hmcts/cp/services/CourtScheduleService.java @@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; @@ -18,6 +19,7 @@ public class CourtScheduleService { private static final Logger LOG = LoggerFactory.getLogger(CourtScheduleService.class); + @Qualifier("courtScheduleRepositoryImpl") private final CourtScheduleRepository courtScheduleRepository; public CourtScheduleResponse getCourtScheduleByCaseId(final String caseId) throws ResponseStatusException { diff --git a/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java new file mode 100644 index 0000000..6bbf915 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryImplTest.java @@ -0,0 +1,53 @@ +package uk.gov.hmcts.cp.repositories; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +class CourtScheduleRepositoryImplTest { + + private CourtScheduleRepositoryImpl courtScheduleRepository; + + @BeforeEach + void setUp() { + courtScheduleRepository = new CourtScheduleRepositoryImpl(); + } + + @Test + void getCourtScheduleByCaseId_shouldReturnNewResponseIfNotExists() { + String caseUrn = "test-case-urn"; + + CourtScheduleResponse response = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(response); + assertEquals(1, response.getCourtSchedule().size()); + } + + @Test + void getCourtScheduleByCaseId_shouldReturnExistingResponseIfExists() { + String caseUrn = "test-case-urn"; + CourtScheduleResponse expectedResponse = CourtScheduleResponse.builder().build(); + + courtScheduleRepository.saveCourtSchedule(caseUrn, expectedResponse); + CourtScheduleResponse actualResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(actualResponse); + assertEquals(expectedResponse, actualResponse); + } + + @Test + void saveCourtSchedule_shouldStoreResponse() { + String caseUrn = "test-case-urn"; + CourtScheduleResponse response = CourtScheduleResponse.builder().build(); + + courtScheduleRepository.saveCourtSchedule(caseUrn, response); + CourtScheduleResponse storedResponse = courtScheduleRepository.getCourtScheduleByCaseId(caseUrn); + + assertNotNull(storedResponse); + assertEquals(response, storedResponse); + } +} \ No newline at end of file diff --git a/src/test/resources/hearing.json b/src/test/resources/hearing.json new file mode 100644 index 0000000..312a3db --- /dev/null +++ b/src/test/resources/hearing.json @@ -0,0 +1,104 @@ +{ + "hearings": [ + { + "id": "348a288e-6e0d-479c-bd14-f363580d2181", + "type": { + "id": "4a0e892d-c0c5-3c51-95b8-704d8c781776", + "description": "First hearing" + }, + "endDate": "2025-07-21", + "allocated": true, + "judiciary": [], + "startDate": "2025-07-21", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDays": [ + { + "endTime": "2025-07-21T15:20:00.000Z", + "sequence": 0, + "startTime": "2025-07-21T15:00:00.000Z", + "courtRoomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "hearingDate": "2025-07-21", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "durationMinutes": 20 + } + ], + "listedCases": [ + { + "id": "f552dee6-f092-415b-839c-5e5b5f46635e", + "markers": [], + "defendants": [ + { + "id": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "address": { + "address1": "Add1", + "postcode": "CB3 0GU" + }, + "isYouth": false, + "lastName": "Test2", + "offences": [ + { + "id": "922cf1fd-9ef1-415d-809f-5a871ec24ec8", + "count": 0, + "startDate": "2025-07-10", + "orderIndex": 1, + "offenceCode": "TH68023A", + "shadowListed": false, + "offenceWording": "Before 10 Jul 2025 at df attempted to rob dfd of dfdf to the value of sds .", + "statementOfOffence": { + "title": "Attempt robbery", + "welshTitle": "Ymgais i ysbeilio (robbery)", + "legislation": "Contrary to section 1(1) of the Criminal Attempts Act 1981.", + "welshLegislation": "Yn groes i adran 1(1) Deddf Ymgeisiau i Droseddu 1981." + }, + "restrictFromCourtList": false + } + ], + "firstName": "Teat1", + "bailStatus": { + "id": "86009c70-759d-3308-8de4-194886ff9a77", + "code": "A", + "description": "Not applicable" + }, + "dateOfBirth": "1984-01-12", + "masterDefendantId": "4e7853ab-67f8-4ebe-9a31-dc1ed271ebb9", + "hearingLanguageNeeds": "ENGLISH", + "restrictFromCourtList": false, + "nationalityDescription": "British", + "courtProceedingsInitiated": "2025-07-21T13:19:54.727Z" + } + ], + "shadowListed": false, + "caseIdentifier": { + "authorityId": "31af405e-7b60-4dd8-a244-c24c2d3fa595", + "authorityCode": "TFL", + "caseReference": "CIK2JQKECS" + }, + "restrictFromCourtList": false + } + ], + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "isSlotsBooked": false, + "nonDefaultDays": [ + { + "roomId": "9e4932f7-97b2-3010-b942-ddd2624e4dd8", + "duration": 20, + "startTime": "2025-07-21T15:00:00.000Z", + "courtCentreId": "f8254db1-1683-483e-afb3-b87fde5a0a26" + } + ], + "nonSittingDays": [], + "hearingLanguage": "ENGLISH", + "estimatedMinutes": 20, + "jurisdictionType": "MAGISTRATES", + "courtApplications": [], + "courtCentreDetails": { + "id": "f8254db1-1683-483e-afb3-b87fde5a0a26", + "defaultDuration": 420, + "defaultStartTime": "10:00:00" + }, + "isGroupProceedings": false, + "numberOfGroupCases": 1, + "sendNotificationToParties": false + } + ] +} \ No newline at end of file