From 9416ea11d23541ac2df2153fbe9a7300976ecbe9 Mon Sep 17 00:00:00 2001 From: lucas-phillips28 <140058662+lucas-phillips28@users.noreply.github.com> Date: Thu, 23 May 2024 13:08:25 +0100 Subject: [PATCH] S28 2965: Undelete Recording Cascade (#514) --- .../controllers/BookingControllerFT.java | 10 ++++-- .../CaptureSessionControllerFT.java | 13 ++++++- .../controllers/RecordingControllerFT.java | 36 ++++++++++++++++++- .../controllers/TestingSupportController.java | 1 + .../preapi/services/BookingService.java | 10 ++++-- .../services/CaptureSessionService.java | 7 +++- .../preapi/services/BookingServiceTest.java | 12 +++++++ .../services/CaptureSessionServiceTest.java | 12 +++++++ 8 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/BookingControllerFT.java b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/BookingControllerFT.java index b4b8ba698..b9f7fceed 100644 --- a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/BookingControllerFT.java +++ b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/BookingControllerFT.java @@ -327,6 +327,7 @@ void createBookingWithParticipantNotInCase() throws JsonProcessingException { @DisplayName("Scenario: Restore booking") @Test void undeleteBooking() throws JsonProcessingException { + // create booking var caseEntity = createCase(); var participants = Set.of( createParticipant(ParticipantType.WITNESS), @@ -345,14 +346,19 @@ void undeleteBooking() throws JsonProcessingException { var putResponse = putBooking(booking); assertResponseCode(putResponse, 201); assertBookingExists(booking.getId(), true); + assertCaseExists(caseEntity.getId(), true); - var deleteResponse = doDeleteRequest(BOOKINGS_ENDPOINT + "/" + booking.getId(), true); - assertResponseCode(deleteResponse, 204); + // delete case (and associated booking) + var deleteResponse = doDeleteRequest(CASES_ENDPOINT + "/" + caseEntity.getId(), true); + assertResponseCode(deleteResponse, 200); assertBookingExists(booking.getId(), false); + assertCaseExists(caseEntity.getId(), false); + // undelete booking var undeleteResponse = doPostRequest(BOOKINGS_ENDPOINT + "/" + booking.getId() + "/undelete", true); assertResponseCode(undeleteResponse, 200); assertBookingExists(booking.getId(), true); + assertCaseExists(caseEntity.getId(), true); } private CreateBookingDTO createBooking(UUID caseId, Set participants) { diff --git a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/CaptureSessionControllerFT.java b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/CaptureSessionControllerFT.java index 503a5a555..3c9a6f9cb 100644 --- a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/CaptureSessionControllerFT.java +++ b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/CaptureSessionControllerFT.java @@ -4,6 +4,7 @@ import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import uk.gov.hmcts.reform.preapi.dto.BookingDTO; import uk.gov.hmcts.reform.preapi.dto.CreateCaptureSessionDTO; import uk.gov.hmcts.reform.preapi.enums.RecordingOrigin; import uk.gov.hmcts.reform.preapi.enums.RecordingStatus; @@ -114,18 +115,28 @@ void shouldCreateCaptureSession() throws JsonProcessingException { @DisplayName("Scenario: Restore capture session") @Test void undeleteCaptureSession() throws JsonProcessingException { + // create capture session var dto = createCaptureSession(); var putResponse = putCaptureSession(dto); assertResponseCode(putResponse, 201); assertCaptureSessionExists(dto.getId(), true); + var bookingResponse = assertBookingExists(dto.getBookingId(), true); + var caseId = bookingResponse.as(BookingDTO.class).getCaseDTO().getId(); + assertCaseExists(caseId, true); - var deleteResponse = doDeleteRequest(CAPTURE_SESSIONS_ENDPOINT + "/" + dto.getId(), true); + // delete case (and associated bookings + capture session) + var deleteResponse = doDeleteRequest(CASES_ENDPOINT + "/" + caseId, true); assertResponseCode(deleteResponse, 200); assertCaptureSessionExists(dto.getId(), false); + assertBookingExists(dto.getBookingId(), false); + assertCaseExists(caseId, false); + // undelete capture session var undeleteResponse = doPostRequest(CAPTURE_SESSIONS_ENDPOINT + "/" + dto.getId() + "/undelete", true); assertResponseCode(undeleteResponse, 200); assertCaptureSessionExists(dto.getId(), true); + assertBookingExists(dto.getBookingId(), true); + assertCaseExists(caseId, true); } private CreateCaptureSessionDTO createCaptureSession(UUID bookingId) { diff --git a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/RecordingControllerFT.java b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/RecordingControllerFT.java index 910726326..b349dc294 100644 --- a/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/RecordingControllerFT.java +++ b/src/functionalTest/java/uk/gov/hmcts/reform/preapi/controllers/RecordingControllerFT.java @@ -15,7 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class RecordingControllerFT extends FunctionalTestBase { - private record CreateRecordingResponse(UUID bookingId, UUID captureSessionId, UUID recordingId) { + private record CreateRecordingResponse(UUID caseId, UUID bookingId, UUID captureSessionId, UUID recordingId) { } @DisplayName("Scenario: Restore recording") @@ -80,6 +80,40 @@ void deleteRecordingThatDoesntExist() { assertResponseCode(deleteResponse, 404); } + @DisplayName("Undelete a recording should cascade to associated capture sessions, bookings and cases") + @Test + void shouldUndeleteRecording() throws JsonProcessingException { + // create recording + var recordingDetails = createRecording(); + assertRecordingExists(recordingDetails.recordingId, true); + assertCaptureSessionExists(recordingDetails.captureSessionId, true); + assertBookingExists(recordingDetails.bookingId, true); + assertCaseExists(recordingDetails.caseId, true); + + // must delete all recordings associated to case before deleting case + var deleteRecording = doDeleteRequest(RECORDINGS_ENDPOINT + "/" + recordingDetails.recordingId, true); + assertResponseCode(deleteRecording, 200); + + // delete case (deleting associated bookings + capture sessions) + var deleteCase = doDeleteRequest(CASES_ENDPOINT + "/" + recordingDetails.caseId, true); + assertResponseCode(deleteCase, 200); + assertRecordingExists(recordingDetails.recordingId, false); + assertCaptureSessionExists(recordingDetails.captureSessionId, false); + assertBookingExists(recordingDetails.bookingId, false); + assertCaseExists(recordingDetails.caseId, false); + + // undelete recording (and associated capture session, booking, case) + var undeleteRecording = doPostRequest( + RECORDINGS_ENDPOINT + "/" + recordingDetails.recordingId + "/undelete", + true + ); + assertResponseCode(undeleteRecording, 200); + assertRecordingExists(recordingDetails.recordingId, true); + assertCaptureSessionExists(recordingDetails.captureSessionId, true); + assertBookingExists(recordingDetails.bookingId, true); + assertCaseExists(recordingDetails.caseId, true); + } + private CreateRecordingDTO createRecording(UUID captureSessionId) { var dto = new CreateRecordingDTO(); dto.setId(UUID.randomUUID()); diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/controllers/TestingSupportController.java b/src/main/java/uk/gov/hmcts/reform/preapi/controllers/TestingSupportController.java index ac4b7d8e3..570e7bc03 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/controllers/TestingSupportController.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/controllers/TestingSupportController.java @@ -258,6 +258,7 @@ public ResponseEntity> shouldDeleteRecordingsForBooking() { var response = new HashMap() { { + put("caseId", caseEntity.getId().toString()); put("bookingId", booking.getId().toString()); put("recordingId", recording.getId().toString()); put("captureSessionId", captureSession.getId().toString()); diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/services/BookingService.java b/src/main/java/uk/gov/hmcts/reform/preapi/services/BookingService.java index 03260f6fa..287915b28 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/services/BookingService.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/services/BookingService.java @@ -1,6 +1,7 @@ package uk.gov.hmcts.reform.preapi.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.access.prepost.PreAuthorize; @@ -33,24 +34,26 @@ @SuppressWarnings("PMD.SingularField") public class BookingService { - private final BookingRepository bookingRepository; private final ParticipantRepository participantRepository; private final CaseRepository caseRepository; private final CaptureSessionService captureSessionService; private final ShareBookingService shareBookingService; + private final CaseService caseService; @Autowired public BookingService(final BookingRepository bookingRepository, final CaseRepository caseRepository, final ParticipantRepository participantRepository, final CaptureSessionService captureSessionService, - final ShareBookingService shareBookingService) { + final ShareBookingService shareBookingService, + @Lazy CaseService caseService) { this.bookingRepository = bookingRepository; this.participantRepository = participantRepository; this.caseRepository = caseRepository; this.captureSessionService = captureSessionService; this.shareBookingService = shareBookingService; + this.caseService = caseService; } @PreAuthorize("@authorisationService.hasBookingAccess(authentication, #id)") @@ -171,10 +174,11 @@ public void markAsDeleted(UUID id) { bookingRepository.deleteById(id); } - @Transactional + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) @PreAuthorize("@authorisationService.hasBookingAccess(authentication, #id)") public void undelete(UUID id) { var entity = bookingRepository.findById(id).orElseThrow(() -> new NotFoundException("Booking: " + id)); + caseService.undelete(entity.getCaseId().getId()); if (!entity.isDeleted()) { return; } diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionService.java b/src/main/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionService.java index 945e52df5..7d9328230 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionService.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionService.java @@ -1,6 +1,7 @@ package uk.gov.hmcts.reform.preapi.services; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.access.prepost.PreAuthorize; @@ -34,16 +35,19 @@ public class CaptureSessionService { private final CaptureSessionRepository captureSessionRepository; private final BookingRepository bookingRepository; private final UserRepository userRepository; + private final BookingService bookingService; @Autowired public CaptureSessionService(RecordingService recordingService, CaptureSessionRepository captureSessionRepository, BookingRepository bookingRepository, - UserRepository userRepository) { + UserRepository userRepository, + @Lazy BookingService bookingService) { this.recordingService = recordingService; this.captureSessionRepository = captureSessionRepository; this.bookingRepository = bookingRepository; this.userRepository = userRepository; + this.bookingService = bookingService; } @Transactional @@ -159,6 +163,7 @@ public UpsertResult upsert(CreateCaptureSessionDTO createCaptureSessionDTO) { public void undelete(UUID id) { var entity = captureSessionRepository.findById(id).orElseThrow(() -> new NotFoundException("Capture Session: " + id)); + bookingService.undelete(entity.getBooking().getId()); if (!entity.isDeleted()) { return; } diff --git a/src/test/java/uk/gov/hmcts/reform/preapi/services/BookingServiceTest.java b/src/test/java/uk/gov/hmcts/reform/preapi/services/BookingServiceTest.java index 6168e6d4b..c6690c362 100644 --- a/src/test/java/uk/gov/hmcts/reform/preapi/services/BookingServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/preapi/services/BookingServiceTest.java @@ -64,6 +64,9 @@ class BookingServiceTest { @MockBean private ShareBookingService shareBookingService; + @MockBean + private CaseService caseService; + @Autowired private BookingService bookingService; @@ -439,29 +442,38 @@ void deleteCascadeSuccess() { @DisplayName("Should undelete a booking successfully when booking is marked as deleted") @Test void undeleteSuccess() { + var aCase = new Case(); + aCase.setId(UUID.randomUUID()); + aCase.setDeletedAt(Timestamp.from(Instant.now())); var booking = new Booking(); booking.setId(UUID.randomUUID()); booking.setDeletedAt(Timestamp.from(Instant.now())); + booking.setCaseId(aCase); when(bookingRepository.findById(booking.getId())).thenReturn(Optional.of(booking)); bookingService.undelete(booking.getId()); verify(bookingRepository, times(1)).findById(booking.getId()); + verify(caseService, times(1)).undelete(aCase.getId()); verify(bookingRepository, times(1)).save(booking); } @DisplayName("Should do nothing when booking is not deleted") @Test void undeleteNotDeletedSuccess() { + var aCase = new Case(); + aCase.setId(UUID.randomUUID()); var booking = new Booking(); booking.setId(UUID.randomUUID()); + booking.setCaseId(aCase); when(bookingRepository.findById(booking.getId())).thenReturn(Optional.of(booking)); bookingService.undelete(booking.getId()); verify(bookingRepository, times(1)).findById(booking.getId()); + verify(caseService, times(1)).undelete(aCase.getId()); verify(bookingRepository,never()).save(booking); } diff --git a/src/test/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionServiceTest.java index aba76e1b4..31fe44092 100644 --- a/src/test/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/preapi/services/CaptureSessionServiceTest.java @@ -55,6 +55,9 @@ public class CaptureSessionServiceTest { @MockBean private UserRepository userRepository; + @MockBean + private BookingService bookingService; + @Autowired private CaptureSessionService captureSessionService; @@ -447,29 +450,38 @@ void createCaptureSessionFinishedByNotFound() { @DisplayName("Should undelete a capture session successfully when capture session is marked as deleted") @Test void undeleteSuccess() { + var booking = new Booking(); + booking.setId(UUID.randomUUID()); + booking.setDeletedAt(Timestamp.from(Instant.now())); var captureSession = new CaptureSession(); captureSession.setId(UUID.randomUUID()); captureSession.setDeletedAt(Timestamp.from(Instant.now())); + captureSession.setBooking(booking); when(captureSessionRepository.findById(captureSession.getId())).thenReturn(Optional.of(captureSession)); captureSessionService.undelete(captureSession.getId()); verify(captureSessionRepository, times(1)).findById(captureSession.getId()); + verify(bookingService, times(1)).undelete(booking.getId()); verify(captureSessionRepository, times(1)).save(captureSession); } @DisplayName("Should do nothing when capture session is not deleted") @Test void undeleteNotDeletedSuccess() { + var booking = new Booking(); + booking.setId(UUID.randomUUID()); var captureSession = new CaptureSession(); captureSession.setId(UUID.randomUUID()); + captureSession.setBooking(booking); when(captureSessionRepository.findById(captureSession.getId())).thenReturn(Optional.of(captureSession)); captureSessionService.undelete(captureSession.getId()); verify(captureSessionRepository, times(1)).findById(captureSession.getId()); + verify(bookingService, times(1)).undelete(booking.getId()); verify(captureSessionRepository, never()).save(captureSession); }