Skip to content

Commit

Permalink
dmp-4393-amend-get-media-by-id (#2390)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomReed authored Dec 23, 2024
1 parent 7189b78 commit 507838e
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.gov.hmcts.darts.audio.controller;

import org.hamcrest.core.IsNull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.skyscreamer.jsonassert.JSONAssert;
Expand Down Expand Up @@ -271,6 +273,74 @@ void shouldDenyAccess(SecurityRoleEnum role) throws Exception {
""", jsonString, JSONCompareMode.STRICT);
}

@Test
void getMediaById_shouldReturnCaseWithCasIdAndActualHearing_whenMediaHasLinkedCase() throws Exception {
// Given
given.anAuthenticatedUserWithGlobalAccessAndRole(SecurityRoleEnum.SUPER_USER);
UserAccountEntity userAccountEntity = databaseStub.getUserAccountRepository().findAll().stream()
.findFirst()
.orElseThrow();

// Create hearing and mark it as actual
var hearingEntity = databaseStub.createHearing(COURTHOUSE_NAME, COURTROOM_NAME, CASE_NUMBER, HEARING_START_AT.toLocalDateTime());
hearingEntity.setHearingIsActual(true);
databaseStub.getHearingRepository().save(hearingEntity);

// Create media and link it to hearing
var mediaEntity = createAndSaveMediaEntity(hearingEntity, userAccountEntity, false);

// Create media linked case with court case
databaseStub.createMediaLinkedCase(mediaEntity, hearingEntity.getCourtCase());

// When
mockMvc.perform(get(ENDPOINT.resolve(String.valueOf(mediaEntity.getId()))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.cases", hasSize(1)))
.andExpect(jsonPath("$.cases[0].id").value(hearingEntity.getCourtCase().getId()))
.andExpect(jsonPath("$.cases[0].case_number").value(CASE_NUMBER))
.andExpect(jsonPath("$.cases[0].source").value("Legacy"))
.andExpect(jsonPath("$.cases[0].courthouse.id").value(hearingEntity.getCourtCase().getCourthouse().getId()))
.andExpect(jsonPath("$.cases[0].courthouse.display_name").value(COURTHOUSE_NAME))
.andExpect(jsonPath("$.hearings", hasSize(1)))
.andExpect(jsonPath("$.hearings[0].id").value(hearingEntity.getId()))
.andExpect(jsonPath("$.hearings[0].case_id").value(hearingEntity.getCourtCase().getId()))
.andExpect(jsonPath("$.hearings[0].case_number").value(CASE_NUMBER))
.andExpect(jsonPath("$.hearings[0].hearing_date").value(HEARING_START_AT.toLocalDate().toString()))
.andExpect(jsonPath("$.hearings[0].courthouse.id").value(hearingEntity.getCourtCase().getCourthouse().getId()))
.andExpect(jsonPath("$.hearings[0].courthouse.display_name").value(COURTHOUSE_NAME))
.andExpect(jsonPath("$.hearings[0].courtroom.id").value(hearingEntity.getCourtroom().getId()))
.andExpect(jsonPath("$.hearings[0].courtroom.name").value(COURTROOM_NAME));
}

@Test
void getMediaById_shouldReturnCaseWithBaseDetails_whenCaseHasNoCourtCaseRecord() throws Exception {
// Given
given.anAuthenticatedUserWithGlobalAccessAndRole(SecurityRoleEnum.SUPER_USER);
UserAccountEntity userAccountEntity = databaseStub.getUserAccountRepository().findAll().stream()
.findFirst()
.orElseThrow();

// Create media without hearing
var mediaEntity = createAndSaveMediaEntity(null, userAccountEntity, false);

// Create media linked case without court case
databaseStub.createMediaLinkedCase(
mediaEntity,
"MIGRATED_CASE",
COURTHOUSE_NAME
);

// When
mockMvc.perform(get(ENDPOINT.resolve(String.valueOf(mediaEntity.getId()))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.cases", hasSize(1)))
.andExpect(jsonPath("$.cases[0].id").value(IsNull.nullValue()))
.andExpect(jsonPath("$.cases[0].case_number").value("MIGRATED_CASE"))
.andExpect(jsonPath("$.cases[0].source").value("Legacy"))
.andExpect(jsonPath("$.cases[0].courthouse.display_name").value(COURTHOUSE_NAME))
.andExpect(jsonPath("$.cases[0].courthouse.id").doesNotExist());
}

private MediaEntity createAndSaveMediaEntity(HearingEntity hearingEntity, UserAccountEntity userAccountEntity, boolean isDeleted) {
MediaEntity mediaEntity = databaseStub.createMediaEntity(COURTHOUSE_NAME,
COURTROOM_NAME,
Expand All @@ -292,9 +362,12 @@ private MediaEntity createAndSaveMediaEntity(HearingEntity hearingEntity, UserAc
mediaEntity.setIsCurrent(true);

mediaEntity.setHearingList(Collections.singletonList(hearingEntity));
hearingEntity.setMediaList(Collections.singletonList(mediaEntity));
databaseStub.getHearingRepository()
.save(hearingEntity);
if (hearingEntity != null) {
mediaEntity.setHearingList(Collections.singletonList(hearingEntity));
hearingEntity.setMediaList(Collections.singletonList(mediaEntity));
databaseStub.getHearingRepository()
.save(hearingEntity);
}

return databaseStub.getMediaRepository()
.saveAndFlush(mediaEntity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import uk.gov.hmcts.darts.common.entity.HearingEntity;
import uk.gov.hmcts.darts.common.entity.JudgeEntity;
import uk.gov.hmcts.darts.common.entity.MediaEntity;
import uk.gov.hmcts.darts.common.entity.MediaLinkedCaseEntity;
import uk.gov.hmcts.darts.common.entity.NodeRegisterEntity;
import uk.gov.hmcts.darts.common.entity.ObjectRecordStatusEntity;
import uk.gov.hmcts.darts.common.entity.RetentionPolicyTypeEntity;
Expand All @@ -45,6 +46,7 @@
import uk.gov.hmcts.darts.common.entity.UserAccountEntity;
import uk.gov.hmcts.darts.common.entity.base.CreatedModifiedBaseEntity;
import uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum;
import uk.gov.hmcts.darts.common.enums.MediaLinkedCaseSourceType;
import uk.gov.hmcts.darts.common.enums.ObjectRecordStatusEnum;
import uk.gov.hmcts.darts.common.enums.SecurityGroupEnum;
import uk.gov.hmcts.darts.common.enums.SecurityRoleEnum;
Expand Down Expand Up @@ -1018,4 +1020,53 @@ public Revisions<Long, RetentionPolicyTypeEntity> findRetentionPolicyRevisionsFo
public SecurityRoleEntity findSecurityRole(SecurityRoleEnum role) {
return securityRoleRepository.findById(role.getId()).orElseThrow();
}

@Transactional
public MediaLinkedCaseEntity createMediaLinkedCase(
MediaEntity mediaEntity,
CourtCaseEntity courtCase,
String caseNumber,
String courthouseName,
MediaLinkedCaseSourceType source
) {
var mediaLinkedCase = new MediaLinkedCaseEntity();
mediaLinkedCase.setMedia(mediaEntity);
mediaLinkedCase.setCourtCase(courtCase);
mediaLinkedCase.setCaseNumber(caseNumber);
mediaLinkedCase.setCourthouseName(courthouseName);
mediaLinkedCase.setSource(source);
mediaLinkedCase.setCreatedBy(userAccountRepository.getReferenceById(0));
return mediaLinkedCaseRepository.save(mediaLinkedCase);
}

// (court case exists - modernised data)
@Transactional
public MediaLinkedCaseEntity createMediaLinkedCase(
MediaEntity mediaEntity,
CourtCaseEntity courtCase
) {
return createMediaLinkedCase(
mediaEntity,
courtCase,
null, // case number comes from court case
null, // courthouse name comes from court case
MediaLinkedCaseSourceType.LEGACY
);
}

// migrated data - case number and courthouse name are provided
@Transactional
public MediaLinkedCaseEntity createMediaLinkedCase(
MediaEntity mediaEntity,
String caseNumber,
String courthouseName
) {
return createMediaLinkedCase(
mediaEntity,
null, // no court case
caseNumber,
courthouseName,
MediaLinkedCaseSourceType.LEGACY
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import uk.gov.hmcts.darts.common.entity.MediaEntity;

@Mapper(componentModel = "spring",
uses = {ObjectActionMapper.class, CourthouseMapper.class, CourtroomMapper.class},
uses = {ObjectActionMapper.class, CourthouseMapper.class, CourtroomMapper.class, MediaLinkedCaseMapper.class},
unmappedSourcePolicy = ReportingPolicy.IGNORE,
unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface AdminMediaMapper {
Expand Down Expand Up @@ -42,6 +42,7 @@ public interface AdminMediaMapper {
@Mapping(target = "courthouse", source = "courtroom.courthouse"),
@Mapping(target = "courtroom", source = "courtroom"),
@Mapping(target = "hearings", source = "hearingList"),
@Mapping(target = "cases", source = "mediaLinkedCaseList"),
@Mapping(target = "isCurrent", source = "isCurrent")
})
AdminMediaResponse toApiModel(MediaEntity mediaEntity);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package uk.gov.hmcts.darts.audio.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
import org.openapitools.jackson.nullable.JsonNullable;
import uk.gov.hmcts.darts.audio.model.AdminMediaCaseResponseItem;
import uk.gov.hmcts.darts.audio.model.AdminMediaCaseResponseItemCourthouse;
import uk.gov.hmcts.darts.common.entity.MediaLinkedCaseEntity;
import uk.gov.hmcts.darts.common.enums.MediaLinkedCaseSourceType;

@Mapper(componentModel = "spring",
uses = {CourthouseMapper.class},
unmappedSourcePolicy = ReportingPolicy.IGNORE,
unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface MediaLinkedCaseMapper {


@Mappings({
@Mapping(target = "id", source = ".", qualifiedByName = "mapId"),
@Mapping(target = "caseNumber", source = ".", qualifiedByName = "getCaseNumber"),
@Mapping(target = "source", source = "source", qualifiedByName = "mapSource"),
@Mapping(target = "courthouse", source = ".", qualifiedByName = "mapCourthouse")
})
AdminMediaCaseResponseItem toApiModel(MediaLinkedCaseEntity mediaLinkedCase);

@Named("mapId")
default JsonNullable<Integer> mapId(MediaLinkedCaseEntity mediaLinkedCase) {
if (mediaLinkedCase.getCourtCase() != null) {
return JsonNullable.of(mediaLinkedCase.getCourtCase().getId());
}
return JsonNullable.of(null);
}

@Named("getCaseNumber")
default String getCaseNumber(MediaLinkedCaseEntity mediaLinkedCase) {
if (mediaLinkedCase.getCourtCase() != null) {
return mediaLinkedCase.getCourtCase().getCaseNumber();
}
return mediaLinkedCase.getCaseNumber();
}

@Named("mapSource")
default AdminMediaCaseResponseItem.SourceEnum mapSource(MediaLinkedCaseSourceType source) {
if (source == null) {
return null;
}
return switch (source) {
case LEGACY -> AdminMediaCaseResponseItem.SourceEnum.LEGACY;
case ADD_AUDIO_METADATA -> AdminMediaCaseResponseItem.SourceEnum.ADD_AUDIO_METADATA;
case ADD_AUDIO_EVENT_LINKING -> AdminMediaCaseResponseItem.SourceEnum.ADD_AUDIO_EVENT_LINKING;
case AUDIO_LINKING_TASK -> AdminMediaCaseResponseItem.SourceEnum.AUDIO_LINKING_TASK;
};
}

@Named("mapCourthouse")
default AdminMediaCaseResponseItemCourthouse mapCourthouse(MediaLinkedCaseEntity mediaLinkedCase) {
AdminMediaCaseResponseItemCourthouse courthouse = new AdminMediaCaseResponseItemCourthouse();

if (mediaLinkedCase.getCourtCase() != null && mediaLinkedCase.getCourtCase().getCourthouse() != null) {
courthouse.setId(mediaLinkedCase.getCourtCase().getCourthouse().getId());
courthouse.setDisplayName(mediaLinkedCase.getCourtCase().getCourthouse().getDisplayName());
} else {
courthouse.setId(null);
courthouse.setDisplayName(mediaLinkedCase.getCourthouseName());
}

return courthouse;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ public interface ObjectActionMapper {
@Mappings({
@Mapping(target = "id", source = "id"),
@Mapping(target = "hearingDate", source = "hearingDate"),
@Mapping(target = "caseId", source = "courtCase.id")
@Mapping(target = "caseId", source = "courtCase.id"),
@Mapping(target = "caseNumber", source = "courtCase.caseNumber"),
@Mapping(target = "courthouse.id", source = "courtroom.courthouse.id"),
@Mapping(target = "courthouse.displayName", source = "courtroom.courthouse.displayName"),
@Mapping(target = "courtroom.id", source = "courtroom.id"),
@Mapping(target = "courtroom.name", source = "courtroom.name")
})
AdminMediaHearingResponseItem toApiModel(HearingEntity hearingEntity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.openapitools.jackson.nullable.JsonNullableModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
Expand All @@ -21,6 +22,7 @@ public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.registerModule(new ProblemModule());
objectMapper.registerModule(new JsonNullableModule());

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Expand Down
51 changes: 49 additions & 2 deletions src/main/resources/openapi/audio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,10 @@ components:
$ref: '#/components/schemas/AdminMediaCourthouseResponse'
courtroom:
$ref: '#/components/schemas/AdminMediaCourtroomResponse'
cases:
type: array
items:
$ref: '#/components/schemas/AdminMediaCaseResponseItem'
hearings:
type: array
items:
Expand All @@ -629,15 +633,58 @@ components:
name:
$ref: '#/components/schemas/CourtroomName'

AdminMediaCaseResponseItem:
type: object
description: |
case_number and courthouse come from either court_case table or media_linked_case table
1. When cas_id exists: data is populated from court_case table including case number and full courthouse details
2. When cas_id is null: data is populated directly from media_linked_case table
properties:
id:
type: integer
description: 'The case id'
nullable: true
case_number:
type: string
description: 'The case number'
source:
type: string
description: 'The source of the case'
enum: [ 'Legacy', 'Add Audio Metadata', 'Add Audio Event Linking', 'Audio Linking Task' ]
courthouse:
type: object
properties:
id:
$ref: '#/components/schemas/CourthouseId'
nullable: true
display_name:
$ref: '#/components/schemas/CourthouseDisplayName'

AdminMediaHearingResponseItem:
type: object
properties:
id:
$ref: '#/components/schemas/HearingId'
hearing_date:
$ref: '#/components/schemas/HearingDate'
case_id:
$ref: '#/components/schemas/CaseId'
case_number:
type: string
hearing_date:
$ref: '#/components/schemas/HearingDate'
courthouse:
type: object
properties:
id:
$ref: '#/components/schemas/CourthouseId'
display_name:
$ref: '#/components/schemas/CourthouseDisplayName'
courtroom:
type: object
properties:
id:
$ref: '#/components/schemas/CourtroomId'
name:
$ref: '#/components/schemas/CourtroomName'

GetAdminMediaResponseItem:
type: object
Expand Down

0 comments on commit 507838e

Please sign in to comment.