diff --git a/pom.xml b/pom.xml
index a42534bf..9c84bcc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -251,6 +251,13 @@
0.4.8
+
+ org.apache.commons
+ commons-csv
+ 1.10.0
+
+
+
@@ -271,8 +278,8 @@
liquibase-maven-plugin
src/main/resources/application.properties
-
-
-
+
+
+
diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
index b192fba5..4f15580c 100644
--- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
+++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
@@ -499,6 +499,36 @@ public class GepafinConstant {
public static final String PASSWORD_EXPIRED = "PasswordExpired";
public static final String PASSWORD_EXPIRED_LOGIN_TO_ODESSA = "password.expired.for.login.to.odessa";
+
+ public static final String APPLICATION="application";
+ public static final String APPLICATION_ID="applicationId";
+ public static final String USER_WITH_COMPANY_ID="userWithCompanyId";
+ public static final String ASSIGNED_USER_ID="assignedUserId";
+ public static final String APPLICATION_USER_ID="applicationUserId";
+ public static final String INVALID_USER_ID="invalid.user";
+ public static final String COMPANY_NAME="companyName";
+ public static final String TABLE_COLUMNS="table_columns";
+ public static final String PREDEFINED="predefined";
+ public static final String EBABLE_CSV="enableCsv";
+ public static final String LABEL_CSV="labelCsv";
+ public static final String GET="get";
+ public static final String REPORT_COLUMNS="reportColumns";
+ public static final String FIELD_TYPE="fieldtype";
+ public static final String ENABLE_FORMULA="enableFormula";
+ public static final String STATE_FIELD_DATA="stateFieldData";
+ public static final String REPORT_ENABLE="reportEnable";
+ public static final String TABLE="table";
+ public static final String GET_FIELD_TYPE="getFieldType";
+ public static final String GET_APPLICATION_FORM_ID="getApplicationFormId";
+ public static final String GET_APPLICATION_ID="getApplicationId";
+ public static final String GET_ID="getId";
+ public static final String GET_CLASS="getClass";
+ public static final String GET_FORM_ID="getFormId";
+ public static final String GET_FIELD_ID="getFieldId";
+ public static final String GET_FIELD_LABEL="getFieldLabel";
+ public static final String GET_FIELD_VALUE="getFieldValue";
+ public static final String GET_REPORT_ENABLE="getReportEnable";
+ public static final String GET_REPORT_HEADER="getReportHeader";
}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
index c7592e3e..d6b66527 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
@@ -1,10 +1,15 @@
package net.gepafin.tendermanagement.dao;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.itextpdf.text.BaseColor;
+import com.itextpdf.text.Font;
+import com.itextpdf.text.FontFactory;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.*;
+import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
@@ -23,15 +28,14 @@ import net.gepafin.tendermanagement.service.FormService;
import net.gepafin.tendermanagement.service.HubService;
import net.gepafin.tendermanagement.service.SystemEmailTemplatesService;
import net.gepafin.tendermanagement.service.UserService;
-import net.gepafin.tendermanagement.util.DateTimeUtil;
-import net.gepafin.tendermanagement.util.FieldValidator;
-import net.gepafin.tendermanagement.util.LoggingUtil;
-import net.gepafin.tendermanagement.util.Utils;
-import net.gepafin.tendermanagement.util.Validator;
+import net.gepafin.tendermanagement.util.*;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.commons.lang3.StringUtils;
import org.h2.util.IOUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -49,17 +53,17 @@ import jakarta.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Method;
import java.math.BigDecimal;
+
import java.sql.Timestamp;
import java.text.MessageFormat;
-import java.text.NumberFormat;
-import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -69,7 +73,6 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static org.apache.commons.lang3.StringUtils.isEmpty;
-import static org.hibernate.validator.internal.engine.messageinterpolation.el.RootResolver.FORMATTER;
@Component
public class ApplicationDao {
@@ -195,6 +198,15 @@ public class ApplicationDao {
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
+ @Autowired
+ private ApplicationFormViewRepository applicationFormViewRepository;
+
+ @Autowired
+ private FormRepository formRepository;
+
+ @Autowired
+ private ApplicationEvaluationDao applicationEvaluationDao;
+
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) {
FormEntity formEntity = formService.validateForm(formId);
@@ -1878,4 +1890,313 @@ public class ApplicationDao {
}
return application;
}
+ public List getApplicationFormData(Long callId) {
+ List applicationFormViews=new ArrayList<>();
+
+ applicationFormViews= applicationFormViewRepository.findByCallId(callId);
+
+ return applicationFormViews;
+ }
+
+ private List getStaticGetterMethods() {
+ List excluded = Arrays.asList(
+ GepafinConstant.GET_FIELD_TYPE,GepafinConstant.GET_APPLICATION_FORM_ID,GepafinConstant.GET_ID,GepafinConstant.GET_CLASS,GepafinConstant.GET_FORM_ID,GepafinConstant.GET_FIELD_ID,GepafinConstant.GET_FIELD_LABEL,GepafinConstant.GET_FIELD_VALUE,GepafinConstant.GET_REPORT_HEADER,GepafinConstant.GET_REPORT_ENABLE
+ );
+
+ Method applicationIdMethod = null;
+
+ List methods = new ArrayList<>();
+
+ for (Method m : ApplicationFormView.class.getMethods()) {
+ if (m.getName().equals(GepafinConstant.GET_APPLICATION_ID)) {
+ applicationIdMethod = m;
+ } else if (m.getName().startsWith(GepafinConstant.GET) && m.getParameterCount() == 0 && !excluded.contains(m.getName())) {
+ methods.add(m);
+ }
+ }
+
+ methods.sort(Comparator.comparing(Method::getName)); // Sort remaining
+
+ if (applicationIdMethod != null) {
+ methods.add(0, applicationIdMethod); // Add it to the beginning
+ }
+
+ return methods;
+
+ }
+
+ private String methodToHeader(Method method) {
+ String name = method.getName().substring(3); // strip "get"
+ return Arrays.stream(name.split("(?=[A-Z])"))
+ .map(String::toLowerCase)
+ .map(word -> Character.toUpperCase(word.charAt(0)) + word.substring(1))
+ .collect(Collectors.joining(" "));
+ }
+
+ private String invokeGetter(ApplicationFormView view, Method method) {
+ try {
+ Object value = method.invoke(view);
+ if (value == null) return "";
+
+ String stringValue;
+
+ if (value instanceof LocalDate) {
+ stringValue = ((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+ } else if (value instanceof LocalDateTime) {
+ stringValue = ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+ } else if (value instanceof Date) {
+ stringValue = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) value);
+ } else {
+ stringValue = value.toString();
+ }
+
+ // Wrap it in ="..." to make Excel treat it as a literal string
+ return "=\"" + stringValue.replace("\"", "\"\"") + "\"";
+
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
+
+ public byte[] exportCsv(Long callId) {
+
+ List results = getApplicationFormData(callId);
+
+
+ Map appInfo = new HashMap<>();
+ Map> appFieldValues = new LinkedHashMap<>();
+ Set tableFieldIds = new HashSet<>();
+ Map fieldIdToLabel = new LinkedHashMap<>();
+
+ for (ApplicationFormView row : results) {
+ appInfo.putIfAbsent(row.getApplicationId(), row);
+ String label=row.getReportHeader();
+ if(Boolean.TRUE.equals(StringUtils.isEmpty(label))){
+ label=row.getFieldLabel();
+ }
+ fieldIdToLabel.putIfAbsent(row.getFieldId(), label);
+
+ if (GepafinConstant.TABLE.equalsIgnoreCase(row.getFieldType())) {
+ tableFieldIds.add(row.getFieldId());
+ continue;
+ }
+
+ String value = Optional.ofNullable(row.getFieldValue())
+ .map(v -> v.startsWith("\"") && v.endsWith("\"") ? v.substring(1, v.length() - 1) : v)
+ .orElse("");
+
+ appFieldValues
+ .computeIfAbsent(row.getApplicationId(), k -> new LinkedHashMap<>())
+ .merge(row.getFieldId(), value, (v1, v2) -> v1.equals(v2) ? v1 : String.join(", ", v1, v2));
+ }
+
+ Map> tableHeadersByFieldId = new LinkedHashMap<>();
+ Map> tableDataByApp = new HashMap<>();
+ prepareTableFieldData(results, tableFieldIds, tableHeadersByFieldId, tableDataByApp);
+
+ // Final header construction
+ List staticMethods = getStaticGetterMethods();
+ List staticHeaders = staticMethods.stream().map(this::methodToHeader).toList();
+
+ List dynamicHeaders = new ArrayList<>();
+ for (String fieldId : fieldIdToLabel.keySet()) {
+ if (tableHeadersByFieldId.containsKey(fieldId)) {
+ dynamicHeaders.addAll(tableHeadersByFieldId.get(fieldId));
+ } else {
+ dynamicHeaders.add(fieldIdToLabel.get(fieldId));
+ }
+ }
+
+ List allHeaders = new ArrayList<>(staticHeaders);
+ allHeaders.addAll(dynamicHeaders);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try (CSVPrinter printer = new CSVPrinter(new OutputStreamWriter(out), CSVFormat.DEFAULT.withHeader(allHeaders.toArray(new String[0])))) {
+ for (Long appId : appFieldValues.keySet()) {
+ ApplicationFormView appRow = appInfo.get(appId);
+ Map flatFieldVals = appFieldValues.get(appId);
+ Map tableVals = tableDataByApp.getOrDefault(appId, Collections.emptyMap());
+
+ List row = new ArrayList<>();
+ for (Method method : staticMethods) {
+ row.add(invokeGetter(appRow, method));
+ }
+
+ for (String fieldId : fieldIdToLabel.keySet()) {
+ if (tableHeadersByFieldId.containsKey(fieldId)) {
+ for (String header : tableHeadersByFieldId.get(fieldId)) {
+ row.add(tableVals.getOrDefault(header, ""));
+ }
+ } else {
+ row.add(flatFieldVals.getOrDefault(fieldId, ""));
+ }
+ }
+
+ printer.printRecord(row);
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("CSV generation failed", e);
+ }
+
+ return out.toByteArray();
+ }
+ private Map extractTableData(String fieldType,
+ ContentResponseBean content, String fieldValue) {
+
+ if (content == null) return Map.of();
+
+ Map result = new LinkedHashMap<>();
+
+ List