diff --git a/build.gradle b/build.gradle index 4cf7766b450..ca6ca6fb433 100644 --- a/build.gradle +++ b/build.gradle @@ -315,7 +315,7 @@ sonarqube { property "sonar.projectKey", "civil-service" property "sonar.coverage.jacoco.xmlReportPaths", "${jacocoTestReport.reports.xml.destination.path}" property "sonar.coverage.exclusions", "**/model/**, **/config/**/*Configuration.java, **/testingsupport/**, **/*ExternalTaskListener.java, **/*BaseExternalTaskHandler.java, **/stereotypes/**, **/*Exception.java, **/EventHistoryMapper*.java, **/model/hearingvalues/**, **/enums/hearing/**, **/fees/client/**, **/enums/sdo/**, **/service/PaymentsService.java, **/RetriggerCases*.java" - property "sonar.cpd.exclusions", "**/*DocumentManagementService.java, **/*Spec*.java" + property "sonar.cpd.exclusions", "**/*DocumentManagementService.java, **/*Spec*.java, **/*CcdDashboardClaimantClaimMatcher.java" property "sonar.exclusions", "**/hmc/model/**, **/model/hearingvalues/**" property "sonar.host.url", "https://sonar.reform.hmcts.net/" } @@ -396,7 +396,7 @@ dependencies { implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign' implementation group: 'org.springframework.cloud', name: 'spring-cloud-openfeign-core' implementation group: 'uk.gov.hmcts.reform', name: 'properties-volume-spring-boot-starter', version: '0.1.0' - implementation group: 'uk.gov.hmcts.reform', name: 'service-auth-provider-client', version: '4.0.0' + implementation group: 'uk.gov.hmcts.reform', name: 'service-auth-provider-client', version: '4.0.3' implementation group: 'io.github.openfeign', name: 'feign-httpclient', version: '12.4' implementation group: 'org.springframework.retry', name: 'spring-retry' @@ -496,6 +496,10 @@ dependencies { integrationTestImplementation sourceSets.main.runtimeClasspath integrationTestImplementation sourceSets.test.runtimeClasspath + // https://mvnrepository.com/artifact/com.opencsv/opencsv + implementation group: 'com.opencsv', name: 'opencsv', version: '5.8', { + exclude group: 'commons-collections', module: 'commons-collections' + } } mainClassName = 'uk.gov.hmcts.reform.civil.Application' diff --git a/charts/civil-service/Chart.yaml b/charts/civil-service/Chart.yaml index dbf0c702042..bc3f1ae9b6c 100644 --- a/charts/civil-service/Chart.yaml +++ b/charts/civil-service/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 description: A Helm chart for civil-service App name: civil-service home: https://github.com/hmcts/civil-service -version: 0.0.52 +version: 0.0.53 maintainers: - name: HMCTS Civil team diff --git a/charts/civil-service/values.yaml b/charts/civil-service/values.yaml index 54a997ceadd..fc9b9e0d99f 100644 --- a/charts/civil-service/values.yaml +++ b/charts/civil-service/values.yaml @@ -74,6 +74,7 @@ java: ASYNC_HANDLER_CORE_POOL_SIZE: 7 ASYNC_HANDLER_MAX_POOL_SIZE: 42 ASYNC_HANDLER_QUEUE_CAPACITY: 10 + CIVIL_S2S_AUTHORISED_SERVICES: payment_app,ccd_data,civil_service,civil-citizen-ui keyVaults: civil: diff --git a/docker/docmosis/templates/CV-UNS-HNO-ENG-01200.docx b/docker/docmosis/templates/CV-UNS-HNO-ENG-01200.docx index 56e1165f73d..864bb9ebb62 100644 Binary files a/docker/docmosis/templates/CV-UNS-HNO-ENG-01200.docx and b/docker/docmosis/templates/CV-UNS-HNO-ENG-01200.docx differ diff --git a/docker/docmosis/templates/CV-UNS-HNO-ENG-01201.docx b/docker/docmosis/templates/CV-UNS-HNO-ENG-01201.docx new file mode 100644 index 00000000000..78cc5d54741 Binary files /dev/null and b/docker/docmosis/templates/CV-UNS-HNO-ENG-01201.docx differ diff --git a/docker/docmosis/templates/CV-UNS-HNO-ENG-01202.docx b/docker/docmosis/templates/CV-UNS-HNO-ENG-01202.docx new file mode 100644 index 00000000000..0409b5c1e6f Binary files /dev/null and b/docker/docmosis/templates/CV-UNS-HNO-ENG-01202.docx differ diff --git a/docker/docmosis/templates/CV-UNS-HNO-ENG-01203.docx b/docker/docmosis/templates/CV-UNS-HNO-ENG-01203.docx new file mode 100644 index 00000000000..45d3ad6dff5 Binary files /dev/null and b/docker/docmosis/templates/CV-UNS-HNO-ENG-01203.docx differ diff --git a/docker/docmosis/templates/CV-UNS-HNO-ENG-01204.docx b/docker/docmosis/templates/CV-UNS-HNO-ENG-01204.docx new file mode 100644 index 00000000000..936cbacb36e Binary files /dev/null and b/docker/docmosis/templates/CV-UNS-HNO-ENG-01204.docx differ diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/BaseIntegrationTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/BaseIntegrationTest.java index 139b311e778..a844c3a91fc 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/BaseIntegrationTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/BaseIntegrationTest.java @@ -22,8 +22,10 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import uk.gov.hmcts.reform.authorisation.ServiceAuthorisationApi; import uk.gov.hmcts.reform.civil.Application; import uk.gov.hmcts.reform.civil.TestIdamConfiguration; +import uk.gov.hmcts.reform.civil.service.AuthorisationService; import uk.gov.hmcts.reform.civil.service.UserService; import uk.gov.hmcts.reform.idam.client.models.UserInfo; @@ -61,6 +63,9 @@ public abstract class BaseIntegrationTest { .roles(of("caseworker-civil-solicitor")) .build(); + private static final String s2sToken = "s2s AuthToken"; + @MockBean + private ServiceAuthorisationApi serviceAuthorisationApi; @MockBean protected UserService userService; @MockBean @@ -69,6 +74,8 @@ public abstract class BaseIntegrationTest { protected SecurityContext securityContext; @MockBean protected JwtDecoder jwtDecoder; + @MockBean + public AuthorisationService authorisationService; @Autowired protected ObjectMapper objectMapper; @@ -78,11 +85,13 @@ public abstract class BaseIntegrationTest { @BeforeEach public void setUpBase() { + when(authorisationService.isServiceAuthorized(any())).thenReturn(true); when(userService.getAccessToken(any(), any())).thenReturn("arbitrary access token"); when(userService.getUserInfo(anyString())).thenReturn(USER_INFO); when(securityContext.getAuthentication()).thenReturn(authentication); SecurityContextHolder.setContext(securityContext); setSecurityAuthorities(authentication); + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("payment_app"); when(jwtDecoder.decode(anyString())).thenReturn(getJwt()); } diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackControllerTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackControllerTest.java index 32dc02b549e..6db03a393c0 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackControllerTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackControllerTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -22,6 +23,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class ServiceRequestUpdateCallbackControllerTest extends BaseIntegrationTest { @@ -31,6 +33,7 @@ class ServiceRequestUpdateCallbackControllerTest extends BaseIntegrationTest { private static final String PAID = "Paid"; private static final String REFERENCE = "reference"; private static final String ACCOUNT_NUMBER = "123445555"; + private static final String s2sToken = "s2s AuthToken"; @MockBean CoreCaseDataApi coreCaseDataApi; @@ -40,6 +43,7 @@ class ServiceRequestUpdateCallbackControllerTest extends BaseIntegrationTest { @BeforeEach void bareMinimumToMakeAPositiveRequest() { + when(authorisationService.isServiceAuthorized(any())).thenReturn(true); CaseData caseData = CaseData.builder().businessProcess(BusinessProcess.builder().processInstanceId("instance").camundaEvent("camunda event").build()).build(); CaseDetails caseDetails = CaseDetails.builder().build(); caseDetails.setData(caseData.toMap(objectMapper)); @@ -51,6 +55,30 @@ void bareMinimumToMakeAPositiveRequest() { given(coreCaseDataApi.submitEventForCaseWorker(any(), any(), any(), any(), any(), any(), anyBoolean(), any())).willReturn(caseDetails); } + @Test + public void whenValidPaymentCallbackIsReceivedReturnSuccess() throws Exception { + doPut(buildServiceDto(), PAYMENT_CALLBACK_URL, "") + .andExpect(status().isOk()); + } + + @Test + public void whenPaymentCallbackIsReceivedWithoutServiceAuthorisationReturn400() throws Exception { + mockMvc.perform( + MockMvcRequestBuilders.put(PAYMENT_CALLBACK_URL, "") + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(buildServiceDto()))).andExpect(status().is4xxClientError()); + } + + @Test + public void whenPaymentCallbackIsReceivedWithServiceAuthorisationButreturnsfalseReturn400() throws Exception { + when(authorisationService.isServiceAuthorized(any())).thenReturn(false); + mockMvc.perform( + MockMvcRequestBuilders.put(PAYMENT_CALLBACK_URL, "") + .header("ServiceAuthorization", s2sToken) + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(buildServiceDto()))).andExpect(status().is5xxServerError()); + } + @Test public void whenInvalidTypeOfRequestMade_ReturnMethodNotAllowed() throws Exception { @@ -96,6 +124,8 @@ private ServiceRequestUpdateDto buildServiceDto() { protected ResultActions doPut(T content, String urlTemplate, Object... uriVars) { return mockMvc.perform( MockMvcRequestBuilders.put(urlTemplate, uriVars) + .header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN) + .header("ServiceAuthorization", "s2s AuthToken") .contentType(MediaType.APPLICATION_JSON) .content(toJson(content))); } @@ -104,6 +134,8 @@ protected ResultActions doPut(T content, String urlTemplate, Object... uriVa protected ResultActions doPost(T content, String urlTemplate, Object... uriVars) { return mockMvc.perform( MockMvcRequestBuilders.post(urlTemplate, uriVars) + .header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN) + .header("ServiceAuthorization", "s2s AuthToken") .contentType(MediaType.APPLICATION_JSON) .content(toJson(content))); } diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackControllerTest.java b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackControllerTest.java index 673f90234a5..b64ef4426bb 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackControllerTest.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackControllerTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -22,6 +23,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class ServiceRequestUpdateClaimIssuedCallbackControllerTest extends BaseIntegrationTest { @@ -31,7 +33,6 @@ class ServiceRequestUpdateClaimIssuedCallbackControllerTest extends BaseIntegrat private static final String PAID = "Paid"; private static final String REFERENCE = "reference"; private static final String ACCOUNT_NUMBER = "123445555"; - @MockBean CoreCaseDataApi coreCaseDataApi; @@ -40,6 +41,7 @@ class ServiceRequestUpdateClaimIssuedCallbackControllerTest extends BaseIntegrat @BeforeEach void bareMinimumToMakeAPositiveRequest() { + when(authorisationService.isServiceAuthorized(any())).thenReturn(true); CaseData caseData = CaseData.builder().businessProcess(BusinessProcess.builder().processInstanceId("instance").camundaEvent("camunda event").build()).build(); CaseDetails caseDetails = CaseDetails.builder().build(); @@ -77,6 +79,30 @@ public void whenServiceRequestUpdateRequestButUnexpectedErrorOccurs_thenHttp5xx( .andExpect(status().is5xxServerError()); } + @Test + public void whenValidPaymentCallbackIsReceivedReturnSuccess() throws Exception { + doPut(buildServiceDto(), PAYMENT_CALLBACK_URL, "") + .andExpect(status().isOk()); + } + + @Test + public void whenPaymentCallbackIsReceivedWithoutServiceAuthorisationReturn400() throws Exception { + mockMvc.perform( + MockMvcRequestBuilders.put(PAYMENT_CALLBACK_URL, "") + .contentType(MediaType.APPLICATION_JSON) + .content(toJson(buildServiceDto()))).andExpect(status().is4xxClientError()); + } + + @Test + public void whenPaymentCallbackIsReceivedWithServiceAuthorisationButreturnsfalseReturn400() throws Exception { + when(authorisationService.isServiceAuthorized(any())).thenReturn(false); + + doPut(buildServiceDto(), PAYMENT_CALLBACK_URL, "") + // Then: the result status must be an HTTP-4xx + .andExpect(status().is5xxServerError()); + + } + private ServiceRequestUpdateDto buildServiceDto() { return ServiceRequestUpdateDto.builder() .ccdCaseNumber(CCD_CASE_NUMBER) @@ -94,6 +120,8 @@ private ServiceRequestUpdateDto buildServiceDto() { protected ResultActions doPut(T content, String urlTemplate, Object... uriVars) { return mockMvc.perform( MockMvcRequestBuilders.put(urlTemplate, uriVars) + .header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN) + .header("ServiceAuthorization", "s2s AuthToken") .contentType(MediaType.APPLICATION_JSON) .content(toJson(content))); } @@ -102,6 +130,8 @@ protected ResultActions doPut(T content, String urlTemplate, Object... uriVa protected ResultActions doPost(T content, String urlTemplate, Object... uriVars) { return mockMvc.perform( MockMvcRequestBuilders.post(urlTemplate, uriVars) + .header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN) + .header("ServiceAuthorization", "s2s AuthToken") .contentType(MediaType.APPLICATION_JSON) .content(toJson(content))); } diff --git a/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackController.java b/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackController.java index 02faefda690..9c6bae36e15 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackController.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateCallbackController.java @@ -7,10 +7,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; import uk.gov.hmcts.reform.civil.enums.FeeType; import uk.gov.hmcts.reform.civil.exceptions.InternalServerErrorException; import uk.gov.hmcts.reform.civil.model.ServiceRequestUpdateDto; +import uk.gov.hmcts.reform.civil.service.AuthorisationService; import uk.gov.hmcts.reform.civil.service.PaymentRequestUpdateCallbackService; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; @@ -22,6 +24,8 @@ public class ServiceRequestUpdateCallbackController { private final PaymentRequestUpdateCallbackService requestUpdateCallbackService; + private final AuthorisationService authorisationService; + @PutMapping(path = "/service-request-update", consumes = APPLICATION_JSON, produces = APPLICATION_JSON) @Operation(summary = "Ways to pay will call this API and send the status of payment with other details") @ApiResponses(value = { @@ -29,9 +33,15 @@ public class ServiceRequestUpdateCallbackController { @ApiResponse(responseCode = "400", description = "Bad Request"), @ApiResponse(responseCode = "500", description = "Internal Server Error") }) - public void serviceRequestUpdate(@RequestBody ServiceRequestUpdateDto serviceRequestUpdateDto) { + public void serviceRequestUpdate( + @RequestHeader("ServiceAuthorization") String s2sToken, + @RequestBody ServiceRequestUpdateDto serviceRequestUpdateDto) { try { - requestUpdateCallbackService.processCallback(serviceRequestUpdateDto, FeeType.HEARING.name()); + if (authorisationService.isServiceAuthorized(s2sToken)) { + requestUpdateCallbackService.processCallback(serviceRequestUpdateDto, FeeType.HEARING.name()); + } else { + throw (new RuntimeException("Invalid Client")); + } } catch (Exception ex) { log.error( "Payment callback is unsuccessful for the CaseID: {}", diff --git a/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackController.java b/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackController.java index 9627d311f54..8230424a778 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackController.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/controllers/fees/ServiceRequestUpdateClaimIssuedCallbackController.java @@ -7,10 +7,12 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; import uk.gov.hmcts.reform.civil.enums.FeeType; import uk.gov.hmcts.reform.civil.exceptions.InternalServerErrorException; import uk.gov.hmcts.reform.civil.model.ServiceRequestUpdateDto; +import uk.gov.hmcts.reform.civil.service.AuthorisationService; import uk.gov.hmcts.reform.civil.service.PaymentRequestUpdateCallbackService; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; @@ -22,14 +24,21 @@ public class ServiceRequestUpdateClaimIssuedCallbackController { private final PaymentRequestUpdateCallbackService requestUpdateCallbackService; + private final AuthorisationService authorisationService; + @PutMapping(path = "/service-request-update-claim-issued", consumes = APPLICATION_JSON, produces = APPLICATION_JSON) @Operation(summary = "Ways to pay will call this API and send the status of payment with other details") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Callback processed."), @ApiResponse(responseCode = "400", description = "Bad Request")}) - public void serviceRequestUpdate(@RequestBody ServiceRequestUpdateDto serviceRequestUpdateDto) { + public void serviceRequestUpdate(@RequestHeader("ServiceAuthorization") String s2sToken, + @RequestBody ServiceRequestUpdateDto serviceRequestUpdateDto) { try { - requestUpdateCallbackService.processCallback(serviceRequestUpdateDto, FeeType.CLAIMISSUED.name()); + if (authorisationService.isServiceAuthorized(s2sToken)) { + requestUpdateCallbackService.processCallback(serviceRequestUpdateDto, FeeType.CLAIMISSUED.name()); + } else { + throw (new RuntimeException("Invalid Client")); + } } catch (Exception ex) { log.error( "Payment callback is unsuccessful for the CaseID: {}", diff --git a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandler.java b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandler.java index 7b1929169e4..43e1f27e4f0 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandler.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandler.java @@ -11,6 +11,7 @@ import uk.gov.hmcts.reform.ccd.client.model.SubmittedCallbackResponse; import uk.gov.hmcts.reform.ccd.model.OrganisationPolicy; import uk.gov.hmcts.reform.civil.callback.Callback; +import uk.gov.hmcts.reform.civil.callback.CallbackException; import uk.gov.hmcts.reform.civil.callback.CallbackHandler; import uk.gov.hmcts.reform.civil.callback.CallbackParams; import uk.gov.hmcts.reform.civil.callback.CaseEvent; @@ -20,12 +21,15 @@ import uk.gov.hmcts.reform.civil.enums.ClaimType; import uk.gov.hmcts.reform.civil.enums.YesOrNo; import uk.gov.hmcts.reform.civil.model.Address; +import uk.gov.hmcts.reform.civil.service.AirlineEpimsDataLoader; +import uk.gov.hmcts.reform.civil.model.AirlineEpimsId; import uk.gov.hmcts.reform.civil.model.BusinessProcess; import uk.gov.hmcts.reform.civil.model.CaseData; import uk.gov.hmcts.reform.civil.model.CaseManagementCategory; import uk.gov.hmcts.reform.civil.model.CaseManagementCategoryElement; import uk.gov.hmcts.reform.civil.model.ClaimAmountBreakup; import uk.gov.hmcts.reform.civil.model.CorrectEmail; +import uk.gov.hmcts.reform.civil.model.FlightDelayDetails; import uk.gov.hmcts.reform.civil.model.IdamUserDetails; import uk.gov.hmcts.reform.civil.model.Party; import uk.gov.hmcts.reform.civil.model.PaymentDetails; @@ -37,8 +41,11 @@ import uk.gov.hmcts.reform.civil.model.common.Element; import uk.gov.hmcts.reform.civil.model.defaultjudgment.CaseLocationCivil; import uk.gov.hmcts.reform.civil.prd.model.Organisation; +import uk.gov.hmcts.reform.civil.referencedata.LocationRefDataService; +import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; import uk.gov.hmcts.reform.civil.repositories.ReferenceNumberRepository; import uk.gov.hmcts.reform.civil.repositories.SpecReferenceNumberRepository; +import uk.gov.hmcts.reform.civil.service.AirlineEpimsService; import uk.gov.hmcts.reform.civil.service.ExitSurveyContentService; import uk.gov.hmcts.reform.civil.service.FeatureToggleService; import uk.gov.hmcts.reform.civil.service.FeesService; @@ -156,6 +163,10 @@ public class CreateClaimSpecCallbackHandler extends CallbackHandler implements P + "to : OCMCNton@justice.gov.uk. The Certificate of Service form can be found here:" + "%n%n"; + private static final String ERROR_MESSAGE_SCHEDULED_DATE_OF_FLIGHT_MUST_BE_TODAY_OR_IN_THE_PAST = "Scheduled date of flight must be today or in the past"; + + private static final String LOCATION_NOT_FOUND_MESSAGE = "Location not found for ePIMS_ID: %s"; + private final ClaimUrlsConfiguration claimUrlsConfiguration; private final ExitSurveyContentService exitSurveyContentService; private final ReferenceNumberRepository referenceNumberRepository; @@ -176,7 +187,10 @@ public class CreateClaimSpecCallbackHandler extends CallbackHandler implements P private final StateFlowEngine stateFlowEngine; private final CaseFlagsInitialiser caseFlagInitialiser; private final ToggleConfiguration toggleConfiguration; + private final LocationRefDataService locationRefDataService; private final String caseDocLocation = "/cases/case-details/%s#CaseDocuments"; + private final AirlineEpimsDataLoader airlineEpimsDataLoader; + private final AirlineEpimsService airlineEpimsService; @Value("${court-location.specified-claim.region-id}") private String regionId; @@ -232,6 +246,8 @@ protected Map callbacks() { .put(callbackKey(MID, "validate-spec-defendant-legal-rep-email"), this::validateSpecRespondentRepEmail) .put(callbackKey(MID, "validate-spec-defendant2-legal-rep-email"), this::validateSpecRespondent2RepEmail) .put(callbackKey(MID, "is-flight-delay-claim"), this::isFlightDelayClaim) + .put(callbackKey(MID, "get-airline-list"), this::getAirlineList) + .put(callbackKey(MID, "validate-date-of-flight"), this::validateDateOfFlight) .build(); } @@ -523,7 +539,6 @@ private CallbackResponse submitClaim(CallbackParams callbackParams) { populateWithPartyIds(dataBuilder); } - List errors = new ArrayList<>(); if (caseData.getSdtRequestIdFromSdt() != null) { // assign StdRequestId, to ensure duplicate requests from SDT/bulk claims are not processed List> stdRequestIdList = new ArrayList<>(); @@ -540,6 +555,7 @@ private CallbackResponse submitClaim(CallbackParams callbackParams) { .build()).build()); } + List errors = new ArrayList<>(); if (getMultiPartyScenario(caseData) == ONE_V_TWO_ONE_LEGAL_REP && caseData.getSpecRespondentCorrespondenceAddressdetails() != null) { // to keep with heading tab @@ -550,6 +566,19 @@ private CallbackResponse submitClaim(CallbackParams callbackParams) { caseData.getSpecRespondentCorrespondenceAddressdetails()); } + if ((toggleService.isSdoR2Enabled() && callbackParams.getCaseData().getFlightDelayDetails() != null)) { + FlightDelayDetails flightDelayDetails = callbackParams.getCaseData().getFlightDelayDetails(); + String selectedAirlineCode = flightDelayDetails.getAirlineList().getValue().getCode(); + + dataBuilder.flightDelayDetails(FlightDelayDetails.builder() + .airlineList(DynamicList.builder().value(flightDelayDetails.getAirlineList().getValue()).build()) + .nameOfAirline(flightDelayDetails.getNameOfAirline()) + .flightNumber(flightDelayDetails.getFlightNumber()) + .scheduledDate(flightDelayDetails.getScheduledDate()) + .flightCourtLocation(getAirlineCaseLocation(selectedAirlineCode, callbackParams)) + .build()); + } + return AboutToStartOrSubmitCallbackResponse.builder() .errors(errors) .data(dataBuilder.build().toMap(objectMapper)) @@ -917,6 +946,36 @@ private CallbackResponse isFlightDelayClaim(CallbackParams callbackParams) { .build(); } + private CallbackResponse getAirlineList(CallbackParams callbackParams) { + CaseData.CaseDataBuilder caseDataBuilder = callbackParams.getCaseData().toBuilder(); + List airlineEpimsIDList = new ArrayList<>(airlineEpimsDataLoader.getAirlineEpimsIDList()); + DynamicList airlineList = DynamicList + .fromList(airlineEpimsIDList.stream() + .map(AirlineEpimsId::getAirline).toList(), Object::toString, Object::toString, null, false); + DynamicList dropdownAirlineList = DynamicList.builder() + .listItems(airlineList.getListItems()).build(); + + FlightDelayDetails flightDelayDetails = FlightDelayDetails.builder().airlineList(dropdownAirlineList).build(); + caseDataBuilder.flightDelayDetails(flightDelayDetails); + return AboutToStartOrSubmitCallbackResponse.builder() + .data(caseDataBuilder.build().toMap(objectMapper)) + .build(); + } + + private CallbackResponse validateDateOfFlight(CallbackParams callbackParams) { + CaseData.CaseDataBuilder caseDataBuilder = callbackParams.getCaseData().toBuilder(); + List errors = new ArrayList<>(); + LocalDate today = LocalDate.now(); + LocalDate scheduledDate = callbackParams.getCaseData().getFlightDelayDetails().getScheduledDate(); + if (scheduledDate.isAfter(today)) { + errors.add(ERROR_MESSAGE_SCHEDULED_DATE_OF_FLIGHT_MUST_BE_TODAY_OR_IN_THE_PAST); + } + return AboutToStartOrSubmitCallbackResponse.builder() + .data(caseDataBuilder.build().toMap(objectMapper)) + .errors(errors) + .build(); + } + private CallbackResponse setRespondent2SameLegalRepToNo(CallbackParams callbackParams) { CaseData.CaseDataBuilder caseDataBuilder = callbackParams.getCaseData().toBuilder(); @@ -943,4 +1002,25 @@ private boolean areRespondentsRepresentedAndRegistered(CaseData caseData) { || caseData.getRespondent2Represented() == NO || caseData.getRespondent2OrgRegistered() == NO); } + + private CaseLocationCivil getAirlineCaseLocation(String airline, CallbackParams callbackParams) { + if (airline.equals("OTHER")) { + return null; + } + String locationEpimmsId = airlineEpimsService.getEpimsIdForAirline(airline); + List locations = fetchLocationData(callbackParams); + var matchedLocations = locations.stream().filter(loc -> loc.getEpimmsId().equals(locationEpimmsId)).toList(); + if (matchedLocations.isEmpty()) { + throw new CallbackException(String.format(LOCATION_NOT_FOUND_MESSAGE, locationEpimmsId)); + } else { + return CaseLocationCivil.builder() + .region(matchedLocations.get(0).getRegionId()) + .baseLocation(matchedLocations.get(0).getEpimmsId()).build(); + } + } + + private List fetchLocationData(CallbackParams callbackParams) { + String authToken = callbackParams.getParams().get(BEARER_TOKEN).toString(); + return locationRefDataService.getCourtLocationsForDefaultJudgments(authToken); + } } diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/AirlineEpimsId.java b/src/main/java/uk/gov/hmcts/reform/civil/model/AirlineEpimsId.java new file mode 100644 index 00000000000..d03bb5bdc02 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/AirlineEpimsId.java @@ -0,0 +1,14 @@ +package uk.gov.hmcts.reform.civil.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +@AllArgsConstructor +public class AirlineEpimsId { + + String airline; + String epimsID; +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/CaseData.java b/src/main/java/uk/gov/hmcts/reform/civil/model/CaseData.java index 7eaee138a62..caa3f46a47b 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/model/CaseData.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/CaseData.java @@ -638,6 +638,7 @@ public boolean hasNoOngoingBusinessProcess() { //SDO-R2 private YesOrNo isFlightDelayClaim; + private FlightDelayDetails flightDelayDetails; /** * There are several fields that can hold the I2P of applicant1 depending diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/FlightDelayDetails.java b/src/main/java/uk/gov/hmcts/reform/civil/model/FlightDelayDetails.java new file mode 100644 index 00000000000..514f0f0ab52 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/FlightDelayDetails.java @@ -0,0 +1,23 @@ +package uk.gov.hmcts.reform.civil.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import uk.gov.hmcts.reform.civil.model.common.DynamicList; +import uk.gov.hmcts.reform.civil.model.defaultjudgment.CaseLocationCivil; + +import java.time.LocalDate; + +@Data +@Builder(toBuilder = true) +@NoArgsConstructor +@AllArgsConstructor +public class FlightDelayDetails { + + private DynamicList airlineList; + private String nameOfAirline; + private String flightNumber; + private LocalDate scheduledDate; + private CaseLocationCivil flightCourtLocation; +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimMatcher.java b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimantClaimMatcher.java similarity index 99% rename from src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimMatcher.java rename to src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimantClaimMatcher.java index fe45e29d735..0b6bb762b99 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimMatcher.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardClaimantClaimMatcher.java @@ -18,7 +18,7 @@ @Slf4j @AllArgsConstructor -public class CcdDashboardClaimMatcher implements Claim { +public class CcdDashboardClaimantClaimMatcher implements Claim { private static final LocalTime FOUR_PM = LocalTime.of(16, 1, 0); private CaseData caseData; diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardDefendantClaimMatcher.java b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardDefendantClaimMatcher.java new file mode 100644 index 00000000000..03a1ebab9d1 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdDashboardDefendantClaimMatcher.java @@ -0,0 +1,297 @@ +package uk.gov.hmcts.reform.civil.model.citizenui; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import uk.gov.hmcts.reform.civil.enums.CaseState; +import uk.gov.hmcts.reform.civil.enums.RespondentResponsePartAdmissionPaymentTimeLRspec; +import uk.gov.hmcts.reform.civil.enums.RespondentResponseTypeSpec; +import uk.gov.hmcts.reform.civil.enums.YesOrNo; +import uk.gov.hmcts.reform.civil.model.CaseData; +import uk.gov.hmcts.reform.civil.model.sdo.FastTrackHearingTime; +import uk.gov.hmcts.reform.civil.model.sdo.SmallClaimsHearing; +import uk.gov.hmcts.reform.civil.service.FeatureToggleService; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Objects; +import java.util.Optional; + +@Slf4j +@AllArgsConstructor +public class CcdDashboardDefendantClaimMatcher implements Claim { + + private static final LocalTime FOUR_PM = LocalTime.of(16, 1, 0); + private CaseData caseData; + private FeatureToggleService featureToggleService; + + @Override + public boolean hasResponsePending() { + return caseData.getRespondent1ResponseDate() == null && !isPaperResponse(); + } + + @Override + public boolean hasResponsePendingOverdue() { + return caseData.getRespondent1ResponseDeadline() != null + && caseData.getRespondent1ResponseDeadline().isBefore(LocalDate.now().atTime(FOUR_PM)) + && caseData.hasBreathingSpace(); + } + + @Override + public boolean hasResponseDueToday() { + return caseData.getRespondent1ResponseDeadline() != null + && caseData.getRespondent1ResponseDeadline().toLocalDate().isEqual(LocalDate.now()) + && caseData.getRespondent1ResponseDeadline().isBefore(LocalDate.now().atTime(FOUR_PM)); + } + + @Override + public boolean hasResponseFullAdmit() { + return caseData.getRespondent1ClaimResponseTypeForSpec() != null + && caseData.getRespondent1ClaimResponseTypeForSpec() == RespondentResponseTypeSpec.FULL_ADMISSION; + } + + @Override + public boolean defendantRespondedWithFullAdmitAndPayImmediately() { + return hasResponseFullAdmit() + && isPayImmediately(); + } + + @Override + public boolean defendantRespondedWithFullAdmitAndPayBySetDate() { + return hasResponseFullAdmit() + && caseData.isPayBySetDate() + && (Objects.isNull(caseData.getApplicant1AcceptFullAdmitPaymentPlanSpec())); + } + + @Override + public boolean defendantRespondedWithFullAdmitAndPayByInstallments() { + return hasResponseFullAdmit() + && caseData.isPayByInstallment() + && (Objects.isNull(caseData.getApplicant1AcceptFullAdmitPaymentPlanSpec())); + } + + @Override + public boolean hasResponseDeadlineBeenExtended() { + return caseData.getRespondent1TimeExtensionDate() != null; + } + + @Override + public boolean isEligibleForCCJ() { + return caseData.getRespondent1ResponseDeadline() != null + && caseData.getRespondent1ResponseDeadline().isBefore(LocalDate.now().atTime(FOUR_PM)) + && caseData.getPaymentTypeSelection() == null; + } + + @Override + public boolean claimantConfirmedDefendantPaid() { + return caseData.getRespondent1CourtOrderPayment() != null && caseData.respondent1PaidInFull(); + } + + @Override + public boolean isSettled() { + return !caseData.isRespondentResponseFullDefence() + && (caseData.respondent1PaidInFull() + || caseData.isResponseAcceptedByClaimant()) + && Objects.isNull(caseData.getCcjPaymentDetails()) + && !caseData.hasApplicantRejectedRepaymentPlan() + || caseData.isPartAdmitClaimSettled(); + } + + @Override + public boolean isSentToCourt() { + return false; + } + + @Override + public boolean claimantRequestedCountyCourtJudgement() { + return caseData.getApplicant1DQ() != null && caseData.getApplicant1DQ().getApplicant1DQRequestedCourt() != null + && !hasSdoBeenDrawn(); + } + + @Override + public boolean isWaitingForClaimantToRespond() { + return RespondentResponseTypeSpec.FULL_DEFENCE == caseData.getRespondent1ClaimResponseTypeForSpec() + && caseData.getApplicant1ResponseDate() == null; + } + + @Override + public boolean isProceedOffline() { + return false; + } + + @Override + public boolean isPaperResponse() { + if (!featureToggleService.isLipVLipEnabled()) { + return false; + } + + return Objects.nonNull(caseData.getTakenOfflineDate()) && Objects.nonNull(caseData.getCcdState()) + && caseData.getCcdState().equals(CaseState.PROCEEDS_IN_HERITAGE_SYSTEM); + } + + @Override + public boolean hasChangeRequestFromDefendant() { + return false; + } + + @Override + public boolean hasChangeRequestedFromClaimant() { + return false; + } + + @Override + public boolean isPassedToCountyCourtBusinessCentre() { + return false; + } + + @Override + public boolean hasClaimantAskedToSignSettlementAgreement() { + return false; + } + + @Override + public boolean hasClaimantAcceptedPartialAdmissionAmount() { + return hasDefendantStatedTheyPaid() && caseData.isResponseAcceptedByClaimant(); + } + + @Override + public boolean haveBothPartiesSignedSettlementAgreement() { + return false; + } + + @Override + public boolean hasCCJByRedetermination() { + return caseData.hasApplicantAcceptedRepaymentPlan(); + } + + @Override + public boolean hasDefendantStatedTheyPaid() { + return defendantRespondedWithPartAdmit() + && isPayImmediately() && !caseData.getApplicant1ResponseDeadlinePassed() + && !(caseData.hasApplicantRejectedRepaymentPlan() || caseData.isPartAdmitClaimNotSettled()); + } + + private boolean isPayImmediately() { + return RespondentResponsePartAdmissionPaymentTimeLRspec.IMMEDIATELY == caseData.getDefenceAdmitPartPaymentTimeRouteRequired(); + } + + @Override + public boolean defendantRespondedWithPartAdmit() { + return RespondentResponseTypeSpec.PART_ADMISSION == caseData.getRespondent1ClaimResponseTypeForSpec() + && !caseData.getApplicant1ResponseDeadlinePassed() + && !(caseData.hasApplicantRejectedRepaymentPlan() || caseData.isPartAdmitClaimNotSettled()); + } + + @Override + public boolean isHearingFormGenerated() { + return !caseData.getHearingDocuments().isEmpty(); + } + + @Override + public boolean hasSdoBeenDrawn() { + return caseData.getSDODocument().isPresent(); + } + + @Override + public boolean isBeforeHearing() { + return isBeforeSmallClaimHearing() || (isBeforeFastTrackHearing() || noHearingScheduled()); + } + + private boolean noHearingScheduled() { + return caseData.getSmallClaimsHearing() == null && caseData.getFastTrackHearingTime() == null; + } + + private boolean isBeforeSmallClaimHearing() { + return Optional.ofNullable(caseData.getSmallClaimsHearing()) + .map(SmallClaimsHearing::getDateFrom) + .map(hearingFromDate -> hearingFromDate.isAfter(LocalDate.now())) + .orElse(false); + } + + private boolean isBeforeFastTrackHearing() { + return Optional.ofNullable(caseData.getFastTrackHearingTime()) + .map(FastTrackHearingTime::getDateFrom) + .map(hearingFromDate -> hearingFromDate.isAfter(LocalDate.now())) + .orElse(false); + } + + @Override + public boolean isMoreDetailsRequired() { + return hasSdoBeenDrawn() && isBeforeHearing() && featureToggleService.isCaseProgressionEnabled(); + } + + @Override + public boolean isMediationSuccessful() { + return !hasSdoBeenDrawn() + && Objects.nonNull(caseData.getMediation()) + && Objects.nonNull(caseData.getMediation().getMediationSuccessful()) + && Objects.nonNull(caseData.getMediation().getMediationSuccessful().getMediationAgreement()); + } + + @Override + public boolean isMediationUnsuccessful() { + return !hasSdoBeenDrawn() + && Objects.nonNull(caseData.getMediation()) + && Objects.nonNull(caseData.getMediation().getUnsuccessfulMediationReason()) + && !caseData.getMediation().getUnsuccessfulMediationReason().isEmpty(); + } + + @Override + public boolean isMediationPending() { + return Objects.nonNull(caseData.getCcdState()) + && caseData.getCcdState().equals(CaseState.IN_MEDIATION) + && Objects.nonNull(caseData.getMediation()) + && Objects.nonNull(caseData.getMediation().getMediationSuccessful()) + && Objects.isNull(caseData.getMediation().getMediationSuccessful().getMediationAgreement()); + } + + @Override + public boolean isCourtReviewing() { + return (!hasSdoBeenDrawn() + && caseData.isRespondentResponseFullDefence() + && caseData.getCcdState().equals(CaseState.JUDICIAL_REFERRAL)) + || (caseData.hasApplicantRejectedRepaymentPlan()); + } + + @Override + public boolean hasClaimEnded() { + return (Objects.nonNull(caseData.getApplicant1ProceedsWithClaimSpec()) + && caseData.getApplicant1ProceedsWithClaimSpec().equals(YesOrNo.NO) + && caseData.isRespondentResponseFullDefence()) + || caseData.getApplicant1ResponseDeadlinePassed(); + } + + @Override + public boolean isClaimRejectedAndOfferSettleOutOfCourt() { + return false; + } + + @Override + public boolean claimantAcceptedOfferOutOfCourt() { + return false; + } + + @Override + public boolean hasClaimantRejectOffer() { + return false; + } + + @Override + public boolean isPartialAdmissionRejected() { + return CaseState.JUDICIAL_REFERRAL.equals(caseData.getCcdState()) + && caseData.isPartAdmitClaimSpec(); + } + + @Override + public boolean isSDOOrderCreated() { + return caseData.getHearingDate() == null + && CaseState.CASE_PROGRESSION.equals(caseData.getCcdState()); + } + + @Override + public boolean isClaimantDefaultJudgement() { + return caseData.getRespondent1ResponseDeadline() != null + && caseData.getRespondent1ResponseDeadline().isBefore(LocalDate.now().atTime(FOUR_PM)) + && caseData.getPaymentTypeSelection() != null; + } + +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ChooseHowToProceed.java b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ChooseHowToProceed.java new file mode 100644 index 00000000000..c163aec3d5e --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ChooseHowToProceed.java @@ -0,0 +1,6 @@ +package uk.gov.hmcts.reform.civil.model.citizenui; + +public enum ChooseHowToProceed { + SIGN_A_SETTLEMENT_AGREEMENT, + REQUEST_A_CCJ, +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ClaimantLiPResponse.java b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ClaimantLiPResponse.java index 782131ceb90..63d103d80b8 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ClaimantLiPResponse.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/model/citizenui/ClaimantLiPResponse.java @@ -16,6 +16,7 @@ public class ClaimantLiPResponse { private DQExtraDetailsLip applicant1DQExtraDetails; private HearingSupportLip applicant1DQHearingSupportLip; private YesOrNo applicant1SignedSettlementAgreement; + private ChooseHowToProceed applicant1ChoosesHowToProceed; @JsonIgnore public boolean hasApplicant1SignedSettlementAgreement() { diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoader.java b/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoader.java new file mode 100644 index 00000000000..718c4755838 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoader.java @@ -0,0 +1,44 @@ +package uk.gov.hmcts.reform.civil.service; + +import com.google.common.collect.ImmutableList; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import com.opencsv.CSVReader; +import com.opencsv.exceptions.CsvException; +import uk.gov.hmcts.reform.civil.model.AirlineEpimsId; + +@Service +@Slf4j +public class AirlineEpimsDataLoader { + + private static final String CSV_FILE_PATH = "airline_ePimsID_csv/airline_ePimsID.csv"; + private final List airlineEpimsIDList = new ArrayList<>(); + + @PostConstruct + protected void init() { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(CSV_FILE_PATH); + try (CSVReader reader = new CSVReader(new InputStreamReader(inputStream))) { + + List linesList = reader.readAll(); + linesList.forEach(line -> { + AirlineEpimsId airlineEpimsID = AirlineEpimsId.builder() + .airline(line[0]) + .epimsID(line[1]) + .build(); + airlineEpimsIDList.add(airlineEpimsID); + }); + } catch (IOException | CsvException e) { + log.error("Error occurred while loading the airline_ePimsID.csv file: " + CSV_FILE_PATH + e); + } + } + + public List getAirlineEpimsIDList() { + return ImmutableList.copyOf(airlineEpimsIDList); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsService.java b/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsService.java new file mode 100644 index 00000000000..00e47a34789 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsService.java @@ -0,0 +1,22 @@ +package uk.gov.hmcts.reform.civil.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import uk.gov.hmcts.reform.civil.model.AirlineEpimsId; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class AirlineEpimsService { + + private final AirlineEpimsDataLoader airlineEpimsDataLoader; + + public String getEpimsIdForAirline(String airline) { + AirlineEpimsId airlineEpimsID = airlineEpimsDataLoader.getAirlineEpimsIDList() + .stream().filter(item -> item.getAirline().equals(airline)).findFirst().orElse(null); + + return Optional.ofNullable(airlineEpimsID) + .map(AirlineEpimsId::getEpimsID) + .orElseThrow(() -> new IllegalStateException("Unable to find epims ID for airline: " + airline)); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/AuthorisationService.java b/src/main/java/uk/gov/hmcts/reform/civil/service/AuthorisationService.java new file mode 100644 index 00000000000..b50f8c1f597 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/AuthorisationService.java @@ -0,0 +1,65 @@ +package uk.gov.hmcts.reform.civil.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import uk.gov.hmcts.reform.authorisation.ServiceAuthorisationApi; +import uk.gov.hmcts.reform.idam.client.IdamClient; +import uk.gov.hmcts.reform.idam.client.models.UserInfo; + +import java.util.List; + +@Service +@Slf4j +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class AuthorisationService { + + private final ServiceAuthorisationApi serviceAuthorisationApi; + + @Value("${civil.authorised-services}") + private List s2sAuthorisedServices; + + private final IdamClient idamClient; + + private UserInfo userInfo; + + public Boolean authoriseService(String serviceAuthHeader) { + String callingService; + try { + String bearerJwt = serviceAuthHeader.startsWith("Bearer ") ? serviceAuthHeader : "Bearer " + serviceAuthHeader; + callingService = serviceAuthorisationApi.getServiceName(bearerJwt); + log.info("Calling Service... {}", callingService); + return (callingService != null && s2sAuthorisedServices.contains(callingService)); + } catch (Exception ex) { + //do nothing + log.error("S2S token is not authorised" + ex); + } + return false; + } + + public Boolean authoriseUser(String authorisation) { + try { + userInfo = idamClient.getUserInfo(authorisation); + return (null != userInfo); + } catch (Exception ex) { + //do nothing + log.error("User token is invalid"); + } + return false; + } + + public UserInfo getUserInfo() { + return this.userInfo; + } + + public boolean isServiceAndUserAuthorized(String authorisation, String s2sToken) { + return Boolean.TRUE.equals(authoriseUser(authorisation)) + && Boolean.TRUE.equals(authoriseService(s2sToken)); + } + + public boolean isServiceAuthorized(String s2sToken) { + return Boolean.TRUE.equals(authoriseService(s2sToken)); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/citizenui/DashboardClaimInfoService.java b/src/main/java/uk/gov/hmcts/reform/civil/service/citizenui/DashboardClaimInfoService.java index 058ab6c0eb8..80c31e0759f 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/service/citizenui/DashboardClaimInfoService.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/citizenui/DashboardClaimInfoService.java @@ -7,8 +7,10 @@ import uk.gov.hmcts.reform.ccd.client.model.SearchResult; import uk.gov.hmcts.reform.civil.helpers.CaseDetailsConverter; import uk.gov.hmcts.reform.civil.model.CaseData; -import uk.gov.hmcts.reform.civil.model.citizenui.CcdDashboardClaimMatcher; +import uk.gov.hmcts.reform.civil.model.citizenui.CcdDashboardClaimantClaimMatcher; +import uk.gov.hmcts.reform.civil.model.citizenui.CcdDashboardDefendantClaimMatcher; import uk.gov.hmcts.reform.civil.model.citizenui.DashboardClaimInfo; +import uk.gov.hmcts.reform.civil.model.citizenui.DashboardClaimStatus; import uk.gov.hmcts.reform.civil.model.citizenui.DashboardClaimStatusFactory; import uk.gov.hmcts.reform.civil.model.citizenui.DashboardResponse; import uk.gov.hmcts.reform.civil.service.CoreCaseDataService; @@ -54,7 +56,7 @@ public DashboardResponse getDashboardDefendantResponse(String authorisation, Str var ccdData = coreCaseDataService.getCCDClaimsForLipDefendant(authorisation, startIndex); int totalPages = getTotalPagesToBeListed(ccdData.getTotal() + ocmcClaims.size()); List currentPageItems = currentPage <= totalPages - ? getDashboardItemsForCurrentPage(ocmcClaims, currentPage, ccdData) : + ? getDashboardItemsForCurrentPage(ocmcClaims, currentPage, ccdData, false) : Collections.emptyList(); return DashboardResponse.builder().totalPages(totalPages).claims(currentPageItems).build(); } @@ -71,7 +73,7 @@ public DashboardResponse getDashboardClaimantResponse(String authorisation, Stri int totalPages = getTotalPagesToBeListed(getCcdClaimsCount(ccdData) + ocmcClaims.size()); List currentPageItems = currentPage <= totalPages - ? getDashboardItemsForCurrentPage(ocmcClaims, currentPage, ccdData) : + ? getDashboardItemsForCurrentPage(ocmcClaims, currentPage, ccdData, true) : Collections.emptyList(); return DashboardResponse.builder().totalPages(totalPages).claims(currentPageItems).build(); } @@ -84,7 +86,8 @@ private List getClaimsForClaimant(String authorisation, Stri private List getDashboardItemsForCurrentPage(List ocmcClaims, int currentPage, - SearchResult ccdClaims) { + SearchResult ccdClaims, + boolean isClaimant) { int startIndex = (currentPage - 1) * CASES_PER_PAGE; int endIndex = startIndex + CASES_PER_PAGE; @@ -96,7 +99,7 @@ private List getDashboardItemsForCurrentPage(List ccdClaimsCount) { int remainingRecords = CASES_PER_PAGE - ccdData.size(); @@ -114,16 +117,19 @@ private List sortOcmcCases(List ocmcCase .collect(Collectors.toList()); } - private List translateSearchResultToDashboardItems(SearchResult claims) { + private List translateSearchResultToDashboardItems(SearchResult claims, boolean isClaimant) { if (claims == null) { return Collections.emptyList(); } - return claims.getCases().stream().map(caseDetails -> translateCaseDataToDashboardClaimInfo(caseDetails)) + return claims.getCases().stream().map(caseDetails -> translateCaseDataToDashboardClaimInfo( + caseDetails, + isClaimant + )) .collect(Collectors.toList()); } - private DashboardClaimInfo translateCaseDataToDashboardClaimInfo(CaseDetails caseDetails) { + private DashboardClaimInfo translateCaseDataToDashboardClaimInfo(CaseDetails caseDetails, boolean isClaimant) { CaseData caseData = caseDetailsConverter.toCaseData(caseDetails); DashboardClaimInfo item = DashboardClaimInfo.builder().claimId(String.valueOf(caseData.getCcdCaseReference())) .createdDate(submittedDateToCreatedDate(caseData)) @@ -133,7 +139,7 @@ private DashboardClaimInfo translateCaseDataToDashboardClaimInfo(CaseDetails cas .claimAmount(nonNull(caseData.getTotalClaimAmount()) ? caseData.getTotalClaimAmount() : null) .admittedAmount(caseData.getPartAdmitPaidValuePounds()) .responseDeadlineTime(caseData.getRespondent1ResponseDeadline()) - .status(dashboardClaimStatusFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher(caseData, featureToggleService))) + .status(getStatus(isClaimant, caseData)) .build(); if (caseData.getRespondent1ResponseDeadline() != null) { item.setResponseDeadline(caseData.getRespondent1ResponseDeadline().toLocalDate()); @@ -170,4 +176,16 @@ private int getCcdClaimsCount(final SearchResult ccdClaims) { return Optional.ofNullable(ccdClaims).map(SearchResult::getTotal).orElse(0); } + + private DashboardClaimStatus getStatus(boolean isClaimant, CaseData caseData) { + return isClaimant + ? dashboardClaimStatusFactory.getDashboardClaimStatus(new CcdDashboardClaimantClaimMatcher( + caseData, + featureToggleService + )) + : dashboardClaimStatusFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( + caseData, + featureToggleService + )); + } } diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/DocmosisTemplates.java b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/DocmosisTemplates.java index 70238616c12..ef6dac12d29 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/DocmosisTemplates.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/DocmosisTemplates.java @@ -52,6 +52,10 @@ public enum DocmosisTemplates { DQ_LIP_RESPONSE("CV-SPC-HRN-ENG-LIP-01283.docx", "%s_directions_questionnaire_form_%s.pdf"), TRIAL_READY("CV-UNS-HRN-ENG-01247-10180.docx", "%s_%s_Trial_Arrangements.pdf"), HEARING_NOTICE_HMC("CV-UNS-HNO-ENG-01200.docx", "hearing_notice_%s.pdf"), + HEARING_SMALL_CLAIMS_AHN("CV-UNS-HNO-ENG-01202.docx", "hearing_small_claim_%s.pdf"), + HEARING_FAST_TRACK_AHN("CV-UNS-HNO-ENG-01203.docx", "hearing_fast_track_%s.pdf"), + HEARING_APPLICATION_AHN("CV-UNS-HNO-ENG-01204.docx", "hearing_application_%s.pdf"), + HEARING_OTHER_AHN("CV-UNS-HNO-ENG-01201.docx", "hearing_other_claim_%s.pdf"), // judge final Order FREE_FORM_ORDER_PDF("CV-UNS-DEC-ENG-01099.docx", "Order_%s.pdf"), ASSISTED_ORDER_PDF("CV-UNS-DEC-ENG-01283.docx", "Order_%s.pdf"); diff --git a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGenerator.java b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGenerator.java index ab243795384..29420287557 100644 --- a/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGenerator.java +++ b/src/main/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGenerator.java @@ -11,8 +11,10 @@ import uk.gov.hmcts.reform.civil.documentmanagement.model.CaseDocument; import uk.gov.hmcts.reform.civil.documentmanagement.model.DocumentType; import uk.gov.hmcts.reform.civil.documentmanagement.model.PDF; + import uk.gov.hmcts.reform.civil.referencedata.LocationRefDataService; import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; +import uk.gov.hmcts.reform.civil.service.FeatureToggleService; import uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates; import uk.gov.hmcts.reform.civil.service.docmosis.DocumentGeneratorService; import uk.gov.hmcts.reform.civil.service.docmosis.TemplateDataGenerator; @@ -28,9 +30,13 @@ import static java.util.Objects.isNull; import static java.util.Objects.nonNull; import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_APPLICATION; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_APPLICATION_AHN; import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_FAST_TRACK; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_FAST_TRACK_AHN; import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_OTHER; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_OTHER_AHN; import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_SMALL_CLAIMS; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_SMALL_CLAIMS_AHN; import static uk.gov.hmcts.reform.civil.utils.HearingUtils.formatHearingDuration; import static uk.gov.hmcts.reform.civil.utils.HearingUtils.getHearingTimeFormatted; import static uk.gov.hmcts.reform.civil.utils.HearingUtils.getHearingType; @@ -42,6 +48,7 @@ public class HearingFormGenerator implements TemplateDataGenerator private final DocumentManagementService documentManagementService; private final DocumentGeneratorService documentGeneratorService; private final AssignCategoryId assignCategoryId; + private final FeatureToggleService featureToggleService; private final LocationRefDataService locationRefDataService; private final CourtLocationUtils courtLocationUtils; @@ -121,15 +128,28 @@ private boolean checkReference(CaseData caseData) { } private DocmosisTemplates getTemplate(CaseData caseData) { - switch (caseData.getHearingNoticeList()) { - case SMALL_CLAIMS: - return HEARING_SMALL_CLAIMS; - case FAST_TRACK_TRIAL: - return HEARING_FAST_TRACK; - case HEARING_OF_APPLICATION: - return HEARING_APPLICATION; - default: - return HEARING_OTHER; + if (!featureToggleService.isAutomatedHearingNoticeEnabled()) { + switch (caseData.getHearingNoticeList()) { + case SMALL_CLAIMS: + return HEARING_SMALL_CLAIMS; + case FAST_TRACK_TRIAL: + return HEARING_FAST_TRACK; + case HEARING_OF_APPLICATION: + return HEARING_APPLICATION; + default: + return HEARING_OTHER; + } + } else { + switch (caseData.getHearingNoticeList()) { + case SMALL_CLAIMS: + return HEARING_SMALL_CLAIMS_AHN; + case FAST_TRACK_TRIAL: + return HEARING_FAST_TRACK_AHN; + case HEARING_OF_APPLICATION: + return HEARING_APPLICATION_AHN; + default: + return HEARING_OTHER_AHN; + } } } } diff --git a/src/main/resources/airline_ePimsID_csv/airline_ePimsID.csv b/src/main/resources/airline_ePimsID_csv/airline_ePimsID.csv new file mode 100644 index 00000000000..49d7c177ec2 --- /dev/null +++ b/src/main/resources/airline_ePimsID_csv/airline_ePimsID.csv @@ -0,0 +1,100 @@ +Aegean,298828 +Aer Lingus,621184 +Aeroflot,298828 +Aeromexico,621184 +Air Algerie,268374 +Air Baltic,317442 +Air Canada,298828 +Air China,36791 +Air Europa,20262 +Air France,298828 +Air India,36791 +Air Malta,298828 +Air Moldova,365554 +Air New Zealand,268374 +Air Portugal,701411 +Air Transat,20262 +All Nippon Airways,268374 +American Airlines,621184 +Aurigny,317442 +Austrian Airways,621184 +Avianca,365554 +Azerbaijan Airlines,268374 +BA/Cityflyer,621184 +Biman Bangladesh,345663 +Blue Air,345663 +Brussels,621184 +Bulgaria Air,298828 +Cathay Pacific,268374 +China Airlines,20262 +China Eastern,20262 +China Southern,621184 +Condor,701411 +Croatia Airlines,298828 +Delta,268374 +Eastern,317442 +Easyjet,365554 +Egyptair,268374 +El Al,20262 +Emirates,701411 +Etihad,345663 +Eurowings,621184 +Eva Air,20262 +Finnair,345663 +Garuda,621184 +Gulf Air,36791 +Iberia/Express,621184 +Icelandair,20262 +Iran Air,268374 +ITA,298828 +Japan Airlines,20262 +Jet2.com,701411 +JetBlue,317442 +Kenya Airways,298828 +KLM,298828 +Korean,20262 +Kuwait Airways,621184 +LATAM/JJ,298828 +Loganair,701411 +LOT,20262 +Lufthansa,621184 +Luxair,20262 +Malaysian,268374 +Middle East,20262 +Norse,317442 +Norweigan,317442 +Oman,701411 +Pakistan,36791 +Pegasus,365554 +Phillipine Airlines,317442 +Play,345663 +Qatar,345663 +Quantas,268374 +Royal Air Maroc,20262 +Royal Brunei,268374 +Royal Jordanian,36791 +Ryanair,345663 +SAS,298828 +SAS,621184 +Saudi Arabian Airlines,20262 +Saudia,20262 +Singapore Airlines,36791 +Sky Express,298828 +Smartwings,365554 +South African Airways,268374 +Sri Lankan,36791 +Swiss International,621184 +Thai Airways,20262 +TUI / Thomson ,365554 +Tunisair,268374 +Turkish,36791 +Ukraine International,36791 +United,621184 +Vietnam Airlines,20262 +Virgin,317442 +Vistara,268374 +Vueling,345663 +WestJet,317442 +Wideroe,298828 +WizzAir,345663 +OTHER, diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 29ac16b639e..15754b2d272 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -129,6 +129,7 @@ idam: s2s-auth: microservice: civil_service + document_management: userRoles: "caseworker-civil,caseworker-civil-solicitor" secured: ${DOCUMENT_MANAGEMENT_SECURED:true} @@ -158,6 +159,7 @@ civil: test-user: username: ${TEST_USERNAME:test@example.com} password: ${TEST_PASSWORD:Password12!} + authorised-services: ${CIVIL_S2S_AUTHORISED_SERVICES:payment_app,ccd_data,civil_service,civil-citizen-ui} core_case_data: api: diff --git a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandlerTest.java b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandlerTest.java index 40c83a10559..a8f216dcd76 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandlerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/handler/callback/user/CreateClaimSpecCallbackHandlerTest.java @@ -29,6 +29,13 @@ import uk.gov.hmcts.reform.civil.enums.YesOrNo; import uk.gov.hmcts.reform.civil.handler.callback.BaseCallbackHandlerTest; import uk.gov.hmcts.reform.civil.helpers.CaseDetailsConverter; +import uk.gov.hmcts.reform.civil.model.AirlineEpimsId; +import uk.gov.hmcts.reform.civil.service.AirlineEpimsDataLoader; +import uk.gov.hmcts.reform.civil.model.FlightDelayDetails; +import uk.gov.hmcts.reform.civil.referencedata.LocationRefDataService; +import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; +import uk.gov.hmcts.reform.civil.sampledata.LocationRefSampleDataBuilder; +import uk.gov.hmcts.reform.civil.service.AirlineEpimsService; import uk.gov.hmcts.reform.civil.service.FeatureToggleService; import uk.gov.hmcts.reform.civil.model.Address; import uk.gov.hmcts.reform.civil.model.CaseData; @@ -207,6 +214,15 @@ class CreateClaimSpecCallbackHandlerTest extends BaseCallbackHandlerTest { @MockBean private ToggleConfiguration toggleConfiguration; + @MockBean + protected LocationRefDataService locationRefDataService; + + @MockBean + private AirlineEpimsDataLoader airlineEpimsDataLoader; + + @MockBean + private AirlineEpimsService airlineEpimsService; + @Nested class AboutToStartCallback { @@ -1623,7 +1639,7 @@ void shouldReturnErrors_whenRequiredAddressIsYesAndNotValid() { } @Nested - class IsFlightDelayClaimMidCallback { + class FlightDelayDetailsMidCallbacks { @ParameterizedTest @ValueSource(booleans = {true, false}) void shouldSetIsFlightDelayClaim_whenPopulatedAndSdoR2Enabled(Boolean toggleStat) { @@ -1661,6 +1677,61 @@ void shouldSetIsFlightDelayClaim_whenPopulatedAndSdoR2Disabled() { assertThat(response.getData()).doesNotHaveToString("isFlightDelayClaim"); assertThat(response.getData()).doesNotHaveToString("claimType"); } + + @Test + void shouldGetAirlineList_whenRequired() { + // Given + List airlineEpimsIDList = new ArrayList<>(); + airlineEpimsIDList.add(AirlineEpimsId.builder().airline("BA/Cityflyer").epimsID("111000").build()); + airlineEpimsIDList.add(AirlineEpimsId.builder().airline("OTHER").epimsID("111111").build()); + + given(airlineEpimsDataLoader.getAirlineEpimsIDList()) + .willReturn(airlineEpimsIDList); + + CaseData caseData = CaseData.builder().build(); + CallbackParams params = callbackParamsOf(caseData, MID, "get-airline-list"); + + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getData()).extracting("flightDelayDetails").extracting("airlineList") + .extracting("list_items").asList().extracting("label") + .contains("BA/Cityflyer"); + + assertThat(response.getData()).extracting("flightDelayDetails").extracting("airlineList") + .extracting("list_items").asList().extracting("label") + .contains("OTHER"); + } + + @Test + void shouldReturnErrorWhenDateOfFlightIsInTheFuture() { + // Given + CaseData caseData = CaseData.builder() + .flightDelayDetails(FlightDelayDetails.builder().scheduledDate(now().plusDays(1)).build()).build(); + + CallbackParams params = callbackParamsOf(caseData, MID, "validate-date-of-flight"); + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getErrors()).contains("Scheduled date of flight must be today or in the past"); + } + + @ParameterizedTest + @ValueSource(ints = {0, 1}) + void shouldNotReturnErrorWhenDateOfFlightIsTodayOrInThePast(Integer days) { + // Given + CaseData caseData = CaseData.builder() + .flightDelayDetails(FlightDelayDetails.builder().scheduledDate(now().minusDays(days)).build()).build(); + + CallbackParams params = callbackParamsOf(caseData, MID, "validate-date-of-flight"); + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getErrors()).isEmpty(); + } } @Nested @@ -2099,6 +2170,63 @@ void shouldMoveStatementOfTruthToCorrectFieldAndResetUIField_whenInvoked() { .doesNotHaveToString("role"); } } + + @Nested + class GetAirlineCourtLocation extends LocationRefSampleDataBuilder { + + @BeforeEach + void mockAirlineEpimsData() { + given(airlineEpimsService.getEpimsIdForAirline("GULF_AIR")) + .willReturn("36791"); + + List locations = new ArrayList<>(); + locations.add(LocationRefData.builder().regionId("Site Name").epimmsId("36791") + .build()); + given(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) + .willReturn(locations); + + when(toggleService.isSdoR2Enabled()).thenReturn(true); + } + + @Test + void shouldReturnExpectedCourtLocation_whenAirlineExists() { + // Given + CaseData caseData = CaseDataBuilder.builder().atStateClaimDraft() + .flightDelay(FlightDelayDetails.builder() + .airlineList( + DynamicList.builder() + .value(DynamicListElement.builder().code("GULF_AIR").label("Gulf Air") + .build()).build()).build()).build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getData()).extracting("flightDelayDetails").extracting("flightCourtLocation").extracting("region").isEqualTo("Site Name"); + } + + @Test + void shouldReturnExpectedCourtLocation_whenOtherAirlineSelected() { + // Given + CaseData caseData = CaseDataBuilder.builder().atStateClaimDraft() + .flightDelay(FlightDelayDetails.builder() + .airlineList( + DynamicList.builder() + .value(DynamicListElement.builder().code("OTHER").label("OTHER") + .build()).build()).build()).build(); + CallbackParams params = callbackParamsOf(caseData, ABOUT_TO_SUBMIT); + + given(locationRefDataService.getCourtLocationsForDefaultJudgments(any())) + .willReturn(getSampleCourLocationsRefObject()); + + // When + var response = (AboutToStartOrSubmitCallbackResponse) handler.handle(params); + + // Then + assertThat(response.getData()).extracting("flightDelayDetails").extracting("flightCourtLocation").isNull(); + } + } } @Nested diff --git a/src/test/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdClaimStatusDashboardFactoryTest.java b/src/test/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdClaimStatusDashboardFactoryTest.java index 50208255a98..3b77acb3d44 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdClaimStatusDashboardFactoryTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/model/citizenui/CcdClaimStatusDashboardFactoryTest.java @@ -56,7 +56,7 @@ void given_hasResponsePending_whenGetStatus_thenReturnNoResponse() { .respondent1ResponseDeadline(LocalDate.now().plusDays(10).atTime(16, 0, 0)) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.NO_RESPONSE); } @@ -68,7 +68,7 @@ void given_isEligibleForCCJ_whenGetStatus_thenReturnEligibleForCCJStatus() { .respondent1ResponseDeadline(LocalDateTime.of(2022, 2, 2, 16, 0)) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.ELIGIBLE_FOR_CCJ); } @@ -81,7 +81,7 @@ void given_isEligibleForCCJ_whenGetStatus_thenReturnDefaultJudgementStatus() { .paymentTypeSelection(DJPaymentTypeSelection.IMMEDIATELY) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.DEFAULT_JUDGEMENT); } @@ -92,7 +92,7 @@ void given_hasResponseDueToday_whenGetStatus_thenReturnResponseDueNow() { .respondent1ResponseDeadline(LocalDate.now().atTime(10, 0, 0)) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.RESPONSE_DUE_NOW); } @@ -104,7 +104,7 @@ void given_moreTimeRequested_whenGetStatus_thenReturnMoreTimeRequested() { .respondent1TimeExtensionDate(LocalDateTime.now().plusDays(30)) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.MORE_TIME_REQUESTED); } @@ -113,7 +113,7 @@ void given_moreTimeRequested_whenGetStatus_thenReturnMoreTimeRequested() { void given_responseAdmitPayImmediately_whenGetStatus_thenReturnAdmitPayImmediately() { CaseData claim = getClaimWithFullAdmitResponse(RespondentResponsePartAdmissionPaymentTimeLRspec.IMMEDIATELY); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.ADMIT_PAY_IMMEDIATELY); } @@ -122,7 +122,7 @@ void given_responseAdmitPayImmediately_whenGetStatus_thenReturnAdmitPayImmediate void given_responseAdmitPayBySetDate_whenGetStatus_thenReturnAdmitPayBySetDate() { CaseData claim = getClaimWithFullAdmitResponse(RespondentResponsePartAdmissionPaymentTimeLRspec.BY_SET_DATE); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.ADMIT_PAY_BY_SET_DATE); } @@ -131,7 +131,7 @@ void given_responseAdmitPayBySetDate_whenGetStatus_thenReturnAdmitPayBySetDate() void given_responseAdmitPayByInstallments_whenGetStatus_thenReturnAdmitPayByInstallments() { CaseData claim = getClaimWithFullAdmitResponse(RespondentResponsePartAdmissionPaymentTimeLRspec.SUGGESTION_OF_REPAYMENT_PLAN); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.ADMIT_PAY_INSTALLMENTS); } @@ -145,7 +145,7 @@ void given_claimantConfirmedDefendantPaid_whenGetStatus_thenReturnClaimantAccept .respondent1ClaimResponsePaymentAdmissionForSpec(RespondentResponseTypeSpecPaidStatus.PAID_FULL_OR_MORE_THAN_CLAIMED_AMOUNT) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.CLAIMANT_ACCEPTED_STATES_PAID); } @@ -158,7 +158,7 @@ void given_defendantPayedInFull_whenGetStatus_thenReturnSettled() { .respondent1ClaimResponsePaymentAdmissionForSpec(RespondentResponseTypeSpecPaidStatus.PAID_FULL_OR_MORE_THAN_CLAIMED_AMOUNT) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.SETTLED); } @@ -171,7 +171,7 @@ void given_claimantAcceptedDefendantResponse_whenGetStatus_thenReturnSettled() { .applicant1AcceptAdmitAmountPaidSpec(YesOrNo.YES) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.SETTLED); } @@ -184,7 +184,7 @@ void given_claimantRequestedCountyCourtJudgement_whenGetStatus_thenReturnRequest .applicant1DQ(Applicant1DQ.builder().applicant1DQRequestedCourt(RequestedCourt.builder().build()).build()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.REQUESTED_COUNTRY_COURT_JUDGEMENT); } @@ -198,7 +198,7 @@ void given_claimantAcceptedAdmission_whenGetStatus_thenReturnRelevantStatus() { .defenceAdmitPartPaymentTimeRouteRequired(RespondentResponsePartAdmissionPaymentTimeLRspec.IMMEDIATELY) .applicant1AcceptPartAdmitPaymentPlanSpec(YesOrNo.YES) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.CLAIMANT_ACCEPTED_ADMISSION_OF_AMOUNT); } @@ -210,7 +210,7 @@ void given_defendantRespondedWithPartAdmit_whenGetStatus_thenReturnRelevantStatu .respondent1ResponseDate(LocalDateTime.now()) .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.PART_ADMISSION) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.DEFENDANT_PART_ADMIT); } @@ -223,7 +223,7 @@ void given_hearingNoticeDocumentIssued_whenGetStatus_thenReturnHearingFormGenera .documentName("testDoc") .build()).build())) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.HEARING_FORM_GENERATED); } @@ -244,7 +244,7 @@ void given_hearingDateForSmallClaimIsAfterToday_and_SDOBeenDrawn_whenGetStatus_m .systemGeneratedCaseDocuments(List.of(document)) .build(); given(featureToggleService.isCaseProgressionEnabled()).willReturn(true); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.MORE_DETAILS_REQUIRED); } @@ -265,7 +265,7 @@ void given_hearingDateForFastTrackClaimIsAfterToday_and_SDOBeenDrawn_whenGetStat .systemGeneratedCaseDocuments(List.of(document)) .build(); given(featureToggleService.isCaseProgressionEnabled()).willReturn(true); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.MORE_DETAILS_REQUIRED); } @@ -280,7 +280,7 @@ void given_mediation_whenGetSatus_mediationSuccessful() { .build()) .build()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.MEDIATION_SUCCESSFUL); } @@ -293,7 +293,7 @@ void given_mediation_whenGetStatus_mediationUnsuccessful() { .unsuccessfulMediationReason("this is a reason") .build()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.MEDIATION_UNSUCCESSFUL); } @@ -308,7 +308,7 @@ void given_mediation_whenGetStatus_mediationPending() { .build()) .build()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.IN_MEDIATION); } @@ -321,7 +321,7 @@ void given_court_whenGetStatus_courtReview() { .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) .applicant1ResponseDate(LocalDateTime.now()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.WAITING_COURT_REVIEW); } @@ -334,7 +334,7 @@ void given_respondentFullDefenceAndApplicantNotProceedsWithClaim_whenGetStatus_c .respondent1ClaimResponseTypeForSpec(RespondentResponseTypeSpec.FULL_DEFENCE) .applicant1ResponseDate(LocalDateTime.now()) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.CLAIM_ENDED); } @@ -347,7 +347,7 @@ void given_applicantRejectPartialAdmit_whenGetStatus_rejectOffer() { .applicant1AcceptPartAdmitPaymentPlanSpec(YesOrNo.NO) .ccdState(CaseState.JUDICIAL_REFERRAL) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.CLAIMANT_REJECT_PARTIAL_ADMISSION); } @@ -376,7 +376,7 @@ void given_SDOBeenDrawn_whenGetStatus_sdoOrderCreatedRequired() { .ccdState(CaseState.CASE_PROGRESSION) .build(); DashboardClaimStatus status = - ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.SDO_ORDER_CREATED); } @@ -388,7 +388,7 @@ void given_claimantNotRespondedWithInDeadLine_whenGetStatus_claimEnded() { .applicant1ResponseDeadline(LocalDateTime.now().minusDays(1)) .build(); DashboardClaimStatus status = - ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.CLAIM_ENDED); } @@ -401,7 +401,7 @@ void given_claimantRejectsDefendantsPaymentPlan() { .applicant1AcceptPartAdmitPaymentPlanSpec(YesOrNo.NO) .ccdState(CaseState.PROCEEDS_IN_HERITAGE_SYSTEM) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.WAITING_COURT_REVIEW); } @@ -418,7 +418,7 @@ void givenClaimStatusInProcessHeritageSystem_WhenGetStatus_thenReturnResponseByP .ccdState(CaseState.PROCEEDS_IN_HERITAGE_SYSTEM) .build(); - DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardClaimMatcher( + DashboardClaimStatus status = ccdClaimStatusDashboardFactory.getDashboardClaimStatus(new CcdDashboardDefendantClaimMatcher( claim, featureToggleService)); assertThat(status).isEqualTo(DashboardClaimStatus.RESPONSE_BY_POST); diff --git a/src/test/java/uk/gov/hmcts/reform/civil/sampledata/CaseDataBuilder.java b/src/test/java/uk/gov/hmcts/reform/civil/sampledata/CaseDataBuilder.java index bc230fb1382..5e445820d77 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/sampledata/CaseDataBuilder.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/sampledata/CaseDataBuilder.java @@ -37,6 +37,7 @@ import uk.gov.hmcts.reform.civil.enums.sdo.TrialHearingTimeEstimateDJ; import uk.gov.hmcts.reform.civil.handler.callback.user.spec.show.ResponseOneVOneShowTag; import uk.gov.hmcts.reform.civil.enums.sdo.DateToShowToggle; +import uk.gov.hmcts.reform.civil.model.FlightDelayDetails; import uk.gov.hmcts.reform.civil.model.UpdateDetailsForm; import uk.gov.hmcts.reform.civil.model.Address; import uk.gov.hmcts.reform.civil.model.Bundle; @@ -504,6 +505,7 @@ public class CaseDataBuilder { private DynamicList transferCourtLocationList; private String reasonForTransfer; + private FlightDelayDetails flightDelayDetails; public CaseDataBuilder sameRateInterestSelection(SameRateInterestSelection sameRateInterestSelection) { this.sameRateInterestSelection = sameRateInterestSelection; @@ -5190,6 +5192,11 @@ public CaseDataBuilder reasonForTransfer(String reasonForTransfer) { return this; } + public CaseDataBuilder flightDelay(FlightDelayDetails flightDelayDetails) { + this.flightDelayDetails = flightDelayDetails; + return this; + } + public CaseData buildMakePaymentsCaseData() { Organisation orgId = Organisation.builder() .organisationID("OrgId").build(); @@ -6545,6 +6552,7 @@ public CaseData build() { .drawDirectionsOrderRequired(drawDirectionsOrderRequired) .transferCourtLocationList(transferCourtLocationList) .reasonForTransfer(reasonForTransfer) + .applicant1LRIndividuals(applicant1LRIndividuals) .respondent1LRIndividuals(respondent1LRIndividuals) .respondent2LRIndividuals(respondent2LRIndividuals) @@ -6552,6 +6560,7 @@ public CaseData build() { .applicant2OrgIndividuals(applicant2OrgIndividuals) .respondent1OrgIndividuals(respondent1OrgIndividuals) .respondent2OrgIndividuals(respondent2OrgIndividuals) + .flightDelayDetails(flightDelayDetails) .build(); } } diff --git a/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoaderTest.java b/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoaderTest.java new file mode 100644 index 00000000000..7b8b2e07427 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsDataLoaderTest.java @@ -0,0 +1,27 @@ +package uk.gov.hmcts.reform.civil.service; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(classes = {AirlineEpimsDataLoader.class}) +class AirlineEpimsDataLoaderTest { + + private AirlineEpimsDataLoader airlineEpimsDataLoader; + + @BeforeEach + public void setUp() { + airlineEpimsDataLoader = new AirlineEpimsDataLoader(); + airlineEpimsDataLoader.init(); + } + + @Test + void shouldGetAnAirlineEpimsList() { + String airline = airlineEpimsDataLoader.getAirlineEpimsIDList().get(0).getAirline(); + String epimsID = airlineEpimsDataLoader.getAirlineEpimsIDList().get(0).getEpimsID(); + assertEquals("Aegean", airline); + assertEquals("298828", epimsID); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsServiceTest.java b/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsServiceTest.java new file mode 100644 index 00000000000..ccbfcd2b902 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/civil/service/AirlineEpimsServiceTest.java @@ -0,0 +1,64 @@ +package uk.gov.hmcts.reform.civil.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import uk.gov.hmcts.reform.civil.model.AirlineEpimsId; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.BDDMockito.given; + +@SpringBootTest(classes = {AirlineEpimsService.class}) +class AirlineEpimsServiceTest { + + @MockBean + private AirlineEpimsDataLoader airlineEpimsDataLoader; + + private AirlineEpimsService airlineEpimsService; + + @BeforeEach + void setup() { + List airlineEpimsIDList = new ArrayList<>(); + airlineEpimsIDList.add(AirlineEpimsId.builder().airline("Gulf Air").epimsID("36791").build()); + airlineEpimsIDList.add(AirlineEpimsId.builder().airline("NoLocationAirline").build()); + + given(airlineEpimsDataLoader.getAirlineEpimsIDList()) + .willReturn(airlineEpimsIDList); + } + + @Test + void getEpimsIdForAirline_shouldReturnCorrespondingEpimsIdForAirline() { + // Given + airlineEpimsService = new AirlineEpimsService(airlineEpimsDataLoader); + + // When + String result = airlineEpimsService.getEpimsIdForAirline("Gulf Air"); + + // Then + assertThat(result).isEqualTo("36791"); + } + + @Test + void getEpimsIdForAirline_givenInvalidAirline_shouldThrowException() { + // Given + airlineEpimsService = new AirlineEpimsService(airlineEpimsDataLoader); + + // Then + assertThatExceptionOfType(IllegalStateException.class) + .isThrownBy(() -> airlineEpimsService.getEpimsIdForAirline("INVALID_AIRLINE")); + } + + @Test + void getEpimsIdForAirline_givenNoLocationAirline_shouldThrowException() { + // Given + airlineEpimsService = new AirlineEpimsService(airlineEpimsDataLoader); + + // Then + assertThatExceptionOfType(IllegalStateException.class) + .isThrownBy(() -> airlineEpimsService.getEpimsIdForAirline("NoLocationAirline")); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/civil/service/AuthorisationServiceTest.java b/src/test/java/uk/gov/hmcts/reform/civil/service/AuthorisationServiceTest.java new file mode 100644 index 00000000000..1a7680539bf --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/civil/service/AuthorisationServiceTest.java @@ -0,0 +1,99 @@ +package uk.gov.hmcts.reform.civil.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; +import uk.gov.hmcts.reform.authorisation.ServiceAuthorisationApi; +import uk.gov.hmcts.reform.idam.client.IdamClient; +import uk.gov.hmcts.reform.idam.client.models.UserInfo; + +import java.util.Arrays; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class AuthorisationServiceTest { + + @InjectMocks + AuthorisationService authorisationService; + + @Mock + ServiceAuthorisationApi serviceAuthorisationApi; + + @Mock + IdamClient idamClient; + + @BeforeEach + public void setup() { + ReflectionTestUtils.setField(authorisationService, "s2sAuthorisedServices", Arrays.asList("payment_app")); + } + + @Test + public void authoriseWhenTheServiceIsCalledFromPayment() { + + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("payment_app"); + assertTrue(authorisationService.authoriseService("Bearer abcasda")); + + } + + @Test + public void authoriseWhenTheServiceAuthHeaderIsNull() { + assertFalse(authorisationService.authoriseService(null)); + } + + @Test + public void doNotAuthoriseWhenTheServiceIsCalledFromUnknownApi() { + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("unknown_api"); + assertFalse(authorisationService.authoriseService("Bearer abc")); + + } + + @Test + public void throwUnAuthorisedExceptionWhenS2sTokenIsMalformed() { + assertFalse(authorisationService.authoriseService("Bearer malformed")); + } + + @Test + public void authoriseUserTheServiceIsCalledWithValidToken() { + when(idamClient.getUserInfo(any())).thenReturn(UserInfo.builder().uid(UUID.randomUUID().toString()).build()); + assertTrue(authorisationService.authoriseUser("Bearer abcasda")); + } + + @Test + public void authoriseUserTheServiceIsCalledWithNullToken() { + assertFalse(authorisationService.authoriseUser(null)); + } + + @Test + public void doNotAuthoriseUserWhenCalledWithInvalidToken() { + assertFalse(authorisationService.authoriseUser("Bearer malformed")); + } + + @Test + public void checkIsAuthorizedForUserAndServiceReturnTrue() { + when(idamClient.getUserInfo(any())).thenReturn(UserInfo.builder().uid(UUID.randomUUID().toString()).build()); + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("payment_app"); + assertTrue(authorisationService.isServiceAndUserAuthorized("Bearer abcasda", "s2s token")); + } + + @Test + public void checkIsAuthorizedForUserAndServiceReturnFalse() { + when(idamClient.getUserInfo(any())).thenReturn(UserInfo.builder().uid(UUID.randomUUID().toString()).build()); + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("unknown_api"); + assertFalse(authorisationService.isServiceAndUserAuthorized("Bearer abcasda", "s2s token")); + } + + @Test + public void checkIsAuthorizedForServiceReturnFalse() { + when(serviceAuthorisationApi.getServiceName(any())).thenReturn("unknown_api"); + assertFalse(authorisationService.isServiceAuthorized("s2s token")); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGeneratorTest.java b/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGeneratorTest.java index 7bdb3603865..d817d478715 100644 --- a/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGeneratorTest.java +++ b/src/test/java/uk/gov/hmcts/reform/civil/service/docmosis/hearing/HearingFormGeneratorTest.java @@ -22,6 +22,7 @@ import uk.gov.hmcts.reform.civil.referencedata.model.LocationRefData; import uk.gov.hmcts.reform.civil.sampledata.CaseDataBuilder; import uk.gov.hmcts.reform.civil.sampledata.CaseDocumentBuilder; +import uk.gov.hmcts.reform.civil.service.FeatureToggleService; import uk.gov.hmcts.reform.civil.service.docmosis.DocumentGeneratorService; import uk.gov.hmcts.reform.civil.documentmanagement.UnsecuredDocumentManagementService; import uk.gov.hmcts.reform.civil.utils.AssignCategoryId; @@ -38,6 +39,13 @@ import static uk.gov.hmcts.reform.civil.documentmanagement.model.DocumentType.DEFAULT_JUDGMENT; import static uk.gov.hmcts.reform.civil.documentmanagement.model.DocumentType.HEARING_FORM; import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_APPLICATION; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_APPLICATION_AHN; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_FAST_TRACK; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_FAST_TRACK_AHN; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_OTHER; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_OTHER_AHN; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_SMALL_CLAIMS; +import static uk.gov.hmcts.reform.civil.service.docmosis.DocmosisTemplates.HEARING_SMALL_CLAIMS_AHN; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { @@ -51,6 +59,13 @@ public class HearingFormGeneratorTest { private static final byte[] bytes = {1, 2, 3, 4, 5, 6}; private static final String fileName_application = String.format( HEARING_APPLICATION.getDocumentTitle(), REFERENCE_NUMBER); + private static final String fileName_small_claim = String.format( + HEARING_SMALL_CLAIMS.getDocumentTitle(), REFERENCE_NUMBER); + private static final String fileName_fast_track = String.format( + HEARING_FAST_TRACK.getDocumentTitle(), REFERENCE_NUMBER); + private static final String fileName_other_claim = String.format( + HEARING_OTHER.getDocumentTitle(), REFERENCE_NUMBER); + private static final CaseDocument CASE_DOCUMENT = CaseDocumentBuilder.builder() .documentName(fileName_application) .documentType(DEFAULT_JUDGMENT) @@ -63,14 +78,17 @@ public class HearingFormGeneratorTest { @MockBean private AssignCategoryId assignCategoryId; @MockBean + FeatureToggleService featureToggleService; + @MockBean private LocationRefDataService locationRefDataService; @MockBean private CourtLocationUtils courtLocationUtils; + @Autowired private HearingFormGenerator generator; @Test - void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided() { + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_application() { when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_APPLICATION))) .thenReturn(new DocmosisDocument(HEARING_APPLICATION.getDocumentTitle(), bytes)); when(documentManagementService @@ -78,6 +96,126 @@ void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided() { .thenReturn(CASE_DOCUMENT); when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(false); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.HEARING_OF_APPLICATION).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_application, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_small_claims() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_SMALL_CLAIMS))) + .thenReturn(new DocmosisDocument(HEARING_SMALL_CLAIMS.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_small_claim, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(false); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.SMALL_CLAIMS).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_small_claim, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_fast_track() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_FAST_TRACK))) + .thenReturn(new DocmosisDocument(HEARING_FAST_TRACK.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_fast_track, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(false); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.FAST_TRACK_TRIAL).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_fast_track, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_oher() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_OTHER))) + .thenReturn(new DocmosisDocument(HEARING_OTHER.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_other_claim, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(false); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.OTHER).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_other_claim, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_application_ahn() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_APPLICATION_AHN))) + .thenReturn(new DocmosisDocument(HEARING_APPLICATION_AHN.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_application, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(true); + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() .listingOrRelisting(ListingOrRelisting.LISTING) .totalClaimAmount(new BigDecimal(2000)) @@ -95,4 +233,94 @@ void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided() { verify(documentManagementService) .uploadDocument(BEARER_TOKEN, new PDF(fileName_application, bytes, HEARING_FORM)); } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_small_claims_ahn() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_SMALL_CLAIMS_AHN))) + .thenReturn(new DocmosisDocument(HEARING_SMALL_CLAIMS_AHN.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_small_claim, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(true); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.SMALL_CLAIMS).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_small_claim, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_fast_track_ahn() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_FAST_TRACK_AHN))) + .thenReturn(new DocmosisDocument(HEARING_FAST_TRACK_AHN.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_fast_track, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(true); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.FAST_TRACK_TRIAL).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_fast_track, bytes, HEARING_FORM)); + } + + @Test + void shouldHearingFormGeneratorOneForm_whenValidDataIsProvided_hearing_other_ahn() { + when(documentGeneratorService.generateDocmosisDocument(any(MappableObject.class), eq(HEARING_OTHER_AHN))) + .thenReturn(new DocmosisDocument(HEARING_OTHER_AHN.getDocumentTitle(), bytes)); + + when(documentManagementService + .uploadDocument(BEARER_TOKEN, new PDF(fileName_other_claim, bytes, HEARING_FORM))) + .thenReturn(CASE_DOCUMENT); + when(courtLocationUtils.findPreferredLocationData(any(), any())).thenReturn(LocationRefData.builder().build()); + + when(featureToggleService.isAutomatedHearingNoticeEnabled()).thenReturn(true); + + CaseData caseData = CaseDataBuilder.builder().atStateNotificationAcknowledged() + .listingOrRelisting(ListingOrRelisting.LISTING) + .totalClaimAmount(new BigDecimal(2000)) + .build().toBuilder() + .hearingLocation(DynamicList.builder().value(DynamicListElement.builder().label("County Court").build()) + .build()) + .hearingTimeHourMinute("0800") + .channel(HearingChannel.IN_PERSON) + .hearingDuration(HearingDuration.DAY_1) + .hearingNoticeList(HearingNoticeList.OTHER).build(); + List caseDocuments = generator.generate(caseData, BEARER_TOKEN); + + assertThat(caseDocuments.size()).isEqualTo(1); + + verify(documentManagementService) + .uploadDocument(BEARER_TOKEN, new PDF(fileName_other_claim, bytes, HEARING_FORM)); + } }