diff --git a/pom.xml b/pom.xml
index c463be91..a42534bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -245,6 +245,12 @@
reactor-netty
+
+ net.objecthunter
+ exp4j
+ 0.4.8
+
+
diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
index d04a6abf..80f30960 100644
--- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
+++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
@@ -408,6 +408,7 @@ public class GepafinConstant {
public static final String ASSIGNED_APPLICATION_STATUS_UPDATED_SUCCESSFULLY = "assigned.application.status.updated.successfully";
public static final String REQUIRED_REQUESTED_AMOUNT_MSG = "validation.required.requested.amount";
+ public static final String FORMULA_AMOUNT_NOT_MATCHED="formula.amount.not.matches.requested.amount";
public static final String CRITERIA_TABLE_COLUMNS="criteria_table_columns";
public static final String DOCUMENTATION_INTEGRATION_REQUEST_SVILUPPUMBRIA= "\n" +
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
index 794e7796..f43a030f 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
@@ -31,6 +31,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundExceptio
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.h2.util.IOUtils;
+import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,11 +50,16 @@ import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -94,29 +100,29 @@ public class ApplicationDao {
@Autowired
private FlowDataRepository flowDataRepository;
-
+
@Autowired
private UserCompanyDelegationRepository userCompanyDelegationRepository;
-
+
@Autowired
private Validator validator;
-
+
@Autowired
private CompanyService companyService;
@Autowired
private S3PathConfig s3PathConfig;
-
+
@Autowired
private SystemEmailTemplatesService systemEmailTemplatesService;
@Autowired
private AssignedApplicationsRepository assignedApplicationsRepository;
-
+
@Value("${default_System_Receiver_Email}")
private String defaultSystemReceiverEmail;
-
+
@Value("${rinaldo_email}")
private String rinaldoEmail;
-
+
@Value("${carlo_email}")
private String carloEmail;
@@ -125,37 +131,37 @@ public class ApplicationDao {
@Autowired
private AmazonS3Service amazonS3Service;
-
+
@Autowired
private ApplicationSignedDocumentRepository applicationSignedDocumentRepository;
-
+
// @Value("${aws.s3.url.folder.signed.document}")
// private String signedDocumentS3Folder;
-
+
@Value("${default.hub.uuid}")
private String defaultHubUuid;
-
+
@Autowired
private UserService userService;
@Autowired
private S3PathConfig s3ConfigBean;
-
+
@Autowired
private ProtocolDao protocolDao;
-
+
@Autowired
private HubService hubService;
@Autowired
private EmailNotificationDao emailNotificationDao;
-
+
@Autowired
private FormDao formDao;
@Autowired
private EmailLogDao emailLogDao;
-
+
@Autowired
private UserWithCompanyRepository userWithCompanyRepository;
@@ -183,6 +189,7 @@ public class ApplicationDao {
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
+
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) {
FormEntity formEntity = formService.validateForm(formId);
// callService.validatePublishedCall(formEntity.getCall().getId());
@@ -258,7 +265,7 @@ public class ApplicationDao {
// List contentResponseBeans = Utils.convertJsonStringToList(
// applicationFormEntity.getForm().getContent(), ContentResponseBean.class);
-
+
List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(applicationFormEntity.getForm()).getContent();
for (ApplicationFormFieldEntity applicationFormFieldEntity : applicationFormFieldEntities) {
@@ -309,7 +316,7 @@ public class ApplicationDao {
);
}
ApplicationEntity oldApplicationDataEntity = Utils.getClonedEntityForData(applicationEntity);
-
+
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
applicationEntity.setIsDeleted(true);
applicationEntity = applicationRepository.save(applicationEntity);
@@ -356,9 +363,9 @@ public class ApplicationDao {
//
// return applicationResponses;
// }
-
+
public List getAllApplications(UserEntity userEntity, Long callId, Long companyId,List statusList) {
-
+
log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType());
Specification spec = search(userEntity, callId, companyId,statusList);
@@ -482,15 +489,18 @@ public class ApplicationDao {
public List createOrUpdateMultipleFormFields(List formFieldResponseBeans,
ApplicationFormEntity applicationFormEntity, FormEntity formEntity) {
+ FieldValidator fieldValidator = FieldValidator.create();
List existingFields = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
- return formFieldResponseBeans.stream().map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity, existingFields, formEntity))
+ List applicationFormFieldEntities=formFieldResponseBeans.stream().map(requestBean -> createOrUpdateApplicationFormField(requestBean, applicationFormEntity, existingFields, formEntity,fieldValidator))
.collect(Collectors.toList());
+ fieldValidator.validate();
+ return applicationFormFieldEntities;
}
public ApplicationFormFieldEntity createOrUpdateApplicationFormField(ApplicationFormFieldRequestBean applicationFormFieldRequestBean,
- ApplicationFormEntity applicationFormEntity, List applicationFormFieldEntities, FormEntity formEntity) {
+ ApplicationFormEntity applicationFormEntity, List applicationFormFieldEntities, FormEntity formEntity,FieldValidator fieldValidator) {
ApplicationFormFieldEntity applicationFormFieldEntity = new ApplicationFormFieldEntity();
@@ -506,7 +516,7 @@ public class ApplicationDao {
.filter(setting -> "isRequestedAmount".equals(setting.getName()) && Boolean.TRUE.equals(setting.getValue()))
.findFirst()
.ifPresent(setting -> {
-
+
Object fieldValue = applicationFormFieldRequestBean.getFieldValue();
if(fieldValue!=null) {
try {
@@ -538,6 +548,7 @@ public class ApplicationDao {
}
}
}
+ calculationProcessForFormula(applicationFormEntity,contentResponseBeans,applicationFormFieldRequestBean,fieldValidator);
Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId());
if (applicationFormFieldRequestBean.getFieldValue() != null) {
@@ -560,7 +571,6 @@ public class ApplicationDao {
VersionHistoryRequest.builder().request(request).actionType(actionType).oldData(oldApplicationFormFieldData).newData(applicationFormField).build());
log.info("Version history logged for action: {}, Field ID: {}", actionType, applicationFormFieldEntity.getFieldId());
-
return applicationFormField;
}
@@ -818,7 +828,7 @@ public class ApplicationDao {
if(formApplicationResponse.getContent() != null && formApplicationResponse.getFormFields() != null) {
formApplicationResponses.add(formApplicationResponse);
}
-
+
}
public FormApplicationResponse processForm(FormEntity formEntity, ApplicationEntity applicationEntity) {
@@ -954,7 +964,7 @@ public class ApplicationDao {
return (int) Math.round(progress);
}
public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) {
-
+
// List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class);
List contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
@@ -1034,7 +1044,7 @@ public class ApplicationDao {
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
.retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY,
hub, null);
-
+
// Create the map for subject placeholders
Map subjectPlaceholders = new HashMap<>();
subjectPlaceholders.put("{{call_name}}", call.getName());
@@ -1211,17 +1221,17 @@ public class ApplicationDao {
}
public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) {
-
+
ApplicationEntity applicationEntity = validateApplication(applicationId);
// validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
-
+
if (validator.checkIsPreInstructor()) {
ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluationByApplicationId(applicationId);
validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId());
} else {
validator.validateUserId(request, applicationEntity.getUserId());
}
-
+
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if(applicationSignedDocument == null) {
@@ -1230,11 +1240,11 @@ public class ApplicationDao {
}
return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
}
-
+
public void deleteSignedDocument(HttpServletRequest request, Long applicationId) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validator.validateUserWithCompany(request, applicationEntity.getCompanyId());
-
+
ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
//cloned entity for old data
@@ -1539,5 +1549,135 @@ public class ApplicationDao {
}
}
+ public void calculationProcessForFormula(ApplicationFormEntity applicationFormEntity, List contentResponseBeans, ApplicationFormFieldRequestBean applicationFormFieldRequestBean,FieldValidator fieldValidator) {
+ List formulaValue = new ArrayList<>();
+ String formulaValueOpt=null;
+ String label=null;
+ for (ContentResponseBean contentResponseBean:contentResponseBeans){
+ if(contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())){
+ for (SettingResponseBean settingResponseBean:contentResponseBean.getSettings()){
+ if (settingResponseBean.getName().equals("label")){
+ label= String.valueOf(settingResponseBean.getValue());
+ }
+ if(settingResponseBean.getName().equals("formula")){
+ String value= (String) settingResponseBean.getValue();
+ formulaValueOpt=value;
+ formulaValue=Utils.extractValues(value);
+ }
+ }
+ }
+ }
+ Map mappedFormulaValue = new HashMap<>();
+ Object fieldValue = applicationFormFieldRequestBean.getFieldValue();
+ if (formulaValueOpt != null && fieldValue==null) {
+ fieldValue=0;
+ }
+
+ for (ContentResponseBean contentResponseBean : contentResponseBeans) {
+ String contentId = contentResponseBean.getId();
+
+ // Extract variable values once per contentResponseBean to avoid repeated stream operations
+ Set variableValues = contentResponseBean.getSettings().stream()
+ .filter(setting -> "variable".equals(setting.getName()))
+ .flatMap(setting -> {
+ Object value = setting.getValue(); // Get the raw value
+ if (value instanceof String) {
+ return Stream.of((String) value); // Handle single String case
+ } else if (value instanceof List) {
+ return ((List>) value).stream()
+ .filter(item -> item instanceof String) // Ensure it's a String
+ .map(item -> (String) item); // Convert to String
+ } else {
+ return Stream.empty(); // Ignore unexpected types
+ }
+ })
+ .collect(Collectors.toSet()); // Collect into a Set for uniqueness
+
+ for (String formula : formulaValue) {
+ if (variableValues.contains(formula)) { // O(1) lookup instead of O(n)
+ mappedFormulaValue.put(formula, contentId);
+ }
+ }
+ }
+ Map updatedMappedFormulaValue = new HashMap<>();
+
+ for (Map.Entry entry : mappedFormulaValue.entrySet()) {
+ String variable = entry.getKey();
+ String contentId = entry.getValue();
+
+ // Repository call using contentId
+ Optional optionalEntity = applicationFormFieldRepository.findByApplicationFormIdAndFieldId(applicationFormEntity.getId(),contentId);
+ // If entity is found, extract fieldValue and fieldId
+ optionalEntity.ifPresent(entity -> {
+ String entityFieldValue = entity.getFieldValue(); // Assuming getter method exists
+ String fieldId = entity.getFieldId(); // Assuming getter method exists
+ String tableType = contentResponseBeans.stream()
+ .filter(content -> content.getId().equals(fieldId)) // Match Content ID with fieldId
+ .flatMap(content -> content.getSettings().stream()) // Extract settings
+ .filter(setting -> "criteria_table_columns".equals(setting.getName())) // Match name
+ .map(setting -> setting.getName()) // Return the name of the setting
+ .findFirst() // Get the first match
+ .orElse(null); // Default to null if no match
+
+ if(tableType!=null){
+ JSONObject jsonObject = new JSONObject(entityFieldValue);
+
+ // Extract the value of total
+ entityFieldValue = jsonObject.getString("total");
+
+ }
+
+ updatedMappedFormulaValue.put(fieldId, entityFieldValue);
+ });
+ }
+ if(formulaValueOpt==null || formulaValueOpt.isEmpty()){
+ return;
+ }
+ double finalValue = evaluateFormula(formulaValueOpt, mappedFormulaValue, updatedMappedFormulaValue);
+
+ fieldValidator.formulaValidation(fieldValue, finalValue, label);
+ }
+
+
+ public static double evaluateFormula(String formula, Map mappedFormulaValue, Map updatedMappedFormulaValue) {
+ // Step 1: Extract all placeholders (variables) like {rest}, {another_var}, etc.
+ Pattern pattern = Pattern.compile("\\{(.*?)\\}");
+ Matcher matcher = pattern.matcher(formula);
+ List variables = new ArrayList<>();
+
+ while (matcher.find()) {
+ variables.add(matcher.group(1)); // Extract variable names inside the curly braces
+ }
+
+ // Step 2: Replace placeholders with corresponding fieldValue
+ Map variableValues = new HashMap<>();
+
+ for (String variable : variables) {
+ String fieldId = mappedFormulaValue.get(variable);
+ if (fieldId != null && updatedMappedFormulaValue.containsKey(fieldId)) {
+ String fieldValueStr = updatedMappedFormulaValue.get(fieldId);
+ try {
+ double fieldValue = Double.parseDouble(fieldValueStr); // Assuming fieldValue is numeric
+ variableValues.put(variable, fieldValue);
+ } catch (NumberFormatException e) {
+ // Handle invalid number format gracefully (e.g., log an error or default to 0)
+ variableValues.put(variable, 0.0);
+ }
+ }
+ }
+
+ // Step 3: Replace variables in the formula with their corresponding values
+ String expression = formula;
+ for (String variable : variables) {
+ Double value = variableValues.get(variable);
+ if (value != null) {
+ // Replace {variable} with its corresponding value in the formula
+ expression = expression.replace("{" + variable + "}", String.valueOf(value));
+ }
+ }
+
+ // Step 4: Evaluate the mathematical expression
+ return Utils.evaluateExpression(expression);
+ }
}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
index 0ffa0b42..acb098ef 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
@@ -20,6 +20,7 @@ import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.util.Validator;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
+import net.gepafin.tendermanagement.web.rest.api.errors.ForbiddenAccessException;
import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
@@ -597,5 +598,58 @@ public class UserDao {
return userResponseBeans;
}
+ public UserResponseBean updateUserDetails(HttpServletRequest request , Long userId, UpdateUserReqForBeneficiary userReq){
+ log.info("Updating user by beneficiary with ID: {}", userId);
+ UserEntity userEntity = validator.validateUserId(request, userId);
+
+ UserEntity oldUserEntity = Utils.getClonedEntityForData(userEntity);
+ log.info("Current user details: {}", userEntity);
+ log.info("New user details: {}", userReq);
+
+ HubEntity hubEntity = hubService.valdateHub(userEntity.getHub().getId());
+ String beneficiaryRoleType = RoleStatusEnum.ROLE_BENEFICIARY.getValue();
+
+ if (validator.checkIsBeneficiary()) {
+ // Validate if the new email already exists for another beneficiary in the same hub
+ boolean emailExistsForBeneficiary = userRepository.existsByEmailIgnoreCaseForBeneficiaries(
+ userReq.getEmail(), hubEntity.getUniqueUuid(), beneficiaryRoleType);
+
+ if (emailExistsForBeneficiary) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS));
+ }
+
+ setIfUpdated(userEntity::getEmail,userEntity::setEmail,userReq.getEmail()); // Only update email if role is beneficiary
+ }
+
+ BeneficiaryEntity oldBeneficiaryEntity = null;
+
+ if(userEntity.getBeneficiary()!=null) {
+ oldBeneficiaryEntity = Utils.getClonedEntityForData(userEntity.getBeneficiary());
+ setIfUpdated(userEntity.getBeneficiary()::getFirstName, userEntity.getBeneficiary()::setFirstName, userReq.getFirstName());
+ setIfUpdated(userEntity.getBeneficiary()::getLastName, userEntity.getBeneficiary()::setLastName, userReq.getLastName());
+ setIfUpdated(userEntity.getBeneficiary()::getOrganization, userEntity.getBeneficiary()::setOrganization, userReq.getOrganization());
+ setIfUpdated(userEntity.getBeneficiary()::getAddress, userEntity.getBeneficiary()::setAddress, userReq.getAddress());
+ setIfUpdated(userEntity.getBeneficiary()::getPhoneNumber, userEntity.getBeneficiary()::setPhoneNumber, userReq.getPhoneNumber());
+ setIfUpdated(userEntity.getBeneficiary()::getDateOfBirth, userEntity.getBeneficiary()::setDateOfBirth, userReq.getDateOfBirth());
+ setIfUpdated(userEntity.getBeneficiary()::getCity, userEntity.getBeneficiary()::setCity, userReq.getCity());
+ setIfUpdated(userEntity.getBeneficiary()::getCountry, userEntity.getBeneficiary()::setCountry, userReq.getCountry());
+
+ /** This code is responsible for adding a version history log for the "Update beneficiary details " operation **/
+ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(oldBeneficiaryEntity).newData(userEntity.getBeneficiary()).build());
+ }
+
+ userEntity = userRepository.save(userEntity);
+
+ /** This code is responsible for adding a version history log for the "Update user details by beneficiary" operation **/
+ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(oldUserEntity).newData(userEntity).build());
+
+ return convertUserEntityToUserResponse(userEntity);
+ }
+
+
+
+
+
}
diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReqForBeneficiary.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReqForBeneficiary.java
new file mode 100644
index 00000000..3516db8f
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateUserReqForBeneficiary.java
@@ -0,0 +1,18 @@
+package net.gepafin.tendermanagement.model.request;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class UpdateUserReqForBeneficiary {
+ private String firstName;
+ private String lastName;
+ private String email;
+ private String phoneNumber;
+ private String organization;
+ private String address;
+ private String city;
+ private String country;
+ private LocalDateTime dateOfBirth;
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java
index 6a92a667..d13d8dff 100644
--- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java
+++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java
@@ -47,4 +47,6 @@ public interface UserService {
public UserEntity getUserEntityById(Long userId);
List getAllUsers(HttpServletRequest request, List roleIds);
+ UserResponseBean updateUserDetails(HttpServletRequest request, Long userId, UpdateUserReqForBeneficiary userReq);
+
}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
index b959ba61..320cb616 100644
--- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
+++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
@@ -130,4 +130,10 @@ public class UserServiceImpl implements UserService {
UserEntity user=validator.validateUser(request);
return userDao.getAllUsers(user, roleIds);
}
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public UserResponseBean updateUserDetails(HttpServletRequest request, Long userId, UpdateUserReqForBeneficiary userReq) {
+ return userDao.updateUserDetails(request , userId, userReq);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java
index ffcdfcac..951a6b3a 100644
--- a/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java
+++ b/src/main/java/net/gepafin/tendermanagement/util/FieldValidator.java
@@ -2,6 +2,10 @@ package net.gepafin.tendermanagement.util;
import java.text.MessageFormat;
import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -9,12 +13,18 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.dao.FormDao;
import net.gepafin.tendermanagement.dao.VatCheckDao;
+import net.gepafin.tendermanagement.entities.ApplicationFormEntity;
+import net.gepafin.tendermanagement.entities.ApplicationFormFieldEntity;
+import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.ContentRequestBean;
import net.gepafin.tendermanagement.model.response.ContentResponseBean;
import net.gepafin.tendermanagement.model.response.SettingResponseBean;
+import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository;
+import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import net.gepafin.tendermanagement.web.rest.api.errors.ValidationException;
import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
@@ -272,5 +282,17 @@ public class FieldValidator {
// Now contentRequestBean is populated with the data from the JSON
return contentRequestBean;
}
-
+ public FieldValidator formulaValidation(Object fieldValue, double finalValue, String label) {
+ if (fieldValue != null) {
+ try {
+ double fieldValueAsDouble = Double.parseDouble(fieldValue.toString()); // Convert fieldValue to double
+ if (Double.compare(finalValue, fieldValueAsDouble) != 0) { // Compare doubles safely
+ errors.add(MessageFormat.format(Translator.toLocale(GepafinConstant.FORMULA_AMOUNT_NOT_MATCHED), label));
+ }
+ } catch (NumberFormatException e) {
+ throw new CustomValidationException(Status.BAD_REQUEST, "Invalid field value: " + fieldValue);
+ }
+ }
+ return this;
+ }
}
diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java
index 0be87340..f444d69d 100644
--- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java
+++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java
@@ -11,6 +11,7 @@ import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -27,6 +28,8 @@ import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.model.request.GlobalFilters;
+import net.objecthunter.exp4j.Expression;
+import net.objecthunter.exp4j.ExpressionBuilder;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,6 +57,9 @@ import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
import static org.apache.commons.lang3.StringUtils.isEmpty;
@@ -753,6 +759,25 @@ public class Utils {
private static Map defaultErrorResponse() {
return Collections.singletonMap("message", Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
}
+ public static List extractValues(String input) {
+ List extractedValues = new ArrayList<>();
+ Pattern pattern = Pattern.compile("\\{(.*?)\\}"); // Regex to match {value}
+ Matcher matcher = pattern.matcher(input);
+
+ while (matcher.find()) {
+ extractedValues.add(matcher.group(1)); // Extract value inside {}
+ }
+ return extractedValues;
+ }
+ public static double evaluateExpression(String expression) {
+ try {
+ Expression exp = new ExpressionBuilder(expression).build();
+ return exp.evaluate();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return Double.NaN; // Return NaN if the expression is invalid
+ }
+ }
public static boolean isNumeric(String input) {
if (input == null || input.trim().isEmpty()) {
return false;
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
index 6dc45bec..b5517cd6 100644
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
@@ -47,7 +47,7 @@ public interface UserApi {
return new ResponseEntity>(HttpStatus.NOT_IMPLEMENTED);
}
- @Operation(summary = "Api to update user",
+ @Operation(summary = "Api to update user (Only for super admin)",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@@ -243,6 +243,24 @@ public interface UserApi {
@RequestMapping("favicon.ico")
@ResponseBody
void returnNoFavicon();
+
+ @Operation(summary = "Api to update user",
+ responses = {
+ @ApiResponse(responseCode = "200", description = "OK"),
+ @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE)})),
+ @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
+ @RequestMapping(value = "/{userId}/update-details",
+ produces = {"application/json"},
+ method = RequestMethod.PUT)
+ default ResponseEntity> updateUserDetails(HttpServletRequest request,
+ @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId,
+ @Parameter(description = "User request object", required = true) @Valid @RequestBody UpdateUserReqForBeneficiary userReq) {
+ return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+ }
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
index 0d649943..35088a3b 100644
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
@@ -247,5 +247,21 @@ public class UserApiController implements UserApi {
public void returnNoFavicon() {
// Do nothing
}
-
+
+ @Override
+ public ResponseEntity> updateUserDetails(HttpServletRequest request,
+ @PathVariable("userId") Long userId,
+ @Valid @RequestBody UpdateUserReqForBeneficiary userReq) {
+ log.info("Update User for Beneficiary- User ID: {}, Request Body: {}", userId, userReq);
+
+ /** This code is responsible for "Updating user details by beneficiary" operation. **/
+ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE)
+ .actionContext(UserActionContextEnum.UPDATE_USER_DETAILS).build());
+
+ UserResponseBean updatedUser = userService.updateUserDetails(request, userId, userReq);
+
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(new Response<>(updatedUser, Status.SUCCESS, Translator.toLocale(GepafinConstant.USER_UPDATED_SUCCESS_MSG)));
+ }
+
}
\ No newline at end of file
diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml
index 2b7fbb71..8b6833b4 100644
--- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml
+++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml
@@ -2386,4 +2386,11 @@
+
+
+
+
+
+
diff --git a/src/main/resources/db/dump/update_form_field_data_06-02-2025.sql b/src/main/resources/db/dump/update_form_field_data_06-02-2025.sql
new file mode 100644
index 00000000..970f442b
--- /dev/null
+++ b/src/main/resources/db/dump/update_form_field_data_06-02-2025.sql
@@ -0,0 +1,14 @@
+
+INSERT INTO FORM_FIELD (ID, SORT_ORDER, NAME, LABEL, DESCRIPTION, SETTINGS, VALIDATORS, CREATED_DATE, UPDATED_DATE)
+VALUES
+(
+ 22,
+ 22,
+ 'switch',
+ 'Casella di spunta "Checklist"',
+ 'Per selezioni binarie, accettazioni, conferme',
+ '[{"name":"label","value":"Casella di Spunta"},{"name":"isChecklistItem","value":true}]',
+ '{"isRequired":false}',
+ CURRENT_TIMESTAMP,
+ CURRENT_TIMESTAMP
+);
\ No newline at end of file
diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties
index ef54674d..901ab8a6 100644
--- a/src/main/resources/message_en.properties
+++ b/src/main/resources/message_en.properties
@@ -368,5 +368,6 @@ either.applicationId.or.assignedApplicationId.must.be.provided=Either applicatio
assigned.application.status.updated.successfully=Assigned application status updated successfully.
validation.required.requested.amount=The Requested Amount configuration should be mandatory.
+formula.amount.not.matches.requested.amount= The {0} does not matches to calculated amount.
diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties
index e14120cd..5f2ca8b0 100644
--- a/src/main/resources/message_it.properties
+++ b/src/main/resources/message_it.properties
@@ -359,6 +359,5 @@ either.applicationId.or.assignedApplicationId.must.be.provided = "� necessario
assigned.application.status.updated.successfully=Stato dell'applicazione assegnata aggiornato con successo.
validation.required.requested.amount=La configurazione dell'importo richiesto � obbligatoria.
-
-
+formula.amount.not.matches.requested.amount=Il {0} non corrisponde all'importo calcolato.