Skip to content

Commit

Permalink
story(ccls-2055) add update application endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilDigitalJustice committed Mar 12, 2024
1 parent 28dad6e commit a0c6d1c
Show file tree
Hide file tree
Showing 16 changed files with 362 additions and 29 deletions.
37 changes: 37 additions & 0 deletions caab-api/open-api-specification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,43 @@ paths:
description: 'Not found'
'500':
description: 'Internal server error'
patch:
tags:
- applications
summary: 'Update Application'
operationId: 'updateApplication'

requestBody:
description: Update a application
content:
application/json:
schema:
$ref: '#/components/schemas/applicationDetail'
parameters:
- name: 'id'
in: 'path'
required: true
schema:
type: 'integer'
format: 'int64'
example: '1234567890'
- name: 'Caab-User-Login-Id'
in: header
required: true
schema:
type: 'string'
example: '[email protected]'
responses:
'200':
description: 'Successful operation'
'400':
description: 'Bad request'
'401':
description: 'Unauthorized'
'404':
description: 'Not found'
'500':
description: 'Internal server error'
/applications/clients/{client-reference-id}:
patch:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -81,6 +83,90 @@ private String generateTestCaseRef(){
return stringBuilder.toString();
}

private static Stream<Arguments> createApplicationUpdateArguments() {
return Stream.of(
Arguments.of("/json/applicationUpdate_caseReferenceNumber.json", "getCaseReferenceNumber", "caseReferenceNumber"),
Arguments.of("/json/applicationUpdate_clientFirstName.json", "getClient.getFirstName", "client"),
Arguments.of("/json/applicationUpdate_costLimit.json", "getCostLimit.getLimitAtTimeOfMerits", "costLimit"),
Arguments.of("/json/applicationUpdate_applicationType.json", "getApplicationType.getId", "applicationType"),
Arguments.of("/json/applicationUpdate_categoryOfLaw.json", "getCategoryOfLaw.getId", "categoryOfLaw"),
Arguments.of("/json/applicationUpdate_correspondenceAddress.json", "getCorrespondenceAddress.getPostcode", "correspondenceAddress"),
Arguments.of("/json/applicationUpdate_providerContact.json", "getProviderDetails.getProviderContact.getId", "providerDetails"),
Arguments.of("/json/applicationUpdate_status.json", "getStatus.getId", "status")
);
}


@ParameterizedTest
@MethodSource("createApplicationUpdateArguments")
@Sql(scripts = "/sql/application_insert.sql")
public void testUpdateApplication(String fileInput, String methodCall, String fieldToIgnore)
throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ApplicationDetail patchedApplicationDetails = loadObjectFromJson(
fileInput, ApplicationDetail.class);

final Long id = 21L;

//get the application before doing the update
ApplicationDetail beforeUpdateApplication = applicationService.getApplication(id);

String auditUser = "[email protected]";
ResponseEntity<Void> responseEntity =
applicationController.updateApplication(id, auditUser, patchedApplicationDetails);

assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());

//get the application after doing the update
ApplicationDetail afterUpdateApplication = applicationService.getApplication(id);

// Split the methodCall string and iterate over it to get the final value
String[] methodCalls = methodCall.split("\\.");
Object expectedVariable = getObjectToCheckFromMethod(patchedApplicationDetails, methodCalls);
Object actualVariable = getObjectToCheckFromMethod(afterUpdateApplication, methodCalls);
assertEquals(expectedVariable, actualVariable);

//check other variables are not changed
assertTrue(areAllFieldsEqual(
beforeUpdateApplication,
afterUpdateApplication,
ApplicationDetail.class, List.of(fieldToIgnore, "auditTrail")));
}

// Utility method to resolve the method chain and get the value
private Object getObjectToCheckFromMethod(Object initialObject, String[] methodCalls)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

Object currentObject = initialObject;
for (String methodName : methodCalls) {
Method method = currentObject.getClass().getMethod(methodName);
currentObject = method.invoke(currentObject);
}
return currentObject;
}


public static boolean areAllFieldsEqual(Object obj1, Object obj2, Class<?> clazz, List<String> fieldsToIgnore)
throws IllegalArgumentException, IllegalAccessException {

for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);

// Continue to the next field if it should be ignored
if (fieldsToIgnore.contains(field.getName())) {
continue;
}

Object value1 = field.get(obj1);
Object value2 = field.get(obj2);

if (!Objects.equals(value1, value2)) {
System.out.println("Field " + field.getName() + " is not equal: " + value1 + " != " + value2);
return false;
}
}
return true;
}

/**
* Arguments for the testCreateApplication test method.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"application_type": {
"id": "LEGAL_HELP",
"display_value": "Legal Help",
"devolved_powers": {
"used": true,
"date_used": "2024-01-01",
"contract_flag": "No"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"case_reference_number": "300001234567"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"category_of_law": {
"id": "FAM",
"display_value": "Family"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"client": {
"first_name": "John"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"correspondence_address": {
"no_fixed_abode": true,
"postcode": "NA",
"house_name_or_number": "NA",
"address_line_1": "NA",
"address_line_2": "NA",
"city": "NA",
"county": "NA",
"country": "GBR",
"care_of": "NA",
"preferred_address": "NA"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cost_limit": {
"limit_at_time_of_merits": 2000
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"provider_details": {
"provider_contact": {
"id": "2027080",
"display_value": "[email protected]"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"status": {
"id": "SUBMITTED",
"display_value": "Submitted"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,15 @@ public ResponseEntity<ApplicationDetail> getApplication(
return new ResponseEntity<>(application, HttpStatus.OK);
}

@Override
public ResponseEntity<Void> updateApplication(
final Long id,
final String caabUserLoginId,
final ApplicationDetail applicationDetail) {
applicationService.updateApplication(id, applicationDetail);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

//correspondence address

/**
Expand Down Expand Up @@ -412,9 +421,10 @@ public ResponseEntity<Void> updatePriorAuthority(

//clients
@Override
public ResponseEntity<Void> updateApplicationClient(final String clientReferenceId,
final String caabUserLoginId,
final BaseClient baseClient) {
public ResponseEntity<Void> updateApplicationClient(
final String clientReferenceId,
final String caabUserLoginId,
final BaseClient baseClient) {
applicationService.updateClient(baseClient, clientReferenceId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@


import java.util.List;
import org.mapstruct.BeanMapping;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Named;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.springframework.data.domain.Page;
import uk.gov.laa.ccms.caab.api.entity.Address;
import uk.gov.laa.ccms.caab.api.entity.Application;
Expand Down Expand Up @@ -76,6 +79,16 @@ public interface ApplicationMapper {
qualifiedByName = "toAddress")
Application toApplication(ApplicationDetail applicationDetail);

@InheritConfiguration(name = "toApplication")
@Mapping(target="opponents", ignore = true)
@Mapping(target="linkedCases", ignore = true)
@Mapping(target="proceedings", ignore = true)
@Mapping(target="priorAuthorities", ignore = true)
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void mapIntoApplication(
@MappingTarget Application application,
ApplicationDetail applicationDetail);

/**
* After mapping, set the parent entity in the child entities.
*
Expand Down Expand Up @@ -117,7 +130,7 @@ default void setParentInChildEntities(@MappingTarget Application application) {
}
}

@InheritInverseConfiguration
@InheritInverseConfiguration(name = "toApplication")
@Mapping(target = "costs", source = "costs", qualifiedByName = "toCostStructureModel")
@Mapping(target = "correspondenceAddress", source = "correspondenceAddress",
qualifiedByName = "toAddressModel")
Expand Down Expand Up @@ -253,6 +266,18 @@ void addApplicationType(@MappingTarget Application application,
source = "devolvedPowersContractFlag")
ApplicationType toApplicationType(Application application);

@Mapping(target = "provider.id", source = "providerId")
@Mapping(target = "provider.displayValue", source = "providerDisplayValue")
@Mapping(target = "office.id", source = "officeId")
@Mapping(target = "office.displayValue", source = "officeDisplayValue")
@Mapping(target = "supervisor.id", source = "supervisor")
@Mapping(target = "supervisor.displayValue", source = "supervisorDisplayValue")
@Mapping(target = "feeEarner.id", source = "feeEarner")
@Mapping(target = "feeEarner.displayValue", source = "feeEarnerDisplayValue")
@Mapping(target = "providerContact.id", source = "providerContact")
@Mapping(target = "providerContact.displayValue", source = "providerContactDisplayValue")
ApplicationProviderDetails toProviderDetails(Application application);

@Mapping(target = "id", ignore = true)
@Mapping(target = "auditTrail", ignore = true)
@Mapping(target = "providerId", source = "providerDetails.provider.id")
Expand All @@ -269,18 +294,6 @@ void addApplicationType(@MappingTarget Application application,
void addProviderDetails(@MappingTarget Application application,
ApplicationProviderDetails providerDetails);

@Mapping(target = "provider.id", source = "providerId")
@Mapping(target = "provider.displayValue", source = "providerDisplayValue")
@Mapping(target = "office.id", source = "officeId")
@Mapping(target = "office.displayValue", source = "officeDisplayValue")
@Mapping(target = "supervisor.id", source = "supervisor")
@Mapping(target = "supervisor.displayValue", source = "supervisorDisplayValue")
@Mapping(target = "feeEarner.id", source = "feeEarner")
@Mapping(target = "feeEarner.displayValue", source = "feeEarnerDisplayValue")
@Mapping(target = "providerContact.id", source = "providerContact")
@Mapping(target = "providerContact.displayValue", source = "providerContactDisplayValue")
ApplicationProviderDetails toProviderDetails(Application application);


/**
* Adds/Updates an application with a new correspondence address.
Expand Down Expand Up @@ -337,19 +350,8 @@ void updatePriorAuthority(
@MappingTarget PriorAuthority priorAuthority,
uk.gov.laa.ccms.caab.model.PriorAuthority priorAuthorityModel);

@Mapping(target = "auditTrail", ignore = true)
@Mapping(target = "id", ignore = true)
@Mapping(target = "matterType", source = "matterType.id")
@Mapping(target = "matterTypeDisplayValue", source = "matterType.displayValue")
@Mapping(target = "proceedingType", source = "proceedingType.id")
@Mapping(target = "proceedingTypeDisplayValue", source = "proceedingType.displayValue")
@Mapping(target = "levelOfService", source = "levelOfService.id")
@Mapping(target = "levelOfServiceDisplayValue", source = "levelOfService.displayValue")
@Mapping(target = "clientInvolvement", source = "clientInvolvement.id")
@Mapping(target = "clientInvolvementDisplayValue", source = "clientInvolvement.displayValue")
@Mapping(target = "status", source = "status.id")
@Mapping(target = "displayStatus", source = "status.displayValue")
@Mapping(target = "typeOfOrder", source = "typeOfOrder.id")
@InheritConfiguration(name = "toProceeding")
void updateProceeding(
@MappingTarget Proceeding proceeding,
uk.gov.laa.ccms.caab.model.Proceeding proceedingModel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,27 @@ public ApplicationDetail getApplication(final Long applicationId) {
HttpStatus.NOT_FOUND));
}

/**
* Updates an application with new details.
*
* @param applicationId The unique identifier of the application to be updated.
* @param applicationDetail The ApplicationDetail object containing the details of the
* application to be updated.
* @throws CaabApiException If the application with the specified ID is not found.
*/
@Transactional
public void updateApplication(
final Long applicationId,
final ApplicationDetail applicationDetail) {
Application application = applicationRepository.findById(applicationId)
.orElseThrow(() -> new CaabApiException(
String.format("Application with id %s not found", applicationId),
HttpStatus.NOT_FOUND));

applicationMapper.mapIntoApplication(application, applicationDetail);
applicationRepository.save(application);
}

/**
* Updates a client's information in the application repository.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,25 @@ public void getApplication() throws Exception {
.andExpect(status().isOk());
}

@Test
@Test
public void updateApplication() throws Exception {
Long id = 1L;
String caabUserLoginId = "testUserLoginId";
ApplicationDetail applicationDetail = new ApplicationDetail();

doNothing().when(applicationService).updateApplication(id, applicationDetail);

this.mockMvc.perform(patch("/applications/{id}", id)
.header("Caab-User-Login-Id", caabUserLoginId)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(applicationDetail)))
.andExpect(status().isNoContent());

verify(applicationService).updateApplication(id, applicationDetail);
}


@Test
public void getApplicationType() throws Exception {
Long id = 123L;
ApplicationType applicationType = new ApplicationType();
Expand Down
Loading

0 comments on commit a0c6d1c

Please sign in to comment.