From 6a6a5199a0b15c3a324d4fb9136db59f25e18df7 Mon Sep 17 00:00:00 2001 From: "vluk@2fi-solutions.com.hk" Date: Tue, 30 Sep 2025 21:28:13 +0800 Subject: [PATCH] no message --- .../lioner/pdf/service/PdfMergeService.java | 195 +++++++++++++++++- .../lioner/pdf/service/PdfService.java | 67 +++--- .../modules/lioner/pdf/web/PdfController.java | 27 +++ .../template/service/TemplateService.java | 1 + .../userActionLog/entity/UserActionLog.java | 68 ++++++ .../entity/UserActionLogRepository.java | 6 + .../req/UpdateUserActionLogReq.java | 61 ++++++ .../service/UserActionLogService.java | 77 +++++++ .../web/UserActionLogController.java | 97 +++++++++ .../30_user_action_log/01_drop_and_create.sql | 21 ++ .../30_user_action_log/02_username.sql | 6 + .../30_user_action_log/03_userid_remove.sql | 7 + 12 files changed, 601 insertions(+), 32 deletions(-) create mode 100644 src/main/java/com/ffii/lioner/modules/lioner/userActionLog/entity/UserActionLog.java create mode 100644 src/main/java/com/ffii/lioner/modules/lioner/userActionLog/entity/UserActionLogRepository.java create mode 100644 src/main/java/com/ffii/lioner/modules/lioner/userActionLog/req/UpdateUserActionLogReq.java create mode 100644 src/main/java/com/ffii/lioner/modules/lioner/userActionLog/service/UserActionLogService.java create mode 100644 src/main/java/com/ffii/lioner/modules/lioner/userActionLog/web/UserActionLogController.java create mode 100644 src/main/resources/db/changelog/changes/30_user_action_log/01_drop_and_create.sql create mode 100644 src/main/resources/db/changelog/changes/30_user_action_log/02_username.sql create mode 100644 src/main/resources/db/changelog/changes/30_user_action_log/03_userid_remove.sql diff --git a/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfMergeService.java b/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfMergeService.java index d4dfb93..4760d3e 100644 --- a/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfMergeService.java +++ b/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfMergeService.java @@ -54,7 +54,17 @@ public class PdfMergeService { final int IDA_SIG_PAGE = 11; // Page to skip for IDA final int FNA_SIG_PAGE = 7; // Page to skip for FNA final int HSBC_REP_PAGE = 11; // Page to replace for HSBCFIN + final int HSBCA31_REP_START = 28; // Start page to replace for HSBCA31 (Page 28) + final int HSBCA31_REP_END = 29; // End page to replace for HSBCA31 (Page 29) + final int HSBCA31_REP_COUNT = 2; // Number of pages from pdfB to insert + final int MLB03S_REP_PAGE = 9; + final int MLFNA_REP_PAGE = 4; + + final int SLFNA_REP_PAGE = 5; + final int SLAPP_REP_PAGE = 16; + final int SLGII_REP_PAGE = 13; + // Use java.io.ByteArrayOutputStream try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { @@ -68,7 +78,46 @@ public class PdfMergeService { int totalPagesA = docA.getNumberOfPages(); - if ("IDA".equals(formCode) && totalPagesA >= IDA_SIG_PAGE) { + // --- Single Page Replacement Forms (New Logic) --- + int repPage = -1; // Page number to be replaced in docA + + if ("MLB03S".equals(formCode)) { + repPage = MLB03S_REP_PAGE; + } else if ("MLFNA_EN".equals(formCode) || "MLFNA_CHI".equals(formCode)) { + repPage = MLFNA_REP_PAGE; + } else if ("SLFNA_EN".equals(formCode) || "SLFNA_CHI".equals(formCode)) { + repPage = SLFNA_REP_PAGE; + } else if ("SLAPP".equals(formCode)) { + repPage = SLAPP_REP_PAGE; + } else if ("SLGII".equals(formCode)) { + repPage = SLGII_REP_PAGE; + } + + if (repPage != -1 && totalPagesA >= repPage) { + // This block handles all single-page replacements (repPage in docA replaced by docB page 1) + + // A. Copy pages 1 up to (repPage - 1) + if (repPage > 1) { + merger.merge(docA, 1, repPage - 1); + } + + // B. Insert replacement page (page 1) from PDF B (if available) + if (pdfBBytes != null && pdfBBytes.length > 0) { + try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); + PdfDocument docB = new PdfDocument(readerB)) { + + // Copy ONLY page 1 from docB + merger.merge(docB, 1, 1); + } + } + + // C. Copy pages (repPage + 1) through the end + if (totalPagesA > repPage) { + merger.merge(docA, repPage + 1, totalPagesA); + } + + // --- Existing Logic (Skip/Multi-page Replace) --- + } else if ("IDA".equals(formCode) && totalPagesA >= IDA_SIG_PAGE) { // --- IDA: SKIP page 11, then merge rest of A --- // Copy pages 1 through 10 (IDA_SIG_PAGE - 1) @@ -93,7 +142,7 @@ public class PdfMergeService { } } else if ("HSBCFIN".equals(formCode) && totalPagesA >= HSBC_REP_PAGE) { - // --- HSBCFIN: REPLACE page 11 with PDF B page 1 --- + // --- HSBCFIN: REPLACE page 11 with PDF B page 1 (Similar to new logic, but kept separate for history) --- // A. Copy pages 1 up to 10 (HSBC_REP_PAGE - 1) if (HSBC_REP_PAGE > 1) { @@ -103,7 +152,7 @@ public class PdfMergeService { // B. Insert replacement page from PDF B (if available) if (pdfBBytes != null && pdfBBytes.length > 0) { try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); - PdfDocument docB = new PdfDocument(readerB)) { + PdfDocument docB = new PdfDocument(readerB)) { // Copy ONLY page 1 from docB merger.merge(docB, 1, 1); @@ -114,14 +163,43 @@ public class PdfMergeService { if (totalPagesA > HSBC_REP_PAGE) { merger.merge(docA, HSBC_REP_PAGE + 1, totalPagesA); } - + + } else if ("HSBCA31".equals(formCode) && totalPagesA >= HSBCA31_REP_END) { + // --- HSBCA31: REPLACE pages 28-29 with PDF B pages 1-2 --- + + // A. Copy pages 1 up to 27 (HSBCA31_REP_START - 1) + if (HSBCA31_REP_START > 1) { + merger.merge(docA, 1, HSBCA31_REP_START - 1); + } + + // B. Insert replacement pages (1 and 2) from PDF B (if available) + if (pdfBBytes != null && pdfBBytes.length > 0) { + try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); + PdfDocument docB = new PdfDocument(readerB)) { + + // Copy ONLY pages 1 and 2 from docB + if (docB.getNumberOfPages() >= HSBCA31_REP_COUNT) { + merger.merge(docB, 1, HSBCA31_REP_COUNT); + } else { + // Optionally log or throw error if pdfB is too short + } + } + } + + // C. Copy pages 30 through the end (HSBCA31_REP_END + 1) + if (totalPagesA > HSBCA31_REP_END) { + merger.merge(docA, HSBCA31_REP_END + 1, totalPagesA); + } + } else { // Default: Copy all pages from docA merger.merge(docA, 1, totalPagesA); } } - // 2. Process PDF B (Only appended if IDA or FNA, as HSBCFIN already merged it) + // 2. Process PDF B (Only appended if IDA or FNA) + // Note: Single-page replacement forms (MLB03S, MLFNA, etc.) are NOT appending pdfB, + // as pdfB page 1 was used for replacement and the requirement did not specify appending. if (pdfBBytes != null && pdfBBytes.length > 0) { if ("IDA".equals(formCode) || "FNA".equals(formCode)){ try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); @@ -141,4 +219,111 @@ public class PdfMergeService { } // baos is closed here } + + public byte[] mergePdf2sItext7(String formCode, byte[] pdfABytes, byte[] pdfBBytes) throws IOException { + + // UPDATED CONSTANTS FOR NEW REQUIREMENTS + final int MLB03S_REP_PAGE_A = 12; + final int SLAPP_REP_START_A = 18; + final int SLAPP_REP_END_A = 19; + final int SLAPP_REP_COUNT_B = 2; + final int SLGII_REP_START_A = 15; + final int SLGII_REP_END_A = 16; + final int SLGII_REP_COUNT_B = 2; + + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + + PdfWriter writer = new PdfWriter(baos); + PdfDocument mergedPdf = new PdfDocument(writer); + PdfMerger merger = new PdfMerger(mergedPdf); + + // 1. Process PDF A (The primary document) + try (PdfReader readerA = new PdfReader(new ByteArrayInputStream(pdfABytes)); + PdfDocument docA = new PdfDocument(readerA)) { + + int totalPagesA = docA.getNumberOfPages(); + + // --- Multi-page Replacement Forms (New/Existing Logic) --- + int repStartA = -1; // Start page in docA to replace + int repEndA = -1; // End page in docA to replace + int repCountB = -1; // Number of pages from docB to insert + + if ("SLAPP".equals(formCode)) { + repStartA = SLAPP_REP_START_A; + repEndA = SLAPP_REP_END_A; + repCountB = SLAPP_REP_COUNT_B; + } else if ("SLGII".equals(formCode)) { + repStartA = SLGII_REP_START_A; + repEndA = SLGII_REP_END_A; + repCountB = SLGII_REP_COUNT_B; + } + + if (repStartA != -1 && totalPagesA >= repEndA) { + // This block handles all multi-page replacements + + // A. Copy pages 1 up to (repStartA - 1) + if (repStartA > 1) { + merger.merge(docA, 1, repStartA - 1); + } + + // B. Insert replacement pages from PDF B (if available) + if (pdfBBytes != null && pdfBBytes.length > 0) { + try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); + PdfDocument docB = new PdfDocument(readerB)) { + + // Copy the required number of pages from docB starting from page 1 + if (docB.getNumberOfPages() >= repCountB) { + merger.merge(docB, 1, repCountB); + } else { + // Log or handle case where pdfB is too short + System.err.println("PDF B too short for " + formCode + " replacement."); + } + } + } + + // C. Copy pages (repEndA + 1) through the end + if (totalPagesA > repEndA) { + merger.merge(docA, repEndA + 1, totalPagesA); + } + + // --- Single Page Replacement Forms (New/Existing Logic) --- + } else if ("MLB03S".equals(formCode) && totalPagesA >= MLB03S_REP_PAGE_A) { + // MLB03S: REPLACE page 12 with PDF B page 1 (New Requirement) + + // A. Copy pages 1 up to 11 (MLB03S_REP_PAGE_A - 1) + if (MLB03S_REP_PAGE_A > 1) { + merger.merge(docA, 1, MLB03S_REP_PAGE_A - 1); + } + + // B. Insert replacement page from PDF B (if available) + if (pdfBBytes != null && pdfBBytes.length > 0) { + try (PdfReader readerB = new PdfReader(new ByteArrayInputStream(pdfBBytes)); + PdfDocument docB = new PdfDocument(readerB)) { + + // Copy ONLY page 1 from docB + if (docB.getNumberOfPages() >= 1) { + merger.merge(docB, 1, 1); + } + } + } + + // C. Copy pages 13 through the end (MLB03S_REP_PAGE_A + 1) + if (totalPagesA > MLB03S_REP_PAGE_A) { + merger.merge(docA, MLB03S_REP_PAGE_A + 1, totalPagesA); + } + + } else { + // Default: Copy all pages from docA + merger.merge(docA, 1, totalPagesA); + } + } + + // 3. Close the merged PDF document + mergedPdf.close(); + + // 4. Return the resulting byte array + return baos.toByteArray(); + + } // baos is closed here + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java b/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java index 902d84e..f8672b4 100644 --- a/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java +++ b/src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java @@ -20,6 +20,7 @@ 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.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -40,6 +41,7 @@ import com.ffii.lioner.modules.lioner.pdf.entity.PdfRepository; import com.ffii.lioner.modules.lioner.pdf.req.UpdatePdfReq; import com.ffii.lioner.modules.lioner.service.FileService; import com.ffii.lioner.modules.lioner.template.service.TemplateService; +import com.ffii.lioner.modules.lioner.userActionLog.service.UserActionLogService; import com.itextpdf.forms.PdfAcroForm; import com.itextpdf.forms.fields.PdfFormField; import com.itextpdf.io.source.ByteArrayOutputStream; @@ -53,6 +55,9 @@ import liquibase.util.StringUtil; @Service public class PdfService extends AbstractBaseEntityService { + @Autowired + private UserActionLogService userActionLogService; + private String pdf_path = "templates/pdf/"; private AuditLogService auditLogService; @@ -2310,6 +2315,7 @@ public class PdfService extends AbstractBaseEntityService template = templateService.loadTemplate(record.getTemplateId()); + //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(); - Map template = templateService.loadTemplate(record.getTemplateId()); String formCode = (String)template.get("remarks"); if ("IDA".equals(formCode)) { @@ -2461,10 +2467,14 @@ public class PdfService extends AbstractBaseEntityService commonField.getOthers().put("insuranceSumInsured1_2", fieldValue); case "4_1_sum1_3" -> commonField.getOthers().put("insuranceSumInsured1_3", fieldValue); case "ch4_1_life" -> { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) commonField.setInsuranceLife1("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) @@ -3502,7 +3512,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()){ commonField.setInsuranceOther1("Yes"); commonField.setInsuranceOtherDesc1("Accident"); @@ -3514,7 +3524,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) commonField.setInsuranceCritical1("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) @@ -3523,7 +3533,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()){ commonField.setInsuranceOther1("Yes"); commonField.setInsuranceOtherDesc1("Hospital"); @@ -3544,7 +3554,7 @@ public class PdfService extends AbstractBaseEntityService commonField.getOthers().put("insuranceSumInsured2_2", fieldValue); case "4_1_sum2_3" -> commonField.getOthers().put("insuranceSumInsured12_3", fieldValue); case "ch4_2_life" -> { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) commonField.setInsuranceLife2("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) @@ -3553,7 +3563,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()){ commonField.setInsuranceOther2("Yes"); commonField.setInsuranceOtherDesc2("Accident"); @@ -3565,7 +3575,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) commonField.setInsuranceCritical2("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) @@ -3574,7 +3584,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()){ commonField.setInsuranceOther2("Yes"); commonField.setInsuranceOtherDesc2("Hospital"); @@ -3595,7 +3605,7 @@ public class PdfService extends AbstractBaseEntityService commonField.getOthers().put("insuranceSumInsured3_2", fieldValue); case "4_1_sum3_3" -> commonField.getOthers().put("insuranceSumInsured3_3", fieldValue); case "ch4_3_life" -> { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) commonField.setInsuranceLife3("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) @@ -3604,7 +3614,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()){ commonField.setInsuranceOther3("Yes"); commonField.setInsuranceOtherDesc3("Accident"); @@ -3616,7 +3626,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) commonField.setInsuranceCritical3("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) @@ -3625,7 +3635,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()){ commonField.setInsuranceOther3("Yes"); commonField.setInsuranceOtherDesc3("Hospital"); @@ -3929,7 +3939,7 @@ public class PdfService extends AbstractBaseEntityService commonField.getOthers().put("insuranceSumInsured3_2", fieldValue); case "4_1_sum3_3" -> commonField.getOthers().put("insuranceSumInsured3_3", fieldValue); case "ch4_1_life" -> { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) commonField.setInsuranceLife1("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) @@ -3938,7 +3948,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()){ commonField.setInsuranceOther1("Yes"); commonField.setInsuranceOtherDesc1("Accident"); @@ -3950,7 +3960,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) commonField.setInsuranceCritical1("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()) @@ -3959,7 +3969,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum1").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum1") != null && acroForm.getField("4_1_sum1").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum1").getValueAsString().isBlank()){ commonField.setInsuranceOther1("Yes"); commonField.setInsuranceOtherDesc1("Hospital"); @@ -3971,7 +3981,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) commonField.setInsuranceLife2("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) @@ -3980,7 +3990,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()){ commonField.setInsuranceOther2("Yes"); commonField.setInsuranceOtherDesc2("Accident"); @@ -3992,7 +4002,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) commonField.setInsuranceCritical2("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()) @@ -4001,7 +4011,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum2").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum2") != null && acroForm.getField("4_1_sum2").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum2").getValueAsString().isBlank()){ commonField.setInsuranceOther2("Yes"); commonField.setInsuranceOtherDesc2("Hospital"); @@ -4013,7 +4023,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) commonField.setInsuranceLife3("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) @@ -4022,7 +4032,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()){ commonField.setInsuranceOther3("Yes"); commonField.setInsuranceOtherDesc3("Accident"); @@ -4034,7 +4044,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) commonField.setInsuranceCritical3("Yes"); else if("On".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()) @@ -4043,7 +4053,7 @@ public class PdfService extends AbstractBaseEntityService { - if(acroForm.getField("4_1_sum3").getValueAsString() != null ){ + if(acroForm.getField("4_1_sum3") != null && acroForm.getField("4_1_sum3").getValueAsString() != null ){ if("Off".equals(fieldValue) && !acroForm.getField("4_1_sum3").getValueAsString().isBlank()){ commonField.setInsuranceOther3("Yes"); commonField.setInsuranceOtherDesc3("Hospital"); @@ -4302,12 +4312,15 @@ public class PdfService extends AbstractBaseEntityService response = new HashMap<>(); response.put("message", "File uploaded and processed successfully."); + + Map d = pdfService.getFilledFormPdf(refId); + //action log + userActionLogService.createLog("Upload Signiture1 of Client Code:" + d.get("clientCode") + " Form:" + d.get("templateName") , refId, refType); return ResponseEntity.ok(response); } catch (Exception ex) { @@ -186,6 +197,10 @@ public class PdfController { .map(val -> ((Integer) val).longValue()) .orElse(null); + Long upload2FileId = Optional.ofNullable(d.get("upload2FileId")) + .map(val -> ((Integer) val).longValue()) + .orElse(null); + // Safely retrieve byte arrays using Optional chaining (prevents NullPointerExceptions) byte[] pdfBytes = Optional.ofNullable(fileId) .flatMap(fileService::findFileBlobByFileId) @@ -198,6 +213,11 @@ public class PdfController { .map(FileBlob::getBytes) .orElse(null); + byte[] pdfUpload2Bytes = Optional.ofNullable(upload2FileId) + .flatMap(fileService::findFileBlobByFileId) + .map(FileBlob::getBytes) + .orElse(null); + // Check if the primary file is missing if (pdfBytes == null || pdfBytes.length == 0) { logger.info("Both null:"); @@ -212,6 +232,10 @@ public class PdfController { logger.info("formCode:" + formCode); finalPdfBytes = pdfMergeService.mergePdfsItext7(formCode, pdfBytes, pdfUpload1Bytes); + + //Forms that need to have 2nd upload sig + if(d.get("upload2FileId") != null) + finalPdfBytes = pdfMergeService.mergePdf2sItext7(formCode, finalPdfBytes, pdfUpload2Bytes); // --- 4. Build ResponseEntity --- HttpHeaders headers = new HttpHeaders(); @@ -220,6 +244,9 @@ public class PdfController { headers.setContentType(MediaType.APPLICATION_PDF); headers.setContentLength(finalPdfBytes.length); + //action log + userActionLogService.createLog("Download Merged Form of Client Code:" + d.get("clientCode") + " Form:" + d.get("templateName") , id, "MergePDF"); + return new ResponseEntity<>(finalPdfBytes, headers, HttpStatus.OK); } diff --git a/src/main/java/com/ffii/lioner/modules/lioner/template/service/TemplateService.java b/src/main/java/com/ffii/lioner/modules/lioner/template/service/TemplateService.java index 8add854..3e1aa40 100644 --- a/src/main/java/com/ffii/lioner/modules/lioner/template/service/TemplateService.java +++ b/src/main/java/com/ffii/lioner/modules/lioner/template/service/TemplateService.java @@ -157,6 +157,7 @@ public class TemplateService extends AbstractBaseEntityService{ + + @Column + private String actionDesc; + + @Column + private String refType; + + @Column + private Long refId; + + @Column + private String username; + + public String getActionDesc() { + return actionDesc; + } + + public void setActionDesc(String actionDesc) { + this.actionDesc = actionDesc; + } + + public String getRefType() { + return refType; + } + + public void setRefType(String refType) { + this.refType = refType; + } + + public Long getRefId() { + return refId; + } + + public void setRefId(Long refId) { + this.refId = refId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + +} + diff --git a/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/entity/UserActionLogRepository.java b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/entity/UserActionLogRepository.java new file mode 100644 index 0000000..f28c5ac --- /dev/null +++ b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/entity/UserActionLogRepository.java @@ -0,0 +1,6 @@ +package com.ffii.lioner.modules.lioner.userActionLog.entity; + +import com.ffii.core.support.AbstractRepository; + +public interface UserActionLogRepository extends AbstractRepository { +} diff --git a/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/req/UpdateUserActionLogReq.java b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/req/UpdateUserActionLogReq.java new file mode 100644 index 0000000..05772c4 --- /dev/null +++ b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/req/UpdateUserActionLogReq.java @@ -0,0 +1,61 @@ +package com.ffii.lioner.modules.lioner.userActionLog.req; + +import jakarta.validation.constraints.Size; + +public class UpdateUserActionLogReq { + + private Long id; + + @Size(max = 255) + String actionDesc; + + @Size(max = 50) + String refType; + + Long refId; + + Long userId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getActionDesc() { + return actionDesc; + } + + public void setActionDesc(String actionDesc) { + this.actionDesc = actionDesc; + } + + public String getRefType() { + return refType; + } + + public void setRefType(String refType) { + this.refType = refType; + } + + public Long getRefId() { + return refId; + } + + public void setRefId(Long refId) { + this.refId = refId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + + +} diff --git a/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/service/UserActionLogService.java b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/service/UserActionLogService.java new file mode 100644 index 0000000..3728dbe --- /dev/null +++ b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/service/UserActionLogService.java @@ -0,0 +1,77 @@ +package com.ffii.lioner.modules.lioner.userActionLog.service; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.ffii.core.support.AbstractBaseEntityService; +import com.ffii.core.support.JdbcDao; +import com.ffii.core.utils.BeanUtils; +import com.ffii.lioner.modules.lioner.userActionLog.entity.UserActionLogRepository; +import com.ffii.lioner.modules.lioner.userActionLog.req.UpdateUserActionLogReq; +import com.ffii.lioner.modules.common.SecurityUtils; +import com.ffii.lioner.modules.lioner.userActionLog.entity.UserActionLog; + +@Service +public class UserActionLogService extends AbstractBaseEntityService { + + public UserActionLogService(JdbcDao jdbcDao, UserActionLogRepository repository) { + super(jdbcDao, repository); + } + + public void createLog(String actionDesc, Long refId, String refType) { + UserActionLog userActionLog = new UserActionLog(); + userActionLog.setUsername(SecurityUtils.getUser().get().getUsername()); + userActionLog.setActionDesc(actionDesc); + userActionLog.setRefId(refId); + userActionLog.setRefType(refType); + save(userActionLog); + } + + public Map saveOrUpdate(UpdateUserActionLogReq req) { + UserActionLog instance; + // List onUsingIdList = new ArrayList(); + if (req.getId() > 0){ + instance = find(req.getId()).get(); + } + else { + instance = new UserActionLog(); + } + + BeanUtils.copyProperties(req,instance); + + instance = save(instance); + + return Map.of( + "id", instance.getId() + ); + } + + public List> list(Map args){ + StringBuilder sql = new StringBuilder("SELECT" + + " user_action_log.actionDesc, " + + " user_action_log.created, " + + " user.fullname, " + + " user.username " + + " from user_action_log " + + " left join user on user_action_log.username = user.username " + + " WHERE user_action_log.deleted = FALSE " + + ); + + if (args != null) { + if (args.containsKey("username")) sql.append(" AND user_action_log.username = :username"); + if (args.containsKey("actionDesc")) sql.append(" AND user_action_log.actionDesc = :actionDesc"); + if (args.containsKey("fromDate"))sql.append(" AND user_action_log.created >= :fromDate"); + if (args.containsKey("toDate"))sql.append(" AND user_action_log.created < :toDate"); + } + + // } + sql.append(" ORDER BY user_action_log.id desc "); + + return jdbcDao.queryForList(sql.toString(), args); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/web/UserActionLogController.java b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/web/UserActionLogController.java new file mode 100644 index 0000000..9e38837 --- /dev/null +++ b/src/main/java/com/ffii/lioner/modules/lioner/userActionLog/web/UserActionLogController.java @@ -0,0 +1,97 @@ +package com.ffii.lioner.modules.lioner.userActionLog.web; + +import java.io.IOException; +import java.time.LocalDate; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.http.CacheControl; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.ServletRequestBindingException; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.ffii.lioner.modules.lioner.client.entity.Client; +import com.ffii.lioner.modules.lioner.userActionLog.req.UpdateUserActionLogReq; +import com.ffii.lioner.modules.lioner.userActionLog.service.UserActionLogService; + +import aj.org.objectweb.asm.Type; + +import com.ffii.lioner.modules.common.service.ExcelReportService; +import com.ffii.core.exception.NotFoundException; +import com.ffii.core.response.DataRes; +import com.ffii.core.response.RecordsRes; +import com.ffii.core.utils.CriteriaArgsBuilder; +import com.ffii.core.utils.Params; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +@RestController +@RequestMapping("/userActionLog") +public class UserActionLogController{ + + private final Log logger = LogFactory.getLog(getClass()); + + @Autowired + private UserActionLogService userActionLogService; + + private ExcelReportService excelReportService; + + public UserActionLogController(UserActionLogService userActionLogService, ExcelReportService excelReportService) { + this.userActionLogService = userActionLogService; + this.excelReportService = excelReportService; + } + + @GetMapping("/{id}") + public Map get(@PathVariable Long id) { + return Map.of( + Params.DATA, userActionLogService.find(id).orElseThrow(NotFoundException::new) + // "eventDivision", userActionLogService.getEventDivision(Map.of("id",id)) + ); + } + + @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false) + @PostMapping("/save") + public Map saveOrUpdate(@RequestBody @Valid UpdateUserActionLogReq req) { + return Map.of( + Params.DATA,userActionLogService.saveOrUpdate(req) + ); + } + + @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false) + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void delete(@PathVariable Long id) { + userActionLogService.markDelete(userActionLogService.find(id).get()); + // userActionLogService.markDeleteWithAuditLog(userActionLogService.find(id).get()); + } + + @GetMapping + public RecordsRes> list(HttpServletRequest request) throws ServletRequestBindingException { + return new RecordsRes<>(userActionLogService.list( + CriteriaArgsBuilder.withRequest(request) + .addString("username") + .addStringLike("actionDesc") + .addDate("fromDate") + .addDateTo("toDate") + .build())); + } + +} diff --git a/src/main/resources/db/changelog/changes/30_user_action_log/01_drop_and_create.sql b/src/main/resources/db/changelog/changes/30_user_action_log/01_drop_and_create.sql new file mode 100644 index 0000000..ad45056 --- /dev/null +++ b/src/main/resources/db/changelog/changes/30_user_action_log/01_drop_and_create.sql @@ -0,0 +1,21 @@ +--liquibase formatted sql + +--changeset vin:drop and create again + +DROP TABLE IF EXISTS `user_action_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `user_action_log` ( + `id` int NOT NULL AUTO_INCREMENT, + `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(30) DEFAULT NULL, + `version` int NOT NULL DEFAULT '0', + `modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modifiedBy` varchar(30) DEFAULT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT '0', + `userId` bigint NOT NULL, + `actionDesc` varchar(50) DEFAULT NULL, + `refId` bigint NOT NULL, + `refType` varchar(30) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC; \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/30_user_action_log/02_username.sql b/src/main/resources/db/changelog/changes/30_user_action_log/02_username.sql new file mode 100644 index 0000000..9f176e4 --- /dev/null +++ b/src/main/resources/db/changelog/changes/30_user_action_log/02_username.sql @@ -0,0 +1,6 @@ +--liquibase formatted sql + +--changeset vin:drop and create again + +ALTER TABLE `lionerdb`.`user_action_log` +ADD COLUMN `username` VARCHAR(100) NULL AFTER `refType`; diff --git a/src/main/resources/db/changelog/changes/30_user_action_log/03_userid_remove.sql b/src/main/resources/db/changelog/changes/30_user_action_log/03_userid_remove.sql new file mode 100644 index 0000000..a685b28 --- /dev/null +++ b/src/main/resources/db/changelog/changes/30_user_action_log/03_userid_remove.sql @@ -0,0 +1,7 @@ +--liquibase formatted sql + +--changeset vin:drop and create again + + +ALTER TABLE `lionerdb`.`user_action_log` +DROP COLUMN `userId`;