diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index e95c04f3..dd163bf1 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -375,6 +375,10 @@ public class GepafinConstant { public static final String STATUS_CODE_STRING = "statusCode"; public static final String GET_STATUS_CODE_STRING = "status"; 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"; public static final String AMOUNT_ACCEPTED_REQUIRED_WHILE_APPROVING_APPLICATION="amount.accepted.required"; public static final String CALL_NAME="callName"; public static final String NUMBER_OF_APPLICATIONS="numberOfSubmitedApplications"; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 7cced04a..8c89b510 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -618,7 +618,7 @@ public class ApplicationEvaluationDao { entity.setIsDeleted(false); setIfUpdated(entity::getNote, entity::setNote, req.getNote()); setIfUpdated(entity::getMotivation, entity::setMotivation, req.getMotivation()); - if(Boolean.TRUE.equals(req.getApplicationStatus().equals(ApplicationStatusForEvaluation.APPROVED)) && (req.getAmountAccepted()==null || req.getAmountAccepted().compareTo(BigDecimal.ZERO) < 0)){ + if(req.getApplicationStatus()!=null && (Boolean.TRUE.equals(req.getApplicationStatus().equals(ApplicationStatusForEvaluation.APPROVED)) && (req.getAmountAccepted()==null || req.getAmountAccepted().compareTo(BigDecimal.ZERO) < 0))){ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.AMOUNT_ACCEPTED_REQUIRED_WHILE_APPROVING_APPLICATION)); } if (req.getAmountAccepted() != null && req.getAmountAccepted().compareTo(BigDecimal.ZERO) > 0) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 1b3a6798..b014b779 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -143,17 +143,20 @@ public class CompanyDao { entity.setNumberOfEmployees(request.getNumberOfEmployees()); entity.setAnnualRevenue(request.getAnnualRevenue()); entity.setHub(userEntity.getHub()); - Map vatCheckResponse = request.getVatCheckResponse(); if (request.getVatCheckResponse() != null) { - if (vatCheckResponse.containsKey("dettaglio")) { - Map dettaglio = (Map) vatCheckResponse.get("dettaglio"); - if (dettaglio != null) { - if (dettaglio.containsKey("codice_ateco")) { - Object codiceAtecoObj = dettaglio.get("codice_ateco"); - String codiceAteco = (codiceAtecoObj != null) ? codiceAtecoObj.toString() : null; + Map vatCheckResponse = request.getVatCheckResponse(); + Map data = (Map) vatCheckResponse.get("data"); + if (data != null) { + if (data.containsKey("dettaglio")) { + Map dettaglio = (Map) data.get("dettaglio"); + if (dettaglio != null) { + if (dettaglio.containsKey("codice_ateco")) { + Object codiceAtecoObj = dettaglio.get("codice_ateco"); + String codiceAteco = (codiceAtecoObj != null) ? codiceAtecoObj.toString() : null; - if (codiceAteco != null) { - entity.setCodiceAteco(codiceAteco); + if (codiceAteco != null) { + entity.setCodiceAteco(codiceAteco); + } } } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index a2e437cd..28be65b9 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -10,6 +10,7 @@ import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.*; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.model.request.FieldLabelValuePairRequest; import net.gepafin.tendermanagement.model.response.*; @@ -29,6 +30,8 @@ import org.springframework.stereotype.Component; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.text.NumberFormat; +import java.text.ParseException; import java.util.*; import java.util.List; import java.util.stream.Collectors; @@ -258,10 +261,11 @@ public class PdfDao { // Create a PdfPTable with dynamic column count based on stateFieldMap size Map stateFieldMap = new HashMap<>(); Map stateFieldBoolean = new HashMap<>(); -// Font textFont = FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new BaseColor(178, 190, 181)); // Gray text + Map formulaEnabledMap = new HashMap<>(); + Map formulaTypeMap = new HashMap<>(); + Map 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" .map(SettingResponseBean::getValue) .filter(Objects::nonNull) // Ensure value is not null @@ -273,28 +277,27 @@ public class PdfDao { .forEach(fieldData -> { String fieldName = (String) fieldData.get("name"); // Get the name 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) { 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) settingValue) // Cast to Map - .map(valueMap -> (List>) 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) { + if (fieldName != null && predefined != null) { 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.setTableEvent(new RoundedBorderEvent()); @@ -314,12 +317,9 @@ public class PdfDao { } List orderedKeys = new ArrayList<>(trueKeys); orderedKeys.addAll(falseKeys); - // Iterate through extracted data to populate the table - // Add headers once - if (!headersAdded) { + 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 PdfPCell headerCell = PdfUtils.htmlToPdfPCell(headerValue, textFont); headerCell.setHorizontalAlignment(Element.ALIGN_CENTER); // Center align headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE); @@ -332,18 +332,20 @@ public class PdfDao { } headersAdded = true; // Prevent headers from being added again } + Map columnSums = new HashMap<>(); - // Add data rows matching stateFieldMap keys for (Map row : extractedData) { - // 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 String fieldValue= (String) value; - if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(fieldValue)) ){ + if(Boolean.TRUE.equals(Utils.isItalianFormattedAmount(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); dataCell.setBackgroundColor(new BaseColor(239, 243, 248)); // Light blue for the cell dataCell.setMinimumHeight(30f); @@ -356,23 +358,66 @@ public class PdfDao { } } - // 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 } } + + 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 document.add(table); return document; } + private static void calculateValue(String key, String fieldValue, Map formulaTypeMap, Map 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 { @Override public void tableLayout(PdfPTable table, float[][] widths, float[] heights,