Skip to content
2 changes: 1 addition & 1 deletion charts/ia-case-api/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v2
name: ia-case-api
home: https://github.com/hmcts/ia-case-api
version: 0.0.63
version: 0.0.64
description: Immigration & Asylum Case API
maintainers:
- name: HMCTS Immigration & Asylum Team
Expand Down
1 change: 1 addition & 0 deletions charts/ia-case-api/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ java:
REQUEST_RESPONDENT_EVIDENCE_ADA_DUE_IN_DAYS: 3
REQUEST_RESPONDENT_REVIEW_DUE_IN_DAYS: 14
REQUEST_RESPONDENT_REVIEW_ADA_DUE_IN_DAYS: 2
REQUEST_RESPONDENT_REVIEW_DETAINED_DUE_IN_DAYS: 7
APPELLANT_REASONS_FOR_APPEAL_DUE_IN_DAYS: 28
PAYMENT_AFTER_REMISSION_REJECTION_DUE_IN_MINUTES: 20160
PAYMENT_EA_HU_NO_REMISSION_DUE_IN_MINUTES: 20160
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"description": "DIAC-1078 Request respondent review when detained - check sendDirectionDateDue ",
"request": {
"uri": "/asylum/ccdAboutToStart",
"credentials": "CaseOfficer",
"input": {
"eventId": "requestRespondentReview",
"state": "awaitingRespondentReview",
"caseData": {
"template": "minimal-appeal-submitted.json",
"replacements": {
"appellantInDetention": "Yes",
"homeOfficeSearchStatus": "SUCCESS",
"sendDirectionExplanation": null,
"sendDirectionParties": null,
"sendDirectionDateDue": null
}
}
}
},
"expectation": {
"status": 200,
"errors": [],
"caseData": {
"template": "minimal-appeal-submitted.json",
"replacements": {
"sendDirectionExplanation": "By the date below you must review the appellant’s ASA and bundle.\nThe review must comply with (i) Rule 24A (3) of the Tribunal Procedure Rules 2014 and (ii) Practice Direction (1.11.2024) Part 2, section 2.1 (e), Part 3, sections 7.11 – 7.12. Specifically, the review must:\n\n- be meaningful.\n- explain whether you agree that the schedule of disputed issues is correct. If not, the review must set out the correct list of disputed issues, including whether there are any further issues that the respondent wishes to raise.\n- state whether you oppose or accept the appellant’s position on each issue and why.\n- cross-reference your submissions to paragraphs in the decision under appeal, pages in the respondent’s bundle, any country information evidence schedule, and/or any additional evidence relied upon.\n- specify which, if any, witnesses you intend to cross-examine and if you do not intend to cross-examine a witness, outline any objections to that witness’s statement being read by a judge.\n- address whether the appeal should be allowed on any ground if the appellant and/or their key witnesses are found to be credible according to the applicable standard of proof.\n- identify whether you are prepared to withdraw the decision (or part of it).\n- state whether the appeal can be resolved without a hearing.\n- not exceed 6 pages unless reasons are submitted in an accompanying application.\n- not contain standard or pro-forma paragraphs.\n- provide the name of the author of the review and the date.\n\nParties must ensure they conduct proceedings with procedural rigour. The Tribunal will not overlook breaches of the requirements of the Procedure Rules, Practice Statement or Practice Direction, nor failures to comply with directions issued by the Tribunal. Parties are reminded of the sanctions for non-compliance set out in paragraph 5.3 of the Practice Direction of 01.11.24.",
"sendDirectionParties": "respondent",
"sendDirectionDateDue": "{$TODAY+7}"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"description": "DIAC-1078 Request respondent review when NOT detained - check sendDirectionDateDue ",
"request": {
"uri": "/asylum/ccdAboutToStart",
"credentials": "CaseOfficer",
"input": {
"eventId": "requestRespondentReview",
"state": "awaitingRespondentReview",
"caseData": {
"template": "minimal-appeal-submitted.json",
"replacements": {
"appellantInDetention": "No",
"homeOfficeSearchStatus": "SUCCESS",
"sendDirectionExplanation": null,
"sendDirectionParties": null,
"sendDirectionDateDue": null
}
}
}
},
"expectation": {
"status": 200,
"errors": [],
"caseData": {
"template": "minimal-appeal-submitted.json",
"replacements": {
"sendDirectionExplanation": "By the date below you must review the appellant’s ASA and bundle.\nThe review must comply with (i) Rule 24A (3) of the Tribunal Procedure Rules 2014 and (ii) Practice Direction (1.11.2024) Part 2, section 2.1 (e), Part 3, sections 7.11 – 7.12. Specifically, the review must:\n\n- be meaningful.\n- explain whether you agree that the schedule of disputed issues is correct. If not, the review must set out the correct list of disputed issues, including whether there are any further issues that the respondent wishes to raise.\n- state whether you oppose or accept the appellant’s position on each issue and why.\n- cross-reference your submissions to paragraphs in the decision under appeal, pages in the respondent’s bundle, any country information evidence schedule, and/or any additional evidence relied upon.\n- specify which, if any, witnesses you intend to cross-examine and if you do not intend to cross-examine a witness, outline any objections to that witness’s statement being read by a judge.\n- address whether the appeal should be allowed on any ground if the appellant and/or their key witnesses are found to be credible according to the applicable standard of proof.\n- identify whether you are prepared to withdraw the decision (or part of it).\n- state whether the appeal can be resolved without a hearing.\n- not exceed 6 pages unless reasons are submitted in an accompanying application.\n- not contain standard or pro-forma paragraphs.\n- provide the name of the author of the review and the date.\n\nParties must ensure they conduct proceedings with procedural rigour. The Tribunal will not overlook breaches of the requirements of the Procedure Rules, Practice Statement or Practice Direction, nor failures to comply with directions issued by the Tribunal. Parties are reminded of the sanctions for non-compliance set out in paragraph 5.3 of the Practice Direction of 01.11.24.",
"sendDirectionParties": "respondent",
"sendDirectionDateDue": "{$TODAY+14}"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,20 @@ public class RequestRespondentReviewPreparer implements PreSubmitCallbackHandler

private final int requestRespondentReviewDueInDays;
private final int requestRespondentReviewDueInDaysForAda;
private final int requestRespondentReviewDueInDaysForDetained;
private final DateProvider dateProvider;
private final DueDateService dueDateService;

public RequestRespondentReviewPreparer(
@Value("${requestRespondentReview.dueInDays}") int requestRespondentReviewDueInDays,
@Value("${requestRespondentReviewAda.dueInDays}") int requestRespondentReviewDueInDaysForAda,
@Value("${requestRespondentReviewDetained.dueInDays}") int requestRespondentReviewDueInDaysForDetained,
DateProvider dateProvider,
DueDateService dueDateService
) {
this.requestRespondentReviewDueInDays = requestRespondentReviewDueInDays;
this.requestRespondentReviewDueInDaysForAda = requestRespondentReviewDueInDaysForAda;
this.requestRespondentReviewDueInDaysForDetained = requestRespondentReviewDueInDaysForDetained;
this.dateProvider = dateProvider;
this.dueDateService = dueDateService;
}
Expand Down Expand Up @@ -82,14 +85,27 @@ public PreSubmitCallbackResponse<AsylumCase> handle(
);

asylumCase.write(SEND_DIRECTION_PARTIES, Parties.RESPONDENT);

LocalDate dueDate = HandlerUtils.isAcceleratedDetainedAppeal(asylumCase)
? dueDateService.calculateDueDate(dateProvider.now().atStartOfDay(ZoneOffset.UTC), requestRespondentReviewDueInDaysForAda).toLocalDate()
: dateProvider.now().plusDays(requestRespondentReviewDueInDays);

LocalDate dueDate = getDueDate(asylumCase);

asylumCase.write(SEND_DIRECTION_DATE_DUE, dueDate.toString());

asylumCase.write(UPLOAD_HOME_OFFICE_APPEAL_RESPONSE_ACTION_AVAILABLE, YesOrNo.YES);

return new PreSubmitCallbackResponse<>(asylumCase);
}

private LocalDate getDueDate(AsylumCase asylumCase) {
LocalDate dueDate;

if (HandlerUtils.isAcceleratedDetainedAppeal(asylumCase)) {
dueDate = dueDateService.calculateDueDate(dateProvider.now().atStartOfDay(ZoneOffset.UTC), requestRespondentReviewDueInDaysForAda).toLocalDate();
} else if (HandlerUtils.isAppellantInDetention(asylumCase)) {
dueDate = dateProvider.now().plusDays(requestRespondentReviewDueInDaysForDetained);
} else {
dueDate = dateProvider.now().plusDays(requestRespondentReviewDueInDays);
}

return dueDate;
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ requestRespondentEvidence.dueInDays: ${REQUEST_RESPONDENT_EVIDENCE_DUE_IN_DAYS:1
requestRespondentEvidence.dueInDaysAda: ${REQUEST_RESPONDENT_EVIDENCE_ADA_DUE_IN_DAYS:3}
requestRespondentReview.dueInDays: ${REQUEST_RESPONDENT_REVIEW_DUE_IN_DAYS:14}
requestRespondentReviewAda.dueInDays: ${REQUEST_RESPONDENT_REVIEW_ADA_DUE_IN_DAYS:2}
requestRespondentReviewDetained.dueInDays: ${REQUEST_RESPONDENT_REVIEW_DETAINED_DUE_IN_DAYS:7}
appellantReasonsForAppeal.dueInDays: ${APPELLANT_REASONS_FOR_APPEAL_DUE_IN_DAYS:28}
paymentAfterRemissionRejection.dueInMinutes: ${PAYMENT_AFTER_REMISSION_REJECTION_DUE_IN_MINUTES:20160}
legalRepresentativeRemissionReminder.dueInMinutes: ${LEGAL_REP_REMISSION_REMINDER_DUE_IN_MINUTES:10080}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static uk.gov.hmcts.reform.iacaseapi.domain.entities.AppealType.PA;
import static uk.gov.hmcts.reform.iacaseapi.domain.entities.AsylumCaseFieldDefinition.*;

import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -30,6 +33,7 @@
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import uk.gov.hmcts.reform.iacaseapi.domain.DateProvider;
import uk.gov.hmcts.reform.iacaseapi.domain.entities.AppealType;
import uk.gov.hmcts.reform.iacaseapi.domain.entities.AsylumCase;
import uk.gov.hmcts.reform.iacaseapi.domain.entities.AsylumCaseFieldDefinition;
import uk.gov.hmcts.reform.iacaseapi.domain.entities.Parties;
Expand All @@ -49,6 +53,7 @@ class RequestRespondentReviewPreparerTest {

private static final int DUE_IN_DAYS = 14;
private static final int ADA_DUE_IN_DAYS = 2;
private static final int DETAINED_DUE_IN_DAYS = 7;
@Mock
private DateProvider dateProvider;
@Mock
Expand All @@ -73,7 +78,7 @@ class RequestRespondentReviewPreparerTest {
@BeforeEach
public void setUp() {
requestRespondentReviewPreparer =
new RequestRespondentReviewPreparer(DUE_IN_DAYS, ADA_DUE_IN_DAYS, dateProvider, dueDateService);
new RequestRespondentReviewPreparer(DUE_IN_DAYS, ADA_DUE_IN_DAYS, DETAINED_DUE_IN_DAYS, dateProvider, dueDateService);
}

@ParameterizedTest
Expand Down Expand Up @@ -186,4 +191,64 @@ void should_not_allow_null_arguments() {
.hasMessage("callback must not be null")
.isExactlyInstanceOf(NullPointerException.class);
}

@Test
void should_return_due_date_for_accelerated_detained_appeal() {
LocalDate today = LocalDate.of(2025, 5,5);
ZonedDateTime adaDueDate = today.plusDays(ADA_DUE_IN_DAYS).atStartOfDay(ZoneOffset.UTC);
String expectedDueDate = "2025-05-07";

when(callback.getCaseDetails()).thenReturn(caseDetails);
when(callback.getEvent()).thenReturn(Event.REQUEST_RESPONDENT_REVIEW);
when(caseDetails.getCaseData()).thenReturn(asylumCase);
when(asylumCase.read(IS_ACCELERATED_DETAINED_APPEAL, YesOrNo.class)).thenReturn(Optional.of(YesOrNo.YES));
when(dateProvider.now()).thenReturn(today);
when(asylumCase.read(APPEAL_TYPE, AppealType.class)).thenReturn(Optional.of(PA));
when(dueDateService.calculateDueDate(
any(), anyInt()))
.thenReturn(adaDueDate);

PreSubmitCallbackResponse<AsylumCase> response =
requestRespondentReviewPreparer.handle(PreSubmitCallbackStage.ABOUT_TO_START, callback);

verify(asylumCase).write(SEND_DIRECTION_DATE_DUE, expectedDueDate);
}

@Test
void should_return_due_date_for_standard_case() {
LocalDate today = LocalDate.of(2025, 5,5);
String expectedDueDate = "2025-05-19";

when(callback.getCaseDetails()).thenReturn(caseDetails);
when(callback.getEvent()).thenReturn(Event.REQUEST_RESPONDENT_REVIEW);
when(caseDetails.getCaseData()).thenReturn(asylumCase);
when(asylumCase.read(IS_ACCELERATED_DETAINED_APPEAL, YesOrNo.class)).thenReturn(Optional.of(YesOrNo.NO));
when(dateProvider.now()).thenReturn(today);
when(asylumCase.read(APPEAL_TYPE, AppealType.class)).thenReturn(Optional.of(PA));

PreSubmitCallbackResponse<AsylumCase> response =
requestRespondentReviewPreparer.handle(PreSubmitCallbackStage.ABOUT_TO_START, callback);

verify(asylumCase).write(SEND_DIRECTION_DATE_DUE, expectedDueDate);
}

@Test
void should_return_due_date_for_detained_case() {
LocalDate today = LocalDate.of(2025, 5,5);
String expectedDueDate = "2025-05-12";

when(callback.getCaseDetails()).thenReturn(caseDetails);
when(callback.getEvent()).thenReturn(Event.REQUEST_RESPONDENT_REVIEW);
when(caseDetails.getCaseData()).thenReturn(asylumCase);
when(asylumCase.read(IS_ACCELERATED_DETAINED_APPEAL, YesOrNo.class)).thenReturn(Optional.of(YesOrNo.NO));
when(asylumCase.read(APPELLANT_IN_DETENTION, YesOrNo.class)).thenReturn(Optional.of(YesOrNo.YES));
when(dateProvider.now()).thenReturn(today);
when(asylumCase.read(APPEAL_TYPE, AppealType.class)).thenReturn(Optional.of(PA));

PreSubmitCallbackResponse<AsylumCase> response =
requestRespondentReviewPreparer.handle(PreSubmitCallbackStage.ABOUT_TO_START, callback);

verify(asylumCase).write(SEND_DIRECTION_DATE_DUE, expectedDueDate);
}

}