diff --git a/src/main/java/uk/gov/justice/hmpps/prison/api/model/InmateDetail.java b/src/main/java/uk/gov/justice/hmpps/prison/api/model/InmateDetail.java index 5d5d5fd6ac..79bb996a82 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/api/model/InmateDetail.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/api/model/InmateDetail.java @@ -153,6 +153,9 @@ public class InmateDetail { @ApiModelProperty(value = "Offence History", notes = "Only returned when requesting extra details") private List offenceHistory; + @ApiModelProperty(value = "Current Sentence Terms", notes = "Only returned when requesting extra details") + private List sentenceTerms; + @ApiModelProperty(value = "Aliases", notes = "Only returned when requesting extra details") private List aliases; @@ -162,6 +165,9 @@ public class InmateDetail { @ApiModelProperty(value = "Legal Status", example = "REMAND", notes = "Only returned when requesting extra details") private LegalStatus legalStatus; + @ApiModelProperty(value = "Recall", example = "true", notes = "Only returned when requesting extra details") + private Boolean recall; + @ApiModelProperty(value = "The prisoner's imprisonment status.", example="LIFE", notes = "Only returned when requesting extra details") private String imprisonmentStatus; diff --git a/src/main/java/uk/gov/justice/hmpps/prison/api/model/LegalStatusCalc.java b/src/main/java/uk/gov/justice/hmpps/prison/api/model/LegalStatusCalc.java index a1a022857e..280ed49bc4 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/api/model/LegalStatusCalc.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/api/model/LegalStatusCalc.java @@ -5,6 +5,8 @@ import java.util.List; +import static uk.gov.justice.hmpps.prison.api.model.LegalStatusCalc.LegalStatus.RECALL; + public class LegalStatusCalc { @Getter @@ -27,7 +29,38 @@ public enum LegalStatus { } } - private final static List RECALL_STATUS_CODES = List.of("14FTR_ORA","14FTRHDC_ORA","CUR_ORA","FTR/08","FTR_HDC","FTR_HDC_ORA","FTR_ORA","FTR_SCH15","FTRSCH15_ORA","HDR_ORA","LR","LR_ALP","LR_ALP_LASPO","LR_DLP","LR_DPP","LR_EPP","LR_ES","LR_HDC","LR_IPP","LR_LASPO_AR","LR_LASPO_DR","LR_LIFE","LR_MLP","LR_ORA","LR_SEC236A","LR_SEC91_ORA","LR_YOI","LR_YOI_ORA"); + private final static List RECALL_STATUS_CODES = List.of("14FTR_ORA","14FTRHDC_ORA","CUR_ORA","FTR/08","FTR_HDC","FTR_HDC_ORA","FTR_ORA","FTR_SCH15","FTRSCH15_ORA","HDR_ORA","LR","LR_ALP","LR_ALP_LASPO","LR_DLP","LR_DPP","LR_EPP","LR_ES","LR_HDC","LR_IPP","LR_LASPO_AR","LR_LASPO_DR","LR_LIFE","LR_MLP","LR_ORA","LR_SEC236A","LR_SEC91_ORA","LR_YOI","LR_YOI_ORA"); + + public static final List RECALL_SENTENCE_CODES = List.of("14FTRHDC_ORA", + "14FTR_ORA", + "CUR_ORA", + "FTR_HDC", + "FTR_HDC_ORA", + "FTR_ORA", + "FTR_SCH15", + "FTRSCH15_ORA", + "LR", + "LR_ALP", + "LR_ALP_LASPO", + "LR_DLP", + "LR_DPP", + "LR_EPP", + "LR_ES", + "LR_IPP", + "LR_LASPO_AR", + "LR_LASPO_DR", + "LR_LIFE", + "LR_MLP", + "LR_ORA", + "LR_SEC236A", + "LR_SEC91_ORA", + "LR_YOI_ORA", + "HDR_ORA", + "AGG_LR_ORA", + "AGG_HDR_ORA", + "AGGFTRHDCORA", + "FTR", + "HDR"); public static LegalStatus getLegalStatus(final String bandCode, final String mainLegalStatusCode) { @@ -83,4 +116,19 @@ public static String getConvictedStatus(final String bandCode) { } return null; } + + public static boolean calcRecall(final Long bookingId, final LegalStatus legalStatus, final List offenceHistory, final List sentenceTerms) { + if (legalStatus == RECALL) { + return true; + } else { + if (offenceHistory.stream() + .filter(off -> off.getBookingId().equals(bookingId)) + .anyMatch(off -> "1501".equals(off.getPrimaryResultCode()))) { + return true; + } else { + return sentenceTerms.stream() + .anyMatch(st -> RECALL_SENTENCE_CODES.contains(st.getSentenceType())); + } + } + } } diff --git a/src/main/java/uk/gov/justice/hmpps/prison/repository/SentenceRepository.java b/src/main/java/uk/gov/justice/hmpps/prison/repository/SentenceRepository.java index 2ac32ad091..e98e3ed6c0 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/repository/SentenceRepository.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/repository/SentenceRepository.java @@ -14,5 +14,7 @@ public interface SentenceRepository { List getOffenceHistory(String offenderNo, boolean convictionsOnly); + List getOffencesForBooking(Long bookingId, boolean convictionsOnly); + Optional getConfirmedReleaseDate(Long bookingId); } diff --git a/src/main/java/uk/gov/justice/hmpps/prison/repository/impl/SentenceRepositoryImpl.java b/src/main/java/uk/gov/justice/hmpps/prison/repository/impl/SentenceRepositoryImpl.java index dfebcabef2..2bd675a6ec 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/repository/impl/SentenceRepositoryImpl.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/repository/impl/SentenceRepositoryImpl.java @@ -55,6 +55,17 @@ public List getOffenceHistory(final String offenderNo, fin offenceHistoryMapper); } + @Override + public List getOffencesForBooking(final Long bookingId, final boolean convictionsOnly) { + Objects.requireNonNull(bookingId, "offenderNo is a required parameter"); + final var sql = getQuery("GET_OFFENCES_FOR_BOOKING"); + + return jdbcTemplate.query( + sql, + createParams("bookingId", bookingId, "convictionsOnly", convictionsOnly ? "Y": "N"), + offenceHistoryMapper); + } + @Override public Optional getConfirmedReleaseDate(final Long bookingId) { Objects.requireNonNull(bookingId, "bookingId is a required parameter"); diff --git a/src/main/java/uk/gov/justice/hmpps/prison/service/BookingService.java b/src/main/java/uk/gov/justice/hmpps/prison/service/BookingService.java index d539bf37ff..bca56ede42 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/service/BookingService.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/service/BookingService.java @@ -69,7 +69,6 @@ import javax.validation.constraints.NotNull; import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -85,7 +84,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static java.lang.String.format; -import static java.time.LocalDate.from; import static java.time.LocalDate.now; import static java.time.temporal.ChronoUnit.DAYS; import static java.util.Comparator.naturalOrder; @@ -670,6 +668,10 @@ public List getOffenceHistory(final String offenderNo, fin return sentenceRepository.getOffenceHistory(offenderNo, convictionsOnly); } + public List getOffencesForBooking(final Long bookingId, final boolean convictionsOnly) { + return sentenceRepository.getOffencesForBooking(bookingId, convictionsOnly); + } + @VerifyBookingAccess(overrideRoles = {"SYSTEM_USER", "GLOBAL_SEARCH"}) public List getEventsToday(final Long bookingId) { final var today = now(); diff --git a/src/main/java/uk/gov/justice/hmpps/prison/service/InmateService.java b/src/main/java/uk/gov/justice/hmpps/prison/service/InmateService.java index ddfd668f57..2417b20a95 100644 --- a/src/main/java/uk/gov/justice/hmpps/prison/service/InmateService.java +++ b/src/main/java/uk/gov/justice/hmpps/prison/service/InmateService.java @@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.WordUtils; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; @@ -26,6 +25,7 @@ import uk.gov.justice.hmpps.prison.api.model.ImageDetail; import uk.gov.justice.hmpps.prison.api.model.InmateBasicDetails; import uk.gov.justice.hmpps.prison.api.model.InmateDetail; +import uk.gov.justice.hmpps.prison.api.model.LegalStatusCalc; import uk.gov.justice.hmpps.prison.api.model.OffenderBooking; import uk.gov.justice.hmpps.prison.api.model.OffenderCategorise; import uk.gov.justice.hmpps.prison.api.model.OffenderIdentifier; @@ -43,8 +43,6 @@ import uk.gov.justice.hmpps.prison.api.support.Page; import uk.gov.justice.hmpps.prison.api.support.PageRequest; import uk.gov.justice.hmpps.prison.repository.InmateRepository; -import uk.gov.justice.hmpps.prison.repository.KeyWorkerAllocationRepository; -import uk.gov.justice.hmpps.prison.repository.UserRepository; import uk.gov.justice.hmpps.prison.repository.jpa.model.OffenderLanguage; import uk.gov.justice.hmpps.prison.repository.jpa.repository.OffenderLanguageRepository; import uk.gov.justice.hmpps.prison.security.AuthenticationFacade; @@ -94,10 +92,7 @@ public class InmateService { private final ReferenceDomainService referenceDomainService; private final AuthenticationFacade authenticationFacade; private final int maxBatchSize; - private final UserRepository userRepository; - private final KeyWorkerAllocationRepository keyWorkerAllocationRepository; private final OffenderLanguageRepository offenderLanguageRepository; - private final Environment env; private final TelemetryClient telemetryClient; private final String locationTypeGranularity; @@ -109,10 +104,7 @@ public InmateService(final InmateRepository repository, final BookingService bookingService, final AgencyService agencyService, final UserService userService, - final UserRepository userRepository, final AuthenticationFacade authenticationFacade, - final KeyWorkerAllocationRepository keyWorkerAllocationRepository, - final Environment env, final TelemetryClient telemetryClient, @Value("${api.users.me.locations.locationType:WING}") final String locationTypeGranularity, @Value("${batch.max.size:1000}") final int maxBatchSize, @@ -125,9 +117,6 @@ public InmateService(final InmateRepository repository, this.locationTypeGranularity = locationTypeGranularity; this.bookingService = bookingService; this.agencyService = agencyService; - this.userRepository = userRepository; - this.keyWorkerAllocationRepository = keyWorkerAllocationRepository; - this.env = env; this.authenticationFacade = authenticationFacade; this.maxBatchSize = maxBatchSize; this.userService = userService; @@ -240,9 +229,7 @@ private InmateDetail getOffenderDetails(final InmateDetail inmate, final boolean inmate.setInterpreterRequired("Y".equalsIgnoreCase(offenderLanguage.getInterpreterRequestedFlag())); }); - getFirstPreferredWrittenLanguage(bookingId).ifPresent(offenderLanguage -> { - inmate.setWrittenLanguage(offenderLanguage.getReferenceCode().getDescription()); - }); + getFirstPreferredWrittenLanguage(bookingId).ifPresent(offenderLanguage -> inmate.setWrittenLanguage(offenderLanguage.getReferenceCode().getDescription())); inmate.setPhysicalAttributes(getPhysicalAttributes(bookingId)); inmate.setPhysicalCharacteristics(getPhysicalCharacteristics(bookingId)); @@ -260,7 +247,6 @@ private InmateDetail getOffenderDetails(final InmateDetail inmate, final boolean // TODO: Hack for now to make sure there wasn't a reason this was removed. } if (extraInfo) { - inmate.setOffenceHistory(bookingService.getOffenceHistory(inmate.getOffenderNo(), true)); inmate.setAliases(repository.findInmateAliases(bookingId, "createDate", Order.ASC, 0, 100).getItems()); inmate.setPrivilegeSummary(bookingService.getBookingIEPSummary(bookingId, false)); inmate.setIdentifiers(getOffenderIdentifiers(bookingId, null)); @@ -271,11 +257,19 @@ private InmateDetail getOffenderDetails(final InmateDetail inmate, final boolean inmate.setLegalStatus(status.getLegalStatus()); inmate.setImprisonmentStatus(status.getImprisonmentStatus()); }); + + final var offenceHistory = bookingService.getOffencesForBooking(bookingId, true); + final var sentenceTerms = bookingService.getOffenderSentenceTerms(bookingId, null); + inmate.setOffenceHistory(offenceHistory); + inmate.setSentenceTerms(sentenceTerms); + inmate.setRecall(LegalStatusCalc.calcRecall(bookingId, inmate.getLegalStatus(), offenceHistory, sentenceTerms)); } } return inmate; } + + private Optional getFirstPreferredSpokenLanguage(final Long bookingId) { return offenderLanguageRepository .findByOffenderBookId(bookingId) diff --git a/src/main/resources/sqls/SentenceRepositoryImpl.sql b/src/main/resources/sqls/SentenceRepositoryImpl.sql index 87d39cbddd..404bb8dd94 100644 --- a/src/main/resources/sqls/SentenceRepositoryImpl.sql +++ b/src/main/resources/sqls/SentenceRepositoryImpl.sql @@ -59,6 +59,39 @@ WHERE OFFENDERS.OFFENDER_ID_DISPLAY = :offenderNo ORDER BY OCH.offence_date } +GET_OFFENCES_FOR_BOOKING { +SELECT OCH.OFFENDER_BOOK_ID AS BOOKING_ID, + OCH.OFFENCE_DATE, + OCH.OFFENCE_RANGE_DATE, + OFFS.DESCRIPTION AS OFFENCE_DESCRIPTION, + OCH.MOST_SERIOUS_FLAG AS MOST_SERIOUS, + OCH.OFFENCE_CODE, + OCH.STATUTE_CODE, + ORC1.CONVICTION_FLAG AS PRIMARY_RESULT_CONVICTION, + ORC2.CONVICTION_FLAG AS SECONDARY_RESULT_CONVICTION, + ORC1.DESCRIPTION AS PRIMARY_RESULT_DESCRIPTION, + ORC2.DESCRIPTION AS SECONDARY_RESULT_DESCRIPTION, + OCH.RESULT_CODE_1 AS PRIMARY_RESULT_CODE, + OCH.RESULT_CODE_2 AS SECONDARY_RESULT_CODE, + CEC.EVENT_DATE AS COURT_DATE, + OCH.CASE_ID +FROM OFFENDER_CHARGES OCH + INNER JOIN OFFENCES OFFS ON OFFS.OFFENCE_CODE = OCH.OFFENCE_CODE AND OFFS.STATUTE_CODE = OCH.STATUTE_CODE + LEFT JOIN OFFENCE_RESULT_CODES ORC1 ON OCH.RESULT_CODE_1 = ORC1.RESULT_CODE + LEFT JOIN OFFENCE_RESULT_CODES ORC2 ON OCH.RESULT_CODE_2 = ORC2.RESULT_CODE + LEFT JOIN ( SELECT max(EVENT_DATE) as event_date, OFFENDER_CHARGE_ID + from COURT_EVENT_CHARGES CEC inner join COURT_EVENTS CE on CEC.EVENT_ID = CE.EVENT_ID + group by CEC.OFFENDER_CHARGE_ID ) CEC on OCH.OFFENDER_CHARGE_ID = CEC.OFFENDER_CHARGE_ID +WHERE OCH.OFFENDER_BOOK_ID = :bookingId + AND ( :convictionsOnly = 'N' OR ( + ORC1.CONVICTION_FLAG = 'Y' + OR ORC2.CONVICTION_FLAG = 'Y' + )) + -- Avoid dups from merges (from NART team) + AND NOT (OCH.CREATE_USER_ID = 'SYS' AND OCH.AUDIT_MODULE_NAME = 'MERGE') +ORDER BY OCH.offence_date +} + GET_BOOKING_CONFIRMED_RELEASE_DATE { SELECT RELEASE_DATE FROM OFFENDER_RELEASE_DETAILS diff --git a/src/test/java/uk/gov/justice/hmpps/prison/service/InmateServiceImplTest.java b/src/test/java/uk/gov/justice/hmpps/prison/service/InmateServiceImplTest.java index 060cbfe5aa..8640118829 100644 --- a/src/test/java/uk/gov/justice/hmpps/prison/service/InmateServiceImplTest.java +++ b/src/test/java/uk/gov/justice/hmpps/prison/service/InmateServiceImplTest.java @@ -90,8 +90,7 @@ public class InmateServiceImplTest { @BeforeEach public void init() { serviceToTest = new InmateService(repository, caseLoadService, inmateAlertService, - referenceDomainService, bookingService, agencyService, userService, userRepository, authenticationFacade, - keyWorkerAllocationRepository, env, telemetryClient, "WING", 100, offenderLanguageRepository); + referenceDomainService, bookingService, agencyService, userService, authenticationFacade, telemetryClient, "WING", 100, offenderLanguageRepository); } @Test diff --git a/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail.json b/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail.json index 7034aa63a8..2c355fcf6c 100644 --- a/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail.json +++ b/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail.json @@ -1,12 +1,13 @@ { + "offenderNo": "A1234AB", "bookingId": -2, "bookingNo": "A00112", "offenderId": -1002, "rootOffenderId": -1002, - "offenderNo": "A1234AB", "firstName": "GILLIAN", "middleName": "EVE", "lastName": "ANDERSON", + "dateOfBirth": "1998-08-28", "agencyId": "LEI", "assignedLivingUnitId": -19, "activeFlag": true, @@ -48,9 +49,6 @@ "description": "H-1-5", "agencyName": "Leeds" }, - "facialImageId": -2, - "dateOfBirth": "1998-08-28", - "age": 21, "physicalAttributes": { "gender": "Female", "raceCode": "W2", @@ -124,14 +122,62 @@ "releaseDate": "2018-04-19" }, "offenceHistory": [], + "sentenceTerms": [ + { + "bookingId": -2, + "sentenceSequence": 2, + "termSequence": 1, + "sentenceType": "FTR_ORA", + "sentenceTypeDescription": "ORA 28 Day Fixed Term Recall", + "startDate": "2017-05-22", + "years": 2, + "lifeSentence": false, + "caseId": "-2", + "fineAmount": 120.0, + "sentenceTermCode": "IMP", + "lineSeq": 1, + "sentenceStartDate": "2017-07-05" + }, + { + "bookingId": -2, + "sentenceSequence": 2, + "termSequence": 2, + "sentenceType": "FTR_ORA", + "sentenceTypeDescription": "ORA 28 Day Fixed Term Recall", + "startDate": "2017-06-22", + "weeks": 2, + "days": 3, + "lifeSentence": false, + "caseId": "-2", + "fineAmount": 120.0, + "sentenceTermCode": "IMP", + "lineSeq": 1, + "sentenceStartDate": "2017-07-05" + }, + { + "bookingId": -2, + "sentenceSequence": 2, + "termSequence": 3, + "sentenceType": "FTR_ORA", + "sentenceTypeDescription": "ORA 28 Day Fixed Term Recall", + "startDate": "2017-07-22", + "years": 25, + "lifeSentence": true, + "caseId": "-2", + "fineAmount": 120.0, + "sentenceTermCode": "IMP", + "lineSeq": 1, + "sentenceStartDate": "2017-07-05" + } + ], "aliases": [], "status": "ACTIVE IN", "legalStatus": "SENTENCED", + "recall": true, "imprisonmentStatus": "SENT", "privilegeSummary": { "bookingId": -2, "iepLevel": "Basic", - "iepDate": "2017-09-06", - "iepTime": "2017-09-06T09:44:01" + "iepDate": "2017-09-06" } } \ No newline at end of file diff --git a/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail_aliases.json b/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail_aliases.json index f07249f634..9fa4551899 100644 --- a/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail_aliases.json +++ b/src/test/resources/uk/gov/justice/hmpps/prison/api/resource/impl/offender_detail_aliases.json @@ -1,12 +1,13 @@ { + "offenderNo": "A1234AI", "bookingId": -9, "bookingNo": "A00119", "offenderId": -1009, "rootOffenderId": -1009, - "offenderNo": "A1234AI", "firstName": "CHESTER", "middleName": "JAMES", "lastName": "THOMPSON", + "dateOfBirth": "1970-03-01", "agencyId": "LEI", "assignedLivingUnitId": -7, "activeFlag": true, @@ -45,9 +46,6 @@ "description": "A-1-5", "agencyName": "Leeds" }, - "facialImageId": -9, - "dateOfBirth": "1970-03-01", - "age": 50, "physicalAttributes": { "gender": "Male", "raceCode": "M2", @@ -91,7 +89,6 @@ "physicalMarks": [], "birthCountryCode": "UK", "inOutStatus": "IN", - "identifiers": [], "sentenceDetail": { "sentenceExpiryDate": "2018-05-31", "conditionalReleaseDate": "2018-01-31", @@ -107,7 +104,23 @@ "confirmedReleaseDate": "2018-01-13", "releaseDate": "2018-01-13" }, - "offenceHistory": [], + "sentenceTerms": [ + { + "bookingId": -9, + "sentenceSequence": 1, + "termSequence": 1, + "sentenceType": "R", + "sentenceTypeDescription": "Prohibited Activity", + "startDate": "2017-09-01", + "months": 9, + "lifeSentence": false, + "caseId": "-9", + "fineAmount": 120.0, + "sentenceTermCode": "IMP", + "lineSeq": 1, + "sentenceStartDate": "2017-07-05" + } + ], "aliases": [ { "firstName": "CHESNEY", @@ -131,6 +144,7 @@ ], "status": "ACTIVE IN", "legalStatus": "SENTENCED", + "recall": false, "imprisonmentStatus": "SENT", "privilegeSummary": { "bookingId": -9,