diff --git a/Dockerfile b/Dockerfile
index ceacf16e..18ed6c1a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,5 @@
FROM amazoncorretto:17.0.8-alpine3.17
+ENV TZ="Europe/Rome"
EXPOSE 8080
ADD /target/tendermanagement-0.0.1-SNAPSHOT.jar tendermanagement-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar","tendermanagement-0.0.1-SNAPSHOT.jar"]
diff --git a/Jenkinsfile b/Jenkinsfile
index 968d3a2b..d488b39e 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -56,7 +56,7 @@ pipeline {
}
}
script {
- sh 'ssh ubuntu@46.105.65.89 "sh gepafin-production-api.sh"'
+ sh 'ssh ubuntu@79.137.88.15 "sh gepafin-production-api.sh"'
}
}
}
diff --git a/pom.xml b/pom.xml
index a2a1e712..b443ec18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,7 +94,7 @@
commons-io
commons-io
- 2.11.0
+ 2.17.0
@@ -173,12 +173,51 @@
4.1.3
+
+ org.apache.poi
+ poi-ooxml
+ 5.3.0
+
+
+
+ com.mailgun
+ mailgun-java
+ 1.0.2
+
+
org.apache.santuario
xmlsec
2.3.0
+
+ com.itextpdf
+ itextpdf
+ 5.5.13.3
+
+
+
+
+ com.itextpdf
+ itext7-core
+ 8.0.5
+ pom
+
+
+
+
+ com.itextpdf
+ layout
+ 8.0.5
+
+
+
+ io.springfox
+ springfox-boot-starter
+ 3.0.0
+
+
diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java
new file mode 100644
index 00000000..c66e26f1
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/config/SamlConfig.java
@@ -0,0 +1,203 @@
+package net.gepafin.tendermanagement.config;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.time.Instant;
+import java.util.UUID;
+
+import org.bouncycastle.util.io.pem.PemReader;
+import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
+import org.opensaml.saml.common.SAMLVersion;
+import org.opensaml.saml.common.xml.SAMLConstants;
+import org.opensaml.saml.saml2.core.AuthnContextClassRef;
+import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
+import org.opensaml.saml.saml2.core.AuthnRequest;
+import org.opensaml.saml.saml2.core.RequestedAuthnContext;
+import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder;
+import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
+import org.opensaml.xmlsec.signature.Signature;
+import org.opensaml.xmlsec.signature.support.SignatureConstants;
+import org.opensaml.xmlsec.signature.support.Signer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.saml2.core.Saml2X509Credential;
+import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
+import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
+import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
+import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
+import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
+import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
+
+@Configuration
+public class SamlConfig {
+
+ private final Logger logger = LoggerFactory.getLogger(SamlConfig.class);
+
+ @Value("${base-url}")
+ String baseUrl;
+
+ @Value("${spid.ipd.base.url}")
+ String ipdBaseUrl;
+
+ @Value("${active.profile.folder}")
+ String activeProfileFolder;
+
+ @Bean
+ public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
+
+ String entityId = baseUrl + "/v1/saml/gw/metadata";
+ String acsUrl = baseUrl + "/login/saml2/sso/loginumbria";
+
+ RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria")
+ .entityId(entityId)
+ .signingX509Credentials(credentials -> {
+ try {
+ credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ })
+ .assertionConsumerServiceLocation(acsUrl)
+ .assertingPartyDetails(details -> details.entityId(ipdBaseUrl + "/gw/metadata")
+ .singleSignOnServiceLocation(ipdBaseUrl + "/gw/SSOProxy/SAML2")
+ .singleSignOnServiceBinding(Saml2MessageBinding.POST)
+ .wantAuthnRequestsSigned(true)
+ .verificationX509Credentials(credentials -> {
+ try {
+ // Load the IDP's public certificate for verifying the SAML response signature
+ credentials.add(Saml2X509Credential.verification(readIdpCertificate()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ })
+ )
+ .build();
+
+ return new InMemoryRelyingPartyRegistrationRepository(registration);
+ }
+
+ public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception {
+ AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory()
+ .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME)
+ .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME);
+
+ authnRequest.setID("_" + UUID.randomUUID().toString());
+ authnRequest.setVersion(SAMLVersion.VERSION_20);
+ // authnRequest.setIssueInstant(new DateTime());
+ authnRequest.setIssueInstant(Instant.now());
+
+
+ // Sign the AuthnRequest
+ // BasicCredential signingCredential = new BasicCredential(certificate, privateKey);
+ BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey);
+
+ Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory()
+ .getBuilder(Signature.DEFAULT_ELEMENT_NAME)
+ .buildObject(Signature.DEFAULT_ELEMENT_NAME);
+
+ signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signature.setSigningCredential(signingCredential);
+ signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1
+
+ authnRequest.setSignature(signature);
+ DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration();
+
+ // Marshall and sign the object
+ XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest);
+ Signer.signObject(signature);
+
+ return authnRequest;
+ }
+
+@Bean
+public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
+ RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
+ OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver);
+
+ authenticationRequestResolver.setAuthnRequestCustomizer((context) -> {
+ // Set the required attributes
+ AuthnRequest authnRequest = context.getAuthnRequest();
+ authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID
+ authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0
+ authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST
+
+ // Set Authentication Context
+ authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext());
+
+ // Log the SAML AuthnRequest after setting context
+ String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest);
+ logger.info("SAML AuthnRequest after setting context: " + samlRequest);
+ });
+
+ return authenticationRequestResolver;
+}
+
+private RequestedAuthnContext buildRequestedAuthnContext() {
+ AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
+ AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject(
+ SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX
+ );
+ // Set the SPID Level 2 authentication context
+ authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword");
+
+ RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder();
+ RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject();
+ requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
+ requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);
+
+ return requestedAuthnContext;
+}
+
+ public PrivateKey readPrivateKey() throws Exception {
+ // Path to your private key PEM file
+ try (PemReader pemReader = new PemReader(new InputStreamReader(readKey(activeProfileFolder + "/saml/private-key.pem")))) {
+ // Read the PEM content
+ byte[] pemContent = pemReader.readPemObject().getContent();
+ // Decode the PEM content
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent);
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA algorithm
+ // Generate and return the PrivateKey
+ return keyFactory.generatePrivate(keySpec);
+ }
+ }
+ public X509Certificate readCertificate() throws Exception {
+ // Path to your certificate PEM fileFile
+ try (InputStream inStream = readKey(activeProfileFolder + "/saml/public-cert.pem")) {
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ return (X509Certificate) certFactory.generateCertificate(inStream);
+ }
+ }
+
+ public X509Certificate readIdpCertificate() throws Exception {
+ // Path to your IDP public certificate PEM file
+ try (InputStream inStream = readKey(activeProfileFolder + "/saml/idp-certificate.pem")) {
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ return (X509Certificate) certFactory.generateCertificate(inStream);
+ }
+ }
+
+
+ public InputStream readKey(String path) throws IOException {
+ ClassLoader classLoader = getClass().getClassLoader();
+ InputStream inputStream = classLoader.getResourceAsStream(path);
+
+ if (inputStream == null) {
+ throw new FileNotFoundException("file not found : "+path);
+ }
+ return inputStream;
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java
new file mode 100644
index 00000000..171b7e12
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/config/SamlFailureHandler.java
@@ -0,0 +1,35 @@
+package net.gepafin.tendermanagement.config;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.AuthenticationFailureHandler;
+import org.springframework.stereotype.Component;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+@Component
+public class SamlFailureHandler implements AuthenticationFailureHandler {
+
+ private final Logger logger = LoggerFactory.getLogger(SamlFailureHandler.class);
+
+ @Value("${fe.base.url}")
+ private String feBaseUrl;
+
+ @Override
+ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException exception) throws IOException {
+ try {
+ logger.error("SAML login failed: " + exception.getMessage());
+
+ response.sendRedirect(feBaseUrl + "/login");
+ } catch (Exception e) {
+ logger.error("Error processing SAML failure handler", e);
+ }
+ }
+
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java
new file mode 100644
index 00000000..868b0eae
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java
@@ -0,0 +1,98 @@
+package net.gepafin.tendermanagement.config;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
+import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.gepafin.tendermanagement.constants.GepafinConstant;
+import net.gepafin.tendermanagement.entities.SamlResponseEntity;
+import net.gepafin.tendermanagement.entities.UserEntity;
+import net.gepafin.tendermanagement.repositories.SamlResponseRepository;
+import net.gepafin.tendermanagement.repositories.UserRepository;
+import net.gepafin.tendermanagement.util.Utils;
+import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
+import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+
+@Component
+public class SamlSuccessHandler implements AuthenticationSuccessHandler {
+
+ private final Logger logger = LoggerFactory.getLogger(SamlSuccessHandler.class);
+
+ @Autowired
+ private SamlResponseRepository samlResponseLogRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Value("${fe.base.url}")
+ private String feBaseUrl;
+
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
+ Authentication authentication) throws IOException {
+ try {
+ logger.info("SAML login in Authentication Success Handler");
+ Saml2Authentication samlAuth = (Saml2Authentication) authentication;
+ Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal();
+
+ Map> userAttributes = principal.getAttributes();
+ String token = Utils.generateSecureToken();
+ logger.info("SAML User Attributes: " + userAttributes);
+
+ SamlResponseEntity samlResponseLogEntity = new SamlResponseEntity();
+ samlResponseLogEntity.setAuthenticationObject(authentication.toString());
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ String userAttributesJson = objectMapper.writeValueAsString(userAttributes);
+ samlResponseLogEntity.setAuthenticationObject(userAttributesJson);
+ samlResponseLogEntity.setToken(token);
+ samlResponseLogRepository.save(samlResponseLogEntity);
+
+ String redirectUrl = feBaseUrl;
+
+ logger.info("SAML login successful for user: " + principal.getName());
+ String cf = userAttributes.get("CodiceFiscale").get(0).toString();
+ UserEntity userEntity = userRepository.findByBeneficiaryCodiceFiscale(cf).orElse(null);
+ if (userEntity == null) {
+ redirectUrl += "/registration?temp_token=" + token;
+ } else {
+ redirectUrl += "/login?temp_token=" + token;
+ }
+ response.sendRedirect(redirectUrl);
+ logger.info("SAML redirect Url: " + redirectUrl);
+ } catch (Exception e) {
+ logger.error("Error processing SAML success handler", e);
+ }
+ }
+
+ public void validateToken(String token, String codiceFiscale) {
+ SamlResponseEntity samlResponseLogEntity = samlResponseLogRepository.findByToken(token);
+ if (samlResponseLogEntity == null) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG));
+ }
+ Map> userAttributes = Utils
+ .convertStringIntoMap(samlResponseLogEntity.getAuthenticationObject());
+ String cf = userAttributes.get("CodiceFiscale").get(0).toString();
+ if (codiceFiscale == null || Boolean.FALSE.equals(codiceFiscale.equals(cf))) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.INVALID_TOKEN_MSG));
+ }
+ samlResponseLogRepository.delete(samlResponseLogEntity);
+ }
+
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java
index c83cc513..89182902 100644
--- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java
+++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java
@@ -1,39 +1,5 @@
package net.gepafin.tendermanagement.config;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.security.KeyFactory;
-import java.security.PrivateKey;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.time.Instant;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.xml.security.Init;
-import org.bouncycastle.util.io.pem.PemReader;
-import org.opensaml.core.config.InitializationService;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.common.SAMLVersion;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.saml2.core.AuthnContextClassRef;
-import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
-import org.opensaml.saml.saml2.core.AuthnRequest;
-import org.opensaml.saml.saml2.core.RequestedAuthnContext;
-import org.opensaml.saml.saml2.core.impl.AuthnContextClassRefBuilder;
-import org.opensaml.saml.saml2.core.impl.RequestedAuthnContextBuilder;
-import org.opensaml.security.x509.BasicX509Credential;
-import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
-import org.opensaml.xmlsec.signature.Signature;
-import org.opensaml.xmlsec.signature.support.SignatureConstants;
-import org.opensaml.xmlsec.signature.support.Signer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@@ -49,17 +15,6 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
@@ -69,63 +24,34 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
-import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletResponse;
import net.gepafin.tendermanagement.config.jwt.JWTFilter;
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
-import net.gepafin.tendermanagement.entities.SamlResponseLogEntity;
-import net.gepafin.tendermanagement.repositories.SamlResponseLogRepository;
-//import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
-//import org.springframework.security.saml2.core.Saml2AuthenticationRequest;
+
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
- private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
private final TokenProvider tokenProvider;
+ private final SamlSuccessHandler samlSuccessHandler;
+ private final SamlFailureHandler samlFailureHandler;
@Value("${base-url}")
String baseUrl;
@Autowired
- private SamlResponseLogRepository samlResponseLogRepository;
-
- @Autowired
- public SecurityConfig(TokenProvider tokenProvider) {
+ public SecurityConfig(TokenProvider tokenProvider, SamlSuccessHandler samlSuccessHandler, SamlFailureHandler samlFailureHandler) {
this.tokenProvider = tokenProvider;
+ this.samlSuccessHandler =samlSuccessHandler;
+ this.samlFailureHandler=samlFailureHandler;
}
-
- @PostConstruct
- public void initXmlSecurity() throws Exception {
- // Initialize Apache XML Security (Santuario)
- Init.init();
- }
-
-
- @PostConstruct
- public void initOpenSAML() throws Exception {
- InitializationService.initialize();
- }
-
-//
-// @Bean
-// public Saml2AuthenticationRequestResolver authenticationRequestResolver() {
-// return (Saml2AuthenticationRequestContext context) -> {
-// Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(context)
-// .authenticationContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword") // Add context here
-// .build();
-// return request;
-// };
-// }
-
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
@@ -173,12 +99,23 @@ public class SecurityConfig {
http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth
// Allow public access to the login endpoints
.requestMatchers("/v1/user/login").permitAll() // JWT-based login
+ .requestMatchers("/v1/user").permitAll() // User registration
+ .requestMatchers("/v1/user/sso/validate/existing-user/{token}").permitAll()
+ .requestMatchers("/v1/user/sso/validate/new-user/{token}").permitAll()
.requestMatchers("/v1/saml/**").permitAll() // JWT-based login
.requestMatchers("/saml2/**").permitAll() // SAML login initiation
.requestMatchers("/swagger-ui/**").permitAll() // Swagger docs
.requestMatchers("/v1/api-docs/**").permitAll() // API docs
+ .requestMatchers("/v1/user/reset-password/initiate").permitAll()
+ .requestMatchers("/v1/user/reset-password").permitAll()
.anyRequest().authenticated())
- .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
+ .exceptionHandling(exceptionHandling -> exceptionHandling
+ .authenticationEntryPoint((request, response, authException) -> {
+ // Send 403 Forbidden when there is no JWT token provided
+ response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: Authentication token is missing or invalid");
+ })
+ )
.addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class)
// Add SAML2 login configuration (for BENEFICIARI)
@@ -186,55 +123,8 @@ public class SecurityConfig {
* .saml2Login(saml -> saml.loginPage("/saml/login") // Entry point for SAML
* login .defaultSuccessUrl("/") // Redirect after successful SAML login );
*/
- .saml2Login(saml ->
- saml.defaultSuccessUrl("/")
- .successHandler((request, response, authentication) -> {
- try {
- // Cast the authentication object to Saml2Authentication
- Saml2Authentication samlAuth = (Saml2Authentication) authentication;
- Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal();
-
- // Extract the user attributes from the principal
- Map> userAttributes = principal.getAttributes();
-
- // Log the user attributes for debugging purposes
- logger.info("SAML User Attributes: " + userAttributes);
-
- // Save the authentication details in the database (Optional)
- SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity();
- samlResponseLogEntity.setAuthenticationObject(authentication.toString());
-
- // Convert user attributes to JSON and save in DB
- ObjectMapper objectMapper = new ObjectMapper();
- String userAttributesJson = objectMapper.writeValueAsString(userAttributes);
- samlResponseLogEntity.setAuthenticationObject(userAttributesJson);
- samlResponseLogRepository.save(samlResponseLogEntity);
-
- // Successful login logic
- logger.info("SAML login successful for user: " + principal.getName());
- response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login");
- } catch (Exception e) {
- logger.error("Error processing SAML success handler", e);
- }
- })
- .failureHandler((request, response, exception) -> {
- try {
- logger.error("SAML login failed: " + exception.getMessage());
-
- // Log the failure details to the database (Optional)
- SamlResponseLogEntity samlResponseLogEntity = new SamlResponseLogEntity();
- samlResponseLogEntity.setRequest(request.toString());
- samlResponseLogEntity.setResponse(response.toString());
- samlResponseLogEntity.setExceptionObject(exception.toString());
- samlResponseLogRepository.save(samlResponseLogEntity);
-
- // Handle failure redirection
- response.sendRedirect("http://gepafin-staging-fe.s3-website.eu-central-1.amazonaws.com/login");
- } catch (Exception e) {
- logger.error("Error processing SAML failure handler", e);
- }
- })
- );
+ .saml2Login(saml -> saml.defaultSuccessUrl("/").successHandler(samlSuccessHandler)
+ .failureHandler(samlFailureHandler));
return http.build();
@@ -250,148 +140,5 @@ public class SecurityConfig {
.scheme("bearer").bearerFormat("JWT")));
}
- @Bean
- public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
-
- String entityId = baseUrl + "/v1/saml/gw/metadata";
- String acsUrl = baseUrl + "/login/saml2/sso/loginumbria";
-
- RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("loginumbria")
- .entityId(entityId)
- .signingX509Credentials(credentials -> {
- try {
- credentials.add(Saml2X509Credential.signing(readPrivateKey(), readCertificate()));
- } catch (Exception e) {
- e.printStackTrace();
- }
- })
- .assertionConsumerServiceLocation(acsUrl)
- .assertingPartyDetails(details -> details.entityId("https://federatest.umbriadigitale.it/gw/metadata")
- .singleSignOnServiceLocation("https://federatest.umbriadigitale.it/gw/SSOProxy/SAML2")
- .singleSignOnServiceBinding(Saml2MessageBinding.POST)
- .wantAuthnRequestsSigned(true)
- .verificationX509Credentials(credentials -> {
- try {
- // Load the IDP's public certificate for verifying the SAML response signature
- credentials.add(Saml2X509Credential.verification(readIdpCertificate()));
- } catch (Exception e) {
- e.printStackTrace();
- }
- })
- )
- .build();
-
- return new InMemoryRelyingPartyRegistrationRepository(registration);
- }
-
- public AuthnRequest createSignedAuthnRequest(PrivateKey privateKey, X509Certificate certificate) throws Exception {
- AuthnRequest authnRequest = (AuthnRequest) XMLObjectProviderRegistrySupport.getBuilderFactory()
- .getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME)
- .buildObject(AuthnRequest.DEFAULT_ELEMENT_NAME);
-
- authnRequest.setID("_" + UUID.randomUUID().toString());
- authnRequest.setVersion(SAMLVersion.VERSION_20);
- // authnRequest.setIssueInstant(new DateTime());
- authnRequest.setIssueInstant(Instant.now());
-
-
- // Sign the AuthnRequest
- // BasicCredential signingCredential = new BasicCredential(certificate, privateKey);
- BasicX509Credential signingCredential = new BasicX509Credential(certificate, privateKey);
-
- Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory()
- .getBuilder(Signature.DEFAULT_ELEMENT_NAME)
- .buildObject(Signature.DEFAULT_ELEMENT_NAME);
-
- signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
- signature.setSigningCredential(signingCredential);
- signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); // Set RSA-SHA1
-
- authnRequest.setSignature(signature);
- DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration();
-
- // Marshall and sign the object
- XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(authnRequest).marshall(authnRequest);
- Signer.signObject(signature);
-
- return authnRequest;
- }
-
-@Bean
-public Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) {
- RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
- OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver);
-
- authenticationRequestResolver.setAuthnRequestCustomizer((context) -> {
- // Set the required attributes
- AuthnRequest authnRequest = context.getAuthnRequest();
- authnRequest.setID("_" + UUID.randomUUID().toString()); // Add a unique ID
- authnRequest.setVersion(SAMLVersion.VERSION_20); // Ensure version is 2.0
- authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); // HTTP-POST
-
- // Set Authentication Context
- authnRequest.setRequestedAuthnContext(buildRequestedAuthnContext());
-
- // Log the SAML AuthnRequest after setting context
- String samlRequest = SamlRequestLogger.convertSAMLObjectToString(authnRequest);
- logger.info("SAML AuthnRequest after setting context: " + samlRequest);
- });
-
- return authenticationRequestResolver;
-}
-
-private RequestedAuthnContext buildRequestedAuthnContext() {
- AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
- AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject(
- SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX
- );
- // Set the SPID Level 2 authentication context
- authnContextClassRef.setURI("urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword");
-
- RequestedAuthnContextBuilder requestedAuthnContextBuilder = new RequestedAuthnContextBuilder();
- RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject();
- requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
- requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);
-
- return requestedAuthnContext;
-}
-
- public PrivateKey readPrivateKey() throws Exception {
- // Path to your private key PEM file
- try (PemReader pemReader = new PemReader(new InputStreamReader(readKey("dev/saml/private-key.pem")))) {
- // Read the PEM content
- byte[] pemContent = pemReader.readPemObject().getContent();
- // Decode the PEM content
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemContent);
- KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA algorithm
- // Generate and return the PrivateKey
- return keyFactory.generatePrivate(keySpec);
- }
- }
- public X509Certificate readCertificate() throws Exception {
- // Path to your certificate PEM fileFile
- try (InputStream inStream = readKey("dev/saml/public-cert.pem")) {
- CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- return (X509Certificate) certFactory.generateCertificate(inStream);
- }
- }
-
- public X509Certificate readIdpCertificate() throws Exception {
- // Path to your IDP public certificate PEM file
- try (InputStream inStream = readKey("dev/saml/idp-certificate.pem")) {
- CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
- return (X509Certificate) certFactory.generateCertificate(inStream);
- }
- }
-
-
- public InputStream readKey(String path) throws IOException {
- ClassLoader classLoader = getClass().getClassLoader();
- InputStream inputStream = classLoader.getResourceAsStream(path);
-
- if (inputStream == null) {
- throw new FileNotFoundException("file not found : "+path);
- }
- return inputStream;
- }
+
}
\ No newline at end of file
diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java
index 15c51b7a..884c848f 100644
--- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java
+++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java
@@ -82,10 +82,11 @@ public class TokenProvider {
log.info("JWT Secret Key initialized.");
}
- public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) {
- String authorities = authentication.getAuthorities().stream()
- .map(GrantedAuthority::getAuthority)
- .collect(Collectors.joining(","));
+ public String createToken(Boolean rememberMe, UserEntity user) {
+// String authorities = authentication.getAuthorities().stream()
+// .map(GrantedAuthority::getAuthority)
+// .collect(Collectors.joining(","));
+ String authorities = user.getRoleEntity().getRoleType();
Long now;
Date validity;
@@ -99,10 +100,14 @@ public class TokenProvider {
log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds);
}
- String payload = authentication.getName();
+ String payload = user.getEmail();
if(user != null) {
payload += ":"+user.getId();
}
+
+ if(user != null) {
+ payload += ":"+user.getHub().getId();
+ }
String token = Jwts.builder()
.setSubject(payload)
diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
index 4a7560e5..b60fc36a 100644
--- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
+++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
@@ -24,7 +24,7 @@ public class GepafinConstant {
public static final String GET_REGION_SUCCESS_MSG = "get.region.success";
public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success";
public static final String REGION_NOT_FOUND_MSG = "user.region.not.found";
- public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match";
+ public static final String PASSWORD_DOESNT_MATCH = "password.doesnt.match";
public static final String USER_NOT_EXIST_MSG = "user.not.exist";
public static final String REGION_NOT_FOUND = "region.not.found";
public static final String USER_ID_NOT_NULL_MSG = "user.id.not.null";
@@ -36,13 +36,13 @@ public class GepafinConstant {
public static final String LOOK_UP_DATA_NOT_VALID_MSG = "look.up.data.not.valid";
public static final String FILES_UPLOADED_MSG = "files.uploaded";
public static final String CALL_CREATED_SUCCESSFULLY_MSG = "call.created.successfully";
- public static final String FILE_DELETED_SUCCESSFULLY_MSG="file.deleted.successfully";
- public static final String DOCUMENT_NOT_FOUND="document.not.found";
- public static final String LOGIN_SUCCESS_MSG="login.successfully";
- public static final String PASSWORD_MIN_LEN ="pass.min.len.msg";
+ public static final String FILE_DELETED_SUCCESSFULLY_MSG = "file.deleted.successfully";
+ public static final String DOCUMENT_NOT_FOUND = "document.not.found";
+ public static final String LOGIN_SUCCESS_MSG = "login.successfully";
+ public static final String PASSWORD_MIN_LEN = "pass.min.len.msg";
public static final String EMAIL_ALREADY_EXISTS = "email.already.exists";
- public static final String DOCUMENT_ID_NOT_FOUND="document.id.not.found";
- public static final String INVALID_DATE_MSG = "call.invalid.date";
+ public static final String DOCUMENT_ID_NOT_FOUND = "document.id.not.found";
+ public static final String INVALID_DATE_MSG = "call.invalid.date";
public static final String FORM_NOT_FOUND = "form.not.found";
public static final String FORM_CREATED_SUCCESSFULLY = "form.created.successfully";
public static final String FORM_UPDATED_SUCCESSFULLY = "form.updated.suucessfully";
@@ -61,12 +61,12 @@ public class GepafinConstant {
public static final String FORM_TEMPLATE_DELETED_SUCCESSFULLY = "form.template.deleted.successfully";
public static final String FORM_TEMPLATE_FETCHED_SUCCESSFULLY = "form.template.fetched.successfully";
public static final String REQUIRED_PARAMETER_NOT_FOUND_FOR_FORM_TEMPLATE = "required.parameter.not.found.for.form.template";
- public static final String FORM_NOT_FOUND_FOR_CALL_ID="form.not.found.for.call.id";
- public static final String STEP_1 = "STEP_1";
- public static final String STEP_2 = "STEP_2";
- public static final String VALIDATE_REQUEST = "VALIDATE_REQUEST";
- public static final String CALL_UPDATE_SUCCESSFULLY_MSG = "call.update.successfully";
- public static final String CALL_NOT_FOUND = "call.not.found";
+ public static final String FORM_NOT_FOUND_FOR_CALL_ID = "form.not.found.for.call.id";
+ public static final String STEP_1 = "STEP_1";
+ public static final String STEP_2 = "STEP_2";
+ public static final String VALIDATE_REQUEST = "VALIDATE_REQUEST";
+ public static final String CALL_UPDATE_SUCCESSFULLY_MSG = "call.update.successfully";
+ public static final String CALL_NOT_FOUND = "call.not.found";
public static final String CALL_FETCH_SUCCESS_MSG = "call.fetch.success";
public static final String EVALUATION_CRITERIA_NOT_FOUND = "evaluation.criteria.not.found";
@@ -74,7 +74,7 @@ public class GepafinConstant {
public static final String EVALUATION_CRITERIA_FETCH_SUCCESSFULLY = "evaluation.criteria.fetch.successfully";
public static final String EVALUATION_CRITERIA_UPDATED_SUCCESSFULLY = "evaluation.criteria.updated.successfully";
public static final String EVALUATION_CRITERIA_DELETED_SUCCESSFULLY = "evaluation.criteria.deleted.successfully";
- public static final String SCORE_NOT_NULL_MSG="score.not.null";
+ public static final String SCORE_NOT_NULL_MSG = "score.not.null";
public static final String FAQ_NOT_FOUND = "faq.not.found";
public static final String FAQ_CREATED_SUCCESSFULLY = "faq.created.successfully";
public static final String FAQ_FETCHED_SUCCESSFULLY = "faq.fetched.successfully";
@@ -102,42 +102,41 @@ public class GepafinConstant {
public static final String INVALID_STATUS_CHANGE_FROM_DRAFT = "invalid.status.change.from.draft";
public static final String INVALID_STATUS_CHANGE_FROM_PUBLISH = "invalid.status.change.from.publish";
public static final String STATUS_CANNOT_BE_CHANGED = "status.cannot.be.changed";
- public static final String PUBLISHED_CALL_NOT_UPDATE = "published.call.not.update";
+ public static final String PUBLISHED_CALL_NOT_UPDATE = "published.call.not.update";
public static final String INVALID_USER = "invalid_user";
- public static final String FLOW_CREATED_SUCCESSFULLY="flow.created.successfully";
- public static final String FLOW_FETCHED_SUCCESSFULLY="flow.fetched.successfully";
- public static final String FLOW_ALREADY_EXISTS="flow.already.exists";
- public static final String FLOW_REQUEST_NOT_PROPER="flow.request.not.complete";
+ public static final String FLOW_CREATED_SUCCESSFULLY = "flow.created.successfully";
+ public static final String FLOW_FETCHED_SUCCESSFULLY = "flow.fetched.successfully";
+ public static final String FLOW_ALREADY_EXISTS = "flow.already.exists";
+ public static final String FLOW_REQUEST_NOT_PROPER = "flow.request.not.complete";
public static final String APPLICATION_CREATED_SUCCESS_MSG = "application.created.success";
public static final String APPLICATION_UPDATED_SUCCESS_MSG = "application.updated.success";
public static final String DELETE_APPLICATION_SUCCESS_MSG = "application.deleted.success";
public static final String GET_APPLICATION_SUCCESS_MSG = "application.get.success";
public static final String APPLICATION_NOT_FOUND_MSG = "application.not.found";
- public static final String APPLICATION_FORM_FIELD_NOT_FOUND="application.form.field.not.found";
- public static final String FORM_ID_DOES_NOT_MACTHES="Form.not.matches.to.call.initial.form";
+ public static final String APPLICATION_FORM_FIELD_NOT_FOUND = "application.form.field.not.found";
+ public static final String FORM_ID_DOES_NOT_MACTHES = "Form.not.matches.to.call.initial.form";
public static final String VALIDATION_FIELD_REQUIRED = "validation.field.required";
public static final String VALIDATION_FIELD_MIN_LENGTH = "validation.field.min_length";
public static final String VALIDATION_FIELD_MAX_LENGTH = "validation.field.max_length";
public static final String VALIDATION_FIELD_PATTERN = "validation.field.pattern";
public static final String VALIDATION_FIELD_NOT_NULL = "validation.field.not_null";
public static final String VALIDATION_FIELD_NOT_EMPTY = "validation.field.not_empty";
- public static final String APPLICATION_ALREADY_EXISTS="application.already.exists";
- // public static final String NEXT_FORM_NOT_FOUND = "next.form.not.found";
- // public static final String PREVIOUS_FORM_NOT_FOUND = "previous.form.not.found";
- public static final String CURRENT_FORM_INCOMPLETE = "current.form.incomplete";
+ public static final String APPLICATION_ALREADY_EXISTS = "application.already.exists";
+ // public static final String NEXT_FORM_NOT_FOUND = "next.form.not.found";
+ // public static final String PREVIOUS_FORM_NOT_FOUND = "previous.form.not.found";
+ public static final String CURRENT_FORM_INCOMPLETE = "current.form.incomplete";
public static final String FLOW_NOT_FOUND = "flow.not.found";
- public static final String VALIDATION_MESSAGE = "validation.message";
- public static final String ACTION_REQUIRED = "action.required";
- public static final String CALL_NOT_PUBLISHED="call.not.published";
- public static final String APPLICATION_ALREADY_SUBMITTED="application.already.submitted";
- public static final String INITAL_AND_FINAL_FORM_CANNOT_NULL="initial.and.final.form.cannot.null";
- public static final String APPLICATION_FORM_NOT_FOUND="application.form.not.found";
- public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW="updating.form.value.impact.on.flow";
+ public static final String VALIDATION_MESSAGE = "validation.message";
+ public static final String ACTION_REQUIRED = "action.required";
+ public static final String CALL_NOT_PUBLISHED = "call.not.published";
+ public static final String APPLICATION_ALREADY_SUBMITTED = "application.already.submitted";
+ public static final String INITAL_AND_FINAL_FORM_CANNOT_NULL = "initial.and.final.form.cannot.null";
+ public static final String APPLICATION_FORM_NOT_FOUND = "application.form.not.found";
+ public static final String UPDATING_FORM_VALUE_IMPACT_ON_FLOW = "updating.form.value.impact.on.flow";
public static final String APPLICATION_IS_INCOMPLETE_MSG = "application.is.incomplete";
public static final String AUTHORIZATION = "Authorization";
public static final String CHECK_VATNUMBER_V2_NEW_URL = "https://imprese.openapi.it/advance";
- public static final String VATNUMBER_V2 = "https://imprese.openapi.it/advance";
- public static final String VALIDATION_FIELD_CUSTOM="validation.field.custom";
+ public static final String VALIDATION_FIELD_CUSTOM = "validation.field.custom";
public static final String VALIDATION_CODICE_FISCALE = "validation.codice.fiscale";
public static final String VALIDATION_CAP = "validation.cap";
public static final String VALIDATION_IBAN = "validation.iban";
@@ -146,17 +145,95 @@ public class GepafinConstant {
public static final String VALIDATION_URL = "validation.url";
public static final String VALIDATION_MARCA_DA_BOLLO = "validation.marca.da.bollo";
public static final String VALIDATION_PIVA = "validation.piva";
- public static final String VALIDATION_VALID_PIVA="valid.vat.number";
- public static final String IS_MARCA_DA_BOLLO="isMarcaDaBollo";
- public static final String IS_URL="isUrl";
- public static final String IS_EMAIL_PEC="isEmailPEC";
- public static final String IS_EMAIL="isEmail";
- public static final String IS_IBAN="isIBAN";
- public static final String IS_CAP="isCAP";
- public static final String IS_CODICE_FISCALE="isCodiceFiscale";
- public static final String IS_PIVA="isPIVA";
+ public static final String VALIDATION_VALID_PIVA = "valid.vat.number";
+ public static final String IS_MARCA_DA_BOLLO = "isMarcaDaBollo";
+ public static final String IS_URL = "isUrl";
+ public static final String IS_EMAIL_PEC = "isEmailPEC";
+ public static final String IS_EMAIL = "isEmail";
+ public static final String IS_IBAN = "isIBAN";
+ public static final String IS_CAP = "isCAP";
+ public static final String IS_CODICE_FISCALE = "isCodiceFiscale";
+ public static final String IS_PIVA = "isPIVA";
+ public static final String FAILED_RETAIN_FIELD = "failed.retain.field";
+ public static final String USER_ALREADY_EXIST_MSG = "user.already.exist.msg";
+ public static final String TOKEN_VALIDATE_SUCCESS_MSE = "token.validate.success";
+ public static final String INVALID_REQUEST = "invalid.request";
+ public static final String CODICE_FISCALE_EXISTS = "codice.fiscale.exists";
+ public static final String TOTAL_STEPS_NOT_BE_ZERO = "total.steps.not.zero";
+ public static final String COMPLETED_STEPS_NOT_VALID = "completed.steps.not.valid";
+ public static final String FIELD_ID_NOT_FOUND = "field.id.not.found";
+ public static final String VALIDATE_EMAIL = "validate.email";
+ public static final String ROLE_ID_MANDATORY = "role.id.mandatory";
+ public static final String VALIDATE_PASSWORD = "validate.password";
+
+ public static final String COMPANY_CREATED_SUCCESS_MSG = "company.created.success";
+ public static final String COMPANY_UPDATED_SUCCESS_MSG = "company.updated.success";
+ public static final String COMPANY_DELETE_SUCCESS_MSG = "company.delete.success";
+ public static final String COMPANY_GET_SUCCESS_MSG = "company.get.success";
+ public static final String COMPANY_NOT_FOUND_MSG = "company.not.found";
+ public static final String CHECK_VATNUMBER_SUCCESS_MSG = "check.vatnumber.success";
+ public static final String INVALID_VATNUMBER = "invalid.vatnumber";
+ public static final String VATNUMBER_MANDATORY = "vatnumber.mandatory";
+ public static final String VATNUMBER_ALREADY_EXISTS = "vatnumber.already.exists";
+ public static final String INVALID_EMAIL = "invalid.email";
+ public static final String UNAUTHORIZED = "UNAUTHORIZED";
+ public static final String COMPANY_ID_MANDATORY = "company.id.mandatory";
+ public static final String USER_ALREADY_CONNECTED_TO_COMPANY = "user.already.connected.to.company";
+ public static final String YYYY_MM_DD_DASH = "yyyy-MM-dd";
+ public static final String YYYY_MM_DD_SLASH = "yyyy/MM/dd";
+ public static final String DELEGATION_TEMPLATE = "DELEGATION_TEMPLATE";
+ public static final String VALIDATION_ERROR_MISSING_FIRSTNAME = "validation.error.missing.firstName";
+ public static final String VALIDATION_ERROR_MISSING_LASTNAME = "validation.error.missing.lastName";
+ public static final String VALIDATION_ERROR_MISSING_CODICEFISCALE = "validation.error.missing.codiceFiscale";
+ public static final String DELEGATION_FILE_UPLOAD_SUCCESS = "delegation.file.upload.success";
+ public static final String DELEGATION_FETCH_SUCCESS = "delegation.fetch.success";
+ public static final String DELEGATION_TEMPLATE_GENERATION_ERROR = "delegation.template.generation.error";
+ public static final String VALIDATION_ERROR_FILE_EMPTY = "validation.error.file.empty";
+ public static final String VALIDATION_ERROR_FILE_INVALIDTYPE = "validation.error.file.invalidType";
+ public static final String UPLOAD_ERROR_S3 = "upload.error.s3";
+
+ public static final String CALL_NOT_STARTED_YET = "call.not.started.yet";
+ public static final String CALL_ALREADY_ENDED = "call.already.ended";
+ public static final String APPLICATION_STATUS_UPDATED_SUCCESSFULLY = "application.status.updated.successfully";
+ public static final String APPLICATION_ALREADY_IN_PREVIOUS_STATUS = "application.already.in.provided.status";
+ public static final String DELEGATION_NOT_FOUND = "delegation.not.found";
+ public static final String USER_COMPANY_RELATION_NOT_FOUND = "user.company.relation.not.found";
+ public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success";
+ public static final String HH_MM_SS = "HH:mm:ss";
+
+ public static final String USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION = "user.not.authorized.create.application";
+ public static final String APPLICATION_SUBMITTED_CANNOT_CHANGE = "application.submitted.cannot.change";
+ public static final String CALL_DOCUMENTS_FETCH_SUCCESS_MSG = "call.documents.fetch.success";
+ public static final String CALL_DOCUMENTS_NOT_FOUND_MSG = "call.documents.not.found";
+
+ public static final String BENEFICIARY_PREFERRED_CALL_CREATED_SUCCESS_MSG = "beneficiary.preferred.call.created.success";
+ public static final String GET_BENEFICIARY_PREFERRED_CALL_SUCCESS_MSG = "beneficiary.preferred.call.get.success";
+ public static final String DELETE_BENEFICIARY_PREFERRED_CALL_SUCCESS_MSG = "beneficiary.preferred.call.delete.success";
+ public static final String GET_BENEFICIARY_PREFERRED_CALLS_SUCCESS_MSG = "beneficiary.preferred.calls.get.success";
+ public static final String BENEFICIARY_PREFERRED_CALL_UPDATED_SUCCESS_MSG = "beneficiary.preferred.call.updated.success";
+ public static final String BENEFICIARY_CALL_NOT_FOUND = "beneficiary.preferred.call.not.found";
+ public static final String BENEFICIARY_PREFERRED_CALL_STATUS_UPDATED_SUCCESS_MSG = "beneficiary.preferred.call.status.updated.success";
+ public static final String GET_ALL_BENEFICIARY_PREFERRED_CALLS_SUCCESS_MSG = "beneficiary.preferred.calls.get.all.success";
+ public static final String USER_ID_AND_BENEFICIARY_ID_ERROR = "userId.and.beneficiaryId.error";
+ public static final String EITHER_USER_OR_BENEFICIARY_ID_REQUIRED = "either.user.or.beneficiary.id.required";
+ public static final String USER_NOT_FOUND_WITH_BENEFICIARYID_MSG = "User.not.found.with.the.given.beneficiaryID";
+ public static final String PERMISSION_DENIED = "permission.denied";
+ public static final String SIGNED_DOCUMENT_FILE_UPLOAD_SUCCESS = "signed.document.file.upload.success";
+ public static final String GET_SIGNED_DOCUMENT_FILE_SUCCESS = "get.signed.document.file.success";
+ public static final String APPLICATION_SIGNED_DOCUMENT_NOT_FOUND = "application.signed.document.not.found";
+ public static final String DELETE_SIGNED_DOCUMENT_FILE_SUCCESS = "delete.signed.document.file.success";
+ public static final String DD_MM_YYYY = "dd/MM/yyyy";
+
+ public static final String DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY="dashboard.widget.fetched.successfully";
+ public static final Integer DEFAULT_PAGE_LIMIT = 1000;
+ public static final Integer DEFAULT_PAGE = 1;
+ public static final String ATTEMPT_DATE = "attemptDate";
+ public static final String LOGIN_ATTEMPTED_CREATED_SUCCESSFULLY="login_attempt_successfully_created";
+ public static final String GET_LOGIN_ATTEMPT_MSG="get_login_attempt_se_msg";
+ public static final String CANNOT_DELETE_COMPANY_WITH_APPLICATION_SUBMITT = "application.in.submit.status.cannot.delete.company";
+ public static final String GET_USERS_SUCCESS_MSG = "get.users.success.msg";
+ public static final String CANNOT_CREATE_BENEFICIARY_USER="cannot.create.beneficiary.user";
- public static final String FAILED_RETAIN_FIELD="failed.retain.field";
public static final String HUB_CREATE_SUCCESS = "hub_create_success";
public static final String HUB_UPDATE_SUCCESS = "hub_update_success";
public static final String HUB_GET_SUCCESS = "hub_get_success";
@@ -164,3 +241,4 @@ public class GepafinConstant {
public static final String HUB_DELETE_SUCCESS = "hub_delete_success";
public static final String HUB_NOT_FOUND = "hub_not_found";
}
+
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
index d153ed5c..83c93371 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java
@@ -3,30 +3,46 @@ package net.gepafin.tendermanagement.dao;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.*;
+import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum;
+import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.enums.RoleStatusEnum;
+import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum;
import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean;
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.response.*;
-import net.gepafin.tendermanagement.repositories.ApplicationFormFieldRepository;
-import net.gepafin.tendermanagement.repositories.ApplicationFormRepository;
-import net.gepafin.tendermanagement.repositories.ApplicationRepository;
+import net.gepafin.tendermanagement.repositories.*;
+import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.service.CallService;
+import net.gepafin.tendermanagement.service.CompanyService;
import net.gepafin.tendermanagement.service.DocumentService;
import net.gepafin.tendermanagement.service.FormService;
+import net.gepafin.tendermanagement.service.SystemEmailTemplatesService;
import net.gepafin.tendermanagement.util.DateTimeUtil;
+import net.gepafin.tendermanagement.util.FieldValidator;
+import net.gepafin.tendermanagement.util.MailUtil;
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.ResourceNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.text.MessageFormat;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
@@ -56,11 +72,61 @@ public class ApplicationDao {
@Autowired
private CallDao callDao;
- public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId,Long applicationId) {
+ @Autowired
+ private FlowFormDao flowFormDao;
+
+ @Autowired
+ private FlowEdgesRepository flowEdgesRepository;
+
+ @Autowired
+ private FlowDataRepository flowDataRepository;
+
+ @Autowired
+ private UserCompanyDelegationRepository userCompanyDelegationRepository;
+
+ @Autowired
+ private Validator validator;
+
+ @Autowired
+ private CompanyService companyService;
+
+ @Autowired
+ private ProtocolRepository protocolRepository;
+
+ @Autowired
+ private SystemEmailTemplatesService systemEmailTemplatesService;
+
+ @Autowired
+ private MailUtil mailUtil;
+
+ @Value("${default_System_Receiver_Email}")
+ private String defaultSystemReceiverEmail;
+
+ @Value("${gepafin_email}")
+ private String gepafinEmail;
+
+ @Value("${rinaldo_email}")
+ private String rinaldoEmail;
+
+ @Value("${carlo_email}")
+ private String carloEmail;
+
+ @Autowired
+ private AmazonS3Service amazonS3Service;
+
+ @Autowired
+ private ApplicationSignedDocumentRepository applicationSignedDocumentRepository;
+
+ @Value("${aws.s3.url.folder.signed.document}")
+ private String signedDocumentS3Folder;
+
+
+ public ApplicationResponseBean createApplication(ApplicationRequestBean applicationRequestBean, UserEntity userEntity, Long formId, Long applicationId) {
FormEntity formEntity = formService.validateForm(formId);
- CallEntity call = callService.validatePublishedCall(formEntity.getCall().getId());
+// callService.validatePublishedCall(formEntity.getCall().getId());
+ validateFormFields(applicationRequestBean,formEntity);
ApplicationEntity applicationEntity = validateApplication(applicationId);
- if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))){
+ if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))) {
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_SUBMITTED));
}
formService.validateFormField(applicationRequestBean.getFormFields(),applicationEntity,formEntity);
@@ -68,18 +134,25 @@ public class ApplicationDao {
createOrUpdateMultipleFormFields(applicationRequestBean.getFormFields(), applicationFormEntity,formEntity);
return getApplicationById(applicationEntity.getId(),formEntity.getId());
}
+ public void validateDelegation(UserEntity user, CompanyEntity company) {
+ UserWithCompanyEntity userWithCompany = companyService.getUserWithCompanyEntity(user.getId(), company.getId());
+
+ UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository
+ .findByUserIdAndCompanyIdAndStatus(user.getId(), company.getId(),
+ UserCompanyDelegationStatusEnum.ACTIVE.getValue());
+
+ if (!userWithCompany.getIsLegalRepresentant() && userCompanyDelegationEntity == null) {
+ throw new CustomValidationException(Status.BAD_REQUEST,
+ Translator.toLocale(GepafinConstant.USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION));
+ }
+ }
+
public ApplicationFormEntity saveApplicationFormEntity(ApplicationFormEntity applicationFormEntity) {
ApplicationFormEntity applicationFormEntity1 = applicationFormRepository.save(applicationFormEntity);
return applicationFormEntity1;
}
- public void validateFormId(FormEntity formEntity, CallEntity callEntity) {
- if (Boolean.FALSE.equals(formEntity.getId().equals(callEntity.getInitialForm()))) {
- throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.FORM_ID_DOES_NOT_MACTHES));
- }
- }
-
public ApplicationFormEntity createApplicationFormEntity(ApplicationEntity application, FormEntity formEntity) {
ApplicationFormEntity applicationFormEntity = new ApplicationFormEntity();
applicationFormEntity.setApplication(application);
@@ -88,9 +161,11 @@ public class ApplicationDao {
return applicationFormEntity;
}
- public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call) {
+ public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, CompanyEntity companyEntity) {
+ validateDelegation(user,companyEntity);
ApplicationEntity entity = new ApplicationEntity();
- entity.setUser(user);
+ entity.setUserId(user.getId());
+ entity.setCompany(companyEntity);
entity.setCall(call);
entity.setIsDeleted(false);
entity.setStatus(ApplicationStatusTypeEnum.DRAFT.getValue());
@@ -103,7 +178,6 @@ public class ApplicationDao {
ApplicationEntity applicationEntity = validateApplication(id);
ApplicationFormEntity applicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(),formId);
List applicationFormFieldResponseBeans=new ArrayList<>();
- ApplicationFormFieldResponseBean applicationFormFieldResponseBeans1=null;
List applicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(applicationFormEntity.getId());
applicationFormFieldResponseBeans=createApplicationFormFieldResponse(applicationFormFieldEntities, applicationFormEntity, applicationFormFieldResponseBeans);
ApplicationResponseBean applicationResponseBean= convertApplicationEntityToApplicationResponseBean(applicationEntity);
@@ -164,58 +238,102 @@ public class ApplicationDao {
log.info("Application deleted with ID: {}", id);
}
- public List getAllApplications(UserEntity userEntity, Long callId) {
- RoleStatusEnum roleStatus = RoleStatusEnum.valueOf(userEntity.getRoleEntity().getRoleType());
- boolean isBeneficiary = RoleStatusEnum.ROLE_BENEFICIARY.equals(roleStatus);
-
- log.info("Fetching applications for RoleType: {}", roleStatus);
- List applicationResponses = new ArrayList<>();
+// public List getAllApplications(UserEntity userEntity, Long callId, CompanyEntity companyEntity) {
+// boolean isBeneficiary = validator.checkIsBeneficiary();
+//
+// log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType());
+// List applicationResponses = new ArrayList<>();
+//
+// if (callId != null) {
+// // Fetch based on callId and user if role is BENEFICIARY, otherwise fetch all for the call
+// log.info("Fetching applications for callId: {}", callId);
+// CallEntity call = callService.validateCall(callId);
+//
+// // Use a single method to handle both conditions for consistency
+// List applicationEntities = isBeneficiary
+// ? applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId())
+// .map(List::of) // Convert Optional to a List of one element
+// .orElse(List.of()) // If not present, return an empty list
+// : applicationRepository.findByCallIdAndIsDeletedFalse(call.getId());
+//
+// applicationResponses = applicationEntities.stream()
+// .map(this::getApplicationResponse)
+// .collect(Collectors.toList());
+//
+// } else {
+// // Fetch all applications for the user if BENEFICIARY, or fetch all applications in general
+// List applicationEntities = isBeneficiary
+// ? applicationRepository.findByUserIdAndIsDeletedFalse(companyEntity.getId())
+// : applicationRepository.findByIsDeletedFalse();
+//
+// applicationResponses = applicationEntities.stream()
+// .map(this::getApplicationResponse)
+// .collect(Collectors.toList());
+// }
+//
+// return applicationResponses;
+// }
+
+ public List getAllApplications(UserEntity userEntity, Long callId, Long companyId) {
+
+ log.info("Fetching applications for RoleType: {}", userEntity.getRoleEntity().getRoleType());
- if (callId != null) {
- // Fetch based on callId and user if role is BENEFICIARY, otherwise fetch all for the call
- log.info("Fetching applications for callId: {}", callId);
- CallEntity call = callService.validateCall(callId);
+ Specification spec = search(userEntity.getId(), callId, companyId);
- // Use a single method to handle both conditions for consistency
- List applicationEntities = isBeneficiary
- ? applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId())
- .map(List::of) // Convert Optional to a List of one element
- .orElse(List.of()) // If not present, return an empty list
- : applicationRepository.findByCallIdAndIsDeletedFalse(call.getId());
+ List applicationEntities = applicationRepository.findAll(spec);
- applicationResponses = applicationEntities.stream()
- .map(this::getApplicationResponse)
- .collect(Collectors.toList());
-
- } else {
- // Fetch all applications for the user if BENEFICIARY, or fetch all applications in general
- List applicationEntities = isBeneficiary
- ? applicationRepository.findByUserIdAndIsDeletedFalse(userEntity.getId())
- : applicationRepository.findByIsDeletedFalse();
-
- applicationResponses = applicationEntities.stream()
- .map(this::getApplicationResponse)
- .collect(Collectors.toList());
- }
-
- return applicationResponses;
+ return applicationEntities.stream()
+ .map(this::getApplicationResponse)
+ .collect(Collectors.toList());
}
- private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) {
+ private Specification search(Long userId, Long callId, Long companyId) {
+ return (root, query, builder) -> {
+ Boolean isBeneficiary = validator.checkIsBeneficiary();
+ Predicate predicate = builder.isFalse(root.get("isDeleted"));
+ if (isBeneficiary) {
+ predicate = builder.and(predicate, builder.equal(root.get("userId"), userId));
+ }
+ if (callId != null) {
+ predicate = builder.and(predicate, builder.equal(root.get("call").get("id"), callId));
+ }
+ if (companyId != null) {
+ predicate = builder.and(predicate, builder.equal(root.get("company").get("id"), companyId));
+ }
+ return predicate;
+ };
+ }
+
+ private ApplicationResponse getApplicationResponse(ApplicationEntity applicationEntity) {
ApplicationResponse responseBean = new ApplicationResponse();
+ List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId());
+ Long totalFormSteps = flowFormDao.calculateTotalSteps(flowEdgesList);
+ Long completedSteps= Long.valueOf(flowFormDao.getCompletedSteps(applicationEntity));
+ Integer progress=calculateProgress(totalFormSteps,completedSteps);
responseBean.setId(applicationEntity.getId());
+ responseBean.setProgress(progress);
+ responseBean.setCallTitle(applicationEntity.getCall().getName());
+ responseBean.setCallEndDate(applicationEntity.getCall().getEndDate());
+ responseBean.setModifiedDate(applicationEntity.getCall().getUpdatedDate());
responseBean.setCallId(applicationEntity.getCall().getId());
responseBean.setSubmissionDate(applicationEntity.getSubmissionDate());
responseBean.setStatus(applicationEntity.getStatus());
responseBean.setComments(applicationEntity.getComments());
+ responseBean.setCompanyId(applicationEntity.getCompany().getId());
+ responseBean.setCompanyName(applicationEntity.getCompany().getCompanyName());
+ if(applicationEntity.getProtocol() != null) {
+ responseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber());
+ }
return responseBean;
}
- public ApplicationEntity validateApplication(Long id) {
- ApplicationEntity applicationEntity= applicationRepository.findById(id).orElseThrow(() ->new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
- return applicationEntity;
- }
+ public ApplicationEntity validateApplication(Long id) {
+ ApplicationEntity applicationEntity = applicationRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
+ return applicationEntity;
+ }
private ApplicationResponseBean convertApplicationEntityToApplicationResponseBean(ApplicationEntity entity) {
ApplicationResponseBean response = new ApplicationResponseBean();
@@ -226,6 +344,9 @@ public class ApplicationDao {
response.setCallId(entity.getCall().getId());
response.setCreatedDate(entity.getCreatedDate());
response.setUpdatedDate(entity.getUpdatedDate());
+ if(entity.getProtocol() != null) {
+ response.setProtocolNumber(entity.getProtocol().getProtocolNumber());
+ }
return response;
}
@@ -259,6 +380,9 @@ public class ApplicationDao {
for (ApplicationFormFieldEntity applicationFormFieldEntity1 : applicationFormFieldEntities) {
if (applicationFormFieldEntity1.getFieldId().equals(applicationFormFieldRequestBean.getFieldId())) {
applicationFormFieldEntity = applicationFormFieldEntity1;
+ if(applicationFormEntity.getForm().getId().equals(applicationFormEntity.getApplication().getCall().getInitialForm())){
+ validateRequiredFields(applicationFormEntity.getForm(),applicationFormEntity.getApplication(), applicationFormFieldRequestBean.getFieldId());
+ }
break;
} else {
applicationFormFieldEntity = new ApplicationFormFieldEntity();
@@ -267,7 +391,13 @@ public class ApplicationDao {
}
}
Utils.setIfUpdated(applicationFormFieldEntity::getFieldId, applicationFormFieldEntity::setFieldId, applicationFormFieldRequestBean.getFieldId());
- Utils.setIfUpdated(applicationFormFieldEntity::getFieldValue, applicationFormFieldEntity::setFieldValue, applicationFormFieldRequestBean.getFieldValue());
+
+ if(applicationFormFieldRequestBean.getFieldValue() !=null ) {
+ applicationFormFieldEntity.setFieldValue(Utils.convertObjectToJsonString(applicationFormFieldRequestBean.getFieldValue()));
+ }
+ if(applicationFormFieldRequestBean.getFieldValue() ==null ) {
+ applicationFormFieldEntity.setFieldValue(null);
+ }
return applicationFormFieldRepository.save(applicationFormFieldEntity);
}
@@ -275,10 +405,15 @@ public class ApplicationDao {
List documentIds=null;
List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class);
for (ContentResponseBean contentResponseBean:contentResponseBeans){
- if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))){
- if(contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) {
- String documentId = applicationFormFieldRequestBean.getFieldValue();
- documentIds = validateDocumentIds(documentId);
+ if(Boolean.TRUE.equals(contentResponseBean.getName().equals("fileupload"))) {
+ if (contentResponseBean.getId().equals(applicationFormFieldRequestBean.getFieldId())) {
+ Object fieldValueObject = applicationFormFieldRequestBean.getFieldValue();
+ if (fieldValueObject instanceof String) {
+ // Safely cast the object to a string
+ String documentId = (String) fieldValueObject;
+ // Now you can use documentId as needed
+ documentIds = validateDocumentIds(documentId);
+ }
}
}
}
@@ -319,7 +454,9 @@ public class ApplicationDao {
ApplicationFormFieldResponseBean applicationFormFieldResponseBean = new ApplicationFormFieldResponseBean();
applicationFormFieldResponseBean.setApplicationFormId(applicationFormId);
applicationFormFieldResponseBean.setFieldId(applicationFormFieldEntity.getFieldId());
- applicationFormFieldResponseBean.setFieldValue(applicationFormFieldEntity.getFieldValue());
+ if(applicationFormFieldEntity.getFieldValue() != null) {
+ applicationFormFieldResponseBean.setFieldValue(Utils.getFieldValueAsObject(applicationFormFieldEntity.getFieldValue()));
+ }
applicationFormFieldResponseBean.setId(applicationFormFieldEntity.getId());
applicationFormFieldResponseBean.setCreatedDate(applicationFormFieldEntity.getCreatedDate());
applicationFormFieldResponseBean.setUpdatedDate(applicationFormFieldEntity.getUpdatedDate());
@@ -330,15 +467,19 @@ public class ApplicationDao {
return applicationEntity;
}
- public ApplicationGetResponseBean getApplicationByFormId( Long applicationId,Long formId, UserEntity userEntity) {
+ public ApplicationGetResponseBean getApplicationByFormId( Long applicationId, Long formId, UserEntity userEntity) {
List formApplicationResponses = new ArrayList<>();
List formEntities = new ArrayList<>();
- ApplicationEntity applicationEntity = applicationRepository.findById(applicationId)
+ boolean isBeneficiary = isBeneficiary(userEntity);
+ ApplicationEntity applicationEntity = isBeneficiary
+ ? applicationRepository.findByIdAndUserIdAndIsDeletedFalse(applicationId, userEntity.getId())
+ .orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)))
+ : applicationRepository.findById(applicationId)
+ .stream().findFirst()
.orElseThrow(() -> new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
-
if (formId != null) {
FormEntity formEntity = formService.validateForm(formId);
- Optional application = applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(),
+ Optional application = applicationRepository.findByIdAndUserIdAndCallIdAndIsDeletedFalse(applicationId, userEntity.getId(),
formEntity.getCall().getId());
applicationEntity=application.get();
formEntities.add(formEntity);
@@ -356,6 +497,12 @@ public class ApplicationDao {
return createApplicationGetResponseBean(applicationEntity, formEntities, formApplicationResponses);
}
+ private boolean isBeneficiary(UserEntity userEntity) {
+ RoleStatusEnum roleStatus = RoleStatusEnum.valueOf(userEntity.getRoleEntity().getRoleType());
+ boolean isBeneficiary = RoleStatusEnum.ROLE_BENEFICIARY.equals(roleStatus);
+ return isBeneficiary;
+ }
+
private void addFormApplication(FormEntity formEntity, ApplicationEntity applicationEntity,
List formApplicationResponses) {
FormApplicationResponse formApplicationResponse = processForm(formEntity, applicationEntity);
@@ -379,7 +526,7 @@ public class ApplicationDao {
}
private ApplicationGetResponseBean createApplicationGetResponseBean(ApplicationEntity applicationEntity, List formEntities, List formApplicationResponses) {
- ApplicationGetResponseBean applicationGetResponseBean =createApplicationGetResponseBean(applicationEntity);
+ ApplicationGetResponseBean applicationGetResponseBean = createApplicationGetResponseBean(applicationEntity);
applicationGetResponseBean.setForm(formApplicationResponses);
return applicationGetResponseBean;
}
@@ -392,6 +539,11 @@ public class ApplicationDao {
applicationGetResponseBean.setSubmissionDate(applicationEntity.getSubmissionDate());
applicationGetResponseBean.setCallId(applicationEntity.getCall().getId());
applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName());
+ applicationGetResponseBean.setCompanyId(applicationEntity.getCompany().getId());
+ if(applicationEntity.getProtocol() != null) {
+ applicationGetResponseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber());
+ }
+ applicationGetResponseBean.setCompanyName(applicationEntity.getCompany().getCompanyName());
return applicationGetResponseBean;
}
@@ -404,51 +556,289 @@ public class ApplicationDao {
return formApplicationResponse;
}
- public ApplicationResponse createApplicationByCallId(ApplicationRequest applicationRequest,Long callId,UserEntity userEntity){
- CallEntity call=callService.validateCall(callId);
- call = callService.validatePublishedCall(call.getId());
- checkIfApplicationExists(call,userEntity);
- ApplicationEntity applicationEntity=createApplicationEntity(userEntity,call);
- applicationEntity.setComments(applicationRequest.getComments());
- applicationEntity=saveApplicationEntity(applicationEntity);
- ApplicationResponse applicationResponse=getApplicationResponse(applicationEntity);
- return applicationResponse;
- }
- public void checkIfApplicationExists(CallEntity call,UserEntity userEntity){
- Optional applicationEntity=applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(),call.getId());
+ public ApplicationResponse createApplicationByCallId(CompanyEntity companyEntity,
+ ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) {
+ CallEntity call = callService.validateCall(callId);
+// call = callService.validatePublishedCall(call.getId());
+ checkIfApplicationExists(call, companyEntity, userEntity);
+ ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, companyEntity);
+ applicationEntity.setComments(applicationRequest.getComments());
+ applicationEntity = saveApplicationEntity(applicationEntity);
+ ApplicationResponse applicationResponse = getApplicationResponse(applicationEntity);
+ return applicationResponse;
+ }
+ public void checkIfApplicationExists(CallEntity call, CompanyEntity companyEntity, UserEntity userEntity){
+ Optional applicationEntity=applicationRepository.findByUserIdAndCompanyIdAndCallIdAndIsDeletedFalse(userEntity.getId(), companyEntity.getId(),call.getId());
if(applicationEntity.isPresent()){
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS));
}
}
-
- public ApplicationEntity getApplicationByCallAndUser(CallEntity call, UserEntity userEntity) {
- return applicationRepository.findByUserIdAndCallIdAndIsDeletedFalse(userEntity.getId(), call.getId())
- .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
- Translator.toLocale(GepafinConstant.APPLICATION_NOT_FOUND_MSG)));
-
- }
-
- public void updateApplicationStatus(Long applicationId, ApplicationStatusTypeEnum status) {
+ public ApplicationResponse updateApplicationStatus(UserEntity userEntity, Long applicationId, ApplicationStatusTypeEnum status) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
+ if (ApplicationStatusTypeEnum.SUBMIT.getValue().equals(applicationEntity.getStatus())) {
+ throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_SUBMITTED_CANNOT_CHANGE));
+ }
+ if(Boolean.TRUE.equals(applicationEntity.getStatus().equals(status.getValue()))){
+ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_IN_PREVIOUS_STATUS));
+ }
if (status.equals(ApplicationStatusTypeEnum.SUBMIT)) {
- CallEntity callEntity = applicationEntity.getCall();
- Long initialFormId = callEntity.getInitialForm();
- Long finalFormId = callEntity.getFinalForm();
-// if (initialFormId == null || finalFormId == null) {
+ callService.validatePublishedCall(applicationEntity.getCall().getId());
+// CallEntity callEntity = applicationEntity.getCall();
+// Long initialFormId = callEntity.getInitialForm();
+// Long finalFormId = callEntity.getFinalForm();
+//// if (initialFormId == null || finalFormId == null) {
+//// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG));
+//// }
+// ApplicationFormEntity initialApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), initialFormId);
+// ApplicationFormEntity finalApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), finalFormId);
+// if (initialApplicationForm == null || finalApplicationForm == null) {
// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG));
// }
- ApplicationFormEntity initialApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), initialFormId);
- ApplicationFormEntity finalApplicationForm = applicationFormRepository.findByApplicationIdAndFormId(applicationEntity.getId(), finalFormId);
- if (initialApplicationForm == null || finalApplicationForm == null) {
+ List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId());
+ Long totalSteps=flowFormDao.calculateTotalSteps(flowEdgesList);
+ Integer completedSteps=flowFormDao.getCompletedSteps(applicationEntity);
+ if (totalSteps.intValue() != completedSteps) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_IS_INCOMPLETE_MSG));
}
+ Long maxProtocolNumber=protocolRepository.findMaxProtocolNumber();
+ Long protocolNumber = (maxProtocolNumber != null) ? maxProtocolNumber + 1 : 1;
+ ProtocolEntity protocolEntity=createProtocolEntity(applicationEntity,protocolNumber);
+ applicationEntity.setProtocol(protocolEntity);
applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue());
applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
+ sendMailToUserAndCompany(userEntity, applicationEntity);
+ sendMailTodefaultSystemAndGepafin(userEntity, applicationEntity);
} else {
applicationEntity.setStatus(status.getValue());
}
- saveApplicationEntity(applicationEntity);
+ applicationEntity = saveApplicationEntity(applicationEntity);
+
+ return getApplicationResponse(applicationEntity);
}
+
+ public Integer calculateProgress(Long totalSteps, Long completedSteps) {
+ if (FieldValidator.isNullOrZero(totalSteps)) {
+ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.TOTAL_STEPS_NOT_BE_ZERO));
+ }
+
+ if (completedSteps < 0 || completedSteps > totalSteps) {
+ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.COMPLETED_STEPS_NOT_VALID));
+ }
+
+ double progress = ((double) completedSteps / totalSteps) * 100;
+ return (int) Math.round(progress);
+ }
+ public void validateFormFields(ApplicationRequestBean request, FormEntity formEntity) {
+
+ List contentResponseBeans=Utils.convertJsonStringToList(formEntity.getContent(),ContentResponseBean.class);
+
+ List requestFields = request.getFormFields();
+
+ Map contentMap = contentResponseBeans.stream()
+ .collect(Collectors.toMap(ContentResponseBean::getId, ContentResponseBean::getLabel)); // Change getLabel() if needed
+ FieldValidator validator = FieldValidator.create();
+ for (ApplicationFormFieldRequestBean requestField : requestFields) {
+ String fieldId = requestField.getFieldId();
+
+ if (!contentMap.containsKey(fieldId)) {
+ validator.addError(MessageFormat.format(Translator.toLocale(GepafinConstant.FIELD_ID_NOT_FOUND), fieldId));
+ }
+
+ }
+ validator.validate();
+ }
+
+ public void validateRequiredFields(FormEntity formEntity, ApplicationEntity applicationEntity, String fieldId) {
+ FlowDataEntity flowDataEntity = flowDataRepository.findByFormIdAndCallId(
+ formEntity.getId(), applicationEntity.getCall().getId());
+
+ if (flowDataEntity == null) {
+ return;
+ }
+
+ ApplicationFormFieldEntity applicationFormFieldEntity = applicationFormFieldRepository
+ .findByFieldIdAndApplicationFormFormIdAndApplicationFormApplicationId(
+ flowDataEntity.getChoosenField(), formEntity.getId(), applicationEntity.getId())
+ .orElse(null);
+
+ if (applicationFormFieldEntity == null || !fieldId.equals(applicationFormFieldEntity.getFieldId())) {
+ return;
+ }
+ List nextFormIds = flowEdgesRepository.findBySourceIdAndCallId(
+ formEntity.getId(), applicationEntity.getCall().getId())
+ .stream()
+ .map(FlowEdgesEntity::getTargetId)
+ .collect(Collectors.toList());
+
+ Optional nextFormIdOptional = flowDataRepository.findByChoosenValueAndFormIdIn(
+ applicationFormFieldEntity.getFieldValue(), nextFormIds)
+ .map(FlowDataEntity::getFormId);
+
+ if (nextFormIdOptional.isPresent()) {
+ Long nextFormId = nextFormIdOptional.get();
+
+ FormEntity nextForm = formService.validateForm(nextFormId);
+ ApplicationFormEntity nextApplicationFormEntity = applicationFormRepository.findByApplicationIdAndFormId(
+ applicationEntity.getId(), nextForm.getId());
+
+ if (nextApplicationFormEntity != null) {
+ List nextApplicationFormFieldEntities = applicationFormFieldRepository.findByApplicationFormId(nextApplicationFormEntity.getId());
+ applicationFormFieldRepository.deleteAll(nextApplicationFormFieldEntities);
+ applicationFormRepository.delete(nextApplicationFormEntity);
+ }
+ }
+ }
+
+ public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Long protocolNumber){
+ ProtocolEntity protocolEntity=new ProtocolEntity();
+ protocolEntity.setCall(applicationEntity.getCall().getId());
+ LocalDateTime utcDateTime = DateTimeUtil.DateServerToUTC(LocalDateTime.now());
+ protocolEntity.setYear(utcDateTime.getYear());
+ protocolEntity.setProtocolNumber(protocolNumber);
+ protocolEntity.setTime(LocalTime.now());
+ protocolEntity.setApplicationId(applicationEntity.getId());
+ protocolRepository.save(protocolEntity);
+ return protocolEntity;
+ }
+ private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) {
+ CallEntity call =applicationEntity.getCall();
+ CompanyEntity company = applicationEntity.getCompany();
+ ProtocolEntity protocol = applicationEntity.getProtocol();
+ SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
+ .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY,
+ call, null);
+
+ // Create the map for subject placeholders
+ Map subjectPlaceholders = new HashMap<>();
+ subjectPlaceholders.put("{{call_name}}", call.getName());
+ subjectPlaceholders.put("{{company_name}}", company.getCompanyName());
+
+ // Create the map for body placeholders
+ Map bodyPlaceholders = new HashMap<>();
+ bodyPlaceholders.put("{{call_name}}", call.getName());
+ bodyPlaceholders.put("{{protocol_number}}", protocol.getProtocolNumber().toString());
+ bodyPlaceholders.put("{{date}}", DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.DD_MM_YYYY));
+ bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS));
+
+ // Replace placeholders in the subject and body
+ String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
+ String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
+
+ String email = userEntity.getEmail();
+ if (userEntity.getBeneficiary() != null) {
+ email = userEntity.getBeneficiary().getEmail();
+ }
+ mailUtil.sendByMailGun(subject, body, List.of(email), null);
+ mailUtil.sendByMailGun(subject, body, List.of(applicationEntity.getCompany().getEmail()), null);
+
+ }
+
+ private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) {
+ CallEntity call = applicationEntity.getCall();
+ CompanyEntity company = applicationEntity.getCompany();
+ ProtocolEntity protocol = applicationEntity.getProtocol();
+ SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
+ .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_GEPAFIN,
+ call, null);
+
+ // Create the map for subject placeholders
+ Map subjectPlaceholders = new HashMap<>();
+ subjectPlaceholders.put("{{call_name}}", call.getName());
+ subjectPlaceholders.put("{{company_name}}", company.getCompanyName());
+
+ // Create the map for body placeholders
+ Map bodyPlaceholders = new HashMap<>();
+ bodyPlaceholders.put("{{call_name}}", call.getName());
+ bodyPlaceholders.put("{{protocol_number}}", protocol.getProtocolNumber().toString());
+ bodyPlaceholders.put("{{date}}", DateTimeUtil.formatLocalDateTime(protocol.getCreatedDate(), GepafinConstant.DD_MM_YYYY));
+ bodyPlaceholders.put("{{time}}", DateTimeUtil.parseLocalTimeToString(protocol.getTime(), GepafinConstant.HH_MM_SS));
+
+ // Replace placeholders in the subject and body
+ String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
+ String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
+
+
+ mailUtil.sendByMailGun(subject, body, List.of(defaultSystemReceiverEmail), null);
+ mailUtil.sendByMailGun(subject, body, List.of(gepafinEmail), null);
+ mailUtil.sendByMailGun(subject, body, List.of(rinaldoEmail), null);
+ mailUtil.sendByMailGun(subject, body, List.of(carloEmail), null);
+
+ }
+ public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId,
+ MultipartFile file) {
+ ApplicationEntity applicationEntity = validateApplication(applicationId);
+ validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
+ validateFileType(file);
+ ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
+ .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
+ if (applicationSignedDocument != null) {
+ applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
+ applicationSignedDocumentRepository.save(applicationSignedDocument);
+ }
+ UploadFileOnAmazonS3Response uploadFileOnAmazonS3 = amazonS3Service.uploadFileOnAmazonS3(signedDocumentS3Folder,
+ file);
+ applicationSignedDocument = new ApplicationSignedDocumentEntity();
+ applicationSignedDocument.setApplication(applicationEntity);
+ applicationSignedDocument.setFileName(uploadFileOnAmazonS3.getFileName());
+ applicationSignedDocument.setFilePath(uploadFileOnAmazonS3.getFilePath());
+ applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
+ applicationSignedDocumentRepository.save(applicationSignedDocument);
+ return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
+ }
+
+ private ApplicationSignedDocumentResponse convertApplicationSignedDocumentToApplicationSignedDocumentResponse(
+ ApplicationSignedDocumentEntity applicationSignedDocument) {
+ ApplicationSignedDocumentResponse applicationSignedDocumentResponse = new ApplicationSignedDocumentResponse();
+ applicationSignedDocumentResponse.setId(applicationSignedDocument.getId());
+ applicationSignedDocumentResponse.setApplicationId(applicationSignedDocument.getApplication().getId());
+ applicationSignedDocumentResponse.setFileName(applicationSignedDocument.getFileName());
+ applicationSignedDocumentResponse.setFilePath(applicationSignedDocument.getFilePath());
+ applicationSignedDocumentResponse
+ .setStatus(ApplicationSignedDocumentStatusEnum.valueOf(applicationSignedDocument.getStatus()));
+ applicationSignedDocumentResponse.setCreatedDate(applicationSignedDocument.getCreatedDate());
+ applicationSignedDocumentResponse.setUpdatedDate(applicationSignedDocument.getUpdatedDate());
+ return applicationSignedDocumentResponse;
+ }
+
+ private void validateFileType(MultipartFile file) {
+ if (file.isEmpty()) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_EMPTY));
+ }
+ String filename = file.getOriginalFilename();
+ if (filename == null || !filename.endsWith(".p7m")) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.VALIDATION_ERROR_FILE_INVALIDTYPE));
+ }
+ }
+
+ public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) {
+
+ ApplicationEntity applicationEntity = validateApplication(applicationId);
+ validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
+
+ ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
+ .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
+ if(applicationSignedDocument == null) {
+ throw new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
+ }
+ return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument);
+ }
+
+ public void deleteSignedDocument(HttpServletRequest request, Long applicationId) {
+ ApplicationEntity applicationEntity = validateApplication(applicationId);
+ validator.validateUserWithCompany(request, applicationEntity.getCompany().getId());
+
+ ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository
+ .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
+ if(applicationSignedDocument == null) {
+ throw new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND));
+ }
+ applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue());
+ applicationSignedDocumentRepository.save(applicationSignedDocument);
+ }
}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java
new file mode 100644
index 00000000..13b0f719
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java
@@ -0,0 +1,131 @@
+package net.gepafin.tendermanagement.dao;
+
+import net.gepafin.tendermanagement.config.Translator;
+import net.gepafin.tendermanagement.constants.GepafinConstant;
+import net.gepafin.tendermanagement.entities.BeneficiaryPreferredCallEntity;
+import net.gepafin.tendermanagement.entities.UserEntity;
+import net.gepafin.tendermanagement.enums.BeneficiaryCallStatus;
+import net.gepafin.tendermanagement.enums.RoleStatusEnum;
+import net.gepafin.tendermanagement.enums.UserStatusEnum;
+import net.gepafin.tendermanagement.model.request.BeneficiaryPreferredCallReq;
+
+import net.gepafin.tendermanagement.model.response.BeneficiaryPreferredCallResponseBean;
+import net.gepafin.tendermanagement.repositories.BeneficiaryPreferredCallRepository;
+import net.gepafin.tendermanagement.service.UserService;
+import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException;
+import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static net.gepafin.tendermanagement.util.Utils.setIfUpdated;
+
+@Component
+public class BeneficiaryPreferredCallDao {
+
+ private final Logger log = LoggerFactory.getLogger(BeneficiaryPreferredCallDao.class);
+
+ @Autowired
+ private BeneficiaryPreferredCallRepository beneficiaryPreferredCallRepository;
+ @Autowired
+ private UserService userService;
+
+ public BeneficiaryPreferredCallResponseBean createBeneficiaryPreferredCall(BeneficiaryPreferredCallReq request,UserEntity user) {
+ log.info("Creating new beneficiary preferred call with details: {}", request);
+ BeneficiaryPreferredCallEntity entity = convertRequestToEntity(request,user);
+ entity = beneficiaryPreferredCallRepository.save(entity);
+ log.info("Beneficiary preferred call created with ID: {}", entity.getId());
+ return convertEntityToResponse(entity);
+ }
+
+ private BeneficiaryPreferredCallEntity convertRequestToEntity(BeneficiaryPreferredCallReq request,UserEntity userEntity) {
+ BeneficiaryPreferredCallEntity entity = new BeneficiaryPreferredCallEntity();
+ UserEntity user= userService.validateUser(userEntity.getId());
+ if (user.getBeneficiary()!=null) {
+ entity.setBeneficiaryId(user.getBeneficiary().getId());
+ }
+ entity.setStatus(BeneficiaryCallStatus.ENABLED.getValue());
+ entity.setCallId(request.getCallId());
+ entity.setUserId(userEntity.getId());
+ entity.setCompanyId(request.getCompanyId());
+ return entity;
+ }
+
+ public BeneficiaryPreferredCallResponseBean getBeneficiaryPreferredCallById(Long id) {
+ log.info("Fetching beneficiary preferred call with ID: {}", id);
+ BeneficiaryPreferredCallEntity entity = validateBeneficiaryPreferredCall(id);
+ log.info("Beneficiary preferred call found: {}", entity);
+ return convertEntityToResponse(entity);
+ }
+// public BeneficiaryPreferredCallResponseBean updateBeneficiaryPreferredCall(Long id, BeneficiaryPreferredCallReq request,
+// UserEntity userEntity) {
+// log.info("Updating beneficiary preferred call with ID: {}", id);
+// BeneficiaryPreferredCallEntity existingEntity = validateBeneficiaryPreferredCall(id);
+// setIfUpdated(existingEntity::getCallId, existingEntity::setCallId, request.getCallId());
+// setIfUpdated(existingEntity::getCompanyId, existingEntity::setCompanyId, request.getCompanyId());
+//
+// existingEntity = beneficiaryPreferredCallRepository.save(existingEntity);
+//
+// log.info("Beneficiary preferred call updated with ID: {}", existingEntity.getId());
+// return convertEntityToResponse(existingEntity);
+// }
+
+ private boolean isUserABeneficiary(Long userId) {
+ UserEntity user=userService.validateUser(userId);
+ return RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(user.getRoleEntity().getRoleType());
+ }
+ public void deleteBeneficiaryPreferredCallById(Long id) {
+ log.info("Deleting beneficiary preferred call with ID: {}", id);
+ validateBeneficiaryPreferredCall(id);
+ beneficiaryPreferredCallRepository.deleteById(id);
+ log.info("Beneficiary preferred call deleted with ID: {}", id);
+ }
+
+ public List getAllBeneficiaryPreferredCalls() {
+ log.info("Fetching all beneficiary preferred calls");
+ List calls = beneficiaryPreferredCallRepository.findAll()
+ .stream()
+ .map(this::convertEntityToResponse)
+ .collect(Collectors.toList());
+ log.info("Total beneficiary preferred calls found: {}", calls.size());
+ return calls;
+ }
+
+ private BeneficiaryPreferredCallEntity validateBeneficiaryPreferredCall(Long id) {
+ log.info("Validating beneficiary preferred call with ID: {}", id);
+ return beneficiaryPreferredCallRepository.findById(id)
+ .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.BENEFICIARY_CALL_NOT_FOUND)));
+ }
+
+ private BeneficiaryPreferredCallResponseBean convertEntityToResponse(BeneficiaryPreferredCallEntity entity) {
+ BeneficiaryPreferredCallResponseBean response = new BeneficiaryPreferredCallResponseBean();
+ response.setId(entity.getId());
+ response.setBeneficiaryId(entity.getBeneficiaryId());
+ response.setStatus(BeneficiaryCallStatus.valueOf(entity.getStatus()));
+ response.setCallId(entity.getCallId());
+ response.setUserId(entity.getUserId());
+ response.setCompanyId(entity.getCompanyId());
+ response.setCreatedDate(entity.getCreatedDate());
+ response.setUpdatedDate(entity.getUpdatedDate());
+
+ return response;
+ }
+ public void updateBeneficiaryPreferredCallStatus(Long id, BeneficiaryCallStatus status) {
+ log.info("Updating status for beneficiary preferred call with ID: {}", id);
+ BeneficiaryPreferredCallEntity existingEntity = validateBeneficiaryPreferredCall(id);
+ existingEntity.setStatus(status.getValue());
+ beneficiaryPreferredCallRepository.save(existingEntity);
+ log.info("Beneficiary preferred call status updated with ID: {}", existingEntity.getId());
+ }
+ public List getBeneficiaryPreferredCallByUserId(UserEntity userEntity, Long companyId) {
+
+ List calls = beneficiaryPreferredCallRepository.findByUserIdAndCompanyId(userEntity.getId(), companyId);
+ return calls.stream()
+ .map(this::convertEntityToResponse)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java
index 1b3f60d0..97ae3216 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java
@@ -1,17 +1,27 @@
package net.gepafin.tendermanagement.dao;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.service.*;
+import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.Utils;
+import org.h2.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@@ -73,20 +83,24 @@ public class CallDao {
@Autowired
private CallTargetAudienceChecklistRepository callTargetAudienceChecklistRepository;
- @Autowired
- private UserService userService;
-
@Autowired
private FaqService faqService;
+
@Autowired
private FlowDao flowDao;
+
@Autowired
private FormDao formDao;
+
+ @Value("${aws.s3.url.folder}")
+ private String s3Folder;
+
+ @Autowired
+ private AmazonS3Service amazonS3Service;
- public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) {
- UserEntity userEntity = userService.validateUser(userId);
+ public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, UserEntity userEntity) {
createCallRequest.setRegionId(userEntity.getRoleEntity().getRegion().getId());
- CallEntity callEntity = convertToCallEntity(createCallRequest);
+ CallEntity callEntity = convertToCallEntity(createCallRequest, userEntity);
updateFaq(createCallRequest.getFaq(), callEntity, userEntity,LookUpDataTypeEnum.FAQ);
@@ -98,8 +112,37 @@ public class CallDao {
return createCallResponseBean;
}
+ public byte[] downloadCallDocumentsAsZip(Long callId) {
+ List documents = documentRepository.findBySourceIdAndSourceAndTypeAndIsDeletedFalse(callId, DocumentSourceTypeEnum.CALL.getValue(),DocumentTypeEnum.DOCUMENT.getValue());
+ if (documents.isEmpty()) {
+ throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND));
+ }
- public CallEntity convertToCallEntity(CreateCallRequestStep1 createCallRequest) {
+ try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
+
+ for (DocumentEntity document : documents) {
+ try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, document.getFileName())) {
+ ZipEntry zipEntry = new ZipEntry(document.getFileName());
+ zos.putNextEntry(zipEntry);
+ IOUtils.copy(fileInputStream, zos);
+ zos.closeEntry();
+ } catch (IOException e) {
+ throw new RuntimeException("Error downloading or adding document to ZIP: " + document.getFileName(), e);
+ }
+ }
+
+ zos.finish();
+ return zipOutputStream.toByteArray();
+
+ } catch (IOException e) {
+ throw new RuntimeException("Error while creating ZIP file", e);
+ }
+ }
+
+
+
+ public CallEntity convertToCallEntity(CreateCallRequestStep1 createCallRequest, UserEntity userEntity) {
CallEntity callEntity = new CallEntity();
// validateCallEntity(createCallRequest);
RegionEntity region = regionRepository.findById(createCallRequest.getRegionId())
@@ -124,6 +167,18 @@ public class CallDao {
callEntity.setConfidi(createCallRequest.getConfidi());
}
callEntity.setDocumentationRequested(createCallRequest.getDocumentationRequested());
+ if (createCallRequest.getAmountMin() != null && createCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG));
+ }
+ callEntity.setAmountMin(createCallRequest.getAmountMin());
+ if(createCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(createCallRequest.getEmail()))){
+ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,createCallRequest.getEmail()));
+ }
+ callEntity.setEmail(createCallRequest.getEmail());
+ callEntity.setPhoneNumber(createCallRequest.getPhoneNumber());
+ callEntity.setStartTime(DateTimeUtil.parseTime(createCallRequest.getStartTime()));
+ callEntity.setEndTime(DateTimeUtil.parseTime(createCallRequest.getEndTime()));
+ callEntity.setHub(userEntity.getHub());
callEntity = callRepository.save(callEntity);
return callEntity;
}
@@ -259,6 +314,11 @@ public class CallDao {
createCallResponseBean.setDocumentationRequested(callEntity.getDocumentationRequested());
createCallResponseBean.setPriorityArea(callEntity.getPriorityArea());
createCallResponseBean.setConfidi(callEntity.getConfidi());
+ createCallResponseBean.setAmountMin(callEntity.getAmountMin());
+ createCallResponseBean.setPhoneNumber(callEntity.getPhoneNumber());
+ createCallResponseBean.setEndTime(callEntity.getEndTime());
+ createCallResponseBean.setStartTime(callEntity.getStartTime());
+ createCallResponseBean.setEmail(callEntity.getEmail());
createCallResponseBean.setCreatedDate(callEntity.getCreatedDate());
createCallResponseBean.setUpdatedDate(callEntity.getUpdatedDate());
return createCallResponseBean;
@@ -358,13 +418,11 @@ public class CallDao {
Translator.toLocale(GepafinConstant.CALL_NOT_FOUND)));
}
- public CallResponse getCallById(Long callId) {
- CallEntity callEntity = validateCall(callId);
+ public CallResponse getCallById(CallEntity callEntity) {
return getCallResponseBean(callEntity);
}
- public CallResponse createCallStep2(Long callId, CreateCallRequestStep2 createCallRequest, Long userId) {
- CallEntity callEntity = validateCall(callId);
+ public CallResponse createCallStep2(CallEntity callEntity, CreateCallRequestStep2 createCallRequest, UserEntity user) {
validateUpdate(callEntity);
setIfUpdated(callEntity::getThreshold, callEntity::setThreshold, createCallRequest.getThreshold());
callRepository.save(callEntity);
@@ -424,8 +482,7 @@ public class CallDao {
}
}
- public CallResponse updateCallStep1(Long callId, UpdateCallRequestStep1 updateCallRequest, Long userId) {
- CallEntity callEntity = validateCall(callId);
+ public CallResponse updateCallStep1(CallEntity callEntity, UpdateCallRequestStep1 updateCallRequest, UserEntity userEntity) {
if(Boolean.TRUE.equals(callEntity.getStatus().equals(CallStatusEnum.PUBLISH.getValue()))) {
try {
Utils.retainOnlySpecificFields(updateCallRequest, Collections.singletonList("faq"));
@@ -433,7 +490,6 @@ public class CallDao {
throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.FAILED_RETAIN_FIELD));
}
}
- UserEntity userEntity = userService.validateUser(userId);
isValidDateRange(updateCallRequest, callEntity);
setIfUpdated(callEntity::getName, callEntity::setName, updateCallRequest.getName());
setIfUpdated(callEntity::getDescriptionShort, callEntity::setDescriptionShort,
@@ -456,6 +512,18 @@ public class CallDao {
setIfUpdated(callEntity::getAmountMax, callEntity::setAmountMax, updateCallRequest.getAmountMax());
setIfUpdated(callEntity::getDocumentationRequested, callEntity::setDocumentationRequested,
updateCallRequest.getDocumentationRequested());
+
+ if (updateCallRequest.getAmountMin() != null && updateCallRequest.getAmountMin().compareTo(BigDecimal.ZERO) < 0) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG));
+ }
+ if(updateCallRequest.getEmail()!=null && Boolean.FALSE.equals(Utils.isValidEmail(updateCallRequest.getEmail()))){
+ throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.VALIDATION_EMAIL,updateCallRequest.getEmail()));
+ }
+ setIfUpdated(callEntity::getAmountMin, callEntity::setAmountMin, updateCallRequest.getAmountMin());
+ setIfUpdated(callEntity::getEmail, callEntity::setEmail, updateCallRequest.getEmail());
+ setIfUpdated(callEntity::getPhoneNumber, callEntity::setPhoneNumber, updateCallRequest.getPhoneNumber());
+ setIfUpdated(callEntity::getStartTime, callEntity::setStartTime, DateTimeUtil.parseTime(updateCallRequest.getStartTime()));
+ setIfUpdated(callEntity::getEndTime, callEntity::setEndTime, DateTimeUtil.parseTime(updateCallRequest.getEndTime()));
setIfUpdated(callEntity::getConfidi, callEntity::setConfidi, updateCallRequest.getConfidi());
updateLookUpData(callEntity, updateCallRequest.getAimedTo(), LookUpDataTypeEnum.AIMED_TO);
updateFaq(updateCallRequest.getFaq(), callEntity, userEntity, LookUpDataTypeEnum.FAQ);
@@ -475,9 +543,9 @@ public class CallDao {
}
List existingChecklist = callTargetAudienceChecklistRepository
.findByCallIdAndLookupDataTypeAndIsDeletedFalse(callEntity.getId(), type.getValue());
- List incomingIds = lookupDataReqList.stream().map(LookUpDataReq::getLookUpDataId)
+ List incomingIds = lookupDataReqList.stream().map(LookUpDataReq::getId)
.filter(id -> id != null && id > 0).collect(Collectors.toList());
- existingChecklist.stream().filter(checklist -> !incomingIds.contains(checklist.getLookupData().getId()))
+ existingChecklist.stream().filter(checklist -> !incomingIds.contains(checklist.getId()))
.forEach(this::softDeleteCallTargetAudienceChecklist);
lookupDataReqList
.forEach(lookUpDataReq -> createOrUpdateCallTargetAudienceChecklist(lookUpDataReq, callEntity, type));
@@ -531,6 +599,11 @@ public class CallDao {
callDetailsResponseBean.setThreshold(callEntity.getThreshold());
callDetailsResponseBean.setDocumentationRequested(callEntity.getDocumentationRequested());
callDetailsResponseBean.setPriorityArea(callEntity.getPriorityArea());
+ callDetailsResponseBean.setAmountMin(callEntity.getAmountMin());
+ callDetailsResponseBean.setEmail(callEntity.getEmail());
+ callDetailsResponseBean.setEndTime(callEntity.getEndTime());
+ callDetailsResponseBean.setStartTime(callEntity.getStartTime());
+ callDetailsResponseBean.setPhoneNumber(callEntity.getPhoneNumber());
callDetailsResponseBean.setCreatedDate(callEntity.getCreatedDate());
callDetailsResponseBean.setUpdatedDate(callEntity.getUpdatedDate());
return callDetailsResponseBean;
@@ -575,7 +648,7 @@ public class CallDao {
validateUpdate(callEntity);
CallResponse callResponseBean = getCallResponseBean(callEntity);
FlowResponseBean flowResponseBean = flowDao.getFlowByCallId(callEntity.getId());
- List formResponseBean = formDao.getFormsByCallId(callEntity.getId());
+ List formResponseBean = formDao.getFormsByCallId(callEntity);
CallValidatorServiceImpl.validateResponse(callResponseBean,flowResponseBean,formResponseBean);
callEntity.setStatus(CallStatusEnum.READY_TO_PUBLISH.getValue());
callRepository.save(callEntity);
@@ -591,8 +664,7 @@ public class CallDao {
return callEntity;
}
- public CallResponse updateCallStatus(Long callId, CallStatusEnum statusReq) {
- CallEntity callEntity = validateCall(callId);
+ public CallResponse updateCallStatus(CallEntity callEntity, CallStatusEnum statusReq) {
CallStatusEnum currentStatus = CallStatusEnum.valueOf(callEntity.getStatus());
validateStatusChange(currentStatus, statusReq);
callEntity.setStatus(statusReq.getValue());
@@ -638,6 +710,25 @@ public class CallDao {
Status.NOT_FOUND,
Translator.toLocale(GepafinConstant.CALL_NOT_PUBLISHED));
}
+ LocalDate currentDate = LocalDate.now();
+ LocalTime currentTime = LocalTime.now();
+
+ if (currentDate.isBefore(callEntity.getStartDate().toLocalDate()) ||
+ (currentDate.isEqual(callEntity.getStartDate().toLocalDate()) && currentTime.isBefore(callEntity.getStartTime()))) {
+ throw new CustomValidationException(
+ Status.BAD_REQUEST,
+ Translator.toLocale(GepafinConstant.CALL_NOT_STARTED_YET)
+ );
+ }
+
+ if (currentDate.isAfter(callEntity.getEndDate().toLocalDate()) ||
+ (currentDate.isEqual(callEntity.getEndDate().toLocalDate()) && currentTime.isAfter(callEntity.getEndTime()))) {
+ throw new CustomValidationException(
+ Status.BAD_REQUEST,
+ Translator.toLocale(GepafinConstant.CALL_ALREADY_ENDED)
+ );
+ }
+
return callEntity;
}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java
new file mode 100644
index 00000000..2208962b
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java
@@ -0,0 +1,228 @@
+package net.gepafin.tendermanagement.dao;
+
+import java.util.List;
+
+import net.gepafin.tendermanagement.entities.*;
+import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
+import net.gepafin.tendermanagement.repositories.ApplicationRepository;
+import net.gepafin.tendermanagement.repositories.FaqRepository;
+import net.gepafin.tendermanagement.web.rest.api.errors.*;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import net.gepafin.tendermanagement.config.Translator;
+import net.gepafin.tendermanagement.constants.GepafinConstant;
+import net.gepafin.tendermanagement.model.request.CompanyRequest;
+import net.gepafin.tendermanagement.model.response.CompanyResponse;
+import net.gepafin.tendermanagement.repositories.CompanyRepository;
+import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository;
+import net.gepafin.tendermanagement.service.UserService;
+import net.gepafin.tendermanagement.util.Utils;
+
+import static net.gepafin.tendermanagement.util.Utils.setIfUpdated;
+
+@Component
+public class CompanyDao {
+
+ @Autowired
+ private CompanyRepository companyRepository;
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private UserWithCompanyRepository userWithCompanyRepository;
+ @Autowired
+ private ApplicationRepository applicationRepository;
+ @Autowired
+ private FaqRepository faqRepository;
+
+
+ public CompanyResponse createCompany(UserEntity userEntity, CompanyRequest companyRequest) {
+ CompanyEntity existingCompany = companyRepository.findByVatNumber(companyRequest.getVatNumber());
+ UserWithCompanyEntity userWithCompanyEntity = null;
+ if (existingCompany != null) {
+ UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), existingCompany.getId())
+ .orElse(null);
+ if (existingRelation == null) {
+ userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant());
+ } else {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.USER_ALREADY_CONNECTED_TO_COMPANY));
+ }
+ return convertCompanyEntityToCompanyResponse(existingCompany, userWithCompanyEntity);
+ } else {
+ validateCompany(companyRequest);
+ CompanyEntity companyEntity = convertCompanyRequestToCompanyEntity(companyRequest);
+ companyRepository.save(companyEntity);
+ userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant());
+ return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity);
+ }
+ }
+
+
+ private void validateCompany(CompanyRequest companyRequest) {
+
+ if (Boolean.FALSE.equals(StringUtils.isEmpty(companyRequest.getEmail()))
+ && Boolean.FALSE.equals(Utils.isValidEmail(companyRequest.getEmail()))) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.INVALID_EMAIL));
+ }
+ if (StringUtils.isEmpty(companyRequest.getVatNumber())) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.VATNUMBER_MANDATORY));
+ }
+ if (companyRepository.existsByVatNumber(companyRequest.getVatNumber())) {
+ throw new CustomValidationException(Status.VALIDATION_ERROR,
+ Translator.toLocale(GepafinConstant.VATNUMBER_ALREADY_EXISTS));
+ }
+ }
+
+ private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant) {
+ UserWithCompanyEntity userWithCompanyEntity = new UserWithCompanyEntity();
+ if (userEntity.getBeneficiary() != null) {
+ userWithCompanyEntity.setBeneficiaryId(userEntity.getBeneficiary().getId());
+ }
+ userWithCompanyEntity.setIsDeleted(Boolean.FALSE);
+ userWithCompanyEntity.setCompanyId(companyEntity.getId());
+ userWithCompanyEntity.setUserId(userEntity.getId());
+ userWithCompanyEntity.setIsLegalRepresentant(isLegalRepresentant);
+ return userWithCompanyRepository.save(userWithCompanyEntity);
+ }
+
+ private CompanyEntity convertCompanyRequestToCompanyEntity(CompanyRequest request) {
+ CompanyEntity entity = new CompanyEntity();
+ entity.setCompanyName(request.getCompanyName());
+ entity.setVatNumber(request.getVatNumber());
+ entity.setCodiceFiscale(request.getCodiceFiscale());
+ entity.setAddress(request.getAddress());
+ entity.setPhoneNumber(request.getPhoneNumber());
+ entity.setCity(request.getCity());
+ entity.setProvince(request.getProvince());
+ entity.setCap(request.getCap());
+ entity.setCountry(request.getCountry());
+ entity.setPec(request.getPec());
+ entity.setEmail(request.getEmail());
+ entity.setNumberOfEmployees(request.getNumberOfEmployees());
+ entity.setAnnualRevenue(request.getAnnualRevenue());
+ entity.setContactName(request.getContactName());
+ entity.setContactEmail(request.getContactEmail());
+ return entity;
+ }
+
+ private CompanyResponse convertCompanyEntityToCompanyResponse(CompanyEntity entity, UserWithCompanyEntity userWithCompanyEntity) {
+ CompanyResponse response = new CompanyResponse();
+ response.setId(entity.getId());
+ response.setCompanyName(entity.getCompanyName());
+ response.setVatNumber(entity.getVatNumber());
+ response.setCodiceFiscale(entity.getCodiceFiscale());
+ response.setAddress(entity.getAddress());
+ response.setPhoneNumber(entity.getPhoneNumber());
+ response.setCity(entity.getCity());
+ response.setProvince(entity.getProvince());
+ response.setCap(entity.getCap());
+ response.setCountry(entity.getCountry());
+ response.setPec(entity.getPec());
+ response.setEmail(entity.getEmail());
+ response.setNumberOfEmployees(entity.getNumberOfEmployees());
+ response.setAnnualRevenue(entity.getAnnualRevenue());
+ if(userWithCompanyEntity!=null) {
+ response.setIsLegalRepresentant(userWithCompanyEntity.getIsLegalRepresentant());
+ }
+ response.setCreatedDate(entity.getCreatedDate());
+ response.setUpdatedDate(entity.getUpdatedDate());
+ response.setContactName(entity.getContactName());
+ response.setContactEmail(entity.getContactEmail());
+ return response;
+ }
+
+ public CompanyResponse updateCompany(UserEntity userEntity, Long companyId, CompanyRequest companyRequest) {
+ CompanyEntity companyEntity = validateCompany(companyId);
+ setIfUpdated(companyEntity::getCompanyName, companyEntity::setCompanyName,
+ companyRequest.getCompanyName());
+ setIfUpdated(companyEntity::getVatNumber, companyEntity::setVatNumber, companyRequest.getVatNumber());
+ setIfUpdated(companyEntity::getCodiceFiscale, companyEntity::setCodiceFiscale,
+ companyRequest.getCodiceFiscale());
+ setIfUpdated(companyEntity::getAddress, companyEntity::setAddress, companyRequest.getAddress());
+ setIfUpdated(companyEntity::getPhoneNumber, companyEntity::setPhoneNumber,
+ companyRequest.getPhoneNumber());
+ setIfUpdated(companyEntity::getCity, companyEntity::setCity, companyRequest.getCity());
+ setIfUpdated(companyEntity::getProvince, companyEntity::setProvince, companyRequest.getProvince());
+ setIfUpdated(companyEntity::getCap, companyEntity::setCap, companyRequest.getCap());
+ setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry());
+ setIfUpdated(companyEntity::getPec, companyEntity::setPec, companyRequest.getPec());
+ setIfUpdated(companyEntity::getEmail, companyEntity::setEmail, companyRequest.getEmail());
+ setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees,
+ companyRequest.getNumberOfEmployees());
+ setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue,
+ companyRequest.getAnnualRevenue());
+ setIfUpdated(companyEntity::getContactName,companyEntity::setContactName,companyRequest.getContactName());
+ setIfUpdated(companyEntity::getContactEmail,companyEntity::setContactEmail,companyRequest.getContactEmail());
+ companyRepository.save(companyEntity);
+ UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId);
+ Utils.setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant,
+ companyRequest.getIsLegalRepresentant());
+ userWithCompanyRepository.save(userWithCompanyEntity);
+ return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity);
+ }
+
+ public CompanyEntity validateCompany(Long companyId) {
+ return companyRepository.findById(companyId).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.COMPANY_NOT_FOUND_MSG)));
+ }
+
+ public CompanyResponse getCompany(UserEntity userEntity, Long companyId) {
+ UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId);
+ return convertCompanyEntityToCompanyResponse(validateCompany(companyId), userWithCompanyEntity);
+ }
+
+ public void deleteCompany(UserEntity userEntity, Long companyId) {
+ CompanyEntity companyEntity = validateCompany(companyId);
+ companyRepository.delete(companyEntity);
+ userWithCompanyRepository.deleteByCompanyIdAndIsDeletedFalse(companyId);
+ }
+
+ public List getCompanyByUserId(Long userId) {
+ UserEntity userEntity = userService.validateUser(userId);
+ List activeCompanyIds = userWithCompanyRepository.findActiveCompanyIdsByUserId(userEntity.getId());
+ List companies = companyRepository.findByIdIn(activeCompanyIds);
+ return companies.stream().map(companyEntity -> {
+ UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyEntity.getId());
+ return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity);
+ }).toList();
+ }
+
+ public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) {
+ return userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userId, companyId).orElseThrow(() -> new ForbiddenAccessException(Status.FORBIDDEN,
+ Translator.toLocale(GepafinConstant.PERMISSION_DENIED)));
+ }
+
+ public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) {
+ return userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userId, compnayId).orElseThrow(
+ () -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_COMPANY_RELATION_NOT_FOUND)));
+ }
+ public void removeCompanyFromList(UserEntity userEntity, Long companyId) {
+ CompanyEntity companyEntity = validateCompany(companyId);
+ UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), companyEntity.getId())
+ .orElseThrow(() -> new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.USER_ALREADY_CONNECTED_TO_COMPANY)));
+ List userApplications = applicationRepository.findByCompanyIdAndUserIdAndIsDeletedFalse(companyEntity.getId(), userEntity.getId());
+ List faqs = faqRepository.findByCompanyIdAndUserIdAndIsDeletedFalse(companyEntity.getId(), userEntity.getId());
+ for (ApplicationEntity application : userApplications) {
+ if(Boolean.TRUE.equals(application.getStatus().equals(ApplicationStatusTypeEnum.SUBMIT.getValue()))) {
+ throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.CANNOT_DELETE_COMPANY_WITH_APPLICATION_SUBMITT));
+ }
+ if(Boolean.TRUE.equals(application.getStatus().equals(ApplicationStatusTypeEnum.DRAFT.getValue()))) {
+ application.setIsDeleted(Boolean.TRUE);
+ applicationRepository.save(application);
+ }
+ }
+ for(FaqEntity faq:faqs) {
+ faq.setIsDeleted(Boolean.TRUE);
+ faqRepository.save(faq);
+ }
+ existingRelation.setIsDeleted(Boolean.TRUE);
+ userWithCompanyRepository.save(existingRelation);
+ }
+
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java
new file mode 100644
index 00000000..5622aa8a
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java
@@ -0,0 +1,118 @@
+package net.gepafin.tendermanagement.dao;
+
+import net.gepafin.tendermanagement.entities.CompanyEntity;
+import net.gepafin.tendermanagement.entities.UserEntity;
+import net.gepafin.tendermanagement.enums.CallStatusEnum;
+import net.gepafin.tendermanagement.enums.RoleStatusEnum;
+import net.gepafin.tendermanagement.enums.UserStatusEnum;
+import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean;
+import net.gepafin.tendermanagement.model.response.Widget1;
+import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean;
+import net.gepafin.tendermanagement.repositories.ApplicationRepository;
+import net.gepafin.tendermanagement.repositories.CallRepository;
+import net.gepafin.tendermanagement.repositories.CompanyRepository;
+import net.gepafin.tendermanagement.repositories.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+
+@Component
+public class DashboardDao {
+
+ @Autowired
+ private CallRepository callRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private ApplicationRepository applicationRepository;
+
+ @Autowired
+ private CompanyRepository companyRepository;
+
+ public SuperAdminWidgetResponseBean getDashboardWidget() {
+ SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean();
+ widgetResponseBean.setWidget1(createWidget1());
+// List