Display column totals for formula-enabled in PDF
This commit is contained in:
@@ -360,5 +360,10 @@ public class GepafinConstant {
|
|||||||
public static final String STATUS_CODE_STRING = "statusCode";
|
public static final String STATUS_CODE_STRING = "statusCode";
|
||||||
public static final String GET_STATUS_CODE_STRING = "status";
|
public static final String GET_STATUS_CODE_STRING = "status";
|
||||||
public static final String MESSAGE_STRING = "message";
|
public static final String MESSAGE_STRING = "message";
|
||||||
|
|
||||||
|
public static final String SUM="sum";
|
||||||
|
public static final String MULTIPLY="multiply";
|
||||||
|
public static final String NUMERIC="numeric";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.itextpdf.text.Rectangle;
|
|||||||
import com.itextpdf.text.pdf.*;
|
import com.itextpdf.text.pdf.*;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import net.gepafin.tendermanagement.constants.GepafinConstant;
|
||||||
import net.gepafin.tendermanagement.entities.*;
|
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.*;
|
||||||
@@ -29,6 +30,8 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -258,9 +261,10 @@ public class PdfDao {
|
|||||||
// Create a PdfPTable with dynamic column count based on stateFieldMap size
|
// Create a PdfPTable with dynamic column count based on stateFieldMap size
|
||||||
Map<String, String> stateFieldMap = new HashMap<>();
|
Map<String, String> stateFieldMap = new HashMap<>();
|
||||||
Map<String, Boolean> stateFieldBoolean = new HashMap<>();
|
Map<String, Boolean> stateFieldBoolean = new HashMap<>();
|
||||||
// Font textFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new BaseColor(178, 190, 181)); // Gray text
|
Map<String, Boolean> formulaEnabledMap = new HashMap<>();
|
||||||
|
Map<String, String> formulaTypeMap = new HashMap<>();
|
||||||
|
Map<String, String> fieldTypeMap = new HashMap<>();
|
||||||
|
|
||||||
// Populate stateFieldMap from contentResponseBean settings
|
|
||||||
contentResponseBean.getSettings().stream()
|
contentResponseBean.getSettings().stream()
|
||||||
.filter(setting -> "table_columns".equals(setting.getName())) // Check for "table_columns"
|
.filter(setting -> "table_columns".equals(setting.getName())) // Check for "table_columns"
|
||||||
.map(SettingResponseBean::getValue)
|
.map(SettingResponseBean::getValue)
|
||||||
@@ -273,27 +277,26 @@ public class PdfDao {
|
|||||||
.forEach(fieldData -> {
|
.forEach(fieldData -> {
|
||||||
String fieldName = (String) fieldData.get("name"); // Get the name field
|
String fieldName = (String) fieldData.get("name"); // Get the name field
|
||||||
String fieldDataValue = (String) fieldData.get("label"); // Get the predefined field
|
String fieldDataValue = (String) fieldData.get("label"); // Get the predefined field
|
||||||
|
Boolean predefined = (Boolean) fieldData.get("predefined"); // Get the predefined field
|
||||||
|
Boolean isFormulaEnabled = (Boolean) fieldData.get("enableFormula");
|
||||||
|
String formulaType = (String) fieldData.get("lastRowFormula");
|
||||||
|
String fieldType = (String) fieldData.get("fieldtype"); // Get the field type (e.g., numeric)
|
||||||
|
|
||||||
if (fieldName != null && fieldDataValue != null) {
|
if (fieldName != null && fieldDataValue != null) {
|
||||||
stateFieldMap.put(fieldName, fieldDataValue);
|
stateFieldMap.put(fieldName, fieldDataValue);
|
||||||
}
|
}
|
||||||
});
|
if (fieldName != null && predefined != null) {
|
||||||
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);
|
stateFieldBoolean.put(fieldName, predefined);
|
||||||
}
|
}
|
||||||
|
formulaEnabledMap.put(fieldName, isFormulaEnabled != null && isFormulaEnabled);
|
||||||
|
if (formulaType != null) {
|
||||||
|
formulaTypeMap.put(fieldName, formulaType);
|
||||||
|
}
|
||||||
|
if (fieldType != null) {
|
||||||
|
fieldTypeMap.put(fieldName, fieldType); // Store the fieldType in the map
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PdfPTable table = new PdfPTable(stateFieldMap.size()); // Number of columns equals the number of map entries
|
PdfPTable table = new PdfPTable(stateFieldMap.size()); // Number of columns equals the number of map entries
|
||||||
table.setWidthPercentage(100); // Set table width to 100%
|
table.setWidthPercentage(100); // Set table width to 100%
|
||||||
table.setTableEvent(new RoundedBorderEvent());
|
table.setTableEvent(new RoundedBorderEvent());
|
||||||
@@ -314,12 +317,9 @@ 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
|
|
||||||
// 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 = PdfUtils.htmlToPdfPCell(headerValue, textFont);
|
PdfPCell headerCell = PdfUtils.htmlToPdfPCell(headerValue, textFont);
|
||||||
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
|
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align
|
||||||
headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
|
headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
|
||||||
@@ -332,10 +332,9 @@ public class PdfDao {
|
|||||||
}
|
}
|
||||||
headersAdded = true; // Prevent headers from being added again
|
headersAdded = true; // Prevent headers from being added again
|
||||||
}
|
}
|
||||||
|
Map<String, Double> columnSums = new HashMap<>();
|
||||||
|
|
||||||
// Add data rows matching stateFieldMap keys
|
|
||||||
for (Map<String, Object> row : extractedData) {
|
for (Map<String, Object> row : extractedData) {
|
||||||
// Add data rows matching stateFieldMap keys
|
|
||||||
for (String key : orderedKeys) {
|
for (String key : orderedKeys) {
|
||||||
if (stateFieldMap.containsKey(key)) { // Only add data cell if key is in stateFieldMap
|
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
|
||||||
@@ -343,7 +342,10 @@ public class PdfDao {
|
|||||||
if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(fieldValue)) ){
|
if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(fieldValue)) ){
|
||||||
fieldValue= String.valueOf(Utils.convertToItalianFormat(fieldValue));
|
fieldValue= String.valueOf(Utils.convertToItalianFormat(fieldValue));
|
||||||
}
|
}
|
||||||
// PdfPCell dataCell = new PdfPCell(new Phrase(fieldValue != null ?fieldValue: "", textFont));
|
if (Boolean.TRUE.equals(formulaEnabledMap.get(key)) && Boolean.TRUE.equals(GepafinConstant.NUMERIC.equalsIgnoreCase(fieldTypeMap.get(key)))) {
|
||||||
|
calculateValue(key, fieldValue, formulaTypeMap, columnSums);
|
||||||
|
}
|
||||||
|
|
||||||
PdfPCell dataCell = PdfUtils.htmlToPdfPCell(fieldValue != null ? fieldValue : "", textFont);
|
PdfPCell dataCell = PdfUtils.htmlToPdfPCell(fieldValue != null ? fieldValue : "", textFont);
|
||||||
dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell
|
dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell
|
||||||
dataCell.setMinimumHeight(30f);
|
dataCell.setMinimumHeight(30f);
|
||||||
@@ -356,23 +358,66 @@ public class PdfDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if adding another row would exceed max height
|
|
||||||
if (table.getTotalHeight() + rowHeight > maxTableHeight) {
|
if (table.getTotalHeight() + rowHeight > maxTableHeight) {
|
||||||
document.add(table); // Add the table to the document
|
document.add(table); // Add the table to the document
|
||||||
document.newPage(); // Start a new page
|
document.newPage(); // Start a new page
|
||||||
table = new PdfPTable(stateFieldMap.size()); // Create a new table for the new page
|
table = new PdfPTable(stateFieldMap.size()); // Create a new table for the new page
|
||||||
table.setWidthPercentage(100); // Reset table width
|
table.setWidthPercentage(100); // Reset table width
|
||||||
|
|
||||||
headersAdded = false; // Reset the header flag for the new page
|
headersAdded = false; // Reset the header flag for the new page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (String key : orderedKeys) {
|
||||||
|
if (Boolean.TRUE.equals(formulaEnabledMap.get(key)) &&
|
||||||
|
(GepafinConstant.SUM.equalsIgnoreCase(formulaTypeMap.get(key)) ||
|
||||||
|
GepafinConstant.MULTIPLY.equalsIgnoreCase(formulaTypeMap.get(key)))) {
|
||||||
|
|
||||||
|
if (columnSums.containsKey(key)) {
|
||||||
|
double total = columnSums.getOrDefault(key, 0.0); // Get the total for the column
|
||||||
|
PdfPCell sumCell = PdfUtils.htmlToPdfPCell(Utils.convertToItalianFormat(String.valueOf(total)), textFont);
|
||||||
|
sumCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for totals
|
||||||
|
sumCell.setHorizontalAlignment(Element.ALIGN_CENTER);
|
||||||
|
sumCell.setMinimumHeight(30f);
|
||||||
|
table.addCell(sumCell); // Add total for the column
|
||||||
|
} else {
|
||||||
|
PdfPCell emptyCell = new PdfPCell(new Phrase(""));
|
||||||
|
emptyCell.setBackgroundColor(new BaseColor(239, 243, 248));
|
||||||
|
table.addCell(emptyCell);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PdfPCell emptyCell = new PdfPCell(new Phrase(""));
|
||||||
|
emptyCell.setBackgroundColor(new BaseColor(239, 243, 248));
|
||||||
|
table.addCell(emptyCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add the last table to the document
|
// Add the last table to the document
|
||||||
document.add(table);
|
document.add(table);
|
||||||
|
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void calculateValue(String key, String fieldValue, Map<String, String> formulaTypeMap, Map<String, Double> columnSums) {
|
||||||
|
try {
|
||||||
|
if (Boolean.FALSE.equals(StringUtils.isEmpty(fieldValue))) {
|
||||||
|
// Use Locale.ITALY to parse the number with the Italian format (comma as decimal separator)
|
||||||
|
NumberFormat format = NumberFormat.getInstance(Locale.ITALY);
|
||||||
|
Number number = format.parse(fieldValue); // Parse the fieldValue as a number
|
||||||
|
double numericValue = number.doubleValue(); // Convert the parsed number to double
|
||||||
|
|
||||||
|
if (GepafinConstant.SUM.equalsIgnoreCase(formulaTypeMap.get(key))) {
|
||||||
|
columnSums.merge(key, numericValue, Double::sum);
|
||||||
|
} else if (GepafinConstant.MULTIPLY.equalsIgnoreCase(formulaTypeMap.get(key))) {
|
||||||
|
columnSums.merge(key, numericValue, (existing, newValue) -> existing == null ? newValue : existing * newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ParseException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class RoundedBorderEvent implements PdfPTableEvent {
|
public static class RoundedBorderEvent implements PdfPTableEvent {
|
||||||
@Override
|
@Override
|
||||||
public void tableLayout(PdfPTable table, float[][] widths, float[] heights,
|
public void tableLayout(PdfPTable table, float[][] widths, float[] heights,
|
||||||
|
|||||||
Reference in New Issue
Block a user