Skip to content

Commit

Permalink
PO-591: GET Draft Account API implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
RustyHMCTS committed Aug 19, 2024
1 parent 52211dc commit f307207
Show file tree
Hide file tree
Showing 15 changed files with 489 additions and 42 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ dependencies {

implementation group: 'com.launchdarkly', name: 'launchdarkly-java-server-sdk', version: '7.5.0'

implementation(group: 'com.networknt', name: 'json-schema-validator', version: '1.5.1');

implementation group: 'io.rest-assured', name: 'rest-assured'
implementation 'org.flywaydb:flyway-core'
runtimeOnly 'org.flywaydb:flyway-database-postgresql:10.17.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import uk.gov.hmcts.opal.dto.ToJsonString;
import uk.gov.hmcts.opal.dto.search.DraftAccountSearchDto;
import uk.gov.hmcts.opal.entity.BusinessUnitEntity;
import uk.gov.hmcts.opal.entity.DraftAccountEntity;
import uk.gov.hmcts.opal.service.opal.DraftAccountService;
import uk.gov.hmcts.opal.service.opal.JsonSchemaValidationService;
import uk.gov.hmcts.opal.service.opal.UserStateService;

import java.time.LocalDate;
import java.util.logging.Logger;

import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
Expand All @@ -31,6 +37,8 @@
@ActiveProfiles({"integration"})
class DraftAccountControllerIntegrationTest {

private static final Logger logger = Logger.getLogger(DraftAccountControllerIntegrationTest.class.getSimpleName());

@Autowired
MockMvc mockMvc;

Expand All @@ -41,21 +49,31 @@ class DraftAccountControllerIntegrationTest {
@MockBean
UserStateService userStateService;

@SpyBean
private JsonSchemaValidationService jsonSchemaValidationService;

@Test
void testGetDraftAccountById() throws Exception {
DraftAccountEntity draftAccountEntity = createDraftAccountEntity();

when(draftAccountService.getDraftAccount(1L)).thenReturn(draftAccountEntity);

mockMvc.perform(get("/api/draft-account/1")
MvcResult result = mockMvc.perform(get("/api/draft-account/1")
.header("authorization", "Bearer some_value"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.draftAccountId").value(1))
.andExpect(jsonPath("$.businessUnit.businessUnitId").value(7))
.andExpect(jsonPath("$.accountType").value("DRAFT"))
.andExpect(jsonPath("$.createdBy").value("Tony"))
.andExpect(jsonPath("$.accountStatus").value("CREATED"));
.andExpect(jsonPath("$.draft_account_id").value(1))
.andExpect(jsonPath("$.business_unit_id").value(7))
.andExpect(jsonPath("$.account_type").value("DRAFT"))
.andExpect(jsonPath("$.submitted_by").value("Tony"))
.andExpect(jsonPath("$.account_status").value("CREATED"))
.andReturn();

String body = result.getResponse().getContentAsString();

logger.info(":testGetDraftAccountById: Response body:\n" + ToJsonString.toPrettyJson(body));

assertTrue(jsonSchemaValidationService.isValid(body, "getDraftAccountResponse.json"));
}


Expand Down Expand Up @@ -83,7 +101,7 @@ void testPostDraftAccountsSearch() throws Exception {
.andExpect(jsonPath("$[0].draftAccountId").value(1))
.andExpect(jsonPath("$[0].businessUnit.businessUnitId").value(7))
.andExpect(jsonPath("$[0].accountType").value("DRAFT"))
.andExpect(jsonPath("$[0].createdBy").value("Tony"))
.andExpect(jsonPath("$[0].submittedBy").value("Tony"))
.andExpect(jsonPath("$[0].accountStatus").value("CREATED"));
}

Expand All @@ -100,10 +118,13 @@ private DraftAccountEntity createDraftAccountEntity() {
return DraftAccountEntity.builder()
.draftAccountId(1L)
.businessUnit(BusinessUnitEntity.builder().businessUnitId((short)007).build())
.createdDate(LocalDate.of(2023, 1, 2))
.createdBy("Tony")
.createdDate(LocalDate.of(2023, 1, 2).atStartOfDay())
.submittedBy("Tony")
.accountType("DRAFT")
.accountStatus("CREATED")
.account("{}")
.accountSnapshot("{}")
.timelineData("{}")
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import uk.gov.hmcts.opal.dto.GetDraftAccountResponseDto;
import uk.gov.hmcts.opal.dto.search.DraftAccountSearchDto;
import uk.gov.hmcts.opal.entity.DraftAccountEntity;
import uk.gov.hmcts.opal.service.opal.DraftAccountService;
import uk.gov.hmcts.opal.service.opal.JsonSchemaValidationService;
import uk.gov.hmcts.opal.service.opal.UserStateService;

import java.util.List;
import java.util.Optional;

import static uk.gov.hmcts.opal.util.DateTimeUtils.toOffsetDateTime;
import static uk.gov.hmcts.opal.util.HttpUtil.buildResponse;


Expand All @@ -28,27 +32,32 @@
@Tag(name = "DraftAccount Controller")
public class DraftAccountController {

private final DraftAccountService opalDraftAccountService;
private final DraftAccountService draftAccountService;

private final UserStateService userStateService;

public DraftAccountController(UserStateService userStateService, DraftAccountService opalDraftAccountService) {
this.opalDraftAccountService = opalDraftAccountService;
private final JsonSchemaValidationService jsonSchemaValidationService;

public DraftAccountController(UserStateService userStateService, DraftAccountService draftAccountService,
JsonSchemaValidationService jsonSchemaValidationService) {
this.draftAccountService = draftAccountService;
this.userStateService = userStateService;
this.jsonSchemaValidationService = jsonSchemaValidationService;
}

@GetMapping(value = "/{draftAccountId}")
@Operation(summary = "Returns the Draft Account for the given draftAccountId.")
public ResponseEntity<DraftAccountEntity> getDraftAccountById(@PathVariable Long draftAccountId,
@RequestHeader(value = "Authorization", required = false) String authHeaderValue) {
public ResponseEntity<GetDraftAccountResponseDto> getDraftAccountById(
@PathVariable Long draftAccountId,
@RequestHeader(value = "Authorization", required = false) String authHeaderValue) {

log.info(":GET:getDraftAccountById: draftAccountId: {}", draftAccountId);

userStateService.checkForAuthorisedUser(authHeaderValue);

DraftAccountEntity response = opalDraftAccountService.getDraftAccount(draftAccountId);
DraftAccountEntity response = draftAccountService.getDraftAccount(draftAccountId);

return buildResponse(response);
return buildResponse(Optional.ofNullable(response).map(this::toGetResponseDto).orElse(null));
}

@PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -59,7 +68,7 @@ public ResponseEntity<List<DraftAccountEntity>> postDraftAccountsSearch(@Request

userStateService.checkForAuthorisedUser(authHeaderValue);

List<DraftAccountEntity> response = opalDraftAccountService.searchDraftAccounts(criteria);
List<DraftAccountEntity> response = draftAccountService.searchDraftAccounts(criteria);

return buildResponse(response);
}
Expand All @@ -72,8 +81,26 @@ public ResponseEntity<DraftAccountEntity> postDraftAccount(@RequestBody DraftAcc

userStateService.checkForAuthorisedUser(authHeaderValue);

DraftAccountEntity response = opalDraftAccountService.saveDraftAccount(entity);
DraftAccountEntity response = draftAccountService.saveDraftAccount(entity);

return buildResponse(response);
}

GetDraftAccountResponseDto toGetResponseDto(DraftAccountEntity entity) {
return GetDraftAccountResponseDto.builder()
.draftAccountId(entity.getDraftAccountId())
.businessUnitId(entity.getBusinessUnit().getBusinessUnitId())
.createdDate(toOffsetDateTime(entity.getCreatedDate()))
.submittedBy(entity.getSubmittedBy())
.validatedDate(toOffsetDateTime(entity.getValidatedDate()))
.validatedBy(entity.getValidatedBy())
.account(entity.getAccount())
.accountSnapshot(entity.getAccountSnapshot())
.accountType(entity.getAccountType())
.accountStatus(entity.getAccountStatus())
.timelineData(entity.getTimelineData())
.accountNumber(entity.getAccountNumber())
.accountId(entity.getAccountId())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package uk.gov.hmcts.opal.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.OffsetDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GetDraftAccountResponseDto implements ToJsonString {

@JsonProperty("draft_account_id")
private Long draftAccountId;

@JsonProperty("business_unit_id")
private Short businessUnitId;

@JsonProperty("created_at")
private OffsetDateTime createdDate;

@JsonProperty("submitted_by")
private String submittedBy;

@JsonProperty("validated_at")
private OffsetDateTime validatedDate;

@JsonProperty("validated_by")
private String validatedBy;

@JsonProperty("account")
private String account;

@JsonProperty("account_snapshot")
private String accountSnapshot;

@JsonProperty("account_type")
private String accountType;

@JsonProperty("account_status")
private String accountStatus;

@JsonProperty("timeline_data")
private String timelineData;

@JsonProperty("account_number")
private String accountNumber;

@JsonProperty("account_id")
private Long accountId;
}
20 changes: 18 additions & 2 deletions src/main/java/uk/gov/hmcts/opal/dto/ToJsonString.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ default String toJson() {
}

default String toPrettyJsonString() throws JsonProcessingException {
return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(this);
return toPrettyJsonString(this);
}

static String toPrettyJsonString(Object original) throws JsonProcessingException {
return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(original);
}

default String toPrettyJson() {
Expand All @@ -34,8 +38,20 @@ default String toPrettyJson() {
}
}

static String toPrettyJson(String json) {
try {
return toPrettyJsonString(toJsonNode(json));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}

default JsonNode toJsonNode() throws JsonProcessingException {
return OBJECT_MAPPER.readTree(this.toJsonString());
return toJsonNode(this.toJsonString());
}

static JsonNode toJsonNode(String json) throws JsonProcessingException {
return OBJECT_MAPPER.readTree(json);
}

static ObjectMapper getObjectMapper() {
Expand Down
34 changes: 15 additions & 19 deletions src/main/java/uk/gov/hmcts/opal/entity/DraftAccountEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand All @@ -13,14 +14,13 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import uk.gov.hmcts.opal.util.KeepAsJsonDeserializer;

import java.time.LocalDate;
import java.time.LocalDateTime;

@Entity
@Table(name = "draft-accounts")
Expand All @@ -44,28 +44,19 @@ public class DraftAccountEntity {
private BusinessUnitEntity businessUnit;

@Column(name = "created_date", nullable = false)
@Temporal(TemporalType.DATE)
private LocalDate createdDate;
private LocalDateTime createdDate;

@Column(name = "created_by", length = 20, nullable = false)
private String createdBy;

@ManyToOne
@JoinColumn(name = "created_by_user_id", nullable = false)
private UserEntity createdByUser;
@Column(name = "submitted_by", length = 20, nullable = false)
private String submittedBy;

@Column(name = "validated_date")
@Temporal(TemporalType.DATE)
private LocalDate validatedDate;
private LocalDateTime validatedDate;

@Column(name = "validated_by", length = 20)
private String validatedBy;

@ManyToOne
@JoinColumn(name = "validated_by_user_id")
private UserEntity validatedByUser;

@Column(name = "account", columnDefinition = "json", nullable = false)
@JsonDeserialize(using = KeepAsJsonDeserializer.class)
@JsonRawValue
private String account;

Expand All @@ -75,14 +66,19 @@ public class DraftAccountEntity {
@Column(name = "account_id")
private Long accountId;

@Column(name = "account_summary_data", columnDefinition = "json", nullable = false)
@Column(name = "account_snapshot", columnDefinition = "json", nullable = false)
@JsonDeserialize(using = KeepAsJsonDeserializer.class)
@JsonRawValue
private String accountSummaryData;
private String accountSnapshot;

@Column(name = "account_status", length = 30, nullable = false)
private String accountStatus;

@Column(name = "status_reason", columnDefinition = "json")
@JsonDeserialize(using = KeepAsJsonDeserializer.class)
@JsonRawValue
private String timelineData;

@Column(name = "account_number", length = 25)
private String accountNumber;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package uk.gov.hmcts.opal.exception;

public class JsonSchemaValidationException extends RuntimeException {

public JsonSchemaValidationException(String msg) {
super(msg);
}

public JsonSchemaValidationException(Throwable t) {
super(t);
}

public JsonSchemaValidationException(String message, Throwable t) {
super(message, t);
}

}
Loading

0 comments on commit f307207

Please sign in to comment.