diff --git a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/error/StampDocumentException.java b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/error/StampDocumentException.java index da9753e795..189cefe144 100644 --- a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/error/StampDocumentException.java +++ b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/error/StampDocumentException.java @@ -2,6 +2,10 @@ public class StampDocumentException extends RuntimeException { + public StampDocumentException(String message) { + super(message); + } + public StampDocumentException(String message, Throwable cause) { super(message, cause); } diff --git a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandler.java b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandler.java index be7a123592..a20eae8131 100644 --- a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandler.java +++ b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandler.java @@ -22,6 +22,7 @@ import uk.gov.hmcts.reform.finrem.caseorchestration.service.GenericDocumentService; import uk.gov.hmcts.reform.finrem.caseorchestration.service.StampType; +import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,6 +31,8 @@ import static org.springframework.util.ObjectUtils.isEmpty; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ConsentedStatus.CONSENT_ORDER_MADE; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.APPROVED_ORDER_COLLECTION; +import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.CONSENTED_ORDER_DIRECTION_DATE; +import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.CONTESTED_ORDER_DIRECTION_DATE; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.LATEST_CONSENT_ORDER; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.STATE; @@ -44,7 +47,6 @@ public class ApprovedConsentOrderAboutToSubmitHandler implements CallbackHandler private final DocumentHelper documentHelper; private final ObjectMapper mapper; - @Override public boolean canHandle(final CallbackType callbackType, final CaseType caseType, final EventType eventType) { @@ -58,7 +60,7 @@ public GenericAboutToStartOrSubmitCallbackResponse> handle(C String userAuthorisation) { CaseDetails caseDetails = callbackRequest.getCaseDetails(); CaseDetails caseDetailsBefore = callbackRequest.getCaseDetailsBefore(); - String caseId = String.valueOf(caseDetails.getId()); + String caseId = String.valueOf(caseDetails.getId()); log.info("ConsentOrderApprovedAboutToSubmitHandle handle Case ID {}", caseId); CaseDocument latestConsentOrder = getLatestConsentOrder(caseDetails.getData()); @@ -77,7 +79,6 @@ private void generateAndPrepareDocuments(String authToken, CaseDetails caseDetai CaseDetails caseDetailsBefore, CaseDocument latestConsentOrder) { String caseId = caseDetails.getId().toString(); log.info("Generating and preparing documents for latest consent order, Case ID: {}", caseId); - Map caseData = caseDetails.getData(); StampType stampType = documentHelper.getStampType(caseData); CaseDocument approvedConsentOrderLetter = consentOrderApprovedDocumentService.generateApprovedConsentOrderLetter(caseDetails, authToken); @@ -92,9 +93,9 @@ private void generateAndPrepareDocuments(String authToken, CaseDetails caseDetai if (Boolean.FALSE.equals(isPensionDocumentsEmpty(caseData))) { log.info("Pension Documents not empty for case - stamping Pension Documents and adding to approvedOrder for Case ID: {}", caseId); - + LocalDate approvalDate = getApprovalDate(caseData); List stampedPensionDocs = consentOrderApprovedDocumentService.stampPensionDocuments( - documentHelper.getPensionDocuments(caseData), authToken, stampType, caseId); + documentHelper.getPensionDocuments(caseData), authToken, stampType, approvalDate, caseId); log.info("Generated StampedPensionDocs = {} for Case ID: {}", stampedPensionDocs, caseDetails.getId()); approvedOrder.setPensionDocuments(stampedPensionDocs); } @@ -132,4 +133,23 @@ private Boolean isPensionDocumentsEmpty(Map caseData) { List pensionDocumentsData = documentHelper.getPensionDocumentsData(caseData); return pensionDocumentsData.isEmpty(); } + + private LocalDate getApprovalDate(Map caseData) { + return (caseData.get(CONTESTED_ORDER_DIRECTION_DATE) != null) + ? parseLocalDate(caseData, CONTESTED_ORDER_DIRECTION_DATE) + : parseLocalDate(caseData, CONSENTED_ORDER_DIRECTION_DATE); + } + + private LocalDate parseLocalDate(Map caseData, String orderDirectionDateKey) { + if (caseData.get(orderDirectionDateKey) instanceof LocalDate) { + return (LocalDate) caseData.get(orderDirectionDateKey); + } else { + try { + return LocalDate.parse((String) caseData.get(orderDirectionDateKey)); + } catch (Exception e) { + log.info("Invalid Approved date of order for key: '" + orderDirectionDateKey + "': " + e.getMessage()); + return null; + } + } + } } diff --git a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentService.java b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentService.java index 65873e5075..cd5da1aa45 100644 --- a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentService.java +++ b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentService.java @@ -26,6 +26,7 @@ import uk.gov.hmcts.reform.finrem.caseorchestration.model.document.BulkPrintDocument; import uk.gov.hmcts.reform.finrem.caseorchestration.service.documentcatergory.ApprovedConsentOrderDocumentCategoriser; +import java.time.LocalDate; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -64,6 +65,7 @@ public class ConsentOrderApprovedDocumentService { private final FinremCaseDetailsMapper finremCaseDetailsMapper; private final BulkPrintCoverLetterDetailsMapper bulkPrintLetterDetailsMapper; private final ApprovedConsentOrderDocumentCategoriser approvedConsentOrderCategoriser; + private final PensionAnnexDateStampService pensionAnnexDateStampService; public CaseDocument generateApprovedConsentOrderLetter(CaseDetails caseDetails, String authToken) { String fileName; @@ -118,19 +120,27 @@ public CaseDocument generateApprovedConsentOrderCoverLetter(FinremCaseDetails ca public List stampPensionDocuments(List pensionList, String authToken, StampType stampType, + LocalDate approvalDate, String caseId) { return pensionList.stream() .filter(pensionCollectionData -> pensionCollectionData.getTypedCaseDocument().getPensionDocument() != null) - .map(pensionCollectionData -> stampPensionDocuments(pensionCollectionData, authToken, stampType, caseId)) + .map(pensionCollectionData -> stampPensionDocuments(pensionCollectionData, authToken, stampType, approvalDate, caseId)) .toList(); } private PensionTypeCollection stampPensionDocuments(PensionTypeCollection pensionDocument, String authToken, StampType stampType, + LocalDate approvalDate, String caseId) { CaseDocument document = pensionDocument.getTypedCaseDocument().getPensionDocument(); CaseDocument stampedDocument = genericDocumentService.stampDocument(document, authToken, stampType, caseId); + try { + stampedDocument = pensionAnnexDateStampService.appendApprovedDateToDocument(stampedDocument, + authToken, approvalDate, caseId); + } catch (Exception ex) { + log.info("Failed to add date stamp to Pension Sharing Annex document. Case ID: {} Exception: {}", caseId, ex.getMessage()); + } PensionTypeCollection stampedPensionData = documentHelper.deepCopy(pensionDocument, PensionTypeCollection.class); stampedPensionData.getTypedCaseDocument().setPensionDocument(stampedDocument); return stampedPensionData; @@ -210,7 +220,8 @@ private List consentInContestedStampPensionDocuments(Finr String caseId) { List pensionDocs = getContestedConsentPensionDocuments(caseData); StampType stampType = documentHelper.getStampType(caseData); - return stampPensionDocuments(pensionDocs, authToken, stampType, caseId); + LocalDate approvalDate = caseData.getConsentOrderWrapper().getConsentDateOfOrder(); + return stampPensionDocuments(pensionDocs, authToken, stampType, approvalDate, caseId); } private List getContestedConsentPensionDocuments(FinremCaseData caseData) { @@ -335,6 +346,8 @@ public void addGeneratedApprovedConsentOrderDocumentsToCase(String userAuthorisa CaseDocument consentOrderAnnexStamped = genericDocumentService.annexStampDocument(finremCaseData.getLatestConsentOrder(), userAuthorisation, stampType, caseId); + LocalDate consentDateOfOrder = finremCaseData.getConsentOrderWrapper().getConsentDateOfOrder(); + LocalDate approvalDate = (consentDateOfOrder == null) ? finremCaseData.getOrderDirectionDate() : consentDateOfOrder; ApprovedOrder approvedOrder = ApprovedOrder.builder() .orderLetter(approvedConsentOrderLetter) @@ -347,7 +360,7 @@ public void addGeneratedApprovedConsentOrderDocumentsToCase(String userAuthorisa + "stamping Pension Documents and adding to approvedOrder for Case ID: {}", caseId); List stampedPensionDocs = stampPensionDocuments(pensionCollection, - userAuthorisation, stampType, caseId); + userAuthorisation, stampType, approvalDate, caseId); log.info("Generated StampedPensionDocs = {} for Case ID: {}", stampedPensionDocs, caseId); approvedOrder.setPensionDocuments(stampedPensionDocs); } diff --git a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/GenericDocumentService.java b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/GenericDocumentService.java index aa4b23d930..d320966b31 100644 --- a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/GenericDocumentService.java +++ b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/GenericDocumentService.java @@ -88,7 +88,7 @@ public CaseDocument stampDocument(CaseDocument document, StampType stampType, String caseId) { CaseDocument pdfCaseDocument = convertDocumentIfNotPdfAlready(document, authorisationToken, caseId); - log.info("Pdf converation if document is not pdf origial {} pdfdocument {} for Case ID: {}", + log.info("Pdf conversion if document is not pdf original {} pdfdocument {} for Case ID: {}", document.getDocumentFilename(), pdfCaseDocument.getDocumentFilename(), caseId); Document stampedDocument = pdfStampingService.stampDocument( Document.builder().url(pdfCaseDocument.getDocumentUrl()) diff --git a/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampService.java b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampService.java new file mode 100644 index 0000000000..b44417c136 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampService.java @@ -0,0 +1,90 @@ +package uk.gov.hmcts.reform.finrem.caseorchestration.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.form.PDField; +import org.apache.pdfbox.pdmodel.interactive.form.PDTextField; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import uk.gov.hmcts.reform.finrem.caseorchestration.error.DocumentStorageException; +import uk.gov.hmcts.reform.finrem.caseorchestration.error.StampDocumentException; +import uk.gov.hmcts.reform.finrem.caseorchestration.model.FinremMultipartFile; +import uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CaseDocument; +import uk.gov.hmcts.reform.finrem.caseorchestration.model.document.Document; +import uk.gov.hmcts.reform.finrem.caseorchestration.model.evidence.FileUploadResponse; +import uk.gov.hmcts.reform.finrem.caseorchestration.service.evidencemanagement.EvidenceManagementDownloadService; +import uk.gov.hmcts.reform.finrem.caseorchestration.service.evidencemanagement.EvidenceManagementUploadService; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Optional; + +import static org.springframework.http.MediaType.APPLICATION_PDF_VALUE; +import static uk.gov.hmcts.reform.finrem.caseorchestration.service.DocumentManagementService.CONVERTER; + +@Service +@RequiredArgsConstructor +@Slf4j +public class PensionAnnexDateStampService { + private final EvidenceManagementUploadService emUploadService; + private final EvidenceManagementDownloadService emDownloadService; + static final String FORM_P1_DATE_OF_ORDER_TEXTBOX_NAME = "Date the court made/varied/discharged an order"; + static final String DATE_STAMP_PATTERN = "dd MMMM yyyy"; + + public CaseDocument appendApprovedDateToDocument(CaseDocument document, + String authToken, + LocalDate approvalDate, + String caseId) throws Exception { + log.info("Adding date stamp to Pension Sharing Annex for Case id: {}", caseId); + Optional optionalApprovalDate = Optional.ofNullable(approvalDate); + if (optionalApprovalDate.isPresent()) { + byte[] docInBytes = emDownloadService.download(document.getDocumentBinaryUrl(), authToken); + byte[] approvedDoc = appendApprovedDateToDocument(docInBytes, approvalDate); + MultipartFile multipartFile = + FinremMultipartFile.builder().name(document.getDocumentFilename()).content(approvedDoc) + .contentType(APPLICATION_PDF_VALUE).build(); + List uploadResponse = + emUploadService.upload(Collections.singletonList(multipartFile), caseId, authToken); + FileUploadResponse fileSaved = Optional.of(uploadResponse.get(0)) + .filter(response -> response.getStatus() == HttpStatus.OK) + .orElseThrow(() -> new DocumentStorageException("Failed to store document Case id: " + caseId)); + Document dateStampedDocument = CONVERTER.apply(fileSaved); + return CaseDocument.from(dateStampedDocument); + } else { + throw new StampDocumentException("Missing or Invalid Approved Date of Order for Case id: " + caseId); + } + } + + private byte[] appendApprovedDateToDocument(byte[] inputDocInBytes, LocalDate approvalDate) throws StampDocumentException, IOException { + PDDocument doc = Loader.loadPDF(inputDocInBytes); + doc.setAllSecurityToBeRemoved(true); + PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm(); + if (acroForm != null && acroForm.getField(FORM_P1_DATE_OF_ORDER_TEXTBOX_NAME) != null + && (acroForm.getField(FORM_P1_DATE_OF_ORDER_TEXTBOX_NAME) instanceof PDTextField)) { + + // Update the default appearance string + PDField field = acroForm.getField(FORM_P1_DATE_OF_ORDER_TEXTBOX_NAME); + PDTextField textBox = (PDTextField) field; + String defaultAppearance = textBox.getAcroForm().getDefaultAppearance(); + + textBox.setDefaultAppearance(defaultAppearance); + textBox.setValue(approvalDate.format(DateTimeFormatter.ofPattern(DATE_STAMP_PATTERN).withLocale(Locale.UK))); + + ByteArrayOutputStream outputBytes = new ByteArrayOutputStream(); + doc.save(outputBytes); + doc.close(); + return outputBytes.toByteArray(); + } else { + throw new StampDocumentException("Pension Order document PDF is flattened / not editable."); + } + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandlerTest.java b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandlerTest.java index 0c9297ae41..99d7b624a8 100644 --- a/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandlerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/handler/ApprovedConsentOrderAboutToSubmitHandlerTest.java @@ -22,6 +22,7 @@ import uk.gov.hmcts.reform.finrem.caseorchestration.service.GenericDocumentService; import java.io.InputStream; +import java.time.LocalDate; import java.util.Map; import static java.util.Collections.singletonList; @@ -31,6 +32,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.never; @@ -40,6 +42,8 @@ import static uk.gov.hmcts.reform.finrem.caseorchestration.TestSetUpUtils.caseDocument; import static uk.gov.hmcts.reform.finrem.caseorchestration.TestSetUpUtils.feignError; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ConsentedStatus.CONSENT_ORDER_MADE; +import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.CONSENTED_ORDER_DIRECTION_DATE; +import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.CONTESTED_ORDER_DIRECTION_DATE; import static uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CCDConfigConstant.STATE; @ExtendWith(MockitoExtension.class) @@ -141,7 +145,7 @@ void given_case_when_NotPaperApplication_then_shouldNotTriggerConsentOrderApprov } @Test - void givenCase_whenNoPendsion_thenShouldUpdateStateToConsentOrderMadeAndBulkPrint() { + void givenCase_whenNoPension_thenShouldUpdateStateToConsentOrderMadeAndBulkPrint() { CallbackRequest callbackRequest = doValidCaseDataSetUp(NO_PENSION_VALID_JSON); whenServiceGeneratesDocument().thenReturn(caseDocument()); @@ -184,6 +188,44 @@ void shouldUpdateStateToConsentOrderMadeAndBulkPrint_noEmails() { any()); } + @Test + void shouldDateStampPensionSharingAnnexContested() { + whenServiceGeneratesDocument().thenReturn(caseDocument()); + when(documentHelper.getPensionDocumentsData(any(Map.class))).thenReturn(singletonList(caseDocument())); + LocalDate approvedDate = LocalDate.of(2024, 12, 01); + + CallbackRequest callbackRequest = + doValidCaseDataSetUp(APPROVE_ORDER_VALID_JSON); + callbackRequest.getCaseDetails().getData().put(CONTESTED_ORDER_DIRECTION_DATE, approvedDate); + callbackRequest.getCaseDetails().getData().put(CONSENTED_ORDER_DIRECTION_DATE, null); + handler.handle(callbackRequest, AUTH_TOKEN); + + verify(consentOrderApprovedDocumentService).stampPensionDocuments(anyList(), + any(), + any(), + any(), + any()); + } + + @Test + void shouldDateStampPensionSharingAnnexConsented() { + whenServiceGeneratesDocument().thenReturn(caseDocument()); + when(documentHelper.getPensionDocumentsData(any(Map.class))).thenReturn(singletonList(caseDocument())); + LocalDate approvedDate = LocalDate.of(2024, 12, 1); + + CallbackRequest callbackRequest = + doValidCaseDataSetUp(APPROVE_ORDER_VALID_JSON); + callbackRequest.getCaseDetails().getData().put(CONTESTED_ORDER_DIRECTION_DATE, null); + callbackRequest.getCaseDetails().getData().put(CONSENTED_ORDER_DIRECTION_DATE, approvedDate); + handler.handle(callbackRequest, AUTH_TOKEN); + + verify(consentOrderApprovedDocumentService).stampPensionDocuments(anyList(), + any(), + any(), + any(), + any()); + } + private CallbackRequest doValidCaseDataSetUp(final String path) { try (InputStream resourceAsStream = getClass().getResourceAsStream(path)) { return objectMapper.readValue(resourceAsStream, CallbackRequest.class); diff --git a/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentServiceTest.java b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentServiceTest.java index fd951514cd..81147105c1 100644 --- a/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/ConsentOrderApprovedDocumentServiceTest.java @@ -35,6 +35,7 @@ import uk.gov.hmcts.reform.finrem.caseorchestration.service.evidencemanagement.EvidenceManagementUploadService; import java.nio.charset.StandardCharsets; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; @@ -318,7 +319,7 @@ public void givenNullDocumentInPensionDocuments_whenStampingDocuments_thenTheNul asList(pensionDocumentData(), pensionCollectionDataWithNullDocument); List stampPensionDocuments = consentOrderApprovedDocumentService - .stampPensionDocuments(pensionDocuments, AUTH_TOKEN, StampType.FAMILY_COURT_STAMP, caseId); + .stampPensionDocuments(pensionDocuments, AUTH_TOKEN, StampType.FAMILY_COURT_STAMP, LocalDate.now(), caseId); assertThat(stampPensionDocuments, hasSize(1)); } diff --git a/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampServiceTest.java b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampServiceTest.java new file mode 100644 index 0000000000..c34d34e361 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/finrem/caseorchestration/service/PensionAnnexDateStampServiceTest.java @@ -0,0 +1,122 @@ +package uk.gov.hmcts.reform.finrem.caseorchestration.service; + +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; +import org.apache.pdfbox.pdmodel.interactive.form.PDField; +import org.apache.pdfbox.pdmodel.interactive.form.PDTextField; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.multipart.MultipartFile; +import uk.gov.hmcts.reform.finrem.caseorchestration.model.ccd.CaseDocument; +import uk.gov.hmcts.reform.finrem.caseorchestration.service.evidencemanagement.EvidenceManagementDownloadService; +import uk.gov.hmcts.reform.finrem.caseorchestration.service.evidencemanagement.EvidenceManagementUploadService; + +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static uk.gov.hmcts.reform.finrem.caseorchestration.TestConstants.AUTH_TOKEN; +import static uk.gov.hmcts.reform.finrem.caseorchestration.util.TestResource.fileUploadResponse; + +@ExtendWith(MockitoExtension.class) +class PensionAnnexDateStampServiceTest { + + @InjectMocks + private PensionAnnexDateStampService service; + @Mock + private EvidenceManagementUploadService emUploadService; + @Mock + private EvidenceManagementDownloadService emDownloadService; + @Mock + private GenericDocumentService genericDocumentService; + private final String caseId = "123123123"; + private final LocalDate approvalDate = LocalDate.of(2024, 12, 31); + @Captor + private ArgumentCaptor> filesCaptor; + private CaseDocument document; + + @BeforeEach + void setUp() { + document = CaseDocument.builder() + .documentBinaryUrl("https:mockurl/binary") + .documentFilename("Testfile") + .documentUrl("http:mockfile").build(); + } + + @Test + void shouldAddApprovalDateToPensionOrderDocument() throws Exception { + byte[] docInBytes = loadResource("/fixtures/P1_pension_sharing_annex.pdf"); + when(emDownloadService.download(document.getDocumentBinaryUrl(), AUTH_TOKEN)) + .thenReturn(docInBytes); + when(emUploadService.upload(any(), anyString(), any())) + .thenReturn(fileUploadResponse()); + service.appendApprovedDateToDocument(document, AUTH_TOKEN, approvalDate, caseId); + + verify(emUploadService).upload(filesCaptor.capture(), anyString(), anyString()); + List uploadedMultipartFiles = filesCaptor.getValue(); + byte[] bytes = uploadedMultipartFiles.get(0).getBytes(); + verifyDateOfOrderField(bytes); + } + + @Test + void shouldAddApprovalDateToPensionOrderDocumentWithNoEmbeddedFonts() throws Exception { + byte[] docInBytes = loadResource("/fixtures/P1_pension_sharing_annex_no_embedded_font.pdf"); + when(emDownloadService.download(document.getDocumentBinaryUrl(), AUTH_TOKEN)) + .thenReturn(docInBytes); + when(emUploadService.upload(any(), anyString(), any())) + .thenReturn(fileUploadResponse()); + service.appendApprovedDateToDocument(document, AUTH_TOKEN, approvalDate, caseId); + + verify(emUploadService).upload(filesCaptor.capture(), anyString(), anyString()); + List uploadedMultipartFiles = filesCaptor.getValue(); + byte[] bytes = uploadedMultipartFiles.get(0).getBytes(); + verifyDateOfOrderField(bytes); + } + + @Test + void shouldNotAddApprovalDateToPensionOrderDocumentIfApprovalDateIsMissing() { + Exception exception = assertThrows(Exception.class, () -> service.appendApprovedDateToDocument(document, AUTH_TOKEN, null, caseId)); + assertEquals("Missing or Invalid Approved Date of Order for Case id: " + caseId, exception.getMessage()); + } + + @Test + void shouldNotAddApprovalDateToPensionOrderFlattenedDocument() throws IOException { + byte[] docInBytes = loadResource("/fixtures/P1_pension_sharing_annex_flattened.pdf"); + when(emDownloadService.download(document.getDocumentBinaryUrl(), AUTH_TOKEN)) + .thenReturn(docInBytes); + + Exception exception = assertThrows(Exception.class, () -> service.appendApprovedDateToDocument(document, AUTH_TOKEN, approvalDate, caseId)); + assertEquals("Pension Order document PDF is flattened / not editable.", exception.getMessage()); + } + + private byte[] loadResource(String testPdf) throws IOException { + try (InputStream resourceAsStream = getClass().getResourceAsStream(testPdf)) { + assert resourceAsStream != null; + return resourceAsStream.readAllBytes(); + } + } + + private void verifyDateOfOrderField(byte[] bytes) throws IOException { + try (PDDocument pdDocument = Loader.loadPDF(bytes)) { + pdDocument.setAllSecurityToBeRemoved(true); + PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm(); + PDField field = pdAcroForm.getField(PensionAnnexDateStampService.FORM_P1_DATE_OF_ORDER_TEXTBOX_NAME); + PDTextField textBox = (PDTextField) field; + assertEquals("31 December 2024", textBox.getValueAsString()); + } + } +} diff --git a/src/test/resources/fixtures/P1_pension_sharing_annex.pdf b/src/test/resources/fixtures/P1_pension_sharing_annex.pdf new file mode 100644 index 0000000000..f6bfca32a4 Binary files /dev/null and b/src/test/resources/fixtures/P1_pension_sharing_annex.pdf differ diff --git a/src/test/resources/fixtures/P1_pension_sharing_annex_flattened.pdf b/src/test/resources/fixtures/P1_pension_sharing_annex_flattened.pdf new file mode 100644 index 0000000000..3f5fc907ad Binary files /dev/null and b/src/test/resources/fixtures/P1_pension_sharing_annex_flattened.pdf differ diff --git a/src/test/resources/fixtures/P1_pension_sharing_annex_no_embedded_font.pdf b/src/test/resources/fixtures/P1_pension_sharing_annex_no_embedded_font.pdf new file mode 100644 index 0000000000..0d6fe03707 Binary files /dev/null and b/src/test/resources/fixtures/P1_pension_sharing_annex_no_embedded_font.pdf differ