Merge pull request #71 from Kitzanos/pdf-html-content-issue-prod

Cherry-pick (PDF changes)
This commit is contained in:
rbonazzo-KZ
2024-10-28 19:45:39 +01:00
committed by GitHub
3 changed files with 248 additions and 83 deletions

View File

@@ -14,8 +14,10 @@ import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest; import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest;
import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.util.PdfUtils;
import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.util.Validator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -91,73 +93,73 @@ public class PdfDao {
Font boldSmallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD,new BaseColor(105, 105, 105)); Font boldSmallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD,new BaseColor(105, 105, 105));
// Adding the "Documenti Allegati" section title // Adding the "Documenti Allegati" section title
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
// pageEvent.setTotalPages(writer.getPageNumber()); //// pageEvent.setTotalPages(writer.getPageNumber());
document.newPage(); // document.newPage();
// pageEvent.setTotalPages(writer.getPageNumber()); //// pageEvent.setTotalPages(writer.getPageNumber());
document.add(new Paragraph("Documenti Allegati", sectionFont)); // document.add(new Paragraph("Documenti Allegati", sectionFont));
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 1. Autocertificazione possesso Requisiti //// 1. Autocertificazione possesso Requisiti
Paragraph p1 = new Paragraph(); // Paragraph p1 = new Paragraph();
p1.add(new Chunk("1. ", boldSmallFont)); // p1.add(new Chunk("1. ", boldSmallFont));
p1.add(new Chunk("Autocertificazione possesso Requisiti ", boldSmallFont)); // p1.add(new Chunk("Autocertificazione possesso Requisiti ", boldSmallFont));
p1.add(new Chunk("ai sensi degli artt. 46 e 47 del DPR 445/2000", smallFont)); // p1.add(new Chunk("ai sensi degli artt. 46 e 47 del DPR 445/2000", smallFont));
document.add(p1); // document.add(p1);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
//
// 2. Informativa Privacy relativa al trattamento dei dati personali //// 2. Informativa Privacy relativa al trattamento dei dati personali
Paragraph p2 = new Paragraph(); // Paragraph p2 = new Paragraph();
p2.add(new Chunk("2. ", boldSmallFont)); // p2.add(new Chunk("2. ", boldSmallFont));
p2.add(new Chunk("Informativa Privacy relativa al trattamento dei dati personali", boldSmallFont)); // p2.add(new Chunk("Informativa Privacy relativa al trattamento dei dati personali", boldSmallFont));
document.add(p2); // document.add(p2);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 3. Dati richiesti per la valutazione delladeguatezza dei flussi finanziari //// 3. Dati richiesti per la valutazione delladeguatezza dei flussi finanziari
Paragraph p3 = new Paragraph(); // Paragraph p3 = new Paragraph();
p3.add(new Chunk("3. ", boldSmallFont)); // p3.add(new Chunk("3. ", boldSmallFont));
p3.add(new Chunk("Dati richiesti per la valutazione delladeguatezza dei flussi finanziari prospettici come da tabella di cui allAppendice 9", boldSmallFont)); // p3.add(new Chunk("Dati richiesti per la valutazione delladeguatezza dei flussi finanziari prospettici come da tabella di cui allAppendice 9", boldSmallFont));
document.add(p3); // document.add(p3);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 4. Rilevazione Centrale dei Rischi //// 4. Rilevazione Centrale dei Rischi
Paragraph p4 = new Paragraph(); // Paragraph p4 = new Paragraph();
p4.add(new Chunk("4. ", boldSmallFont)); // p4.add(new Chunk("4. ", boldSmallFont));
p4.add(new Chunk("Rilevazione Centrale dei Rischi riferita agli ultimi 36 mesi disponibili alla data di presentazione della Domanda", boldSmallFont)); // p4.add(new Chunk("Rilevazione Centrale dei Rischi riferita agli ultimi 36 mesi disponibili alla data di presentazione della Domanda", boldSmallFont));
document.add(p4); // document.add(p4);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 5. Schema di presentazione dei dati di bilancio //// 5. Schema di presentazione dei dati di bilancio
Paragraph p5 = new Paragraph(); // Paragraph p5 = new Paragraph();
p5.add(new Chunk("5. ", boldSmallFont)); // p5.add(new Chunk("5. ", boldSmallFont));
p5.add(new Chunk("Schema di presentazione dei dati di bilancio", boldSmallFont)); // p5.add(new Chunk("Schema di presentazione dei dati di bilancio", boldSmallFont));
document.add(p5); // document.add(p5);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 6. Dettagli bilanci in forma abbreviata //// 6. Dettagli bilanci in forma abbreviata
Paragraph p6 = new Paragraph(); // Paragraph p6 = new Paragraph();
p6.add(new Chunk("6. ", boldSmallFont)); // p6.add(new Chunk("6. ", boldSmallFont));
p6.add(new Chunk("Dettagli bilanci in forma abbreviata", boldSmallFont)); // p6.add(new Chunk("Dettagli bilanci in forma abbreviata", boldSmallFont));
document.add(p6); // document.add(p6);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
//
// 7. Relazione aziendale illustrativa //// 7. Relazione aziendale illustrativa
Paragraph p7 = new Paragraph(); // Paragraph p7 = new Paragraph();
p7.add(new Chunk("7. ", boldSmallFont)); // p7.add(new Chunk("7. ", boldSmallFont));
p7.add(new Chunk("Relazione aziendale illustrativa", boldSmallFont)); // p7.add(new Chunk("Relazione aziendale illustrativa", boldSmallFont));
document.add(p7); // document.add(p7);
document.add(new Paragraph(" ")); // document.add(new Paragraph(" "));
//
addColoredLines(writer,document,greenColor); // addColoredLines(writer,document,greenColor);
document.close(); document.close();
@@ -206,7 +208,9 @@ public class PdfDao {
// Loop through the list of strings and create a cell for each string // Loop through the list of strings and create a cell for each string
for (String item : values) { for (String item : values) {
PdfPCell valueCell = new PdfPCell(new Phrase(item, valueFont));
// PdfPCell valueCell = new PdfPCell(new Phrase(item, valueFont));
PdfPCell valueCell = PdfUtils.htmlToPdfPCell(item, valueFont);
valueCell.setPadding(5f); // Increase padding for better spacing valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
@@ -272,14 +276,21 @@ public class PdfDao {
document.add(valueTable); document.add(valueTable);
} }
else { else {
PdfPCell valueCell = new PdfPCell(new Phrase(String.valueOf(value), valueFont)); String fieldValue1= (String) value;
if(Utils.isValidDateString(fieldValue1)){
fieldValue1=Utils.formatDateString(String.valueOf(value));
}
if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(fieldValue)) ){
fieldValue= String.valueOf(Utils.convertToItalianFormat(fieldValue));
}
// PdfPCell valueCell = new PdfPCell(new Phrase(fieldValue1, valueFont));
PdfPCell valueCell = PdfUtils.htmlToPdfPCell(fieldValue1, valueFont);
valueCell.setPadding(5f); // Increase padding for better spacing valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
valueCell.setMinimumHeight(30f); valueCell.setMinimumHeight(30f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE); valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners
valueTable.addCell(valueCell); valueTable.addCell(valueCell);
document.add(valueTable); document.add(valueTable);
} }
@@ -348,12 +359,12 @@ public class PdfDao {
List<String> orderedKeys = new ArrayList<>(trueKeys); List<String> orderedKeys = new ArrayList<>(trueKeys);
orderedKeys.addAll(falseKeys); orderedKeys.addAll(falseKeys);
// Iterate through extracted data to populate the table // Iterate through extracted data to populate the table
for (Map<String, Object> row : extractedData) {
// Add headers once // Add headers once
if (!headersAdded) { if (!headersAdded) {
for (String key : orderedKeys) { for (String key : orderedKeys) {
String headerValue = stateFieldMap.get(key); // Header text String headerValue = stateFieldMap.get(key); // Header text
PdfPCell headerCell = new PdfPCell(new Phrase(headerValue)); // Create a new PdfPCell for the header // PdfPCell headerCell = new PdfPCell(new Phrase(headerValue)); // Create a new PdfPCell for the header
PdfPCell headerCell = PdfUtils.htmlToPdfPCell(headerValue, null);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE); headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header headerCell.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
@@ -364,15 +375,22 @@ public class PdfDao {
} }
// Add data rows matching stateFieldMap keys // Add data rows matching stateFieldMap keys
for (Map.Entry<String, String> stateField : stateFieldMap.entrySet()) { for (Map<String, Object> row : extractedData) {
for (String key : orderedKeys) { // Iterate over the ordered keys // Add data rows matching stateFieldMap keys
for (String key : orderedKeys) {
if (stateFieldMap.containsKey(key)) { // Only add data cell if key is in stateFieldMap
Object value = row.getOrDefault(key, ""); // Fetch value or use empty string if key not present Object value = row.getOrDefault(key, ""); // Fetch value or use empty string if key not present
PdfPCell dynamicCell = new PdfPCell(new Phrase(value != null ? value.toString() : "", textFont)); String fieldValue= (String) value;
dynamicCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(fieldValue)) ){
dynamicCell.setMinimumHeight(rowHeight); fieldValue= String.valueOf(Utils.convertToItalianFormat(fieldValue));
dynamicCell.setPadding(7f); }
// PdfPCell dataCell = new PdfPCell(new Phrase(fieldValue != null ?fieldValue: "", textFont));
PdfPCell dataCell = PdfUtils.htmlToPdfPCell(value != null ? value.toString() : "", textFont);
dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell
dataCell.setMinimumHeight(rowHeight);
dataCell.setPadding(7f);
table.addCell(dynamicCell); // Add the dynamically created cell to the table table.addCell(dataCell); // Add the cell to the table
} }
} }
@@ -461,7 +479,7 @@ public class PdfDao {
.collect(Collectors.toList()); .collect(Collectors.toList());
fieldValue = names; fieldValue = names;
} }
} else if (name.equals("checkboxes")) { } else if (name.equals("checkboxes") && fieldValue instanceof List<?>) {
List<String> check = (List<String>) fieldValue; List<String> check = (List<String>) fieldValue;
List<SettingResponseBean> settingResponseBeans = content.getSettings(); List<SettingResponseBean> settingResponseBeans = content.getSettings();
List<String> matchedLabels = new ArrayList<>(); List<String> matchedLabels = new ArrayList<>();
@@ -494,7 +512,9 @@ public class PdfDao {
} }
try { try {
addLabelValuePair(writer,document, contentLabel, fieldValue, labelFont,valueFont,content); if((contentLabel!=null && Boolean.FALSE.equals(contentLabel.isEmpty())) || (fieldValue!=null && !StringUtils.isEmpty((CharSequence) fieldValue))) {
addLabelValuePair(writer, document, contentLabel, fieldValue, labelFont, valueFont, content);
}
} catch (DocumentException e) { } catch (DocumentException e) {
log.error("Error checking object: " + e.getMessage(), e); log.error("Error checking object: " + e.getMessage(), e);

View File

@@ -0,0 +1,66 @@
package net.gepafin.tendermanagement.util;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.html.simpleparser.HTMLWorker;
import com.itextpdf.text.html.simpleparser.StyleSheet;
import com.itextpdf.text.Paragraph;
import java.io.StringReader;
import java.util.List;
import org.springframework.stereotype.Component;
@Component
public class PdfUtils {
public static PdfPCell htmlToPdfPCell(String htmlContent, Font font) {
PdfPCell cell = new PdfPCell();
// Check if the content is not null or empty
if (htmlContent != null && !htmlContent.trim().isEmpty()) {
// Wrap plain text in a paragraph tag if it doesn't contain any HTML
// Check if the string does not contain any '<' or '>' characters
if (!htmlContent.contains("<") || !htmlContent.contains(">")) {
htmlContent = "<p>" + htmlContent + "</p>"; // Wrap in paragraph tags
}
try {
// Create a list to hold the elements parsed from the HTML
List<Element> elements = HTMLWorker.parseToList(new StringReader(htmlContent), new StyleSheet());
// Create a paragraph to hold the formatted text
Paragraph paragraph = new Paragraph();
// Add each element to the paragraph
for (Element element : elements) {
// If the element is a Paragraph, set the font directly
if (element instanceof Paragraph) {
((Paragraph) element).setFont(font);
}
// If the element is a Chunk, set the font directly
else if (element instanceof com.itextpdf.text.Chunk) {
((com.itextpdf.text.Chunk) element).setFont(font);
}
// Add the element to the paragraph
paragraph.add(element);
}
// Add the paragraph to the cell
cell.addElement(paragraph);
} catch (Exception e) {
e.printStackTrace(); // Log the exception for debugging
}
}
return cell;
}
}

View File

@@ -4,12 +4,20 @@ import java.lang.reflect.Field;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.itextpdf.styledxmlparser.jsoup.Jsoup;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.collections4.MapUtils; import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -369,5 +377,76 @@ public class Utils {
throw new RuntimeException("Error converting map to string", e); throw new RuntimeException("Error converting map to string", e);
} }
} }
public static boolean isValidDateString(String dateStr) {
Pattern datePattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}");
return datePattern.matcher(dateStr).matches();
}
// Method to convert a valid date string to the "dd-MM-yyyy" format
public static String formatDateString(String dateStr) {
String originalFormatPattern = "yyyy-MM-dd'T'HH:mm:ss";
String targetFormatPattern = "dd-MM-yyyy";
try {
SimpleDateFormat originalFormat = new SimpleDateFormat(originalFormatPattern);
Date date = originalFormat.parse(dateStr);
SimpleDateFormat targetFormat = new SimpleDateFormat(targetFormatPattern);
return targetFormat.format(date);
} catch (ParseException e) {
log.error("error while prcoessing date formate");
return null;
}
}
// public static String convertItalianAmountToDouble(String amount) throws NumberFormatException {
// // Step 1: Remove the thousands separator and replace the decimal separator
// String normalizedAmount = amount.replace(".", "").replace(",", ".");
//
// // Step 2: Parse the string to a double
// double value = Double.parseDouble(normalizedAmount);
// if (value <= 0) {
// return amount;
// }
// // Step 3: Format the double to 2 decimal places
// DecimalFormat decimalFormat = new DecimalFormat("#.00");
// return decimalFormat.format(value); // Return formatted string
// }
public static String convertToItalianFormat(String amount) {
try {
// Step 1: Sanitize and standardize the input
String sanitizedAmount = amount.trim();
if (sanitizedAmount.matches("\\d")) {
return sanitizedAmount;
}
// Step 2: Handle Italian-style input (e.g., "37.192,00")
if (sanitizedAmount.contains(".") && sanitizedAmount.contains(",")) {
// Assume the period is a thousand separator and the comma is a decimal separator
sanitizedAmount = sanitizedAmount.replace(".", "").replace(",", ".");
} else if (sanitizedAmount.contains(",")) {
// If the input contains only a comma, treat it as a decimal separator
sanitizedAmount = sanitizedAmount.replace(",", ".");
}
// Step 3: Parse the cleaned-up string into a double
double parsedAmount = Double.parseDouble(sanitizedAmount);
// Step 4: Format the parsed amount to Italian format
NumberFormat italianFormat = NumberFormat.getInstance(Locale.ITALY);
italianFormat.setMinimumFractionDigits(2);
italianFormat.setMaximumFractionDigits(2);
return italianFormat.format(parsedAmount);
} catch (NumberFormatException e) {
// In case of any issues with parsing, return a default or error message
return "Invalid amount format";
}
}
public static boolean isItalianFormattedAmount(String input) {
// Regular expression to match Italian-style amounts (e.g., 41.003,00 or 123,45)
String sanitizedInput = input.replace(",", "");
// Step 2: Check if the remaining string is a whole number
String wholeNumberPattern = "^\\d+$"; // Regex to match whole numbers
return sanitizedInput.matches(wholeNumberPattern);
}
} }