|
|
@@ -1,5 +1,8 @@ |
|
|
|
package com.ffii.lioner.modules.lioner.pdf.service; |
|
|
|
|
|
|
|
import java.io.ByteArrayInputStream; |
|
|
|
import java.io.File; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
|
|
|
@@ -14,17 +17,29 @@ import java.util.stream.Collectors; |
|
|
|
|
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
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.springframework.core.io.ByteArrayResource; |
|
|
|
import org.springframework.core.io.ClassPathResource; |
|
|
|
|
|
|
|
import com.ffii.lioner.modules.lioner.pdf.entity.Pdf; |
|
|
|
import com.ffii.lioner.modules.lioner.pdf.entity.PdfRepository; |
|
|
|
import com.ffii.lioner.modules.lioner.commonField.entity.CommonField; |
|
|
|
import com.ffii.lioner.modules.lioner.commonField.service.CommonFieldService; |
|
|
|
import com.ffii.lioner.modules.lioner.entity.ImpEvent; |
|
|
|
import com.ffii.lioner.modules.lioner.pdf.req.UpdatePdfReq; |
|
|
|
import com.ffii.lioner.modules.lioner.service.FileService; |
|
|
|
import com.ffii.lioner.modules.common.SecurityUtils; |
|
|
|
import com.ffii.lioner.modules.common.service.AuditLogService; |
|
|
|
import com.ffii.lioner.modules.master.entity.SubDivision; |
|
|
|
import com.itextpdf.forms.PdfAcroForm; |
|
|
|
import com.itextpdf.forms.fields.PdfFormField; |
|
|
|
import com.itextpdf.io.source.ByteArrayOutputStream; |
|
|
|
import com.itextpdf.kernel.pdf.PdfDocument; |
|
|
|
import com.itextpdf.kernel.pdf.PdfReader; |
|
|
|
import com.itextpdf.kernel.pdf.PdfWriter; |
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper; |
|
|
|
import com.ffii.core.exception.NotFoundException; |
|
|
|
import com.ffii.core.exception.UnprocessableEntityException; |
|
|
@@ -35,6 +50,7 @@ import com.ffii.core.utils.JsonUtils; |
|
|
|
import com.ffii.core.utils.Params; |
|
|
|
|
|
|
|
import jakarta.persistence.Table; |
|
|
|
import com.ffii.lioner.modules.lioner.pdf.web.Pdf2Controller; |
|
|
|
|
|
|
|
@Service |
|
|
|
public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfRepository> { |
|
|
@@ -43,11 +59,13 @@ public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfReposito |
|
|
|
|
|
|
|
private AuditLogService auditLogService; |
|
|
|
private FileService fileService; |
|
|
|
private CommonFieldService commonFieldService; |
|
|
|
|
|
|
|
public PdfService(JdbcDao jdbcDao, PdfRepository repository, AuditLogService auditLogService, FileService fileService) { |
|
|
|
public PdfService(JdbcDao jdbcDao, PdfRepository repository, AuditLogService auditLogService, FileService fileService, CommonFieldService commonFieldService) { |
|
|
|
super(jdbcDao, repository); |
|
|
|
this.auditLogService = auditLogService; |
|
|
|
this.fileService = fileService; |
|
|
|
this.commonFieldService = commonFieldService; |
|
|
|
} |
|
|
|
|
|
|
|
// public Map<String,Object> getAuditLogObject(Map<String,Object> req){ |
|
|
@@ -130,10 +148,7 @@ public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfReposito |
|
|
|
System.out.println(e); |
|
|
|
} |
|
|
|
|
|
|
|
// Save the PDF data to the database |
|
|
|
// File pdfForm = new PdfForm(); |
|
|
|
// pdfForm.setPdfData(pdfData); |
|
|
|
// pdfFormRepository.save(pdfForm); // Assuming you have autowired this repository |
|
|
|
saveCmField(convertMultipartFileToFile(file), instance); |
|
|
|
|
|
|
|
response.put("message", "PDF saved successfully."); |
|
|
|
// response.put("id", pdfForm.getId().toString()); // Return the ID of the saved PDF |
|
|
@@ -162,18 +177,136 @@ public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfReposito |
|
|
|
return response; |
|
|
|
} |
|
|
|
|
|
|
|
public byte[] getTemplateForm() { |
|
|
|
// Ensure the template PDF is in src/main/resources/template/pdf |
|
|
|
ClassPathResource pdfFile = new ClassPathResource(pdf_path + "HSBC B24102883_fillable_Financial Needs Analysis for Individual Nov2024.pdf"); |
|
|
|
if (!pdfFile.exists()) { |
|
|
|
throw new UnprocessableEntityException("PDF template not found."); |
|
|
|
// Converter -- WIP |
|
|
|
public File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException { |
|
|
|
// Convert MultipartFile to byte array |
|
|
|
byte[] bytes = multipartFile.getBytes(); |
|
|
|
|
|
|
|
// Create a temporary file |
|
|
|
File file = File.createTempFile("tempFile", multipartFile.getOriginalFilename()); |
|
|
|
|
|
|
|
// Write byte array to the file |
|
|
|
try (FileOutputStream fos = new FileOutputStream(file)) { |
|
|
|
fos.write(bytes); |
|
|
|
} |
|
|
|
try (InputStream is = pdfFile.getInputStream()) { |
|
|
|
return is.readAllBytes(); |
|
|
|
|
|
|
|
return file; |
|
|
|
} |
|
|
|
|
|
|
|
public byte[] getTemplateForm(Long templateId, Long clientId) { |
|
|
|
// Ensure the template PDF is in src/main/resources/template/pdf |
|
|
|
String filename; |
|
|
|
switch (templateId.intValue()) { |
|
|
|
case 1: |
|
|
|
filename = "IDA.pdf"; |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
filename = "FNA.pdf"; |
|
|
|
break; |
|
|
|
case 3: |
|
|
|
filename = "HSBCFIN.pdf"; |
|
|
|
break; |
|
|
|
default: |
|
|
|
filename = "HSBCFIN.pdf"; |
|
|
|
}; |
|
|
|
ClassPathResource pdfFile = new ClassPathResource(pdf_path + filename); |
|
|
|
|
|
|
|
byte[] pdfBytes; |
|
|
|
|
|
|
|
byte[] modifiedPdfBytes; |
|
|
|
try (InputStream is = pdfFile.getInputStream()) { |
|
|
|
pdfBytes = is.readAllBytes(); |
|
|
|
modifiedPdfBytes = pdfBytes; |
|
|
|
} catch (Exception e) { |
|
|
|
throw new UnprocessableEntityException("Fail to load PDF: " + e); |
|
|
|
} |
|
|
|
|
|
|
|
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(pdfBytes); |
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { |
|
|
|
|
|
|
|
PdfReader reader = new PdfReader(inputStream); |
|
|
|
PdfWriter writer = new PdfWriter(outputStream); |
|
|
|
PdfDocument pdfDoc = new PdfDocument(reader, writer); |
|
|
|
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); |
|
|
|
|
|
|
|
if (form != null) { |
|
|
|
// --- START DEBUGGING CODE TO LIST ALL PDF FORM FIELDS --- |
|
|
|
// logger.info("--- Listing all form fields in the PDF (for ID: {}) ---", id); |
|
|
|
// if (form.getFormFields().isEmpty()) { |
|
|
|
// logger.info("No form fields found in this PDF."); |
|
|
|
// } else { |
|
|
|
// form.getFormFields().forEach((fieldName, pdfFormField) -> { |
|
|
|
// logger.info(" - Field Name: '{}', Type: '{}'", fieldName, pdfFormField.getFormType()); |
|
|
|
// }); |
|
|
|
// } |
|
|
|
// logger.info("--- End of form fields list ---"); |
|
|
|
// --- END DEBUGGING CODE --- |
|
|
|
|
|
|
|
// Load common field data |
|
|
|
Long commonFieldId = commonFieldService.getByClientId(clientId); |
|
|
|
// logger.info("id? " + id); |
|
|
|
CommonField commonField = commonFieldService.find(commonFieldId).orElse(null); |
|
|
|
|
|
|
|
if(commonField == null){ |
|
|
|
logger.info("No common field data found for clientId: " + clientId); |
|
|
|
// do nothing |
|
|
|
} else { |
|
|
|
// It's highly recommended to check if the field exists before setting its value |
|
|
|
// This prevents NullPointerExceptions if a field is missing in a template |
|
|
|
|
|
|
|
if(templateId.intValue() == 1){ // This is IDA |
|
|
|
logger.info("Processing IDA form (ID: 1)"); |
|
|
|
setValueIfPresent(form, "fill_6", commonField.getName(), "commonField.getName()"); |
|
|
|
setValueIfPresent(form, "fill_7", commonField.getNameChi(), "commonField.getNameChi()"); |
|
|
|
setValueIfPresent(form, "fill_11", commonField.getIdCard(), "commonField.getIdCard()"); |
|
|
|
|
|
|
|
} else if(templateId.intValue() == 2){ // This is FNA |
|
|
|
logger.info("Processing FNA form (ID: 2)"); |
|
|
|
setValueIfPresent(form, "fna_a_name", commonField.getName(), "commonField.getName()"); |
|
|
|
setValueIfPresent(form, "fna_a_birth", commonField.getDateOfBirth(), "commonField.getDateOfBirth()"); |
|
|
|
setValueIfPresent(form, "fna_a_occupation", commonField.getOccupation(), "commonField.getOccupation()"); |
|
|
|
|
|
|
|
} else if(templateId.intValue() == 3){ // This is HSBCFIN |
|
|
|
logger.info("Processing HSBCFIN form (ID: 3)"); |
|
|
|
setValueIfPresent(form, "fill_3", commonField.getName(), "commonField.getName()"); |
|
|
|
setValueIfPresent(form, "fill_4", commonField.getNameChi(), "commonField.getNameChi()"); |
|
|
|
setValueIfPresent(form, "fill_5", commonField.getGender(), "commonField.getGender()"); |
|
|
|
setValueIfPresent(form, "fill_6", commonField.getDateOfBirth(), "commonField.getDateOfBirth()"); // Note: fill_6 used here again |
|
|
|
setValueIfPresent(form, "fill_9", commonField.getOccupation(), "commonField.getOccupation()"); |
|
|
|
} |
|
|
|
|
|
|
|
// These fields are set unconditionally if commonField is not null |
|
|
|
// Ensure these fields exist across all your templates or handle them conditionally |
|
|
|
setValueIfPresent(form, "address", "123 Main St, Anytown, USA", "hardcoded address"); |
|
|
|
setValueIfPresent(form, "dateOfBirth", "01/01/1990", "hardcoded dateOfBirth"); |
|
|
|
} |
|
|
|
|
|
|
|
//form.flattenFields(); // Flatten fields after setting all values |
|
|
|
|
|
|
|
} else { |
|
|
|
// logger.warn("No AcroForm found in PDF for ID: " + id + ". PDF might not have fillable fields."); |
|
|
|
} |
|
|
|
|
|
|
|
pdfDoc.close(); |
|
|
|
modifiedPdfBytes = outputStream.toByteArray(); |
|
|
|
logger.info("Modified PDF byte array length: " + modifiedPdfBytes.length); |
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
|
// logger.error("Error processing PDF with iText for ID: " + id, e); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!pdfFile.exists()) { |
|
|
|
throw new UnprocessableEntityException("PDF template not found."); |
|
|
|
} |
|
|
|
// try (InputStream is = pdfFile.getInputStream()) { |
|
|
|
// return pdfBytes; |
|
|
|
// } catch (Exception e) { |
|
|
|
// throw new UnprocessableEntityException("Fail to load PDF: " + e); |
|
|
|
// } |
|
|
|
return modifiedPdfBytes; |
|
|
|
// return fileService.getfileBlob((long) 2); |
|
|
|
} |
|
|
|
|
|
|
@@ -245,4 +378,100 @@ public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfReposito |
|
|
|
return jdbcDao.queryForInt(sql.toString(), Map.of("name", name)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void saveCmField(File file, Pdf record) throws IOException { |
|
|
|
// byte[] pdfBytes = Files.readAllBytes(file.toPath()); |
|
|
|
|
|
|
|
// try (FileOutputStream fos = new FileOutputStream(file)) { |
|
|
|
// IOUtils.write(pdfBytes, fos); |
|
|
|
// } |
|
|
|
|
|
|
|
//PDDocument document = PDDocument.load(targetLocation.toFile()); |
|
|
|
PDDocument document = Loader.loadPDF(file); // Changed! |
|
|
|
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm(); |
|
|
|
|
|
|
|
logger.info("acroForm? " + (acroForm != null) ); |
|
|
|
if (acroForm != null) { |
|
|
|
//create CommonField if not exists for this client Id |
|
|
|
Long id = commonFieldService.getByClientId(record.getClientId()); |
|
|
|
logger.info("id? " + id); |
|
|
|
CommonField commonField = null; |
|
|
|
if(id > 0){ |
|
|
|
commonField = commonFieldService.find(id).orElse(new CommonField()); |
|
|
|
}else{ |
|
|
|
commonField = new CommonField(); |
|
|
|
} |
|
|
|
//logger.info("commonField? " + commonField.toString()); |
|
|
|
commonField.setClientId(record.getClientId()); |
|
|
|
|
|
|
|
logger.info("commonField? " + commonField.getId()); |
|
|
|
// Example: Iterate through fields and print values |
|
|
|
for (PDField field : acroForm.getFields()) { |
|
|
|
String fieldName = field.getPartialName(); |
|
|
|
String fieldValue = field.getValueAsString(); |
|
|
|
|
|
|
|
if (record.getTemplateId().intValue() == 1) { |
|
|
|
logger.info("IDA "); |
|
|
|
|
|
|
|
switch (fieldName) { |
|
|
|
case "fill_6" -> commonField.setName(fieldValue); |
|
|
|
case "fill_7" -> commonField.setNameChi(fieldValue); |
|
|
|
case "fill_11" -> commonField.setIdCard(fieldValue); |
|
|
|
|
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
if(record.getTemplateId().intValue() == 2){ |
|
|
|
logger.info("FNA "); |
|
|
|
|
|
|
|
switch (fieldName) { |
|
|
|
case "fna_a_name" -> commonField.setName(fieldValue); |
|
|
|
case "fna_a_birth" -> commonField.setDateOfBirth(fieldValue); |
|
|
|
case "fna_a_occupation" -> commonField.setOccupation(fieldValue); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
if(record.getTemplateId().intValue() == 3){ |
|
|
|
logger.info("HSBCFIN "); |
|
|
|
|
|
|
|
switch (fieldName) { |
|
|
|
case "fill_3" -> commonField.setName(fieldValue); |
|
|
|
case "fill_4" -> commonField.setNameChi(fieldValue); |
|
|
|
case "fill_5" -> commonField.setGender(fieldValue); |
|
|
|
case "fill_6" -> commonField.setDateOfBirth(fieldValue); |
|
|
|
|
|
|
|
case "fill_9" -> commonField.setOccupation(fieldValue); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
logger.info("end Field: " + field.getPartialName() + ", Value: " + field.getValueAsString()); |
|
|
|
// You can save this data to a database, or perform other operations |
|
|
|
} |
|
|
|
|
|
|
|
commonFieldService.save(commonField); |
|
|
|
} |
|
|
|
logger.info("ended"); |
|
|
|
document.close(); |
|
|
|
logger.info("closed"); |
|
|
|
} |
|
|
|
|
|
|
|
private void setValueIfPresent(PdfAcroForm form, String fieldName, String value, String valueSource) { |
|
|
|
PdfFormField field = form.getField(fieldName); |
|
|
|
if (field != null) { |
|
|
|
if (value != null) { |
|
|
|
try { |
|
|
|
field.setValue(value); |
|
|
|
// logger.info("Set field '{}' to value '{}' (from {})", fieldName, value, valueSource); |
|
|
|
} catch (Exception e) { |
|
|
|
// logger.error("Error setting value for field '{}' with value '{}' (from {}): {}", fieldName, value, valueSource, e.getMessage()); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// logger.warn("Value for field '{}' (from {}) is null. Skipping setting value.", fieldName, valueSource); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// logger.warn("PDF field '{}' not found in the document. Skipping setting value.", fieldName); |
|
|
|
} |
|
|
|
} |
|
|
|
} |