Files
bflows-bandi-be/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java
2024-10-28 18:11:41 +05:30

570 lines
28 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package net.gepafin.tendermanagement.dao;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.*;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.service.CallService;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.util.Validator;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
//import com.itextpdf.layout.element.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class PdfDao {
@Autowired
private CallService callService;
@Autowired
private ApplicationDao applicationDao;
@Autowired
private Validator validator;
public static final Logger log = LoggerFactory.getLogger(PdfDao.class);
public byte[] generatePdf(HttpServletRequest request,Long applicationId) {
try {
UserEntity userEntity = validator.validateUser(request);
ApplicationEntity applicationEntity = applicationDao.validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
CallEntity call=callService.validateCall(applicationEntity.getCall().getId());
// Create a byte stream to hold the PDF
ByteArrayOutputStream out = new ByteArrayOutputStream();
float leftMargin = 50f; // Adjust this for the left margin
Document document = new Document(PageSize.A4, leftMargin, 36f, 50f, 35);
PdfWriter writer = PdfWriter.getInstance(document, out);
// CustomPageEvent pageEvent = new CustomPageEvent(call.getName(), 0);
// writer.setPageEvent(pageEvent);
document.open();
// pageEvent.setTotalPages(writer.getPageNumber());
// addLogo(document, "logo.jpg"); // Add your image path here the migration code after cherry-pick
addLogo(document, "https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/logo.jpg");
BaseColor customColor = new BaseColor(0, 128, 0); // Adjust RGB values as needed
// Define fonts and styles
BaseColor greenColor = new BaseColor(0, 128, 0); // Adjust RGB values as needed
BaseColor darkGreenColor = new BaseColor(1, 50, 32); // Adjust RGB values as needed
Font titleFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 16, customColor);
Font sectionFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,darkGreenColor);
Font labelFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,new BaseColor(113,121,126)); // Light grey);
Font smallFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 8,new BaseColor(105, 105, 105));
Font valueFont=FontFactory.getFont(FontFactory.HELVETICA_BOLD,10,new BaseColor(178, 190, 181));
Paragraph title = new Paragraph(call.getName(), titleFont);
title.setAlignment(Element.ALIGN_LEFT);
document.add(title);
BaseColor greyColor=new BaseColor(178, 190, 181); // Very light grey color
addColoredLines(writer,document,greyColor);
document.add(new Paragraph(" "));
ApplicationGetResponseBean applicationGetResponseBean=applicationDao.getApplicationByFormId(request, applicationId, null);
for(FormApplicationResponse formApplicationResponse: applicationGetResponseBean.getForm()) {
List<FieldLabelValuePairRequest> fieldLabelValuePairRequests = getFormFieldsToLabels(formApplicationResponse,writer,document);
addColoredLines(writer,document,greenColor);
document.add(new Paragraph(" ")); // Add line break
}
document.add(new Paragraph("\n")); // Add line break
Font boldSmallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD,new BaseColor(105, 105, 105));
// Adding the "Documenti Allegati" section title
// document.add(new Paragraph(" "));
//
//// pageEvent.setTotalPages(writer.getPageNumber());
// document.newPage();
//// pageEvent.setTotalPages(writer.getPageNumber());
// document.add(new Paragraph("Documenti Allegati", sectionFont));
// document.add(new Paragraph(" "));
//
//
//// 1. Autocertificazione possesso Requisiti
// Paragraph p1 = new Paragraph();
// p1.add(new Chunk("1. ", 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));
// document.add(p1);
// document.add(new Paragraph(" "));
//
//
//
//// 2. Informativa Privacy relativa al trattamento dei dati personali
// Paragraph p2 = new Paragraph();
// p2.add(new Chunk("2. ", boldSmallFont));
// p2.add(new Chunk("Informativa Privacy relativa al trattamento dei dati personali", boldSmallFont));
// document.add(p2);
// document.add(new Paragraph(" "));
//
//
//// 3. Dati richiesti per la valutazione delladeguatezza dei flussi finanziari
// Paragraph p3 = new Paragraph();
// 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));
// document.add(p3);
// document.add(new Paragraph(" "));
//
//
//// 4. Rilevazione Centrale dei Rischi
// Paragraph p4 = new Paragraph();
// 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));
// document.add(p4);
// document.add(new Paragraph(" "));
//
//
//// 5. Schema di presentazione dei dati di bilancio
// Paragraph p5 = new Paragraph();
// p5.add(new Chunk("5. ", boldSmallFont));
// p5.add(new Chunk("Schema di presentazione dei dati di bilancio", boldSmallFont));
// document.add(p5);
// document.add(new Paragraph(" "));
//
//
//// 6. Dettagli bilanci in forma abbreviata
// Paragraph p6 = new Paragraph();
// p6.add(new Chunk("6. ", boldSmallFont));
// p6.add(new Chunk("Dettagli bilanci in forma abbreviata", boldSmallFont));
// document.add(p6);
// document.add(new Paragraph(" "));
//
//
//// 7. Relazione aziendale illustrativa
// Paragraph p7 = new Paragraph();
// p7.add(new Chunk("7. ", boldSmallFont));
// p7.add(new Chunk("Relazione aziendale illustrativa", boldSmallFont));
// document.add(p7);
// document.add(new Paragraph(" "));
//
// addColoredLines(writer,document,greenColor);
document.close();
// Convert to byte array for response
byte[] pdfBytes =PdfPageNumberInserter.addPageNumbers(out.toByteArray());
return pdfBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void addLabelValuePair(PdfWriter writer,Document document, String label, Object value, Font labelFont,Font valueFont,ContentResponseBean contentResponseBean) throws DocumentException {
// Add label
Map<String, Boolean> stateFieldMap= new HashMap<>();
Paragraph labelParagraph = new Paragraph(label, labelFont);
document.add(labelParagraph);
float leftMargin = 20f;
PdfContentByte canvas = writer.getDirectContent();
// Setting the color and width of the line
float lineWidth = 1.0f; // Thickness of the line
canvas.setLineWidth(lineWidth);
// Get the current vertical position in the document
float yPos = writer.getVerticalPosition(true) - 10f; // Adjust this to move line slightly below current content
// Define start and end points for the line (relative to the page size and margins)
if (yPos <= 140) {
// If xEnd is less than or equal to 200, generate a new page
document.newPage();
} // Add a gap between the label and value
document.add(new Paragraph(" ")); // Adding an empty paragraph for spacing
// Create value cell with rounded corners
PdfPTable valueTable = new PdfPTable(1);
valueTable.setWidthPercentage(100);
if (value instanceof List<?>) {
// Further check if the list contains Strings
List<?> list = (List<?>) value;
if (!list.isEmpty() && list.get(0) instanceof String) {
// Cast to List<String>
List<String> values = (List<String>) value;
// Loop through the list of strings and create a cell for each string
for (String item : values) {
PdfPCell valueCell = new PdfPCell(new Phrase(item, valueFont));
valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
valueCell.setMinimumHeight(30f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners
// Add the cell to the table
valueTable.addCell(valueCell);
}
// Finally, add the table to the document
document.add(valueTable);
}
else if (!list.isEmpty() && list.get(0) instanceof Map<?, ?>) {
Object object = value;
String stringvalue = Utils.convertToString(object);
List<Map<String, Object>> fieldValueList = Utils.convertJsonStringIntoJsonList(stringvalue);
document = createPdfTable(fieldValueList, document, contentResponseBean);
}
}
else {
String fieldValue=Utils.convertToString(value);
Image img = null; // This may throw MalformedURLException
if (fieldValue.trim().equalsIgnoreCase("true")) {
// Use images for tick and cross
try {
// img = Image.getInstance("true.jpg"); update code after cherry-pick
img = Image.getInstance("https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/true.png");
} catch (IOException e) {
log.error("Error while uploading image for pdf for true");
}
img.scaleAbsolute(15, 15); // Resize the image if needed
PdfPCell cell = new PdfPCell(img);
cell.setPadding(0); // Remove padding
cell.setBorder(Rectangle.NO_BORDER); // Remove border
cell.setMinimumHeight(15f); // Set height to fit checkbox image
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_LEFT); // Align the checkbox image to the left
valueTable.addCell(cell); // Add cell with checkbox to the table
document.add(valueTable);
} else if (fieldValue.trim().equalsIgnoreCase("false")) {
// Use images for tick and cross
try {
img = Image.getInstance("https://mementoresources.s3.eu-west-1.amazonaws.com/gepafin/false.png");
} catch (IOException e) {
log.error("Error while uploading image for pdf for false");
}
img.scaleAbsolute(15, 15); // Resize the image if needed
PdfPCell cell = new PdfPCell(img);
cell.setPadding(0); // Remove padding
cell.setBorder(Rectangle.NO_BORDER); // Remove border
cell.setMinimumHeight(15f); // Set height to fit checkbox image
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_LEFT); // Align the checkbox image to the left
valueTable.addCell(cell); // Add cell with checkbox to the table
document.add(valueTable);
}
else {
String fieldValue1= (String) value;
if(Utils.isValidDateString(fieldValue1)){
fieldValue1=Utils.formatDateString(String.valueOf(value));
}
PdfPCell valueCell = new PdfPCell(new Phrase(fieldValue1, valueFont));
valueCell.setPadding(5f); // Increase padding for better spacing
valueCell.setPaddingLeft(leftMargin); // Increase left margin for value
valueCell.setBorder(Rectangle.NO_BORDER); // Remove border for value cell
valueCell.setMinimumHeight(30f);
valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
valueCell.setCellEvent(new RoundedCorners()); // Apply rounded corners
valueTable.addCell(valueCell);
document.add(valueTable);
}
}
document.add(new Paragraph("\n")); // Add line break after each value
}
private Document createPdfTable(List<Map<String, Object>> extractedData, Document document, ContentResponseBean contentResponseBean) throws DocumentException {
// Create a PdfPTable with dynamic column count based on stateFieldMap size
Map<String, String> stateFieldMap = new HashMap<>();
Map<String, Boolean> stateFieldBoolean = new HashMap<>();
// Populate stateFieldMap from contentResponseBean settings
contentResponseBean.getSettings().stream()
.filter(setting -> "table_columns".equals(setting.getName())) // Check for "table_columns"
.map(SettingResponseBean::getValue)
.filter(Objects::nonNull) // Ensure value is not null
.filter(settingValue -> settingValue instanceof Map) // Ensure value is a Map
.map(settingValue -> (Map<String, Object>) settingValue) // Cast to Map
.map(valueMap -> (List<Map<String, Object>>) valueMap.get("stateFieldData")) // Extract stateFieldData list
.filter(Objects::nonNull) // Ensure stateFieldData is not null
.flatMap(List::stream) // Flatten the list of field data maps
.forEach(fieldData -> {
String fieldName = (String) fieldData.get("name"); // Get the name field
String fieldDataValue = (String) fieldData.get("label"); // Get the predefined field
if (fieldName != null && fieldDataValue != null) {
stateFieldMap.put(fieldName, fieldDataValue);
}
});
contentResponseBean.getSettings().stream()
.filter(setting -> "table_columns".equals(setting.getName())) // Check for "table_columns"
.map(SettingResponseBean::getValue)
.filter(Objects::nonNull) // Ensure value is not null
.filter(settingValue -> settingValue instanceof Map) // Ensure value is a Map
.map(settingValue -> (Map<String, Object>) settingValue) // Cast to Map
.map(valueMap -> (List<Map<String, Object>>) valueMap.get("stateFieldData")) // Extract stateFieldData list
.filter(Objects::nonNull) // Ensure stateFieldData is not null
.flatMap(List::stream) // Flatten the list of field data maps
.forEach(fieldData -> {
String fieldName = (String) fieldData.get("name"); // Get the name field
Boolean predefined = (Boolean) fieldData.get("predefined"); // Get the predefined field
if (fieldName != null && fieldName != null) {
stateFieldBoolean.put(fieldName, predefined);
}
});
PdfPTable table = new PdfPTable(stateFieldMap.size()); // Number of columns equals the number of map entries
table.setWidthPercentage(100); // Set table width to 100%
table.setTableEvent(new RoundedBorderEvent());
Font textFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new BaseColor(105, 105, 105)); // Gray text
float rowHeight = 20f; // Example row height
float maxTableHeight = 700f; // Maximum height of the table before a page break
boolean headersAdded = false; // Flag to check if headers have been added
List<String> trueKeys = new ArrayList<>();
List<String> falseKeys = new ArrayList<>();
for (Map.Entry<String, Boolean> entry : stateFieldBoolean.entrySet()) {
if (Boolean.TRUE.equals(entry.getValue())) {
trueKeys.add(entry.getKey()); // Store true keys
} else {
falseKeys.add(entry.getKey()); // Store false keys
}
}
List<String> orderedKeys = new ArrayList<>(trueKeys);
orderedKeys.addAll(falseKeys);
// Iterate through extracted data to populate the table
for (Map<String, Object> row : extractedData) {
// Add headers once
if (!headersAdded) {
for (String key : orderedKeys) {
String headerValue = stateFieldMap.get(key); // Header text
PdfPCell headerCell = new PdfPCell(new Phrase(headerValue)); // Create a new PdfPCell for the header
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
headerCell.setFixedHeight(rowHeight);
headerCell.setBackgroundColor(new BaseColor(178, 190, 181)); // Light gray background for header
table.addCell(headerCell); // Add the header cell to the table
}
headersAdded = true; // Prevent headers from being added again
}
// Add data rows matching stateFieldMap keys
for (String key : orderedKeys) {
Object value = row.getOrDefault(key, ""); // Fetch value or use empty string if key not present
PdfPCell dataCell = new PdfPCell(new Phrase(value != null ? value.toString() : "", textFont));
dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell
dataCell.setMinimumHeight(rowHeight);
dataCell.setFixedHeight(rowHeight);
dataCell.setPadding(7f);
table.addCell(dataCell); // Add the cell to the table
}
// Check if adding another row would exceed max height
if (table.getTotalHeight() + rowHeight > maxTableHeight) {
document.add(table); // Add the table to the document
document.newPage(); // Start a new page
table = new PdfPTable(stateFieldMap.size()); // Create a new table for the new page
table.setWidthPercentage(100); // Reset table width
headersAdded = false; // Reset the header flag for the new page
}
}
// Add the last table to the document
document.add(table);
return document;
}
public static class RoundedBorderEvent implements PdfPTableEvent {
@Override
public void tableLayout(PdfPTable table, float[][] widths, float[] heights,
int headerRows, int rowStart, PdfContentByte[] canvases) {
PdfContentByte canvas = canvases[PdfPTable.BASECANVAS];
// Get the table boundaries
float left = widths[0][0];
float right = widths[0][widths[0].length - 1];
float top = heights[0];
float bottom = heights[heights.length - 1];
// Define the corner radius
float radius = 20f;
// Draw a rounded rectangle around the table
canvas.roundRectangle(left, bottom, right - left, top - bottom, radius);
canvas.stroke();
}
}
public List<FieldLabelValuePairRequest> getFormFieldsToLabels(FormApplicationResponse responseBean,PdfWriter writer,Document document) {
List<FieldLabelValuePairRequest> labelValuePairs = new ArrayList<>();
Font labelFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12,new BaseColor(113,121,126)); // Light grey);
Font valueFont=FontFactory.getFont(FontFactory.HELVETICA_BOLD,10,new BaseColor(178, 190, 181));
// Get form fields and contents from the response
List<ApplicationFormFieldResponseBean> formFields = responseBean.getFormFields();
List<ContentResponseBean> contents = responseBean.getContent();
// Iterate through each content in the response
for (ContentResponseBean content : contents) {
String contentId = content.getId(); // Content ID
String label = content.getLabel(); // Content label
String name = content.getName(); // Content name
Object fieldValue = null;
String contentLabel = content.getSettings().stream()
.filter(setting -> "label".equals(setting.getName())) // Filter settings by name
.map(SettingResponseBean::getValue) // Extract the value from the matching setting
.map(Object::toString) // Convert the value to a string
.findFirst() // Get the first matching value
.orElse(null); // If no match is found, set label to null
// Find the form field in the response that matches the contentId
Optional<ApplicationFormFieldResponseBean> matchingFormField = formFields.stream()
.filter(formField -> formField.getFieldId().equals(contentId))
.findFirst();
// If a matching form field is found, process its value
if (matchingFormField.isPresent()) {
ApplicationFormFieldResponseBean formField = matchingFormField.get();
fieldValue = formField.getFieldValue();
// If fieldValue is null, set it to an empty string
if (fieldValue == null) {
fieldValue = "";
}
// Process 'fileupload' and 'checkboxes' cases as in the original logic
if (name.equals("fileupload")) {
if (fieldValue instanceof List<?> && ((List<?>) fieldValue).stream().allMatch(item -> item instanceof DocumentResponseBean)) {
List<DocumentResponseBean> documentList = (List<DocumentResponseBean>) fieldValue;
List<String> names = documentList.stream()
.map(DocumentResponseBean::getName)
.collect(Collectors.toList());
fieldValue = names;
}
} else if (name.equals("checkboxes")) {
List<String> check = (List<String>) fieldValue;
List<SettingResponseBean> settingResponseBeans = content.getSettings();
List<String> matchedLabels = new ArrayList<>();
for (SettingResponseBean settingResponseBean : settingResponseBeans) {
if (settingResponseBean.getValue() instanceof List<?>) {
List<Map<String, String>> options = (List<Map<String, String>>) settingResponseBean.getValue();
for (Map<String, String> field : options) {
for (String val : check) {
String name1 = field.get("name");
if (val.equals(name1)) {
String labelVal = field.get("label");
if (labelVal != null) {
matchedLabels.add(labelVal);
}
}
}
}
}
}
fieldValue = matchedLabels;
}
// Further processing of field value (e.g., finding labels in options)
fieldValue = findLabelInOptions(content.getSettings(), fieldValue);
} else {
// If no matching form field is found, store contentId with an empty string
fieldValue = "";
}
try {
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) {
log.error("Error checking object: " + e.getMessage(), e);
}
// } labelValuePairs.add(new FieldLabelValuePairRequest(contentLabel, fieldValue));
}
return labelValuePairs;
}
public static Object findLabelInOptions(List<SettingResponseBean> settings, Object valueToFind) {
ObjectMapper objectMapper = new ObjectMapper();
try {
if (valueToFind instanceof String) {
String searchValue = (String) valueToFind;
for (SettingResponseBean setting : settings) {
Object value = setting.getValue();
if (value instanceof List) {
List<?> options = (List<?>) value;
for (Object option : options) {
JsonNode optionNode = objectMapper.convertValue(option, JsonNode.class);
if (optionNode.get("name").asText().equals(searchValue)) {
return optionNode.get("label").asText();
}
}
}
}
}
} catch (Exception e) {
}
return valueToFind;
}
public void addLogo(Document document, String logoPath) throws Exception {
Image logo = Image.getInstance(logoPath);
logo.scaleToFit(document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin(), // Fit to document width
document.getPageSize().getHeight() / 4); // Adjust the height as needed (1/4th of the page height)
logo.setAlignment(Image.ALIGN_CENTER); // Align logo to center
document.add(logo);
// Add some space after logo
document.add(new Paragraph("\n")); // Adding space after the logo
}
public void addColoredLines(PdfWriter writer, Document document, BaseColor color){
PdfContentByte canvas = writer.getDirectContent();
// Setting the color and width of the line
canvas.setColorStroke(color);
float lineWidth = 1.0f; // Thickness of the line
canvas.setLineWidth(lineWidth);
// Get the current vertical position in the document
float yPos = writer.getVerticalPosition(true) - 10f; // Adjust this to move line slightly below current content
// Define start and end points for the line (relative to the page size and margins)
float xStart = document.leftMargin(); // Start from the left margin
float xEnd = document.getPageSize().getWidth() - document.rightMargin(); // End at the right margin
// Draw the line at the current Y position
canvas.moveTo(xStart, yPos); // Move to the starting point
canvas.lineTo(xEnd, yPos); // Draw the line to the end point
canvas.stroke(); // Apply the stroke (line)
}
}