Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package uk.gov.hmcts.cp.subscription.mappers;

import org.springframework.stereotype.Component;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayload;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayloadCasesInner;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendant;

import java.util.List;
import java.util.UUID;

@Component
public class NotificationMapper {

public EventNotificationPayload mapToPayload(final UUID documentId, final PcrEventPayload pcrEventPayload) {
final PcrEventPayloadDefendant defendant = pcrEventPayload.getDefendant();
final List<EventNotificationPayloadCasesInner> cases = defendant.getCases().stream()
.map(c -> EventNotificationPayloadCasesInner.builder().urn(c.getUrn()).build())
.toList();
final String prisonEmailAddress = defendant.getCustodyEstablishmentDetails().getEmailAddress();
return EventNotificationPayload.builder()
.cases(cases)
.masterDefendantId(defendant.getMasterDefendantId())
.defendantName(defendant.getName())
.defendantDateOfBirth(defendant.getDateOfBirth())
.documentId(documentId)
.documentGeneratedTimestamp(pcrEventPayload.getTimestamp())
.prisonEmailAddress(prisonEmailAddress)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayload;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayloadCasesInner;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendant;
import uk.gov.hmcts.cp.subscription.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.subscription.mappers.NotificationMapper;
import uk.gov.hmcts.cp.subscription.mappers.SubscriberMapper;
import uk.gov.hmcts.cp.subscription.model.EntityEventType;
import uk.gov.hmcts.cp.subscription.model.Subscriber;
Expand All @@ -22,53 +20,22 @@
@Slf4j
public class CallbackDeliveryService {

@Value("${subscription.service.base-url:}")
private String subscriptionServiceBaseUrl;

private final SubscriptionRepository subscriptionRepository;
private final SubscriberMapper subscriberMapper;
private final NotificationMapper notificationMapper;
private final CallbackService callbackService;

public void processPcrEvent(final PcrEventPayload pcrEventPayload, final UUID documentId) {
final EntityEventType eventType = EntityEventType.valueOf(pcrEventPayload.getEventType().name());
deliverForPCREvent(eventType, pcrEventPayload, documentId);
}

private void deliverForPCREvent(final EntityEventType eventType,
final PcrEventPayload pcrEventPayload,
final UUID documentId) {
if (eventType == EntityEventType.CUSTODIAL_RESULT) {
throw new UnsupportedOperationException("CUSTODIAL_RESULT not implemented");
}
final List<ClientSubscriptionEntity> entities = subscriptionRepository.findByEventType(eventType.name());
final EventNotificationPayload eventNotificationPayload = createEventNotificationPayload(pcrEventPayload, documentId);
final EventNotificationPayload eventNotificationPayload = notificationMapper.mapToPayload(documentId, pcrEventPayload);
for (final ClientSubscriptionEntity entity : entities) {
final Subscriber subscriber = subscriberMapper.toSubscriber(entity);
deliverToSubscriber(subscriber, eventNotificationPayload);
callbackService.sendToSubscriber(subscriber.getNotificationEndpoint(), eventNotificationPayload);
log.info("Subscriber {} notified via callbackUrl {} for documentId {}", subscriber.getId(), subscriber.getNotificationEndpoint(), eventNotificationPayload.getDocumentId());
}
}

private void deliverToSubscriber(final Subscriber subscriber, final EventNotificationPayload eventNotificationPayload) {
final String callbackURL = subscriber.getNotificationEndpoint();
callbackService.sendToSubscriber(callbackURL, eventNotificationPayload);
log.info("Subscriber {} notified via callbackUrl {} for documentId {}", subscriber.getId(), callbackURL, eventNotificationPayload.getDocumentId());
}

private EventNotificationPayload createEventNotificationPayload(final PcrEventPayload pcrEventPayload,
final UUID documentId) {
final PcrEventPayloadDefendant defendant = pcrEventPayload.getDefendant();
final List<EventNotificationPayloadCasesInner> cases = defendant.getCases().stream()
.map(c -> EventNotificationPayloadCasesInner.builder().urn(c.getUrn()).build())
.toList();
final String prisonEmailAddress = defendant.getCustodyEstablishmentDetails().getEmailAddress();
return EventNotificationPayload.builder()
.cases(cases)
.masterDefendantId(defendant.getMasterDefendantId())
.defendantName(defendant.getName())
.defendantDateOfBirth(defendant.getDateOfBirth())
.documentId(documentId)
.documentGeneratedTimestamp(pcrEventPayload.getTimestamp())
.prisonEmailAddress(prisonEmailAddress)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package uk.gov.hmcts.cp.subscription.mappers;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayload;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendant;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendantCasesInner;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendantCustodyEstablishmentDetails;

import java.time.Instant;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(MockitoExtension.class)
class NotificationMapperTest {

@InjectMocks
NotificationMapper notificationMapper;

UUID defendentId = UUID.fromString("f791c82b-dd68-468f-9066-a31008f8f229");
UUID documentId = UUID.fromString("24f36bc0-ecf7-4fa2-985a-afada1cdee98");

@Test
void mapper_should_return_populated_object() {
Instant now = Instant.now();
PcrEventPayloadDefendantCasesInner caseOne = PcrEventPayloadDefendantCasesInner.builder().urn("http://localhost").build();
PcrEventPayloadDefendant.builder().cases(List.of(caseOne)).build();
PcrEventPayloadDefendantCustodyEstablishmentDetails custodyEstablishment = PcrEventPayloadDefendantCustodyEstablishmentDetails.builder()
.emailAddress("prison@example.com")
.build();
PcrEventPayloadDefendant defendant = PcrEventPayloadDefendant.builder()
.cases(List.of(caseOne))
.masterDefendantId(defendentId)
.name("John Doe")
.dateOfBirth(LocalDate.of(2000, 1, 1))
.custodyEstablishmentDetails(custodyEstablishment)
.build();
PcrEventPayload pcrEventPayload = PcrEventPayload.builder()
.defendant(defendant)
.timestamp(now)
.build();

EventNotificationPayload response = notificationMapper.mapToPayload(documentId, pcrEventPayload);

assertThat(response.getCases()).hasSize(1);
assertThat(response.getCases().get(0).getUrn()).isEqualTo("http://localhost");
assertThat(response.getMasterDefendantId()).isEqualTo(defendentId);
assertThat(response.getDefendantName()).isEqualTo("John Doe");
assertThat(response.getDefendantDateOfBirth()).isEqualTo(LocalDate.of(2000, 1, 1));
assertThat(response.getDocumentId()).isEqualTo(documentId);
assertThat(response.getDocumentGeneratedTimestamp()).isEqualTo(now);
assertThat(response.getPrisonEmailAddress()).isEqualTo("prison@example.com");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,98 +5,61 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import uk.gov.hmcts.cp.openapi.model.EventNotificationPayload;
import uk.gov.hmcts.cp.openapi.model.EventType;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayload;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendant;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendantCasesInner;
import uk.gov.hmcts.cp.openapi.model.PcrEventPayloadDefendantCustodyEstablishmentDetails;
import uk.gov.hmcts.cp.subscription.entities.ClientSubscriptionEntity;
import uk.gov.hmcts.cp.subscription.mappers.NotificationMapper;
import uk.gov.hmcts.cp.subscription.mappers.SubscriberMapper;
import uk.gov.hmcts.cp.subscription.model.EntityEventType;
import uk.gov.hmcts.cp.subscription.model.Subscriber;
import uk.gov.hmcts.cp.subscription.repositories.SubscriptionRepository;

import java.time.Instant;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;

import static java.util.UUID.randomUUID;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class CallbackDeliveryServiceTest {
@Mock private SubscriptionRepository subscriptionRepository;
@Mock private SubscriberMapper subscriberMapper;
@Mock private CallbackService callbackService;
@Mock private PcrEventPayload pcrEventPayload;
@Mock
private SubscriptionRepository subscriptionRepository;
@Mock
private NotificationMapper notificationMapper;
@Mock
private SubscriberMapper subscriberMapper;
@Mock
private CallbackService callbackService;

@InjectMocks
private CallbackDeliveryService callbackDeliveryService;

private static final UUID DOCUMENT_ID = randomUUID();
private static final UUID EVENT_ID = randomUUID();
private static final UUID MASTER_DEFENDANT_ID = randomUUID();
private static final String CALLBACK_URL = "https://callback.example.com";
private static final Instant TIMESTAMP = Instant.EPOCH;
private static final String CASE_URN = "CT98KRYCAP";
private static final String PRISON_EMAIL = "prison@example.com";
private static final PcrEventPayloadDefendant DEFENDANT = PcrEventPayloadDefendant.builder()
.masterDefendantId(MASTER_DEFENDANT_ID)
.name("John Doe")
.dateOfBirth(LocalDate.of(1990, 5, 15))
.custodyEstablishmentDetails(PcrEventPayloadDefendantCustodyEstablishmentDetails.builder()
.emailAddress(PRISON_EMAIL)
.build())
.cases(List.of(PcrEventPayloadDefendantCasesInner.builder().urn(CASE_URN).build()))
.build();
private static final PcrEventPayload PCR_EVENT_PAYLOAD = PcrEventPayload.builder()
.eventType(EventType.PRISON_COURT_REGISTER_GENERATED)
.eventId(EVENT_ID)
.timestamp(TIMESTAMP)
.defendant(DEFENDANT)
.build();
private static final ClientSubscriptionEntity SUB_ENTITY = ClientSubscriptionEntity.builder()
.id(randomUUID())
.notificationEndpoint(CALLBACK_URL)
.eventTypes(List.of(EntityEventType.PRISON_COURT_REGISTER_GENERATED))
.build();
private static final Subscriber SUBSCRIBER = Subscriber.builder()
.id(SUB_ENTITY.getId())
.notificationEndpoint(CALLBACK_URL)
.eventTypes(SUB_ENTITY.getEventTypes())
.clientId(randomUUID())
.build();
private final UUID DOCUMENT_ID = randomUUID();
private final String CALLBACK_URL = "https://callback.example.com";
private final ClientSubscriptionEntity subscriptionEntity = ClientSubscriptionEntity.builder().build();
private final Subscriber subscriber = Subscriber.builder().notificationEndpoint(CALLBACK_URL).build();
private final EventNotificationPayload eventNotificationPayload = EventNotificationPayload.builder().build();

@Test
void processPcrEvent_custodialResult_shouldThrowUnsupportedOperation() {
when(pcrEventPayload.getEventType()).thenReturn(EventType.CUSTODIAL_RESULT);

assertThrows(UnsupportedOperationException.class,
() -> callbackDeliveryService.processPcrEvent(pcrEventPayload, DOCUMENT_ID));

PcrEventPayload pcrEventPayload = PcrEventPayload.builder().eventType(EventType.CUSTODIAL_RESULT).build();
assertThrows(UnsupportedOperationException.class, () -> callbackDeliveryService.processPcrEvent(pcrEventPayload, DOCUMENT_ID));
verifyNoInteractions(subscriptionRepository, subscriberMapper, callbackService);
}

@Test
void processPcrEvent_shouldMapEventNotificationPayloadFieldsCorrectly() {
when(subscriptionRepository.findByEventType(EntityEventType.PRISON_COURT_REGISTER_GENERATED.name()))
.thenReturn(List.of(SUB_ENTITY));
when(subscriberMapper.toSubscriber(SUB_ENTITY)).thenReturn(SUBSCRIBER);
PcrEventPayload pcrEventPayload = PcrEventPayload.builder().eventType(EventType.PRISON_COURT_REGISTER_GENERATED).build();
when(subscriptionRepository.findByEventType(EntityEventType.PRISON_COURT_REGISTER_GENERATED.name())).thenReturn(List.of(subscriptionEntity));
when(notificationMapper.mapToPayload(DOCUMENT_ID, pcrEventPayload)).thenReturn(eventNotificationPayload);
when(subscriberMapper.toSubscriber(subscriptionEntity)).thenReturn(subscriber);

callbackDeliveryService.processPcrEvent(PCR_EVENT_PAYLOAD, DOCUMENT_ID);
callbackDeliveryService.processPcrEvent(pcrEventPayload, DOCUMENT_ID);

verify(callbackService).sendToSubscriber(eq(CALLBACK_URL), argThat(p ->
p.getCases().size() == 1 && p.getCases().get(0).getUrn().equals(CASE_URN)
&& p.getMasterDefendantId().equals(MASTER_DEFENDANT_ID)
&& p.getDefendantName().equals("John Doe")
&& p.getDefendantDateOfBirth().equals(LocalDate.of(1990, 5, 15))
&& p.getDocumentId().equals(DOCUMENT_ID)
&& p.getDocumentGeneratedTimestamp().equals(TIMESTAMP)
&& p.getPrisonEmailAddress().equals(PRISON_EMAIL)));
verify(callbackService).sendToSubscriber(CALLBACK_URL, eventNotificationPayload);
}
}