diff --git a/mvnw b/mvnw old mode 100644 new mode 100755 index d7c358e5..19529ddf --- a/mvnw +++ b/mvnw @@ -8,7 +8,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# https://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an diff --git a/mvnw.cmd b/mvnw.cmd index 6f779cff..b150b91e 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,149 +1,149 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM https://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' -$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" -if ($env:MAVEN_USER_HOME) { - $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" -} -$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index 08c677d0..c463be91 100644 --- a/pom.xml +++ b/pom.xml @@ -88,8 +88,8 @@ com.amazonaws - aws-java-sdk-s3 - 1.12.312 + aws-java-sdk + 1.12.563 @@ -225,6 +225,25 @@ 3.0.0 + + + org.springframework + spring-test + + + + + org.springframework.boot + spring-boot-starter-websocket + + + org.springframework.boot + spring-boot-starter-amqp + + + io.projectreactor.netty + reactor-netty + diff --git a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java index 7ec98464..c220b176 100644 --- a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java +++ b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java @@ -23,8 +23,7 @@ public class TendermanagementApplication { @Override public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**").allowedOrigins("http://localhost:3000") - .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD").allowCredentials(true); + registry.addMapping("/**").allowedOrigins("http://localhost:3000").allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD").allowCredentials(true); } } diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 090f3688..8c11eac2 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -109,6 +109,7 @@ public class SecurityConfig { .requestMatchers("/v1/api-docs/**").permitAll() // API docs .requestMatchers("/v1/user/reset-password/initiate").permitAll() .requestMatchers("/v1/user/reset-password").permitAll() + .requestMatchers("/wss/**").permitAll() // if this is not running use this /gs-guide-websocket .anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) .exceptionHandling(exceptionHandling -> exceptionHandling diff --git a/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java b/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java new file mode 100644 index 00000000..1b90a882 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java @@ -0,0 +1,39 @@ +package net.gepafin.tendermanagement.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Value("${spring.rabbitmq.host}") + private String relayHost; + + @Value("${spring.rabbitmq.port}") + private int relayPort; + + @Value("${spring.rabbitmq.username}") + private String clientUserName; + + @Value("${spring.rabbitmq.password}") + private String clientPassword; + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + + config.enableStompBrokerRelay("/topic").setRelayHost(relayHost).setRelayPort(relayPort).setClientLogin(clientUserName).setClientPasscode(clientPassword); + config.setApplicationDestinationPrefixes("/app"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + + registry.addEndpoint("/wss").setAllowedOrigins("http://localhost:3000", "http://127.0.0.1:5500/", "https://bandi-staging.memento.credit/**", "https://bandi.gepafin.it/**") + .withSockJS(); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java index 4d8d5948..8f8f3131 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/JWTFilter.java @@ -1,43 +1,48 @@ package net.gepafin.tendermanagement.config.jwt; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.GenericFilterBean; - import java.io.IOException; -public class JWTFilter extends GenericFilterBean { +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; - private final TokenProvider tokenProvider; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; - public JWTFilter(TokenProvider tokenProvider) { - this.tokenProvider = tokenProvider; - } +public class JWTFilter extends OncePerRequestFilter { - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; - String token = resolveToken(httpServletRequest); + private final TokenProvider tokenProvider; - if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) { - Authentication authentication = tokenProvider.getAuthentication(token); - if (authentication != null) { - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } + public JWTFilter(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } - filterChain.doFilter(servletRequest, servletResponse); - } + protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, + FilterChain filterChain) throws ServletException, IOException { - private String resolveToken(HttpServletRequest request) { - String bearerToken = request.getHeader("Authorization"); - return StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : null; - } + try { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + String token = resolveToken(httpServletRequest); + + if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) { + Authentication authentication = tokenProvider.getAuthentication(token); + if (authentication != null) { + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + + filterChain.doFilter(servletRequest, servletResponse); + } catch (Exception e) { + servletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); + } + + } + + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader("Authorization"); + return StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : null; + } } 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 41d9fc16..fa4ad277 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java +++ b/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java @@ -1,5 +1,39 @@ package net.gepafin.tendermanagement.config.jwt; +import static io.micrometer.common.util.StringUtils.isEmpty; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.crypto.SecretKey; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.time.DateUtils; +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.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import com.google.gson.Gson; + import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @@ -14,30 +48,6 @@ import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.time.DateUtils; -import org.apache.http.HttpResponse; -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.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; - -import javax.crypto.SecretKey; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.stream.Collectors; -import com.google.gson.Gson; - -import static io.micrometer.common.util.StringUtils.isEmpty; @Component @@ -48,7 +58,7 @@ public class TokenProvider { private String secretKey; @Value("${security.authentication.jwt.token-validity-in-seconds}") - private long tokenValidityInSeconds; + private int tokenValidityInSeconds; @Autowired private UserRepository userRepository; @@ -60,7 +70,6 @@ public class TokenProvider { private static final String MERCHANTID="merchantId"; static final String AUTH_SECRET = "X-Api-Secret"; - private final Set invalidatedTokens = new HashSet<>(); private static final String USER_ID = "userId"; public UserEntity validateUser(Map userInfo) { @@ -96,12 +105,12 @@ public class TokenProvider { Date validity; if (Boolean.TRUE.equals(rememberMe)) { - now = DateUtils.addMonths(new Date(), 2).getTime(); + now = DateUtils.addDays(new Date(), 2).getTime(); validity = new Date(now); - log.info("Creating token with extended validity for 2 months."); + log.info("Creating token with extended validity for 2 days."); } else { - now = (new Date()).getTime(); - validity = new Date(now + (this.tokenValidityInSeconds * 1000)); + now = DateUtils.addSeconds(new Date(), this.tokenValidityInSeconds).getTime(); + validity = new Date(now); log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds); } @@ -148,32 +157,15 @@ public class TokenProvider { return authorities; } - public boolean validateToken(String authToken) { - try { - if (isTokenInvalid(authToken)) { - log.warn("Token is invalidated."); - return false; - } - Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(authToken); - log.info("Token is valid."); - return true; - } catch (Exception e) { - log.error("Token validation failed: {}", e.getMessage()); - return false; - } - } + public boolean validateToken(String authToken) { - public void invalidateToken(String token) { - invalidatedTokens.add(token); - log.info("Token invalidated: {}", token); - } + Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(authToken); + log.info("Token is valid."); + return true; - public boolean isTokenInvalid(String token) { - return invalidatedTokens.contains(token); - } + } + + public Map getUserInfoAndUserIdFromToken(HttpServletRequest request) { Map userInfo = new HashMap<>(); String authSecretHeader=request.getHeader(AUTH_SECRET); diff --git a/src/main/java/net/gepafin/tendermanagement/constants/AppointmentApiConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/AppointmentApiConstant.java new file mode 100644 index 00000000..15a3444e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/constants/AppointmentApiConstant.java @@ -0,0 +1,27 @@ +package net.gepafin.tendermanagement.constants; + +public class AppointmentApiConstant { + + public static final String ODESSA_LOGIN = "/WSGatewayLogin.apiLogin"; + public static final String GET_NDG_BY_VAT_NUMBER = "/WSAnagrafica.getListaNdg"; + public static final String CREATE_VISURA = "/WSAnagrafica.createVisura"; + public static final String GET_VISURA_LIST = "/WSAnagrafica.getVisuraList"; + public static final String GET_APPOINTMENT_TEMPLATE = "/WSCrmConsulenza.getAppuntamentoTemplate?idAppuntamentoTemplate=7"; + public static final String CREATE_APPOINTMENT_FROM_TEMPLATE = "/WSCrmConsulenza.createAppointmentFromTemplate"; + public static final String UPLOAD_APOOINTMENT_DOCUMENT = "/WSDocumentDetail.createStream"; + + //get ndg number + public static final int TARGET_PAGE_SIZE = 1; + public static final int RECORD_PER_PAGE_SIZE = 10; + +//create visura request Body constant + public static final boolean CREA_ANAGRAFICA = Boolean.TRUE; + public static final boolean SALVA_DOCUMENTI = Boolean.TRUE; + public static final String VISURA_PROVIDER = "cerved"; + public static final String VISURA_TYPE = "StandardReport"; + public static final String VISURA_MODE = "visure"; + public static final String COD_AGENTE = "UtenzaAPIPortal"; + public static final boolean IS_FROM_RATING = Boolean.FALSE; + public static final boolean IS_ANAGRAFICA_LEGAME = Boolean.FALSE; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index aaa3279b..42853112 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -294,6 +294,9 @@ public class GepafinConstant { public static final String DUPLICATE_BENEFICIARY_CALL = "beneficiary.call.duplicate"; public static final String USER_MUST_BE_ASSOCIATED_WITH_COMPANY="user.must.be.associated.with.company.to.create.application"; public static final String COMPANY_ID_REQUIRED_FOR_PREFERRED_CALL = "company.id.required.for.preferred.call"; + public static final String CREATED_DATE = "createdDate"; + public static final String RESPONSE_DAYS_NOT_NULL="response.days.not.null"; + public static final String APPLICATION_CANNOT_APPROVED_OR_REJECTED="application.cannot.approved.or.rejected"; public static final String SUBMISSION_DATE = "submissionDate"; public static final String ASSIGNED_AT = "assignedAt"; public static final String AUTH = "auth"; @@ -303,5 +306,54 @@ public class GepafinConstant { public static final String LOGIN_ATTEMPT_ID = "loginAttemptId"; public static final String USER_ACTION_ID = "userActionId"; public static final String RESET_PASSWORD_URL_FORMAT = "/reset-password?token=%s&email=%s"; + public static final String VALID_VATNUMBER_MSG = "valid.vatnumber.message"; + public static final String ATLEAST_ONE_ID_REQUIRED="atleast.one.id.required"; + + //Appointment + public static final String NDG_IN_PROGRESS = "IN_PROGRESS"; + public static final String NDG_AVAILABLE = "ndg.available"; + public static final String NDG_GENERATION_IS_IN_PROGRESS = "ndg.generation.in.progress"; + public static final String NDG_GENERATED = "NDG_GENERATED"; + public static final String NDG_FAILED = "FAILED"; + public static final String NDG_NOT_FOUND_FOR_APPLICATION = "ndg.not.found.for.this.application.or.invalid"; + public static final String APPOINTMENT_ALREADY_CREATED = "appointment.already.created"; + public static final String EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG = "document.not.uploaded.to.external.system.please.try.again"; + public static final String PROVIDE_VALID_APPLICATION_DOC_ID = "provide.valid.application.document.id"; + public static final String DOCUMENT_UPLOADED_SUCCESSFULLY_TO_EXTERNAL_SYSTEM = "document.uploaded.successfully.to.external.system"; + public static final String ERROR_UPLOADING_DOCUMENT = "error.in.uploading.document.check.input"; + public static final String DOCUMENT_ALREADY_UPLOADED = "document.already.uploaded"; + public static final String NDG_NOT_MATCHED_OR_NOT_FOUND = "ndg.not.found.or.not.matched"; + public static final String NO_NDG_FOR_ANOTHER_HUB = "ndg.generation.is.only.for.gepafin"; + public static final String NO_APPOINTMENT_FOR_ANOTHER_HUB = "appointment.creation.is.only.for.gepafin"; + public static final String NO_DOCUMENT_UPLOAD_FOR_ANOTHER_HUB = "upload.document.is.only.for.gepafin"; + public static final String APPOINTMENT_CREATED = "appointment.created.successfully"; + public static final String DATA_STRING = "data"; + public static final String DOCUMENT_ATTACHMENT_ID_STRING = "documentAttachmentId"; + public static final String TEMP_FILE_PATH = "/tmp/"; + public static final String RICHIESTA_CLIENTE_STRING = "richiestaCliente"; + public static final String ID_STRING = "id"; + public static final String NULL_STRING = "null"; + public static final String NDG_STRING = "ndg"; + public static final String ID_VISURA_STRING = "idVisura"; + public static final String NDG_FETCH_SUCCESSFULLY = "ndg.fetch.successfully"; + public static final String AUTH_JWT_SECRET_KEY = "hTa5qe$af/4',BFs"; + public static final String JWT_ALGO_HEADER = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; + public static final String HMAC_ALGO = "HmacSHA256"; + public static final String ERROR_IN_GENERATING_NDG_TRY_AGAIN = "error.try.again"; + public static final String POLLING_THREAD_NAME = "Ndg-Polling-Thread-"; + public static final String DOCUMENT_UPLOADING_IN_PROGRESS = "document.uploading.is.in.progress"; + public static final String ASYNC_DOCUMENT_UPLOAD_NAME = "AsyncDocumentUpload-"; + public static final String All_DOCUMENT_CHECKED_AND_ONE_CHECKLIST_CHECKED="all.document.checked.and.one.checklist.checked"; + + //Notification + public static final String COMMON_SINGLE_CHANNEL_PREFIX = "/topic/notifications_user_"; + public static final String COMPANY_PREFIX = "_company_"; + public static final String NOTIFICATION_SENT_SUCCESSFULLY = "notification.sent.successfully"; + public static final String NOTIFICATION_FETCHED_SUCCESSFULLY= "notification.fetched.successfully"; + public static final String NOTIFICATION_NOT_FOUND= "notification.not.found"; + public static final String NOTIFICATION_ALREADY_IN_THAT_STATE="notification.already.in.state"; + public static final String NOTIFICATION_DELETED_SUCCESSFULLY="notification.deleted.successfully"; + public static final String NOTIFICATION_UPDATED_SUCCESSFULLY="notification.updated.successfully"; + public static final String USER_WITH_COMPANY_NOT_FOUND = "user.with.company.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java index 9e08c776..d9b3ed91 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java @@ -34,6 +34,7 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import static java.time.temporal.ChronoUnit.DAYS; import static net.gepafin.tendermanagement.util.Utils.log; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; @@ -92,6 +93,9 @@ public class ApplicationAmendmentRequestDao { @Autowired private EmailLogDao emailLogDao; + @Autowired + private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; + @Autowired LoggingUtil loggingUtil; @@ -101,12 +105,44 @@ public class ApplicationAmendmentRequestDao { @Autowired private AssignedApplicationsDao assignedApplicationsDao; + @Autowired + private ApplicationEvaluationDao applicationEvaluationDao; + + @Autowired + private DocumentRepository documentRepository; + @Autowired + private CompanyService companyService; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private UserRepository userRepository; + public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(Long applicationEvaluationId) { log.info("Fetching the application data for the Amendment process {}", applicationEvaluationId); ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluation(applicationEvaluationId); Long applicationId = applicationEvaluationEntity.getApplicationId(); - ApplicationEntity application = applicationService.validateApplication(applicationId); + List evaluationFileRequests=new ArrayList<>(); + List checklistRequests=new ArrayList<>(); + ApplicationEntity application = applicationService.validateApplication(applicationId); + String file=applicationEvaluationEntity.getFile(); + String checkList=applicationEvaluationEntity.getChecklist(); + if(file != null){ + evaluationFileRequests=Utils.convertJsonStringToList(file,FieldRequest.class); + } + Boolean allValid = evaluationFileRequests.stream() + .anyMatch(fieldRequest -> fieldRequest.getValid() == null); + if(checkList != null) { + checklistRequests=Utils.convertJsonStringToList(checkList,ChecklistRequest.class); + } + boolean resultCheckList = checklistRequests.stream() + .anyMatch(checklistRequest -> Boolean.TRUE.equals(checklistRequest.getValid())) ? false : true; + + if(Boolean.TRUE.equals(allValid) || Boolean.TRUE.equals(resultCheckList)){ + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.All_DOCUMENT_CHECKED_AND_ONE_CHECKLIST_CHECKED)); + } // Set common application-level details String callName = application.getCall().getName(); Long protocolNumber = (application.getProtocol() != null && application.getProtocol().getProtocolNumber() != null) @@ -131,11 +167,18 @@ public class ApplicationAmendmentRequestDao { List forms = applicationFormRepository.findByApplicationId(applicationId); List allFormFields = new ArrayList<>(); - + Map fieldRequestMap = evaluationFileRequests.stream() + .collect(Collectors.toMap(FieldRequest::getId, fieldRequest -> fieldRequest)); for (ApplicationFormEntity form : forms) { String content = form.getForm().getContent(); List> result = filterByName(content, "fileupload"); - allFormFields.addAll(getIdAndLabelFromResult(result)); + List amendmentFormFieldResponses= getIdAndLabelFromResult(result); + amendmentFormFieldResponses.removeIf(amendmentFormFieldResponse -> { + FieldRequest matchingRequest = fieldRequestMap.get(amendmentFormFieldResponse.getFieldId()); + // Remove if no matching FieldRequest exists or if valid is true + return matchingRequest == null || Boolean.TRUE.equals(matchingRequest.getValid()); + }); + allFormFields.addAll(amendmentFormFieldResponses); } response.setFormFields(allFormFields); @@ -196,7 +239,7 @@ public class ApplicationAmendmentRequestDao { log.info("Submiting application data for amendment Process with details: {}", applicationEvaluationId); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = createApplicationAmendmentRequestEntity(applicationAmendmentRequest, applicationEvaluationId); - ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = convertEntityToResponse(applicationAmendmentRequestEntity); + ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = convertEntityToResponse(applicationAmendmentRequestEntity,false); log.info("Application submitted successfully for amendment", applicationAmendmentRequestResponse); if (Boolean.TRUE.equals(applicationAmendmentRequestResponse.getIsSendEmail())) { emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(applicationAmendmentRequestEntity); @@ -208,6 +251,11 @@ public class ApplicationAmendmentRequestDao { ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = new ApplicationAmendmentRequestEntity(); applicationAmendmentRequestEntity.setNote(applicationAmendmentRequest.getNote()); applicationAmendmentRequestEntity.setResponseDays(applicationAmendmentRequest.getResponseDays()); + if(applicationAmendmentRequest.getResponseDays()==null || applicationAmendmentRequest.getResponseDays() < 0){ + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.RESPONSE_DAYS_NOT_NULL)); + } + applicationAmendmentRequestEntity.setEndDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()).plusDays(applicationAmendmentRequest.getResponseDays())); + applicationAmendmentRequestEntity.setIsEmail(applicationAmendmentRequest.getIsSendEmail()); applicationAmendmentRequestEntity.setIsNotification(applicationAmendmentRequest.getIsSendNotification()); applicationAmendmentRequestEntity.setStartDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); @@ -228,17 +276,32 @@ public class ApplicationAmendmentRequestDao { AmendmentFormField formField = new AmendmentFormField(); formField.setFieldId(amendmentFormFieldRequest.getFieldId()); formField.setFieldValue(null); + formField.setLabel(amendmentFormFieldRequest.getLabel()); return formField; }) .collect(Collectors.toList()); String formFieldsJson = Utils.convertObjectToJson(formFieldRequestBean); applicationAmendmentRequestEntity.setFormFields(formFieldsJson); } + List amendmentRequest = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(applicationEvaluationEntity.getId()); + // Ensure startDate and initialDays are not null to avoid NullPointerException + if (amendmentRequest !=null && amendmentRequest.isEmpty() && applicationEvaluationEntity.getStartDate() != null && applicationEvaluationEntity.getInitialDays() != null ) { + Long initialDays = applicationEvaluationEntity.getInitialDays(); + LocalDateTime startDate = applicationEvaluationEntity.getStartDate(); + LocalDateTime nowInUTC = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + // Calculate remaining days + Long remainingDays = initialDays - DAYS.between(startDate, nowInUTC); + // Set remaining days in the entity + applicationEvaluationEntity.setRemainingDays(remainingDays); + //Set stop date time in the entity becuase amendment has started + applicationEvaluationEntity.setStopDateTime(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + } + UserEntity userEntity = userService.validateUser(applicationEvaluationEntity.getUserId()); Long protocolNumber = protocolDao.getProtocolNumber(userEntity.getHub()); ProtocolEntity protocolEntity = protocolDao.createProtocolEntity( applicationEvaluationEntity.getAssignedApplicationsEntity().getApplication(), protocolNumber, - userEntity.getHub().getId()); + userEntity.getHub().getId(),false); applicationAmendmentRequestEntity.setProtocol(protocolEntity); ApplicationAmendmentRequestEntity applicationAmendment = saveApplicationAmendmentRequestEntity(applicationAmendmentRequestEntity, null, VersionActionTypeEnum.INSERT); String evaluationStatusType = applicationEvaluationEntity.getStatus(); @@ -271,6 +334,10 @@ public class ApplicationAmendmentRequestDao { assignedApplicationsEntity.setStatus(AssignedApplicationEnum.SOCCORSO.getValue()); assignedApplicationsRepository.save(assignedApplicationsEntity); + Map placeHolders = notificationDao.sendNotificationToBeneficiary(applicationEntity, NotificationTypeEnum.AMENDMENT_CREATION); + + notificationDao.sendNotificationToInstructor(placeHolders,applicationAmendmentRequestEntity.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_CREATION); + /** This code is responsible for adding a version history log for the "Update Assigned Application" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplication).newData(assignedApplicationsEntity).build()); } @@ -278,6 +345,25 @@ public class ApplicationAmendmentRequestDao { return applicationAmendment; } + private void setAmendmentDocuments(String amendmentNotes, String amendmentFieldRequest, + ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) { + AmendmentDetailsResponseBean amendmentDetails = new AmendmentDetailsResponseBean(); + if (amendmentFieldRequest != null && !amendmentFieldRequest.trim().isEmpty()) { + String[] documentIds = amendmentFieldRequest.split(","); + String validDocumentIds = Arrays.stream(documentIds) + .map(String::trim) + .filter(id -> !id.isEmpty()) + .collect(Collectors.joining(",")); + + amendmentDetails.setAmendmentDocuments(validDocumentIds); + } + if (amendmentNotes != null && !amendmentNotes.trim().isEmpty()) { + amendmentDetails.setAmendmentNotes(amendmentNotes.trim()); + } + amendmentDetails.setValid(null); + String amendmentDetailsJson = Utils.convertObjectToString(amendmentDetails); + applicationAmendmentRequestEntity.setAmendmentDocument(amendmentDetailsJson); + } public ApplicationAmendmentRequestEntity saveApplicationAmendmentRequestEntity(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity,ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity,VersionActionTypeEnum actionTypeEnum) { ApplicationAmendmentRequestEntity applicationAmendmentRequest = applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); @@ -288,23 +374,81 @@ public class ApplicationAmendmentRequestDao { return applicationAmendmentRequest; } - public ApplicationAmendmentRequestResponse convertEntityToResponse(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) { - ApplicationAmendmentRequestResponse response = initializeBasicResponse(applicationAmendmentRequestEntity); + public ApplicationAmendmentRequestResponse convertEntityToResponse(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity,boolean includeEmailContent) { + ApplicationAmendmentRequestResponse response = initializeBasicResponse(applicationAmendmentRequestEntity,includeEmailContent); List forms = applicationFormRepository.findByApplicationId(applicationAmendmentRequestEntity.getApplicationId()); Map fieldIdToLabelMap = extractFieldIdToLabelMap(forms); - +// List amendmentFieldRequests= new ArrayList<>(); List amendmentFormFields = Utils.convertJsonStringToList( applicationAmendmentRequestEntity.getFormFields(), AmendmentFormField.class); Map formFieldEntityMap = getApplicationFormFieldEntityMap(applicationAmendmentRequestEntity, amendmentFormFields); + if (applicationAmendmentRequestEntity.getAmendmentDocument() != null) { + +// List amendmentDetailsList = +// Utils.convertJsonStringToList(applicationAmendmentRequestEntity.getAmendmentDocument(), +// AmendmentDetailsResponseBean.class); + AmendmentDetailsResponseBean amendmentDetails = Utils.convertStringToObject(applicationAmendmentRequestEntity.getAmendmentDocument() ,AmendmentDetailsResponseBean.class); + if(amendmentDetails!=null) { + List documentResponseBeans = new ArrayList<>(); + if (amendmentDetails.getAmendmentDocuments() != null) { + // Extract the comma-separated document IDs as a string + String documentIdsString = amendmentDetails.getAmendmentDocuments(); + + if (documentIdsString != null && !documentIdsString.trim().isEmpty()) { + // Split the comma-separated values and process them + List documentIds = Arrays.stream(documentIdsString.split(",")) + .map(String::trim) + .filter(id -> !id.isEmpty()) + .collect(Collectors.toList()); + + documentResponseBeans.addAll( + documentIds.stream() + .map(id -> { + try { + return createDocumentResponseBean(id); // Convert to Long + } catch (NumberFormatException e) { + // Handle invalid document IDs gracefully + return null; + } + }) + .filter(Objects::nonNull) // Skip null responses + .collect(Collectors.toList()) + ); + response.setAmendmentNotes(amendmentDetails.getAmendmentNotes()); + response.setValid(amendmentDetails.getValid()); + } + } + response.setAmendmentDocuments(documentResponseBeans); + } + + + + } + processFormFields(amendmentFormFields, fieldIdToLabelMap, formFieldEntityMap, response); return response; } - private ApplicationAmendmentRequestResponse initializeBasicResponse(ApplicationAmendmentRequestEntity entity) { + public DocumentResponseBean createDocumentResponseBean(String documentId) { + + if (!StringUtils.isEmpty(documentId)) { + Optional documentEntity = documentRepository.findByIdAndNotDeleted(Long.valueOf(documentId)); + if(documentEntity.isPresent()){ + return applicationEvaluationDao.createDocumentResponseBean(documentEntity.get()); + }} + return null; + } + + + private ApplicationAmendmentRequestResponse initializeBasicResponse(ApplicationAmendmentRequestEntity entity,boolean includeEmailContent) { ApplicationAmendmentRequestResponse response = new ApplicationAmendmentRequestResponse(); + ApplicationEntity applicationEntity = entity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication(); + Long hubId = applicationEntity.getHubId(); + HubEntity hubEntity = hubService.valdateHub(hubId); + response.setId(entity.getId()); response.setApplicationId(entity.getApplicationId()); response.setApplicationEvaluationId(entity.getApplicationEvaluationEntity().getId()); @@ -315,7 +459,8 @@ public class ApplicationAmendmentRequestDao { LocalDateTime startDate = entity.getStartDate(); response.setStartDate(startDate); - response.setExpirationDate(startDate.plus(expirationDays, ChronoUnit.DAYS)); + response.setExpirationDate(entity.getEndDate()); + response.setEvaluationEndDate(entity.getApplicationEvaluationEntity().getEndDate()); response.setIsSendEmail(entity.getIsEmail()); response.setIsSendNotification(entity.getIsNotification()); @@ -325,10 +470,17 @@ public class ApplicationAmendmentRequestDao { UserEntity userEntity = userService.validateUser(application.getUserId()); response.setBeneficiaryName(buildBeneficiaryName(userEntity)); - + CompanyEntity company = companyService.validateCompany(application.getCompanyId()); + response.setCompanyName(company.getCompanyName()); Long protocolNumber = entity.getProtocol() != null ? entity.getProtocol().getProtocolNumber() : null; response.setProtocolNumber(protocolNumber); + if (includeEmailContent) { + Map bodyPlaceholders = emailNotificationDao.prepareEmailPlaceholders(applicationEntity, entity); + EmailContentResponse emailContent = emailNotificationDao.prepareEmailContent(applicationEntity, SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, hubEntity, bodyPlaceholders); + String body = emailContent.getBody(); + response.setEmailTemplate(body); + } return response; } @@ -373,6 +525,7 @@ public class ApplicationAmendmentRequestDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); return responseBean; }) .toList(); @@ -434,7 +587,7 @@ public class ApplicationAmendmentRequestDao { public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(Long id) { log.info("Fetching application amendment with ID: {}", id); ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id); - ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity); + ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity,true); log.info("Application Amendment fetched successfully by ID: {}", response); return response; } @@ -451,7 +604,7 @@ public class ApplicationAmendmentRequestDao { applicationAmendmentRequestRepository.findAll(spec); return applicationAmendmentRequestEntities.stream() - .map(this::convertEntityToResponse) + .map(entity -> convertEntityToResponse(entity, false)) .collect(Collectors.toList()); } @@ -474,6 +627,20 @@ public class ApplicationAmendmentRequestDao { log.info("Updating application amendement with ID: {}", id); ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); + Boolean isBeneficiary=false; + if (Boolean.FALSE.equals(validator.checkIsBeneficiary())) { + validator.validatePreInstructor(request, existingApplicationAmendment.getApplicationEvaluationEntity().getUserId()); + isBeneficiary=false; + } else { + validator.validateUserId(request, existingApplicationAmendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication().getUserId()); + isBeneficiary=true; + } + if(Boolean.TRUE.equals(isBeneficiary) && existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue())){ + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED)); + } + if(Boolean.FALSE.equals(isBeneficiary) && existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())){ + throw new CustomValidationException(Status.VALIDATION_ERROR,Translator.toLocale(GepafinConstant.PERMISSION_DENIED)); + } ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(existingApplicationAmendment); setIfUpdated(existingApplicationAmendment::getNote, existingApplicationAmendment::setNote, updateRequest.getNote()); @@ -486,16 +653,18 @@ public class ApplicationAmendmentRequestDao { if(updateRequest.getApplicationFormFields() != null) { updateRequest.getApplicationFormFields().stream().forEach(applicationFormFieldRequest->{ AmendmentFormField amendmentFormField = getAmendmentFormField(amendmentFormFieldMap,applicationFormFieldRequest.getFieldId()); - ApplicationFormFieldEntity applicationFormFieldEntity = getApplicationFormField(applicationFormFieldMap, applicationFormFieldRequest.getFieldId()); - updateApplicationFormField(applicationFormFieldEntity,applicationFormFieldRequest, amendmentFormField); +// ApplicationFormFieldEntity applicationFormFieldEntity = getApplicationFormField(applicationFormFieldMap, applicationFormFieldRequest.getFieldId()); +// updateApplicationFormField(applicationFormFieldEntity,applicationFormFieldRequest, amendmentFormField); updateFormField(applicationFormFieldRequest, amendmentFormField); }); existingApplicationAmendment.setFormFields(Utils.convertListToJsonString(amendmentFormFieldMap.values().stream().toList())); } existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); - + if(updateRequest.getAmendmentDocuments()!=null && Boolean.FALSE.equals(updateRequest.getAmendmentDocuments().isEmpty())) { + setAmendmentDocuments(updateRequest.getAmendmentNotes(),updateRequest.getAmendmentDocuments(), existingApplicationAmendment); + } ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment,oldApplicationAmendmentEntity,VersionActionTypeEnum.UPDATE); - ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment); + ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment,false); log.info("Application Amendment updated successfully: {}", response); return response; } @@ -560,13 +729,13 @@ public class ApplicationAmendmentRequestDao { String fieldId) { AmendmentFormField amendmentFormField = amendmentFormFieldMap.get(fieldId); if (amendmentFormField == null) { - throw new CustomValidationException(Status.BAD_REQUEST, GepafinConstant.APPLICATION_FORM_FIELD_NOT_FOUND); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_FORM_FIELD_NOT_FOUND)); } return amendmentFormField; } - private void updateFormField(ApplicationFormFieldRequestBean applicationFormFieldRequest, + private void updateFormField(AmendmentFormFieldRequest applicationFormFieldRequest, AmendmentFormField amendmentFormField) { List requestedDocumentIds = extractIds(applicationFormFieldRequest.getFieldValue()); List existingDocumentIds = extractIds(amendmentFormField.getFieldValue()); @@ -575,7 +744,8 @@ public class ApplicationAmendmentRequestDao { if (!existingDocumentIds.isEmpty()) { existingDocumentIds.forEach(this::softDeleteDocument); amendmentFormField.setFieldValue(null); - setIsUploadedBy(amendmentFormField); + amendmentFormField.setValid(applicationFormFieldRequest.getValid()); +// setIsUploadedBy(amendmentFormField); } return; } @@ -589,11 +759,12 @@ public class ApplicationAmendmentRequestDao { if (!newFieldValue.equals(amendmentFormField.getFieldValue())) { amendmentFormField.setFieldValue(newFieldValue); - setIsUploadedBy(amendmentFormField); + amendmentFormField.setValid(applicationFormFieldRequest.getValid()); +// setIsUploadedBy(amendmentFormField); } } - private List extractIds(Object fieldValue) { + public List extractIds(Object fieldValue) { if (fieldValue instanceof String && !StringUtils.isEmpty((String) fieldValue)) { return Arrays.stream(((String) fieldValue).split(",")) .map(Long::valueOf) @@ -604,14 +775,14 @@ public class ApplicationAmendmentRequestDao { - private void setIsUploadedBy(AmendmentFormField amendmentFormField) { - if(validator.checkIsBeneficiary()) { - amendmentFormField.setIsUploadedBy(AmendmentFormField.AmendmentIsUploadedByEnum.BENEFICIARY.getValue()); - }else { - amendmentFormField.setIsUploadedBy(AmendmentFormField.AmendmentIsUploadedByEnum.PRE_INSTRUCTOR.getValue()); - } - - } +// private void setIsUploadedBy(AmendmentFormField amendmentFormField) { +// if(validator.checkIsBeneficiary()) { +// amendmentFormField.setIsUploadedBy(AmendmentFormField.AmendmentIsUploadedByEnum.BENEFICIARY.getValue()); +// }else { +// amendmentFormField.setIsUploadedBy(AmendmentFormField.AmendmentIsUploadedByEnum.PRE_INSTRUCTOR.getValue()); +// } +// +// } // private void updateApplicationFormFields(ApplicationAmendmentRequestEntity applicationAmendment, ApplicationFormFieldRequestBean updatedFormField) { @@ -794,7 +965,7 @@ public class ApplicationAmendmentRequestDao { applicationAmendmentRequestRepository.findByUserId(beneficiaryUserId); return entities.stream() - .map(this::convertEntityToResponse) + .map(entity -> convertEntityToResponse(entity, false)) .collect(Collectors.toList()); } @@ -804,13 +975,25 @@ public class ApplicationAmendmentRequestDao { ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); //cloned entity for old data and versioning ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(existingApplicationAmendment); + List amendmentRequestList = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse( + existingApplicationAmendment.getApplicationEvaluationEntity().getId() + ); + // Check if this is the last amendment being closed + boolean isLastRemaining = amendmentRequestList.stream() + .filter(amendment -> !amendment.getId().equals(id)) // Exclude the current amendment + .allMatch(amendment -> amendment.getStatus().equals(ApplicationAmendmentRequestEnum.CLOSE.getValue())); + + if (isLastRemaining) { + log.info("The current amendment is the last remaining one to be closed."); + applicationAmendmentRequestDao.calculateEndDateAndSuspensionDays(existingApplicationAmendment.getApplicationEvaluationEntity()); + } setIfUpdated(existingApplicationAmendment::getInternalNote, existingApplicationAmendment::setInternalNote, closeAmendmentRequest.getInternalNote()); setIfUpdated(existingApplicationAmendment::getStatus, existingApplicationAmendment::setStatus, ApplicationAmendmentRequestEnum.CLOSE.getValue()); ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment, oldApplicationAmendmentEntity, VersionActionTypeEnum.UPDATE); - ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment); + ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment,false); List amendmentRequests = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse( existingApplicationAmendment.getApplicationEvaluationEntity().getId()); @@ -837,6 +1020,11 @@ public class ApplicationAmendmentRequestDao { AssignedApplicationsEntity oldAssignedApplicationData = Utils.getClonedEntityForData(assignedApplicationsEntity); assignedApplicationsEntity = assignedApplicationsRepository.save(existingApplicationAmendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity()); + + Map placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.AMENDMENT_CLOSED); + + notificationDao.sendNotificationToInstructor(placeHolders,existingApplicationAmendment.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_CLOSED); + /** This code is responsible for adding a version history log for the "Update Application Evaluation" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity) .newData(existingApplicationEvaluationEntity).build()); @@ -856,22 +1044,21 @@ public class ApplicationAmendmentRequestDao { return response; } + public ApplicationAmendmentRequestResponse extendResponseDays(Long id, Long newResponseDays) { - ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.APPLICATION_AMENDMENT_NOT_FOUND_MSG))); + ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id); if (newResponseDays != null && newResponseDays > 0) { - ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(applicationAmendmentRequestEntity); + ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(applicationAmendmentRequestEntity); Long currentResponseDays = applicationAmendmentRequestEntity.getResponseDays() != null ? applicationAmendmentRequestEntity.getResponseDays() : 0L; applicationAmendmentRequestEntity.setResponseDays(currentResponseDays + newResponseDays); + applicationAmendmentRequestEntity.setEndDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now().plusDays(applicationAmendmentRequestEntity.getResponseDays()))); applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationAmendmentEntity).newData(applicationAmendmentRequestEntity).build()); - } - return convertEntityToResponse(applicationAmendmentRequestEntity); + return convertEntityToResponse(applicationAmendmentRequestEntity,false); } public List getAmendmentByApplicationId(HttpServletRequest request, Long applicationId, List statuses) { @@ -896,7 +1083,7 @@ public class ApplicationAmendmentRequestDao { List response = new ArrayList<>(); if (applicationAmendmentRequestEntity != null) { response = applicationAmendmentRequestEntity.stream() - .map(this::convertEntityToResponse) + .map(entity -> convertEntityToResponse(entity, false)) .collect(Collectors.toList()); } return response; @@ -908,7 +1095,7 @@ public class ApplicationAmendmentRequestDao { log.info("Updating application amendment with status: {}", id); ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id); ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(existingApplicationAmendment); - if (Boolean.TRUE.equals(existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())) || Boolean.TRUE.equals(statusTypeEnum.equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED))) { + if (Boolean.TRUE.equals(existingApplicationAmendment.getStatus().equals(ApplicationAmendmentRequestEnum.AWAITING.getValue())) && Boolean.TRUE.equals(statusTypeEnum.equals(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED))) { existingApplicationAmendment.setStatus(ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue()); existingApplicationAmendment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); applicationAmendmentRequestRepository.save(existingApplicationAmendment); @@ -916,7 +1103,7 @@ public class ApplicationAmendmentRequestDao { /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationAmendmentEntity).newData(existingApplicationAmendment).build()); } - ApplicationAmendmentRequestResponse response = convertEntityToResponse(existingApplicationAmendment); + ApplicationAmendmentRequestResponse response = convertEntityToResponse(existingApplicationAmendment,false); log.info("Amendment status updated successfully: {}", response); return response; } @@ -966,13 +1153,32 @@ public class ApplicationAmendmentRequestDao { LocalDateTime dueDate = amendment.getStartDate().plusDays(amendment.getResponseDays()); bodyPlaceholders.put("{{amendment_due_date}}", DateTimeUtil.formatLocalDateTime(dueDate, GepafinConstant.DD_MM_YYYY)); } else { - bodyPlaceholders.put("{{amendment_due_date}}", "Not available"); } return Utils.replacePlaceholders(template.getHtmlContent(), bodyPlaceholders); } + public ApplicationEvaluationEntity calculateEndDateAndSuspensionDays(ApplicationEvaluationEntity applicationEvaluationEntity){ + LocalDateTime currentDate=DateTimeUtil.DateServerToUTC(LocalDateTime.now()); + LocalDateTime endDate=currentDate.plusDays(applicationEvaluationEntity.getRemainingDays()); + Long suspendedDays = ChronoUnit.DAYS.between(applicationEvaluationEntity.getStopDateTime(), currentDate); + + ApplicationEvaluationEntity oldApplicationEvaluationEntity = Utils.getClonedEntityForData(applicationEvaluationEntity); + applicationEvaluationEntity.setEndDate(endDate); + if(applicationEvaluationEntity.getSuspendedDays() == null) { + applicationEvaluationEntity.setSuspendedDays(0L); + } + applicationEvaluationEntity.setSuspendedDays(applicationEvaluationEntity.getSuspendedDays()+suspendedDays); + ApplicationEvaluationEntity applicationEvaluation = applicationEvaluationRepository.save(applicationEvaluationEntity); + + /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity).newData(applicationEvaluation).build()); + + return applicationEvaluation; + + + } private void softDeleteDocument(Long documentId) { documentService.deleteFile(documentId); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 697a8e0b..0b0edf19 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -10,10 +10,12 @@ import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBea import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; import net.gepafin.tendermanagement.model.request.EmailLogRequest; +import net.gepafin.tendermanagement.model.request.NotificationReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.service.ApplicationEvaluationService; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.DocumentService; @@ -148,6 +150,9 @@ public class ApplicationDao { @Autowired private EmailLogDao emailLogDao; + + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; @Autowired private LoggingUtil loggingUtil; @@ -156,14 +161,29 @@ public class ApplicationDao { private HttpServletRequest request; @Autowired - private TokenProvider tokenProvider; + private ApplicationEvaluationService applicationEvaluationService; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); // callService.validatePublishedCall(formEntity.getCall().getId()); validateFormFields(applicationRequestBean,formEntity); ApplicationEntity applicationEntity = validateApplication(applicationId); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); if(Boolean.FALSE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.DRAFT.getValue()))) { throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS)); } @@ -172,12 +192,10 @@ 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()); + public void validateDelegation(UserEntity user, UserWithCompanyEntity userWithCompany) { UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository - .findByUserIdAndCompanyIdAndStatus(user.getId(), company.getId(), + .findByUserIdAndUserWithCompanyIdAndStatus(user.getId(), userWithCompany.getId(), UserCompanyDelegationStatusEnum.ACTIVE.getValue()); if (!userWithCompany.getIsLegalRepresentant() && userCompanyDelegationEntity == null) { @@ -200,13 +218,14 @@ public class ApplicationDao { return applicationFormEntity; } - public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, CompanyEntity companyEntity) { - validateDelegation(user,companyEntity); + public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, UserWithCompanyEntity userWithCompany) { + validateDelegation(user,userWithCompany); ApplicationEntity entity = new ApplicationEntity(); entity.setUserId(user.getId()); - entity.setCompany(companyEntity); + entity.setCompanyId(userWithCompany.getCompanyId()); entity.setCall(call); entity.setHubId(call.getHub().getId()); + entity.setUserWithCompany(userWithCompany); entity.setIsDeleted(false); entity.setStatus(ApplicationStatusTypeEnum.DRAFT.getValue()); return entity; @@ -275,9 +294,11 @@ public class ApplicationDao { log.info("Deleting application with ID: {}", id); - ApplicationEntity applicationEntity = validateApplication(id); + ApplicationEntity applicationEntity= validateApplication(id); + ApplicationEntity oldApplicationDataEntity = Utils.getClonedEntityForData(applicationEntity); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); applicationEntity.setIsDeleted(true); applicationEntity = applicationRepository.save(applicationEntity); @@ -348,9 +369,9 @@ public class ApplicationDao { 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)); - } + if (companyId != null) { + predicate = builder.and(predicate, builder.equal(root.get("companyId"), companyId)); + } if (statusList != null && !statusList.isEmpty()) { List statusNames = statusList.stream() .map(Enum::name) @@ -381,8 +402,19 @@ public class ApplicationDao { responseBean.setSubmissionDate(applicationEntity.getSubmissionDate()); responseBean.setStatus(applicationEntity.getStatus()); responseBean.setComments(applicationEntity.getComments()); - responseBean.setCompanyId(applicationEntity.getCompany().getId()); - responseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); + responseBean.setCompanyId(applicationEntity.getCompanyId()); + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId()); + if(assignedApplicationsOptional.isPresent()){ + responseBean.setAssignedUserId(assignedApplicationsOptional.get().getUserId()); + UserEntity user = userService.validateUser(assignedApplicationsOptional.get().getUserId()); + String firstName = user.getFirstName() != null ? user.getFirstName() : ""; + String lastName = user.getLastName() != null ? user.getLastName() : ""; + String userName = String.join(" ", firstName, lastName).trim(); + responseBean.setAssignedUserName(userName); + } + CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); + responseBean.setCompanyName(company.getCompanyName()); if(applicationEntity.getProtocol() != null) { responseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } @@ -453,7 +485,7 @@ public class ApplicationDao { if (applicationFormFieldEntity1.getFieldId().equals(applicationFormFieldRequestBean.getFieldId())) { applicationFormFieldEntity = applicationFormFieldEntity1; oldApplicationFormFieldData = Utils.getClonedEntityForData(applicationFormFieldEntity); - if (applicationFormEntity.getForm().getId().equals(applicationFormEntity.getApplication().getCall().getInitialForm())) { + if (applicationFormEntity.getForm().getId().equals(applicationFormEntity.getApplication().getCall().getInitialForm()) && checkIfRequestFieldIsDifferent(applicationFormFieldEntity1, applicationFormFieldRequestBean)) { validateRequiredFields(applicationFormEntity.getForm(), applicationFormEntity.getApplication(), applicationFormFieldRequestBean.getFieldId()); } actionType = VersionActionTypeEnum.UPDATE; @@ -489,7 +521,30 @@ public class ApplicationDao { return applicationFormField; } - void updateDocumentDeletionStatus(ApplicationFormFieldEntity applicationFormFieldEntity, ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity, List newDocumentIds, + private Boolean checkIfRequestFieldIsDifferent(ApplicationFormFieldEntity applicationFormFieldEntity, + ApplicationFormFieldRequestBean applicationFormFieldRequestBean) { + + // Retrieve the field values from both objects + String entityFieldValue = applicationFormFieldEntity.getFieldValue(); + Object requestFieldValue = applicationFormFieldRequestBean.getFieldValue(); + + // Check if both are null + if (entityFieldValue == null && requestFieldValue == null) { + return false; // No difference if both are null + } + + // Compare values + Boolean check = !Objects.equals(entityFieldValue, requestFieldValue); + + // Additional comparison if both are non-null + if (Boolean.TRUE.equals(check) && entityFieldValue != null && requestFieldValue != null) { + check = !entityFieldValue.equals(requestFieldValue.toString()); + } + + return check; + } + + void updateDocumentDeletionStatus(ApplicationFormFieldEntity applicationFormFieldEntity, ApplicationFormFieldRequestBean applicationFormFieldRequestBean, FormEntity formEntity, List newDocumentIds, List preInstructorDocumentId,boolean isPreInstructor) { if (newDocumentIds == null) { newDocumentIds = Collections.emptyList(); @@ -750,11 +805,12 @@ public class ApplicationDao { applicationGetResponseBean.setSubmissionDate(applicationEntity.getSubmissionDate()); applicationGetResponseBean.setCallId(applicationEntity.getCall().getId()); applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName()); - applicationGetResponseBean.setCompanyId(applicationEntity.getCompany().getId()); + applicationGetResponseBean.setCompanyId(applicationEntity.getCompanyId()); if(applicationEntity.getProtocol() != null) { applicationGetResponseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } - applicationGetResponseBean.setCompanyName(applicationEntity.getCompany().getCompanyName()); + CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); + applicationGetResponseBean.setCompanyName(company.getCompanyName()); return applicationGetResponseBean; } @@ -771,19 +827,21 @@ public class ApplicationDao { public ApplicationResponse createApplicationByCallId(CompanyEntity companyEntity, ApplicationRequest applicationRequest, Long callId, UserEntity userEntity) { CallEntity call = callService.validateCall(callId); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyEntity.getId()); + // call = callService.validatePublishedCall(call.getId()); - checkIfApplicationExists(call, companyEntity, userEntity); - ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, companyEntity); +// checkIfApplicationExists(call, userWithCompanyEntity, userEntity); + ApplicationEntity applicationEntity = createApplicationEntity(userEntity, call, userWithCompanyEntity); applicationEntity.setComments(applicationRequest.getComments()); applicationEntity = saveApplicationEntity(applicationEntity); return getApplicationResponse(applicationEntity); } - 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 void checkIfApplicationExists(CallEntity call, UserWithCompanyEntity userWithCompanyEntity, UserEntity userEntity){ +// Optional applicationEntity=applicationRepository.findByUserIdAndUserWithCompanyIdAndCallIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId(),call.getId()); +// if(applicationEntity.isPresent()){ +// throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_ALREADY_EXISTS)); +// } +// } public ApplicationResponse updateApplicationStatus(HttpServletRequest request, Long applicationId, ApplicationStatusTypeEnum status) { @@ -793,7 +851,7 @@ public class ApplicationDao { ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity); UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); if (ApplicationStatusTypeEnum.SUBMIT.getValue().equals(applicationEntity.getStatus())) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_SUBMITTED_CANNOT_CHANGE)); } @@ -804,11 +862,13 @@ public class ApplicationDao { if (status.equals(ApplicationStatusTypeEnum.SUBMIT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.READY.getValue()))) { callService.validatePublishedCall(applicationEntity.getCall().getId(), userEntity.getHub().getId()); Long protocolNumber = protocolDao.getProtocolNumber(userEntity.getHub()); - ProtocolEntity protocolEntity = protocolDao.createProtocolEntity(applicationEntity, protocolNumber, userEntity.getHub().getId()); + ProtocolEntity protocolEntity = protocolDao.createProtocolEntity(applicationEntity, protocolNumber, userEntity.getHub().getId(),true); applicationEntity.setProtocol(protocolEntity); applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue()); applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); applicationEntity = applicationRepository.save(applicationEntity); + Map placeHolders=notificationDao.sendNotificationToBeneficiary(applicationEntity,NotificationTypeEnum.APPLICATION_SUBMISSION); + notificationDao.sendNotificationToSuperUser(applicationEntity,placeHolders,NotificationTypeEnum.APPLICATION_SUBMISSION); /** This code is responsible for adding a version history log for "Update application status" operation. **/ loggingUtil.addVersionHistory( @@ -821,6 +881,9 @@ public class ApplicationDao { if (status.equals(ApplicationStatusTypeEnum.DRAFT) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.AWAITING.getValue()))) { applicationEntity.setStatus(status.getValue()); } + if(status.equals(ApplicationStatusTypeEnum.ADMISSIBLE) && Boolean.TRUE.equals(applicationEntity.getStatus().equals(ApplicationStatusTypeEnum.APPOINTMENT.getValue()))){ + applicationEntity.setStatus(status.getValue()); + } applicationEntity = applicationRepository.save(applicationEntity); if (!status.equals(ApplicationStatusTypeEnum.SUBMIT)) { @@ -917,8 +980,9 @@ public class ApplicationDao { private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) { CallEntity call =applicationEntity.getCall(); - CompanyEntity company = applicationEntity.getCompany(); - ProtocolEntity protocol = applicationEntity.getProtocol(); + CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); + UserWithCompanyEntity userWithCompany=companyService.getUserWithCompany(userEntity.getId(),company.getId()); + ProtocolEntity protocol= applicationEntity.getProtocol(); HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService .retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY, @@ -949,8 +1013,8 @@ public class ApplicationDao { emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email),emailLogRequest); List recipientEmails = new ArrayList<>(); // recipientEmails.add(email); - String companyEmail = company.getEmail(); - String contactEmail = company.getContactEmail(); + String companyEmail = userWithCompany.getEmail(); + String contactEmail = userWithCompany.getContactEmail(); if (companyEmail != null && !companyEmail.isEmpty()) { recipientEmails.add(companyEmail); @@ -960,7 +1024,7 @@ public class ApplicationDao { recipientEmails.add(contactEmail); } if(Boolean.FALSE.equals(recipientEmails.isEmpty())){ - emailLogRequest.setRecipientId(applicationEntity.getCompany().getId()); + emailLogRequest.setRecipientId(applicationEntity.getCompanyId()); emailLogRequest.setRecipientType(RecipientTypeEnum.COMPANY); emailLogRequest.setRecipientEmails(companyEmail); } @@ -968,7 +1032,7 @@ public class ApplicationDao { } private void sendMailTodefaultSystemAndGepafin(UserEntity userEntity, ApplicationEntity applicationEntity) { CallEntity call = applicationEntity.getCall(); - CompanyEntity company = applicationEntity.getCompany(); + CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); ProtocolEntity protocol = applicationEntity.getProtocol(); HubEntity hub = hubService.valdateHub(applicationEntity.getHubId()); SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService @@ -1008,14 +1072,13 @@ public class ApplicationDao { emailLogRequest.setRecipientEmails(rinaldoEmail); emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(rinaldoEmail),emailLogRequest); } + public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, + MultipartFile file) { + ApplicationEntity applicationEntity = validateApplication(applicationId); - public ApplicationSignedDocumentResponse uploadSignedDocument(HttpServletRequest request, Long applicationId, MultipartFile file) { - - ApplicationEntity applicationEntity = validateApplication(applicationId); //cloned entity for old data ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(applicationEntity); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); validateFileTypeForCall(file, applicationEntity); ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue()); @@ -1069,7 +1132,7 @@ public class ApplicationDao { } private String generateS3PathForDelegation(Long callId, Long applicationId) { try { - return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId); + return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId,0L); } catch (IllegalArgumentException e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); } @@ -1103,7 +1166,14 @@ public class ApplicationDao { public ApplicationSignedDocumentResponse getSignedDocument(HttpServletRequest request, Long applicationId) { ApplicationEntity applicationEntity = validateApplication(applicationId); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); +// validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); + + if (validator.checkIsPreInstructor()) { + ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluationByApplicationId(applicationId); + validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId()); + } else { + validator.validateUserId(request, applicationEntity.getUserId()); + } ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue()); @@ -1113,23 +1183,22 @@ public class ApplicationDao { } 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()); - //cloned entity for old data + + public void deleteSignedDocument(HttpServletRequest request, Long applicationId) { + ApplicationEntity applicationEntity = validateApplication(applicationId); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); + + ApplicationSignedDocumentEntity applicationSignedDocument = applicationSignedDocumentRepository + .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue()); + //cloned entity for old data ApplicationSignedDocumentEntity oldApplicationSignedDocument = Utils.getClonedEntityForData(applicationSignedDocument); - if (applicationSignedDocument == null) { - throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND)); - } - applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue()); - applicationSignedDocument = applicationSignedDocumentRepository.save(applicationSignedDocument); + if(applicationSignedDocument == null) { + throw new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_SIGNED_DOCUMENT_NOT_FOUND)); + } + applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue()); + applicationSignedDocument = applicationSignedDocumentRepository.save(applicationSignedDocument); - /** This code is responsible for adding a version history log for the "Delete signed document" operation. **/ loggingUtil.addVersionHistory( VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationSignedDocument).newData(applicationSignedDocument) .build()); @@ -1138,11 +1207,10 @@ public class ApplicationDao { public ApplicationResponse validateApplication(HttpServletRequest request, Long applicationId) { ApplicationEntity applicationEntity = validateApplication(applicationId); - ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity); - - userService.validateUser(applicationEntity.getUserId()); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + + UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); if (Boolean.FALSE.equals(ApplicationStatusTypeEnum.DRAFT.getValue().equals(applicationEntity.getStatus()))) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS)); } @@ -1164,90 +1232,121 @@ public class ApplicationDao { } public byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId) { + ApplicationEntity applicationEntity = validateApplication(applicationId); validateAssignedUser(request, applicationId); - Set documentIds = extractDocumentIdsFromApplicationForms(applicationId); List documents = documentRepository.findAllByIdInAndIsDeletedFalse(documentIds); - - ApplicationSignedDocumentEntity signedDocument = applicationSignedDocumentRepository - .findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue()); - if (documents.isEmpty() && signedDocument == null) { + ApplicationSignedDocumentEntity signedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId, + ApplicationSignedDocumentStatusEnum.ACTIVE.getValue()); + List amendmentDocuments = fetchAmendmentDocuments(applicationId); + List evaluationDocuments = fetchEvaluationDocuments(applicationId); + if (documents.isEmpty() && signedDocument == null && amendmentDocuments.isEmpty() && evaluationDocuments.isEmpty()) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND)); } - return createZipWithDocuments(applicationEntity, documents, signedDocument, applicationId); + return createZipWithDocuments(applicationEntity, documents, signedDocument, amendmentDocuments, evaluationDocuments, applicationId); } + private void validateAssignedUser(HttpServletRequest request, Long applicationId) { - AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository - .findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); + + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); if (assignedApplications != null) { validator.validatePreInstructor(request, assignedApplications.getUserId()); } } private Set extractDocumentIdsFromApplicationForms(Long applicationId) { + Set documentIds = new HashSet<>(); List applicationForms = applicationFormRepository.findByApplicationId(applicationId); - applicationForms.forEach(applicationForm -> { FormEntity formEntity = applicationForm.getForm(); if (formEntity != null) { List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); - contentResponseBeans.stream() - .filter(content -> "fileupload".equals(content.getName())) - .forEach(content -> { - Optional formField = applicationFormFieldRepository - .findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( - content.getId(), applicationForm.getId(), applicationId); - formField.ifPresent(field -> { - if (field.getFieldValue() != null) { - Arrays.stream(field.getFieldValue().split(",")) - .map(String::trim) - .map(Long::valueOf) - .forEach(documentIds::add); - } - }); - }); + contentResponseBeans.stream().filter(content -> "fileupload".equals(content.getName())).forEach(content -> { + Optional formField = applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + content.getId(), applicationForm.getId(), applicationId); + formField.ifPresent(field -> { + if (field.getFieldValue() != null) { + Arrays.stream(field.getFieldValue().split(",")).map(String::trim).map(Long::valueOf).forEach(documentIds::add); + } + }); + }); } }); return documentIds; } - private void addDocumentToZip(ZipOutputStream zos, String s3Folder, String filePath, String fileName) { + private List fetchAmendmentDocuments(Long applicationId) { + + List amendmentRequests = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId); + Set amendmentIds = amendmentRequests.stream().map(ApplicationAmendmentRequestEntity::getId).collect(Collectors.toSet()); + return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(amendmentIds, DocumentSourceTypeEnum.AMENDMENT.getValue()); + } + private List fetchEvaluationDocuments(Long applicationId) { + + Optional evaluationEntity = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationId); + if (evaluationEntity.isPresent()) { + Long evaluationId = evaluationEntity.get().getId(); + return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(Collections.singleton(evaluationId), DocumentSourceTypeEnum.EVALUATION.getValue()); + } + return Collections.emptyList(); + } + private String fetchProtocolNumberForAmendment(Long amendmentRequestId) { + + ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentRequestId).orElse(null); + if (amendmentRequest != null && amendmentRequest.getProtocol() != null) { + return amendmentRequest.getProtocol().getProtocolNumber().toString(); + } + return "unknown"; + } + private void addDocumentToZip(ZipOutputStream zos, String s3Folder, String filePath, String fullPath) { + try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, filePath)) { - zos.putNextEntry(new ZipEntry(fileName)); + zos.putNextEntry(new ZipEntry(fullPath)); IOUtils.copy(fileInputStream, zos); zos.closeEntry(); } catch (IOException e) { - throw new RuntimeException("Error downloading or adding document to ZIP: " + fileName, e); + throw new RuntimeException("Error downloading or adding document to ZIP: " + fullPath, e); } } + private byte[] createZipWithDocuments(ApplicationEntity applicationEntity, List documents, ApplicationSignedDocumentEntity signedDocument, + List amendmentDocuments, List evaluationDocuments, Long applicationId) { - private byte[] createZipWithDocuments(ApplicationEntity applicationEntity, List documents, - ApplicationSignedDocumentEntity signedDocument, Long applicationId) { - try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) { - - String s3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, applicationEntity.getCall().getId(), applicationId); - + try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) { + Long callId = applicationEntity.getCall().getId(); + // Add Application Documents + String appS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, callId, applicationId, 0L); for (DocumentEntity document : documents) { String fileName = Utils.extractFileName(document.getFilePath()); - addDocumentToZip(zos, s3Folder, document.getFilePath(), fileName); + addDocumentToZip(zos, appS3Folder, document.getFilePath(), fileName); } - + // Add Signed Document if (signedDocument != null) { - String signedDocS3Folder = s3PathConfig.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, applicationEntity.getCall().getId(), applicationId); - String signedDocFileName = signedDocument.getFileName(); - addDocumentToZip(zos, signedDocS3Folder, signedDocument.getFilePath(), signedDocFileName); + String signedFolder = "SIGNED_DOCUMENT/"; + String signedDocS3Folder = s3PathConfig.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId, 0L); + String fileName = signedDocument.getFileName(); + addDocumentToZip(zos, signedDocS3Folder, signedDocument.getFilePath(), signedFolder + fileName); + } + // Add Amendment (Soccorso) Documents + for (DocumentEntity amendmentDocument : amendmentDocuments) { + String protocolNumber = fetchProtocolNumberForAmendment(amendmentDocument.getSourceId()); + String amendmentFolder = "SOCCORSO_" + protocolNumber + "/"; + String amendmentS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.AMENDMENT, callId, applicationId, amendmentDocument.getSourceId()); + String fileName = Utils.extractFileName(amendmentDocument.getFilePath()); + addDocumentToZip(zos, amendmentS3Folder, amendmentDocument.getFilePath(), amendmentFolder + fileName); + } + // Add Evaluation Documents + for (DocumentEntity evaluationDocument : evaluationDocuments) { + String evaluationFolder = "EVALUATION/"; + String evaluationS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.EVALUATION, callId, applicationId, evaluationDocument.getSourceId()); + String fileName = Utils.extractFileName(evaluationDocument.getFilePath()); + addDocumentToZip(zos, evaluationS3Folder, evaluationDocument.getFilePath(), evaluationFolder + fileName); } - zos.finish(); return zipOutputStream.toByteArray(); - } catch (IOException e) { throw new RuntimeException("Error while creating ZIP file", e); } } - - } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 9c0c8d90..5992314b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -2,7 +2,6 @@ package net.gepafin.tendermanagement.dao; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; @@ -12,23 +11,25 @@ import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.*; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; -import net.gepafin.tendermanagement.service.ApplicationService; -import net.gepafin.tendermanagement.service.AssignedApplicationsService; -import net.gepafin.tendermanagement.service.CallService; -import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.service.*; +import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.util.Validator; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; -import static org.apache.commons.lang3.StringUtils.isNumeric; @Component public class ApplicationEvaluationDao { @@ -91,6 +92,24 @@ public class ApplicationEvaluationDao { @Autowired private HttpServletRequest request; + @Autowired + private CompanyService companyService; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private UserRepository userRepository; + + @Autowired + private Validator validator; + + @Autowired + private DocumentService documentService; + + @Autowired + private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; + private ApplicationEvaluationEntity convertToEntity(UserEntity user, ApplicationEvaluationRequest req, Long assignedApplciationId) { ApplicationEvaluationEntity entity = new ApplicationEvaluationEntity(); @@ -106,6 +125,11 @@ public class ApplicationEvaluationDao { entity.setNote(req.getNote()); entity.setMotivation(req.getMotivation()); entity.setIsDeleted(false); + entity.setInitialDays(30L); + entity.setRemainingDays(30L); + entity.setSuspendedDays(0L); + entity.setStartDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + entity.setEndDate(DateTimeUtil.DateServerToUTC(application.getSubmissionDate().plusDays(30))); entity.setStatus(ApplicationEvaluationStatusTypeEnum.OPEN.getValue()); return entity; } @@ -121,16 +145,103 @@ public class ApplicationEvaluationDao { List checklistEntities = callTargetAudienceChecklistRepository .findByCallIdAndLookupDataTypeAndIsDeletedFalse(call.getId(), LookUpDataEntity.LookUpDataTypeEnum.CHECKLIST.getValue()); List applicationFormEntities = applicationFormRepository.findByApplicationId(entity.getApplicationId()); + setAmendmentDetails(entity,response); setCriteriaResponses(entity, response, evaluationCriterias); setChecklistResponses(entity, response, checklistEntities); setFieldResponses(entity, response, applicationFormEntities); - + List allDocs = prepareEvaluationDocumentBeanList(entity); + setEvaluationDocResponse(response, allDocs); setApplicationDetails(response, entity); return response; } + private void setAmendmentDetails(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response) { + List amendmentRequests=applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(entity.getId()); + List amendmentDocumentResponseBeans=new ArrayList<>(); + for(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity:amendmentRequests){ + AmendmentDocumentResponseBean amendmentDocumentResponseBean=new AmendmentDocumentResponseBean(); + amendmentDocumentResponseBean.setAmendmentId(applicationAmendmentRequestEntity.getId()); + String amendmentDocument=applicationAmendmentRequestEntity.getAmendmentDocument(); + String formField=applicationAmendmentRequestEntity.getFormFields(); + AmendmentDetailsResponseBean amendmentDetails = Utils.convertStringToObject(amendmentDocument, AmendmentDetailsResponseBean.class); + if (amendmentDetails != null) { + if (amendmentDetails.getAmendmentDocuments() != null) { + List documentResponseBeans = Arrays.stream(amendmentDetails.getAmendmentDocuments().split(",")) + .map(String::trim) + .filter(id -> !id.isEmpty()) + .map(documentId -> applicationAmendmentRequestDao.createDocumentResponseBean(documentId)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + amendmentDocumentResponseBean.setFileDetail(documentResponseBeans); + } + amendmentDocumentResponseBean.setFieldId("amend_" + applicationAmendmentRequestEntity.getId()); + amendmentDocumentResponseBean.setLabel(amendmentDetails.getAmendmentNotes()); + amendmentDocumentResponseBean.setValid(amendmentDetails.getValid()); + amendmentDocumentResponseBeans.add(amendmentDocumentResponseBean); + } + List amendmentFormFields = Utils.convertJsonStringToList(formField, AmendmentFormField.class); + if (amendmentFormFields != null) { + for (AmendmentFormField amendmentFormField : amendmentFormFields) { + // Skip fields with null or empty fieldValue + if (StringUtils.isEmpty(amendmentFormField.getFieldValue())) { + continue; + } + + AmendmentDocumentResponseBean formFieldResponseBean = new AmendmentDocumentResponseBean(); + formFieldResponseBean.setAmendmentId(applicationAmendmentRequestEntity.getId()); + formFieldResponseBean.setFieldId(amendmentFormField.getFieldId()); + formFieldResponseBean.setLabel(amendmentFormField.getLabel()); + formFieldResponseBean.setValid(amendmentFormField.getValid()); + + List fileIds = applicationAmendmentRequestDao.extractIds(amendmentFormField.getFieldValue()); + List documentResponseBeans = fileIds.stream() + .map(fileId -> createDocumentResponseBean(documentService.validateDocument(fileId))) + .collect(Collectors.toList()); + + formFieldResponseBean.setFileDetail(documentResponseBeans); + amendmentDocumentResponseBeans.add(formFieldResponseBean); + } + } + } + + response.setAmendmentDetails(amendmentDocumentResponseBeans); + } + + private void setEvaluationDocResponse(ApplicationEvaluationResponse response, List docRequest) { + List evaluationDocResponses = new ArrayList<>(); + + for (EvaluationDocumentRequest doc : docRequest) { + EvaluationDocumentResponse evaluationDocResponse = new EvaluationDocumentResponse(); + if (doc.getFileValue() != null) { + Long fileId = Long.valueOf(doc.getFileValue().toString()); + documentRepository.findByIdAndNotDeleted(fileId).ifPresent(documentEntity -> { + DocumentResponseBean documentResponseBean = new DocumentResponseBean(); + documentResponseBean.setId(documentEntity.getId()); + documentResponseBean.setName(documentEntity.getFileName()); + documentResponseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + documentResponseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + documentResponseBean.setSourceId(documentEntity.getSourceId()); + documentResponseBean.setFilePath(documentEntity.getFilePath()); + documentResponseBean.setCreatedDate(documentEntity.getCreatedDate()); + documentResponseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + documentResponseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); + evaluationDocResponse.setFileValue(List.of(documentResponseBean)); + evaluationDocResponse.setNameValue(doc.getNameValue()); + evaluationDocResponse.setValid(doc.getValid()); + evaluationDocResponse.setFieldId(doc.getFieldId()); + }); + } + if (evaluationDocResponse.getFileValue() == null) { + continue; + } + evaluationDocResponses.add(evaluationDocResponse); + } + response.setEvaluationDocument(evaluationDocResponses); + } + private void populateBasicDetails(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response) { response.setId(entity.getId()); @@ -140,6 +251,7 @@ public class ApplicationEvaluationDao { response.setNote(entity.getNote()); response.setMotivation(entity.getMotivation()); response.setStatus(ApplicationEvaluationStatusTypeEnum.valueOf(entity.getStatus())); + response.setEvaluationEndDate(entity.getEndDate()); response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); } @@ -148,28 +260,32 @@ public class ApplicationEvaluationDao { private void setCriteriaResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List evaluationCriterias) { List criteriaResponsesFromEntity = entity.getCriteria() != null ? - Utils.convertJsonToList(entity.getCriteria(), new TypeReference>() { - }) : + Utils.convertJsonToList(entity.getCriteria(), new TypeReference>() {}) : new ArrayList<>(); - List criteriaResponsesFromDB = getCriteriaResponse(entity.getApplicationId()); addMissingCriteriaResponses(criteriaResponsesFromEntity, criteriaResponsesFromDB, entity.getApplicationId()); - criteriaResponsesFromEntity.forEach(criteriaResponse -> { - EvaluationCriteriaEntity matchingEvaluationCriteria = evaluationCriterias.stream() - .filter(evaluationCriteria -> evaluationCriteria.getId().equals(criteriaResponse.getId())).findFirst().orElse(null); - if (matchingEvaluationCriteria != null) { - criteriaResponse.setLabel(matchingEvaluationCriteria.getLookupData().getValue()); - criteriaResponse.setMaxScore(matchingEvaluationCriteria.getScore()); - - List mappedFields = getMappedFieldsForCriteria(matchingEvaluationCriteria.getId(), entity.getApplicationId()); - criteriaResponse.setCriteriaMappedFields(mappedFields); - } - }); + criteriaResponsesFromEntity = criteriaResponsesFromEntity.stream() + .filter(criteriaResponse -> { + EvaluationCriteriaEntity matchingEvaluationCriteria = evaluationCriterias.stream() + .filter(evaluationCriteria -> evaluationCriteria.getId().equals(criteriaResponse.getId())) // Find matching criteria by ID + .findFirst() + .orElse(null); + if (matchingEvaluationCriteria != null) { + criteriaResponse.setLabel(matchingEvaluationCriteria.getLookupData().getValue()); + criteriaResponse.setMaxScore(matchingEvaluationCriteria.getScore()); + List mappedFields = getMappedFieldsForCriteria(matchingEvaluationCriteria.getId(), entity.getApplicationId()); + criteriaResponse.setCriteriaMappedFields(mappedFields); + return true; + } + return false; + }) + .collect(Collectors.toList()); response.setCriteria(criteriaResponsesFromEntity); } + private void addMissingCriteriaResponses(List criteriaResponsesFromEntity, List criteriaResponsesFromDB, Long applicationId) { Set existingCriteriaIds = criteriaResponsesFromEntity.stream().map(CriteriaResponse::getId).collect(Collectors.toSet()); @@ -256,7 +372,8 @@ public class ApplicationEvaluationDao { Optional formFieldEntityOptional = applicationFormFieldRepository .findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(formFieldId, applicationFormId, applicationId); - if (formFieldEntityOptional.isPresent()) { + if (formFieldEntityOptional.isPresent() && formFieldEntityOptional.get().getFieldValue()!=null && Boolean.FALSE.equals(formFieldEntityOptional.get() + .getFieldValue().isEmpty())) { String[] documentIds = formFieldEntityOptional.get().getFieldValue().split(","); List documentResponseBeans = new ArrayList<>(); @@ -273,6 +390,7 @@ public class ApplicationEvaluationDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); documentResponseBeans.add(responseBean); }); } @@ -290,27 +408,30 @@ public class ApplicationEvaluationDao { private void setChecklistResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List checklistEntities) { - List checklistResponsesFromEntity = entity.getChecklist() != null ? - Utils.convertJsonToList(entity.getChecklist(), new TypeReference>() { - }) : + Utils.convertJsonToList(entity.getChecklist(), new TypeReference>() {}) : new ArrayList<>(); - List checklistResponsesFromDB = getChecklistResponse(entity.getApplicationId()); addMissingChecklistResponses(checklistResponsesFromEntity, checklistResponsesFromDB); - checklistResponsesFromEntity.forEach(checklistResponse -> { - CallTargetAudienceChecklistEntity matchingChecklist = checklistEntities.stream().filter(checklistEntity -> checklistEntity.getId().equals(checklistResponse.getId())) - .findFirst().orElse(null); - - if (matchingChecklist != null) { - checklistResponse.setLabel(matchingChecklist.getLookupData().getValue()); - } - }); + checklistResponsesFromEntity = checklistResponsesFromEntity.stream() + .filter(checklistResponse -> { + CallTargetAudienceChecklistEntity matchingChecklist = checklistEntities.stream() + .filter(checklistEntity -> checklistEntity.getId().equals(checklistResponse.getId())) // Find matching checklist by ID + .findFirst() + .orElse(null); + if (matchingChecklist != null) { + checklistResponse.setLabel(matchingChecklist.getLookupData().getValue()); + return true; + } + return false; + }) + .collect(Collectors.toList()); response.setChecklist(checklistResponsesFromEntity); } + private void addMissingChecklistResponses(List checklistResponsesFromEntity, List checklistResponsesFromDB) { Set existingChecklistIds = checklistResponsesFromEntity.stream().map(ChecklistResponse::getId).collect(Collectors.toSet()); @@ -324,26 +445,31 @@ public class ApplicationEvaluationDao { private void setFieldResponses(ApplicationEvaluationEntity entity, ApplicationEvaluationResponse response, List applicationFormEntities) { - List fieldResponsesFromEntity = entity.getFile() != null ? Utils.convertJsonToList(entity.getFile(), new TypeReference>() { - }) : new ArrayList<>(); + List fieldResponsesFromEntity = entity.getFile() != null ? Utils.convertJsonToList(entity.getFile(), new TypeReference>() {}) : new ArrayList<>(); List fieldResponsesFromDB = getFieldResponses(entity.getApplicationId()); addMissingFieldResponses(fieldResponsesFromEntity, fieldResponsesFromDB); Set processedFieldIds = new HashSet<>(); + List validFieldResponses = new ArrayList<>(); fieldResponsesFromEntity.forEach(fieldResponse -> { if (processedFieldIds.contains(fieldResponse.getId())) { return; } + final Boolean[] allDocumentsDeleted = {true}; + List documentResponseBeans = new ArrayList<>(); + applicationFormEntities.forEach(applicationForm -> { FormEntity formEntity = applicationForm.getForm(); if (formEntity != null) { -// List contentResponseBeans = Utils.convertJsonStringToList(formEntity.getContent(), ContentResponseBean.class); + // Convert the form to a list of content response beans List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); contentResponseBeans.forEach(contentResponseBean -> { + // Check if this is a file upload field that matches the current field response if ("fileupload".equals(contentResponseBean.getName()) && contentResponseBean.getId().equals(fieldResponse.getId())) { String label = null; + // Set the label if available if (contentResponseBean.getSettings() != null) { for (SettingResponseBean setting : contentResponseBean.getSettings()) { if ("label".equals(setting.getName())) { @@ -362,36 +488,44 @@ public class ApplicationEvaluationDao { ApplicationFormFieldEntity formField = optionalFormField.get(); if (formField.getFieldValue() != null) { String[] documentIds = formField.getFieldValue().split(","); - List documentResponseBeans = new ArrayList<>(); for (String docId : documentIds) { - if (Boolean.FALSE.equals(docId.isEmpty())){ + if (!docId.trim().isEmpty()) { Long documentId = Long.valueOf(docId.trim()); + documentRepository.findByIdAndNotDeleted(documentId).ifPresent(documentEntity -> { - DocumentResponseBean responseBean = new DocumentResponseBean(); - responseBean.setId(documentEntity.getId()); - responseBean.setName(documentEntity.getFileName()); - responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); - responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); - responseBean.setSourceId(documentEntity.getSourceId()); - responseBean.setFilePath(documentEntity.getFilePath()); - responseBean.setCreatedDate(documentEntity.getCreatedDate()); - responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); - documentResponseBeans.add(responseBean); + if (documentEntity != null && !documentEntity.getIsDeleted()) { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(documentEntity.getId()); + responseBean.setName(documentEntity.getFileName()); + responseBean.setType(DocumentTypeEnum.valueOf(documentEntity.getType())); + responseBean.setSource(DocumentSourceTypeEnum.valueOf(documentEntity.getSource())); + responseBean.setSourceId(documentEntity.getSourceId()); + responseBean.setFilePath(documentEntity.getFilePath()); + responseBean.setCreatedDate(documentEntity.getCreatedDate()); + responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); + documentResponseBeans.add(responseBean); + allDocumentsDeleted[0] = false; + } }); } } - - fieldResponse.setFileDetail(documentResponseBeans); } } - processedFieldIds.add(fieldResponse.getId()); } }); } }); + + if (Boolean.FALSE.equals(allDocumentsDeleted[0]) && Boolean.FALSE.equals(documentResponseBeans.isEmpty())) { + fieldResponse.setFileDetail(documentResponseBeans); + validFieldResponses.add(fieldResponse); + } + + processedFieldIds.add(fieldResponse.getId()); }); - response.setFiles(fieldResponsesFromEntity); + response.setFiles(validFieldResponses); } private void addMissingFieldResponses(List fieldResponsesFromEntity, List fieldResponsesFromDB) { @@ -408,22 +542,44 @@ public class ApplicationEvaluationDao { private void setApplicationDetails(ApplicationEvaluationResponse response, ApplicationEvaluationEntity entity) { ApplicationEntity application = applicationService.validateApplication(entity.getApplicationId() != null ? entity.getApplicationId() : null); + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository + .findByApplicationIdAndIsDeletedFalse(entity.getApplicationId()).orElse(null); + UserEntity user = userService.validateUser(application.getUserId()); CallEntity call = callRepository.findCallEntityByApplicationId(entity.getApplicationId()); - String firstName = user.getFirstName() != null ? user.getFirstName() : ""; - String lastName = user.getLastName() != null ? user.getLastName() : ""; + String firstName = user.getBeneficiary().getFirstName() != null ? user.getBeneficiary().getFirstName() : ""; + String lastName = user.getBeneficiary().getLastName() != null ? user.getBeneficiary().getLastName() : ""; String beneficiary = String.join(" ", firstName, lastName).trim(); response.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(application.getStatus())); response.setBeneficiary(beneficiary); + response.setNdg(application.getNdg() != null ? application.getNdg() : null); + response.setAppointmentId(application.getAppointmentId() != null ? application.getAppointmentId() : null); + response.setSubmissionDate(application.getSubmissionDate()); response.setMinScore(call.getThreshold() != null ? call.getThreshold() : null); response.setCallName(application.getCall().getName() != null ? application.getCall().getName() : null); response.setProtocolNumber((application.getProtocol() != null && application.getProtocol().getProtocolNumber() != null) ? application.getProtocol().getProtocolNumber() : null); - response.setSubmissionDate(application.getSubmissionDate() != null ? application.getSubmissionDate() : null); - response.setEvaluationDate(application.getSubmissionDate() != null ? application.getSubmissionDate().plusDays(30) : null); + if (assignedApplications != null) { + response.setAssignedAt(assignedApplications.getAssignedAt()); + } + response.setEvaluationEndDate(entity.getEndDate()); + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(application.getId()); + if(assignedApplicationsOptional.isPresent()){ + response.setAssignedUserId(assignedApplicationsOptional.get().getUserId()); + UserEntity assignedUser = userService.validateUser(assignedApplicationsOptional.get().getUserId()); + String assignedUserFirstName = assignedUser.getFirstName() != null ? assignedUser.getFirstName() : ""; + String assignedUserLastName = assignedUser.getLastName() != null ? assignedUser.getLastName() : ""; + String userName = String.join(" ", assignedUserFirstName, assignedUserLastName).trim(); + response.setAssignedUserName(userName); + } LocalDateTime callEndDate = application.getCall().getEndDate(); response.setCallEndDate(callEndDate); + if (application.getCompanyId() != null) { + CompanyEntity company = companyService.validateCompany(application.getCompanyId()); + response.setCompanyName(company.getCompanyName()); + } } @@ -438,22 +594,47 @@ public class ApplicationEvaluationDao { Optional assignedApplications = assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplicationId); ApplicationEvaluationEntity oldApplicationEvaluation = null; - VersionActionTypeEnum actionType = VersionActionTypeEnum.INSERT; + VersionActionTypeEnum actionType; if (existingEntityOptional.isPresent()) { entity = existingEntityOptional.get(); oldApplicationEvaluation = Utils.getClonedEntityForData(entity); - entity.setCriteria(Utils.convertObjectToJson(filterNonNullCriteria(processCriteria(entity, req)))); - entity.setChecklist(Utils.convertObjectToJson(filterNonNullChecklist(processChecklist(entity, req)))); - entity.setFile(Utils.convertObjectToJson(filterNonNullFields(processField(entity, req)))); + if(req.getCriteria()!=null) { + entity.setCriteria(Utils.convertObjectToJson(processCriteria(entity, req))); + } + if(req.getChecklist()!=null) { + entity.setChecklist(Utils.convertObjectToJson(processChecklist(entity, req))); + } + if(req.getFiles()!=null) { + entity.setFile(Utils.convertObjectToJson(processField(entity, req))); + } entity.setIsDeleted(false); setIfUpdated(entity::getNote, entity::setNote, req.getNote()); setIfUpdated(entity::getMotivation, entity::setMotivation, req.getMotivation()); actionType = VersionActionTypeEnum.UPDATE; } else { + AssignedApplicationsEntity assignedApplicationsEntity = assignedApplicationsService.validateAssignedApplication(assignedApplicationId); + ApplicationEntity application = applicationService.validateApplication(assignedApplicationsEntity.getApplication().getId()); entity = convertToEntity(user, req, assignedApplicationId); actionType = VersionActionTypeEnum.INSERT; + + Map placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_CREATION); + notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_CREATION); + notificationDao.sendNotificationToInstructor(placeHolders,entity,NotificationTypeEnum.EVALUATION_CREATION); + } ApplicationStatusForEvaluation status = req.getApplicationStatus(); + // Fetch all amendment request entities associated with the evaluation ID + List applicationAmendmentRequestEntities = + applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(entity.getId()); + if(req.getEvaluationDocument()!=null) { + updateApplicationEvaluation(assignedApplicationId, req.getEvaluationDocument()); + } +// Fetch amendment details from the request + if(req.getAmendmentDetails()!=null) { + List amendmentDetailsRequests = req.getAmendmentDetails(); + + updateAmendmentDocumentsAndFormFields(applicationAmendmentRequestEntities, amendmentDetailsRequests); +} ApplicationEvaluationEntity savedEntity = applicationEvaluationRepository.save(entity); @@ -469,22 +650,212 @@ public class ApplicationEvaluationDao { } } + private void updateAmendmentDocumentsAndFormFields(List applicationAmendmentRequestEntities, List amendmentFormFields) { + // Iterate through amendment request entities - private List filterNonNullChecklist(List checklistRequests) { +// + Map> amendmentFormFieldsMap = amendmentFormFields.stream().collect(Collectors.groupingBy(AmendmentDetailsRequest::getAmendmentId,HashMap::new,Collectors.toCollection(ArrayList::new))); +// amendmentFormFields.forEach(data->{ +// ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = applicationAmendmentRequestMap.get(data.getAmendmentId()); +// if (data.getFieldId().contains("amend_")){ +// updateAmendmentDocument(applicationAmendmentRequestEntity, data); +// } +// }); + applicationAmendmentRequestEntities.forEach(applicationAmendmentRequestEntity->{ + ApplicationAmendmentRequestEntity oldEntity = Utils.getClonedEntityForData(applicationAmendmentRequestEntity); + updateAmendment(applicationAmendmentRequestEntity, amendmentFormFieldsMap.get(applicationAmendmentRequestEntity.getId())); + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().actionType(VersionActionTypeEnum.UPDATE).oldData(oldEntity).newData(applicationAmendmentRequestEntity).build()); + }); + applicationAmendmentRequestRepository.saveAll(applicationAmendmentRequestEntities); - return checklistRequests.stream().filter(request -> request.getValid() != null).collect(Collectors.toList()); + +// for (ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity : applicationAmendmentRequestEntities) { +// // Process form fields if present +// if (applicationAmendmentRequestEntity.getFormFields() != null) { +// // Parse existing form fields from JSON +// List existingFormFields = +// Utils.convertJsonStringToList(applicationAmendmentRequestEntity.getFormFields(), AmendmentFormFieldRequest.class); +// +// // Prepare a new list to hold updated form fields +// List updatedFormFields = new ArrayList<>(); +// +// // Map amendment details for quick lookup by amendment ID +// Map amendmentDetailsMap = amendmentFormFields.stream() +// .filter(details -> applicationAmendmentRequestEntity.getId().equals(details.getAmendmentId())) +// .filter(details -> details.getFieldValue() != null) // Null check for getFormFieldDocuments +// .collect(Collectors.toMap( +// AmendmentDetailsRequest::getAmendmentId, +// AmendmentDetailsRequest::getFieldValue +// )); +// // Get corresponding amendment documents for the current entity +// List amendmentDocuments = (List) amendmentDetailsMap.get(applicationAmendmentRequestEntity.getId()); +// if (amendmentDocuments != null) { +// // Update existing form fields with new values +// for (AmendmentFormFieldRequest existingField : existingFormFields) { +// for (AmendmentFormFieldRequest newField : amendmentDocuments) { +// if (existingField.getFieldId().equals(newField.getFieldId())) { +// // Update fields if there are changes +// Utils.setIfUpdated(existingField::getValid, existingField::setValid, newField.getValid()); +// Utils.setIfUpdated(existingField::getFieldValue, existingField::setFieldValue, newField.getFieldValue()); +// +// updatedFormFields.add(existingField); +// break; // Move to the next existing field +// } +// } +// } +// +// // Convert updated form fields back to JSON and save to the database +// applicationAmendmentRequestEntity.setFormFields(Utils.convertListToJsonString(updatedFormFields)); +// applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); +// } +// } +// +// // Process amendment documents if present +// if (applicationAmendmentRequestEntity.getAmendmentDocument() != null) { +// String existingDocumentIds = applicationAmendmentRequestEntity.getAmendmentDocument(); +// +// // Split comma-separated document IDs into a list +// List existingDocumentIdList = Arrays.stream(existingDocumentIds.split(",")) +// .map(String::trim) +// .filter(id -> !id.isEmpty()) +// .collect(Collectors.toList()); +// +// List updatedDocumentIdList = new ArrayList<>(); +// Map amendmentDetailsMap = amendmentFormFields.stream() +// .filter(details -> applicationAmendmentRequestEntity.getId().equals(details.getAmendmentId())) +// .collect(Collectors.toMap( +// AmendmentDetailsRequest::getAmendmentId, +// AmendmentDetailsRequest::getFieldValue +// )); +// +// String amendmentDocumentIds = (String) amendmentDetailsMap.get(applicationAmendmentRequestEntity.getId()); +// if (amendmentDocumentIds != null) { +// // Split and validate new document IDs +// List newDocumentIdList = Arrays.stream(amendmentDocumentIds.split(",")) +// .map(String::trim) +// .filter(id -> !id.isEmpty()) +// .collect(Collectors.toList()); +// +// for (String existingId : existingDocumentIdList) { +// for (String newId : newDocumentIdList) { +// if (existingId.equals(newId)) { +// Optional documentEntity = documentRepository.findByIdAndNotDeleted(Long.valueOf(newId)); +// if(documentEntity.isPresent()) { +// updatedDocumentIdList.add(newId); +// break; +// } +// } +// } +// } +// +// // Add any new IDs not in the existing list +// for (String newId : newDocumentIdList) { +// if (!existingDocumentIdList.contains(newId)) { +// Optional documentEntity = documentRepository.findByIdAndNotDeleted(Long.valueOf(newId)); +// if(documentEntity.isPresent()) { +// updatedDocumentIdList.add(newId); +// } +// } +// } +// String updatedDocumentIds = String.join(",", updatedDocumentIdList); +// +// // Create the AmendmentDetailsResponseBean for structured data +// AmendmentDetailsResponseBean amendmentDetails = new AmendmentDetailsResponseBean(); +// amendmentDetails.setAmendmentDocuments(updatedDocumentIds); +// AmendmentDetailsRequest amendmentDetailsRequest = amendmentFormFields.stream() +// .filter(details -> applicationAmendmentRequestEntity.getId().equals(details.getAmendmentId())) +// .findFirst() +// .orElse(null); +// +// if (amendmentDetailsRequest != null) { +// amendmentDetails.setValid(amendmentDetailsRequest.getValid()); +// } else { +// amendmentDetails.setValid(false); +// } +// String amendmentDetailsJson = Utils.convertListToJsonString(Collections.singletonList(amendmentDetails)); +// applicationAmendmentRequestEntity.setAmendmentDocument(amendmentDetailsJson); +// applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); +// } +// } +// } } - private List filterNonNullCriteria(List criteriaRequests) { + private void updateAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity, List amendmentDetailsRequestList) { + if (CollectionUtils.isEmpty(amendmentDetailsRequestList)) { + return; + } + Map formFieldsMap = null; + List formFieldList = Utils.convertJsonStringToList(applicationAmendmentRequestEntity.getFormFields(), AmendmentFormField.class); + if(Boolean.FALSE.equals(CollectionUtils.isEmpty(formFieldList))){ + formFieldsMap = formFieldList.stream().collect(Collectors.toMap(AmendmentFormField::getFieldId, Function.identity())); + } + updateAmendmentData(applicationAmendmentRequestEntity, amendmentDetailsRequestList, formFieldsMap); - return criteriaRequests.stream().filter(request -> request.getScore() != null && request.getValid() != null).collect(Collectors.toList()); } - private List filterNonNullFields(List fieldRequests) { - - return fieldRequests.stream().filter(request -> request.getValid() != null).collect(Collectors.toList()); + private static void updateAmendmentData(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity, List amendmentDetailsRequestList, Map formFieldsMap) { + amendmentDetailsRequestList.forEach(amendmentDetailsRequest -> { + if (amendmentDetailsRequest.getFieldId().contains("amend_")) { + AmendmentDetailsResponseBean amendmentDetails = Utils.convertStringToObject(applicationAmendmentRequestEntity.getAmendmentDocument(), AmendmentDetailsResponseBean.class); + if(amendmentDetails!=null) { + amendmentDetails.setValid(amendmentDetailsRequest.getValid()); + applicationAmendmentRequestEntity.setAmendmentDocument(Utils.convertObjectToString(amendmentDetails)); + } + } else if(Boolean.FALSE.equals(CollectionUtils.isEmpty(formFieldsMap))){ + AmendmentFormField amendmentFormField = formFieldsMap.get(amendmentDetailsRequest.getFieldId()); + amendmentFormField.setValid(amendmentDetailsRequest.getValid()); + } + }); + applicationAmendmentRequestEntity.setFormFields(Utils.convertListToJsonString(formFieldsMap.values().stream().toList())); } + +// private void updateAmendmentDocuments(List applicationAmendmentRequestEntities, List amendmentFormFields) { +// for (ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity : applicationAmendmentRequestEntities) { +// // Skip if there are no amendment documents +// if (applicationAmendmentRequestEntity.getAmendmentDocument() == null) { +// continue; +// } +// +// // Parse existing amendment fields from JSON +// List existingAmendmentFields = +// Utils.convertJsonStringToList(applicationAmendmentRequestEntity.getAmendmentDocument(), AmendmentFieldRequest.class); +// +// // Prepare a new list to hold updated amendment fields +// List updatedAmendmentFields = new ArrayList<>(); +// +// // Map amendment details for quick lookup by amendment ID +// Map> amendmentDetailsMap = amendmentFormFields.stream() +// .filter(details -> applicationAmendmentRequestEntity.getId().equals(details.getAmendmentId())) +// .collect(Collectors.toMap(AmendmentDetailsRequest::getAmendmentId, AmendmentDetailsRequest::getAmendmentDocuments)); +// +// // Get corresponding amendment documents for the current entity +// List amendmentDocuments = amendmentDetailsMap.get(applicationAmendmentRequestEntity.getId()); +// if (amendmentDocuments == null) { +// continue; +// } +// +// // Update existing amendment fields with new values +// for (AmendmentFieldRequest existingField : existingAmendmentFields) { +// for (AmendmentFieldRequest newField : amendmentDocuments) { +// if (existingField.getFieldId().equals(newField.getFieldId())) { +// // Update fields if there are changes +// Utils.setIfUpdated(existingField::getIsValid, existingField::setIsValid, newField.getIsValid()); +// Utils.setIfUpdated(existingField::getFileValue, existingField::setFileValue, newField.getFileValue()); +// Utils.setIfUpdated(existingField::getNameValue, existingField::setNameValue, newField.getNameValue()); +// +// updatedAmendmentFields.add(existingField); +// break; // Move to the next existing field +// } +// } +// } +// +// // Convert updated fields back to JSON and save to the database +// applicationAmendmentRequestEntity.setAmendmentDocument(Utils.convertListToJsonString(updatedAmendmentFields)); +// applicationAmendmentRequestRepository.save(applicationAmendmentRequestEntity); +// } +// } + private List processCriteria(ApplicationEvaluationEntity entity, ApplicationEvaluationRequest req) { List incomingCriteriaList = Optional.ofNullable(req.getCriteria()).orElse(new ArrayList<>()); @@ -604,11 +975,52 @@ public class ApplicationEvaluationDao { return entityOptional.get(); } + public void validatePreinstructor(HttpServletRequest request,Long applicationId,Long assignedApplicationId){ + if (applicationId == null && assignedApplicationId == null) { + throw new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.EITHER_APPLICATION_OR_ASSIGNED_APPLICATION_ID_REQUIRED_MSG) + ); + } + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByApplicationIdOrIdAndIsDeletedFalse(applicationId,assignedApplicationId); - public ApplicationEvaluationResponse getApplicationEvaluationByApplicationId(UserEntity user, Long applicationId, Long assignedApplicationId) { + if (assignedApplicationId != null) { + assignedApplicationsOptional = assignedApplicationsOptional.filter(a -> a.getId().equals(assignedApplicationId)); + } + AssignedApplicationsEntity assignedApplications = assignedApplicationsOptional + .orElseThrow(() -> new CustomValidationException( + Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.ASSIGNED_APPLICATION_NOT_FOUND_WITH_ID_MSG) + )); + if (applicationId == null) { + applicationId = assignedApplications.getApplication().getId(); + } + validator.validatePreInstructor(request, assignedApplications.getUserId()); + } + public ApplicationEvaluationResponse getApplicationEvaluationByApplicationId(HttpServletRequest request, UserEntity user, Long applicationID, Long assignedApplicationID) { + Long applicationId; + Long assignedApplicationId; + validatePreinstructor(request, applicationID, assignedApplicationID); + if (applicationID == null && assignedApplicationID != null) { + assignedApplicationId = assignedApplicationID; + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplicationId); + + applicationId = assignedApplicationsOptional.map(a -> a.getApplication().getId()).orElse(null); + } else { + applicationId = applicationID; + if (assignedApplicationID == null && applicationID != null) { + Optional assignedApplicationsOptional = + assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId); + + assignedApplicationId = assignedApplicationsOptional.map(AssignedApplicationsEntity::getId).orElse(null); + } else { + assignedApplicationId = assignedApplicationID; + } + } applicationService.validateApplication(applicationId); - Optional entityOptional; if (applicationId != null && assignedApplicationId != null) { @@ -620,11 +1032,19 @@ public class ApplicationEvaluationDao { } else { entityOptional = applicationEvaluationRepository.findFirstByIsDeletedFalseOrderByCreatedDateDesc(); } - return entityOptional.map(this::convertToResponse) + return entityOptional.map(this::convertToResponse) .orElseGet(() -> { return getEvaluationResponseByApplicationid(user, applicationId, assignedApplicationId); }); } + private List prepareEvaluationDocumentBeanList(ApplicationEvaluationEntity entity) { + List docRequest = new ArrayList<>(); + + if (entity != null && entity.getEvaluationDocument() != null) { + docRequest = Utils.convertJsonToList(entity.getEvaluationDocument(), new TypeReference>() {}); + } + return docRequest; + } public ApplicationEvaluationResponse getEvaluationResponseByApplicationid(UserEntity user, Long applicationId, Long assignedApplicationId) { @@ -659,6 +1079,7 @@ public class ApplicationEvaluationDao { response.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(application.getStatus())); response.setStatus(ApplicationEvaluationStatusTypeEnum.valueOf(ApplicationEvaluationStatusTypeEnum.OPEN.getValue())); response.setMinScore(call.getThreshold()!=null?call.getThreshold():null); + response.setEvaluationEndDate(entity.getEndDate()); LocalDateTime callEndDate = application.getCall().getEndDate(); response.setCallEndDate(callEndDate); setCriteriaResponses(entity, application.getId(), response, evaluationCriterias); @@ -721,7 +1142,7 @@ public class ApplicationEvaluationDao { if (!mappedFieldMap.containsKey(formFieldId)) { // CriteriaMappedField mappedField = new CriteriaMappedField(); CriteriaMappedField mappedField = populateMappedField(formFieldId, criteriaFormField, applicationForm, applicationId); - if(mappedField != null) { + if(mappedField != null) { mappedFieldMap.put(formFieldId, mappedField); } } @@ -807,6 +1228,10 @@ public class ApplicationEvaluationDao { ObjectMapper objectMapper = new ObjectMapper(); findFormFieldValue(applicationId, formFieldId).ifPresent(formField -> { Object value = formField.getFieldValue(); + if (value == null) { + mappedField.setFieldValue(null); + return; + } List labels = new ArrayList<>(); if (value instanceof String) { String fieldValue = (String) value; @@ -846,7 +1271,7 @@ public class ApplicationEvaluationDao { } - private DocumentResponseBean createDocumentResponseBean(DocumentEntity documentEntity) { + public DocumentResponseBean createDocumentResponseBean(DocumentEntity documentEntity) { DocumentResponseBean responseBean = new DocumentResponseBean(); responseBean.setId(documentEntity.getId()); responseBean.setName(documentEntity.getFileName()); @@ -856,6 +1281,7 @@ public class ApplicationEvaluationDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); return responseBean; } @@ -928,6 +1354,7 @@ public class ApplicationEvaluationDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); documentResponseBeans.add(responseBean); }); } @@ -948,17 +1375,27 @@ public class ApplicationEvaluationDao { private void setApplicationDetails(ApplicationEvaluationResponse response, Long applicationId, UserEntity user) { ApplicationEntity application = applicationService.validateApplication(applicationId); + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository + .findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); userService.validateUser(application.getUserId()); - String firstName = user.getFirstName() != null ? user.getFirstName() : ""; - String lastName = user.getLastName() != null ? user.getLastName() : ""; + + String firstName = user.getBeneficiary().getFirstName() != null ? user.getBeneficiary().getFirstName() : ""; + String lastName = user.getBeneficiary().getLastName() != null ? user.getBeneficiary().getLastName() : ""; String beneficiary = String.join(" ", firstName, lastName).trim(); response.setBeneficiary(beneficiary); - + response.setSubmissionDate(application.getSubmissionDate()); + response.setNdg(application.getNdg() != null ? application.getNdg() : null); + response.setAppointmentId(application.getAppointmentId() != null ? application.getAppointmentId() : null); response.setCallName(application.getCall().getName() != null ? application.getCall().getName() : null); response.setProtocolNumber((application.getProtocol() != null && application.getProtocol().getProtocolNumber() != null) ? application.getProtocol().getProtocolNumber() : null); - response.setSubmissionDate(application.getSubmissionDate() != null ? application.getSubmissionDate() : null); - response.setEvaluationDate(application.getSubmissionDate() != null ? application.getSubmissionDate().plusDays(30) : null); + if (assignedApplications != null) { + response.setAssignedAt(assignedApplications.getAssignedAt()); + } + if (application.getCompanyId() != null) { + CompanyEntity company = companyService.validateCompany(application.getCompanyId()); + response.setCompanyName(company.getCompanyName()); + } } private Optional findFormFieldValue(Long applicationId, String formFieldId) { @@ -1144,7 +1581,7 @@ public class ApplicationEvaluationDao { List documentResponseBeans = new ArrayList<>(); findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { String fieldValue = formField.getFieldValue(); - if (fieldValue != null) { + if (fieldValue != null && (Boolean.FALSE.equals(fieldValue.isEmpty()))) { String[] fieldValues = fieldValue.split(","); for (String value : fieldValues) { Long documentId = Long.valueOf(value.trim()); @@ -1168,6 +1605,7 @@ public class ApplicationEvaluationDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); return responseBean; } @@ -1176,7 +1614,10 @@ public class ApplicationEvaluationDao { findFormFieldValue(applicationId, criteriaFormField.getFormFieldId()).ifPresent(formField -> { Object value = formField.getFieldValue(); List labels = new ArrayList<>(); - + if (value == null) { + mappedField.setFieldValue(null); + return; + } if (value instanceof String) { List parsedValue = parseJsonValue((String) value, objectMapper); addLabelsFromParsedValues(parsedValue, contentResponseBean, labels); @@ -1261,7 +1702,7 @@ public class ApplicationEvaluationDao { if (optionalFormField.isPresent()) { ApplicationFormFieldEntity formField = optionalFormField.get(); - if (formField.getFieldValue() != null) { + if (formField.getFieldValue() != null &&(Boolean.FALSE.equals(formField.getFieldValue().isEmpty()))) { FieldResponse fieldResponse = new FieldResponse(); fieldResponse.setId(fieldId); String label = null; @@ -1291,6 +1732,7 @@ public class ApplicationEvaluationDao { responseBean.setFilePath(documentEntity.getFilePath()); responseBean.setCreatedDate(documentEntity.getCreatedDate()); responseBean.setUpdatedDate(documentEntity.getUpdatedDate()); + responseBean.setDocumentAttachmentId(documentEntity.getDocumentAttachmentId()); documentResponseBeans.add(responseBean); }); } @@ -1348,9 +1790,14 @@ public class ApplicationEvaluationDao { ApplicationEvaluationEntity oldApplicationEvaluation = Utils.getClonedEntityForData(existingEntity); AssignedApplicationsEntity oldAssignedApplication = Utils.getClonedEntityForData(assignedApplicationsEntity); + List amendmentRequest = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndStatusAndIsDeletedFalse(existingEntity.getId(),List.of(ApplicationAmendmentRequestEnum.AWAITING.getValue(),ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue())); + if(amendmentRequest !=null && Boolean.FALSE.equals(amendmentRequest.isEmpty())){ + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.APPLICATION_CANNOT_APPROVED_OR_REJECTED)); + } String statusType = application.getStatus(); if (application.getStatus().equals(ApplicationStatusTypeEnum.APPROVED.getValue()) || application.getStatus().equals(ApplicationStatusTypeEnum.REJECTED.getValue())) { existingEntity.setStatus(ApplicationEvaluationStatusTypeEnum.CLOSE.getValue()); + existingEntity.setClosingDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); assignedApplicationsEntity.setStatus(AssignedApplicationEnum.CLOSE.getValue()); } entity = applicationEvaluationRepository.save(existingEntity); @@ -1366,25 +1813,55 @@ public class ApplicationEvaluationDao { } - List amendmentRequest = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(entity.getId()); - for (ApplicationAmendmentRequestEntity amendment : amendmentRequest) { - ApplicationAmendmentRequestEntity oldAmendment = Utils.getClonedEntityForData(amendment); - amendment.setStatus(ApplicationAmendmentRequestEnum.CLOSE.getValue()); - - /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ - loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAmendment).newData(amendment).build()); - - } - applicationAmendmentRequestRepository.saveAll(amendmentRequest); if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.APPROVED.getValue())))) { emailNotificationDao.sendAdmissibilityNotificationEmailForApprovedApplication(application); } if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.REJECTED.getValue())))) { emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(application,existingEntity); } + + Map placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_RESULT); + notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_RESULT); + notificationDao.sendNotificationToInstructor(placeHolders,existingEntity,NotificationTypeEnum.EVALUATION_RESULT); + return convertToResponse(entity); } return null; } + + public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) { + return applicationEvaluationRepository + .findByApplicationIdAndIsDeletedFalse(applicationId) + .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.APPLICATION_EVALUATION_NOT_FOUND))); + } + + public ApplicationEvaluationResponse updateApplicationEvaluation( + Long assignedApplicationId, + List docRequest) { + Optional entityOptional=applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse(assignedApplicationId); + ApplicationEvaluationEntity applicationEvaluationEntity =null; + ApplicationEvaluationEntity oldApplicationEvaluation = Utils.getClonedEntityForData(entityOptional.get()); + applicationEvaluationEntity = entityOptional.get(); + + if (docRequest != null) { + List existingDocs = new ArrayList<>(); + + for (EvaluationDocumentRequest doc : docRequest) { + if (doc.getFileValue() != null) { + Long fileId = Long.valueOf(doc.getFileValue()); + documentService.validateDocument(fileId); + existingDocs.add(doc); + } + } + String updatedEvaluationDocJson = Utils.convertObjectToJson(existingDocs); + applicationEvaluationEntity.setEvaluationDocument(updatedEvaluationDocJson); + } + ApplicationEvaluationEntity savedEntity = applicationEvaluationRepository.save(applicationEvaluationEntity); + + /** This code is responsible for adding a version history log for the "Upload Document in Application Evaluation" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluation).newData(savedEntity).build()); + return convertToResponse(savedEntity); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java new file mode 100644 index 00000000..a45b142d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/AppointmentDao.java @@ -0,0 +1,918 @@ +package net.gepafin.tendermanagement.dao; + +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import feign.FeignException; +import io.jsonwebtoken.Claims; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.config.jwt.TokenProvider; +import net.gepafin.tendermanagement.constants.AppointmentApiConstant; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.entities.HubEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; +import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.model.request.AppointmentCreationRequest; +import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest; +import net.gepafin.tendermanagement.model.request.AppointmentVisuraListRequest; +import net.gepafin.tendermanagement.model.request.AppointmentVisuraRequest; +import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest; +import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; +import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse; +import net.gepafin.tendermanagement.model.response.AppointmentLoginResponse; +import net.gepafin.tendermanagement.model.response.DocumentUploadResponse; +import net.gepafin.tendermanagement.model.response.NdgResponse; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.CompanyRepository; +import net.gepafin.tendermanagement.repositories.DocumentRepository; +import net.gepafin.tendermanagement.repositories.HubRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.CompanyService; +import net.gepafin.tendermanagement.service.feignClient.AppointmentApiService; +import net.gepafin.tendermanagement.util.LoggingUtil; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class AppointmentDao { + + @Value("${appointment.portal.user}") + private String user; + + @Value("${appointment.portal.password}") + private String password; + + @Value("${appointment.portal.source}") + private String source; + + @Value("${appointment.portal.context}") + private String context; + + @Value("${default.hub.uuid}") + private String defaultHubUuid; + + @Value("${aws.s3.url}") + private String s3Url; + + @Value("${aws.s3.bucket.name}") + private String OLD_BUCKET; + + @Value("${flagDaFirmare}") + private Boolean flagDaFirmare; + + @Autowired + private HubRepository hubRepository; + + @Autowired + private AppointmentApiService appointmentApiService; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private CompanyService companyService; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private CompanyRepository companyRepository; + + @Autowired + private DocumentDao documentDao; + + @Autowired + private AmazonS3Client s3Client; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private HttpServletRequest request; + + @Autowired + private LoggingUtil loggingUtil; + + @Autowired + private TokenProvider tokenProvider; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private UserRepository userRepository; + + private final Map executorMap = new ConcurrentHashMap<>(); + + private final ConcurrentHashMap threadForDocumentMap = new ConcurrentHashMap<>(); + + private static final ThreadLocal threadLocalHubId = new ThreadLocal<>(); + + public NdgResponse checkNdgForAppointment(Long applicationId) { + + ApplicationEntity application = applicationService.validateApplication(applicationId); + NdgResponse ndgResponse = new NdgResponse(); + if (application.getNdgStatus() != null && application.getNdgStatus().equalsIgnoreCase(GepafinConstant.NDG_IN_PROGRESS)) { + throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.NDG_GENERATION_IS_IN_PROGRESS)); + } + + if (application.getNdgStatus() != null && application.getNdgStatus().equalsIgnoreCase(GepafinConstant.NDG_GENERATED) && application.getNdg() != null) { + ndgResponse.setNdg(application.getNdg()); + return ndgResponse; + } + + // Update application status + application.setNdgStatus(GepafinConstant.NDG_IN_PROGRESS); + applicationRepository.save(application); + + // Start async processing + startAsyncNdgProcessing(applicationId); + + throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.NDG_GENERATION_IS_IN_PROGRESS)); + } + + private void startAsyncNdgProcessing(Long applicationId) { + // Check if a thread is already running for this application + if (executorMap.containsKey(applicationId)) { + log.warn("Async processing already running for applicationId: {}", applicationId); + return; + } + + // Create a dedicated thread for asynchronous processing + ExecutorService executor = Executors.newSingleThreadExecutor(runnable -> { + Thread thread = new Thread(runnable); + thread.setName("AsyncNdgProcessing-" + applicationId); + return thread; + }); + executorMap.put(applicationId, executor); + + executor.submit(() -> { + try { + log.info("Starting async processing for applicationId: {}", applicationId); + processNdgGeneration(applicationId); + } catch (Exception e) { + log.error("Error in async NDG processing for applicationId: {}", applicationId, e); + } finally { + // Cleanup resources + ExecutorService executorToShutdown = executorMap.remove(applicationId); + if (executorToShutdown != null) { + executorToShutdown.shutdown(); + } + log.info("Async processing completed for applicationId: {}", applicationId); + } + }); + } + + private void processNdgGeneration(Long applicationId) { + // Validate application, company, and hub + ApplicationEntity application = applicationService.validateApplication(applicationId); + CompanyEntity company = companyService.validateCompany(application.getCompanyId()); + HubEntity hub = hubRepository.findByHubId(application.getHubId()); + + if (!hub.getUniqueUuid().equals(defaultHubUuid)) { + log.info("Ndg cannot be created for another Hub, it is default for Gepafin."); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_NDG_FOR_ANOTHER_HUB)); + } + + try { + // Authenticate and fetch token if required + if (hub.getAppointmentAuthTokenId() == null || hub.getAreaCode() == null) { + authenticateAndSaveToken(hub); + } + + String authorizationToken = getBearerToken(hub); + + // Try retrieving NDG by VAT number + AppointmentLoginResponse ndgResponse = retrieveNdgByVatNumber(company.getVatNumber(), authorizationToken, hub, application); + if (isNdgValid(ndgResponse.getNdg())) { + saveNdgAndIdVisura(application, company, ndgResponse.getNdg(), null); + log.info("NDG successfully generated for applicationId: {}", applicationId); + } else { + // If NDG isn't immediately available, start polling + handleNdgPolling(application, company, hub, authorizationToken); + } + } catch (Exception e) { + log.error("Error during NDG generation for applicationId: {}", applicationId, e); + } + } + + private void handleNdgPolling(ApplicationEntity application, CompanyEntity company, HubEntity hub, String authorizationToken) { + + try { + log.info("Starting NDG polling for applicationId: {}", application.getId()); + long startTime = System.currentTimeMillis(); + + while (true) { + if (application.getNdg() != null) { + log.info("NDG retrieved for applicationId: {}", application.getId()); + break; + } + + try { + // Fetch Visura list and attempt to parse NDG + String visuraListJson = getVisuraList(application.getIdVisura(), authorizationToken, application, hub); + String ndg = parseNdgFromVisuraListResponse(visuraListJson); + + if (isNdgValid(ndg)) { + // CompanyEntity oldCompanyData = Utils.getClonedEntityForData(company); + // ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application); + + company.setNdg(ndg); + application.setNdg(ndg); + application.setNdgStatus(GepafinConstant.NDG_GENERATED); + application.setStatus(ApplicationStatusTypeEnum.NDG.getValue()); + applicationRepository.save(application); + companyRepository.save(company); + log.info("NDG saved successfully for applicationId: {}", application.getId()); + + // /** This code is responsible for adding a version history log for the "update application ndg code, status, and Id visura" + // operation. **/ + // loggingUtil.addVersionHistory( + // VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData) + // .newData(application).build()); + // + // /** This code is responsible for adding a version history log for the "update company ndg code" operation. **/ + // loggingUtil.addVersionHistory( + // VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCompanyData) + // .newData(company).build()); + break; + } + + // Check if polling has timed out + if (System.currentTimeMillis() - startTime > TimeUnit.HOURS.toMillis(2)) { + log.warn("NDG polling timed out for applicationId: {}", application.getId()); + application.setNdgStatus(GepafinConstant.NDG_FAILED); + applicationRepository.save(application); + break; + } + + // Wait before the next polling attempt + Thread.sleep(TimeUnit.MINUTES.toMillis(15)); + } catch (InterruptedException e) { + log.warn("NDG polling interrupted for applicationId: {}", application.getId()); + Thread.currentThread().interrupt(); + break; + } catch (Exception e) { + log.error("Error during NDG polling for applicationId: {}", application.getId(), e); + } + } + } finally { + log.info("NDG polling completed for applicationId: {}", application.getId()); + } + } + + private static String getBearerToken(HubEntity hub) { + + return "Bearer " + hub.getAppointmentAuthTokenId(); + } + + private boolean isNdgValid(String ndg) { + + return ndg != null && !ndg.isEmpty(); + } + + private void saveNdgAndIdVisura(ApplicationEntity application, CompanyEntity company, String ndg, String idVisura) { + + //cloned for old application and company data + // ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application); + // CompanyEntity oldCompanyData = Utils.getClonedEntityForData(company); + + application.setNdg(ndg); + application.setIdVisura(idVisura); + application.setNdgStatus(GepafinConstant.NDG_GENERATED); + application.setStatus(ApplicationStatusTypeEnum.NDG.getValue()); + company.setNdg(ndg); + companyRepository.save(company); + applicationRepository.save(application); + Map placeHolders=notificationDao.sendNotificationToBeneficiary(application,NotificationTypeEnum.NDG_GENERATION); + notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.NDG_GENERATION); + + // /** This code is responsible for adding a version history log for the "update application ndg code, status, and Id visura" operation. **/ + // loggingUtil.addVersionHistory( + // VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build()); + // + // /** This code is responsible for adding a version history log for the "update company ndg code" operation. **/ + // loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCompanyData).newData + // (company).build()); + + log.info("NDG saved for applicationId: {}, {}", application.getId(), application.getNdg()); + } + + private String getVisuraList(String idVisura, String authorizationToken, ApplicationEntity application, HubEntity hub) { + + AppointmentVisuraListRequest visuraListRequest = new AppointmentVisuraListRequest(); + AppointmentVisuraListRequest.VisuraFilter filter = new AppointmentVisuraListRequest.VisuraFilter(); + filter.setIdVisura(idVisura); + visuraListRequest.setFilter(filter); + + try { + String requestJson = Utils.convertObjectToJson(visuraListRequest); + ResponseEntity response = appointmentApiService.getVisuraList(requestJson, authorizationToken); + return Utils.convertObjectToJson(response.getBody()); + } catch (FeignException.Forbidden forbiddenException) { + log.error("403 Forbidden received while getting visuraList for Ndg code. Regenerating token..."); + // Regenerate the token and retry + String newAuthorizationToken = regenerateTokenAndSave(hub); + return getVisuraList(idVisura, newAuthorizationToken, application, hub); + } catch (Exception e) { + log.error("Failed to fetch Ndg code: {}", e.getMessage(), e); + throw new RuntimeException("Error fetching Ndg List", e); + } + } + + private HubEntity authenticateAndSaveToken(HubEntity hub) { + + // HubEntity oldHubData = Utils.getClonedEntityForData(hub); + try { + //code to generate token with payload having "iat" epoch timestamp and secret key with no expiry and send in below method call + String authJwtToken = Utils.generateAuthTokenForLoginToOdessa(); + log.info("Got the auth for login to odessa {}", authJwtToken); + hub.setAuthToken(authJwtToken); + hubRepository.save(hub); + + // /** This code is responsible for adding a version history log for the "Updating auth token for login api in hub" operation. **/ + // loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldHubData).newData + // (hub).build()); + + // Prepare the request body (adjust if necessary for login API) + Map body = Collections.emptyMap(); + // Perform login API call + ResponseEntity responseLogin = appointmentApiService.loginWithOdessa(authJwtToken, source, context, user, password, body); + + // Handle successful login + if (responseLogin.getStatusCode() == HttpStatus.OK) { + log.info("Login successful to odessa. Parsing response."); + String loginResponseJson = Utils.convertObjectToJson(responseLogin.getBody()); + AppointmentLoginResponse parsedResponse = parseLoginResponse(loginResponseJson); + + // Validate and save token + if (parsedResponse.getTokenId() != null) { + hub.setAppointmentAuthTokenId(parsedResponse.getTokenId()); + hub.setAreaCode(parsedResponse.getAreaCode()); + hubRepository.save(hub); + + // /** This code is responsible for adding a version history log for the "inserting token and areaCode from login odessa response for + // appointment flow api's" + // * operation. **/ + // loggingUtil.addVersionHistory( + // VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldHubData).newData(hub) + // .build()); + + log.info("Saved new authToken and areaCode for Hub."); + return hub; + } else { + throw new RuntimeException("Login response is missing a valid tokenId for login to odessa system, please try again."); + } + } + // Handle non-OK response + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_IN_GENERATING_NDG_TRY_AGAIN)); + } catch (Exception e) { + log.error("Failed to authenticate user on Odessa : {}", e.getMessage(), e); + throw new RuntimeException("Authentication failed on Odessa. try again", e); + } + } + + private AppointmentLoginResponse retrieveNdgByVatNumber(String vatNumber, String authorizationToken, HubEntity hub, ApplicationEntity application) { + + try { + // Prepare the NDG request + AppointmentNdgRequest ndgRequest = getAppointmentNdgRequest(vatNumber); + // Call the API to retrieve NDG + ResponseEntity response = appointmentApiService.getNdgByVatNumber(ndgRequest, authorizationToken); + String responseJson = Utils.convertObjectToJson(response.getBody()); + // Parse and return the NDG response + return parseNdgResponse(responseJson); + } catch (FeignException.Forbidden forbiddenException) { + logForbiddenError(); + // Regenerate the token and retry + String newAuthorizationToken = regenerateTokenAndSave(hub); + return retrieveNdgByVatNumber(vatNumber, newAuthorizationToken, hub, application); + } catch (Exception e) { + log.error("Failed to retrieve NDG by VAT number: {}", e.getMessage(), e); + throw new RuntimeException("NDG retrieval failed.", e); + } + } + + private String regenerateTokenAndSave(HubEntity hub) { + + try { + hub = authenticateAndSaveToken(hub); + return "Bearer " + hub.getAppointmentAuthTokenId(); + } catch (Exception e) { + log.error("Failed to regenerate token from Odessa: {}", e.getMessage()); + throw new RuntimeException("Token regeneration failed from Odessa.", e); + } + } + + private AppointmentLoginResponse createVisura(CompanyEntity company, String authorizationToken, HubEntity hub) { + + try { + String visuraRequest = getAppointmentVisuraRequest(company, hub.getAreaCode()); + ResponseEntity response = appointmentApiService.createVisura(visuraRequest, authorizationToken); + String responseJson = Utils.convertObjectToJson(response.getBody()); + return parseVisuraResponse(responseJson); + } catch (FeignException.Forbidden forbiddenException) { + logForbiddenError(); + // Regenerate the token and retry + String newAuthorizationToken = regenerateTokenAndSave(hub); + return createVisura(company, newAuthorizationToken, hub); + } catch (Exception e) { + log.error("Failed to create Visura for Ndg : {}", e.getMessage()); + throw new RuntimeException("Visura creation failed for Ndg.", e); + } + } + + private static void logForbiddenError() { + + log.error("403 Forbidden received while retrieving NDG. Regenerating token..."); + } + + private static AppointmentNdgRequest getAppointmentNdgRequest(String vatNumber) { + + AppointmentNdgRequest request = new AppointmentNdgRequest(); + AppointmentNdgRequest.Filter filter = new AppointmentNdgRequest.Filter(); + filter.setPartitaIva(vatNumber); + + AppointmentNdgRequest.Pagination pagination = new AppointmentNdgRequest.Pagination(); + pagination.setTargetPage(AppointmentApiConstant.TARGET_PAGE_SIZE); + pagination.setRecordsPerPage(AppointmentApiConstant.RECORD_PER_PAGE_SIZE); + + request.setFilter(filter); + request.setPagination(pagination); + return request; + } + + private static String getAppointmentVisuraRequest(CompanyEntity company, String areaCode) { + + AppointmentVisuraRequest visuraRequest = new AppointmentVisuraRequest(); + AppointmentVisuraRequest.VisuraInput input = new AppointmentVisuraRequest.VisuraInput(); + input.setPartitaIva(company.getVatNumber()); + input.setCodiceFiscale(company.getCodiceFiscale()); + input.setCodArea(areaCode); + input.setVisuraMode(AppointmentApiConstant.VISURA_MODE); + input.setVisuraProvider(AppointmentApiConstant.VISURA_PROVIDER); + input.setCodAgente(AppointmentApiConstant.COD_AGENTE); + input.setAnagraficaLegame(AppointmentApiConstant.IS_ANAGRAFICA_LEGAME); + input.setCreaAnagrafica(AppointmentApiConstant.CREA_ANAGRAFICA); + input.setFromRating(AppointmentApiConstant.IS_FROM_RATING); + input.setSalvaDocumenti(AppointmentApiConstant.SALVA_DOCUMENTI); + input.setVisuraType(AppointmentApiConstant.VISURA_TYPE); + visuraRequest.setInput(input); + return Utils.convertObjectToJson(visuraRequest); + } + + private String parseNdgFromVisuraListResponse(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING); + + if (dataNode != null && dataNode.isArray() && dataNode.size() > 0) { + JsonNode firstEntry = dataNode.get(0); + JsonNode ndgClienteNode = firstEntry.get("ndgCliente"); + if (ndgClienteNode != null && ndgClienteNode.get("code") != null) { + String code = ndgClienteNode.get("code").asText(); + return normalizeNullValue(code); + } + } + log.warn("NDG not found in Visura List API response."); + return null; + } catch (Exception e) { + log.error("Failed to parse NDG from Visura List API response: {}", e.getMessage(), e); + throw new RuntimeException("Error parsing NDG from Visura List API response", e); + } + } + + public AppointmentLoginResponse parseLoginResponse(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING); + + if (dataNode != null) { + AppointmentLoginResponse response = new AppointmentLoginResponse(); + response.setTokenId(dataNode.get("tokenId").asText()); + JsonNode areasNode = dataNode.get("areas"); + if (areasNode != null && areasNode.isArray() && areasNode.size() > 0) { + response.setAreaCode(areasNode.get(0).get("code").asText()); + } + response.setCompanyId(dataNode.get("companyId").asLong()); + return response; + } else { + throw new RuntimeException("Invalid JSON structure: Missing 'data' node."); + } + } catch (Exception e) { + throw new RuntimeException("Failed to parse response from loginApi for odessa: " + e.getMessage(), e); + } + } + + public AppointmentLoginResponse parseVisuraResponse(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING); + + if (dataNode != null) { + AppointmentLoginResponse response = new AppointmentLoginResponse(); + response.setIdVisura(normalizeNullValue(dataNode.get(GepafinConstant.ID_VISURA_STRING).asText())); + response.setNdg(normalizeNullValue(dataNode.get(GepafinConstant.NDG_STRING).asText())); + return response; + } else { + throw new RuntimeException("Invalid JSON structure: Missing 'data' node."); + } + } catch (Exception e) { + throw new RuntimeException("Failed to parse response: " + e.getMessage(), e); + } + } + + public AppointmentLoginResponse parseNdgResponse(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode dataArray = rootNode.get(GepafinConstant.DATA_STRING); + if (dataArray == null || !dataArray.isArray() || dataArray.isEmpty()) { + log.info("NDG data is empty or missing in the response."); + AppointmentLoginResponse emptyResponse = new AppointmentLoginResponse(); + emptyResponse.setNdg(null); + return emptyResponse; + } + JsonNode firstDataEntry = dataArray.get(0); + AppointmentLoginResponse response = new AppointmentLoginResponse(); + if (firstDataEntry.has(GepafinConstant.NDG_STRING)) { + response.setNdg(normalizeNullValue(firstDataEntry.get(GepafinConstant.NDG_STRING).asText())); + } + return response; + } catch (Exception e) { + log.error("Failed to parse response: {}", e.getMessage(), e); + throw new RuntimeException("Failed to parse NDG response.", e); + } + } + + private String normalizeNullValue(String value) { + + return (value == null || GepafinConstant.NULL_STRING.equalsIgnoreCase(value.trim())) ? null : value; + } + + public AppointmentCreationResponse createAppointment(Long applicationId, CreateAppointmentRequest createAppointmentRequest) { + // Validate the application + ApplicationEntity application = applicationService.validateApplication(applicationId); + + AppointmentCreationResponse appointmentCreationResponse = new AppointmentCreationResponse(); + + ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application); + HubEntity hub = hubRepository.findByHubId(application.getHubId()); + + // Check hub UUID and enforce constraints + if (!hub.getUniqueUuid().equals(defaultHubUuid)) { + log.info("Appointment cannot be created for another Hub; default is required for Gepafin."); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_APPOINTMENT_FOR_ANOTHER_HUB)); + } + + try { + // Pre-check conditions for appointment creation + if (application.getNdg() != null && !Objects.equals(application.getNdgStatus(), GepafinConstant.NDG_IN_PROGRESS) && application.getAppointmentId() != null) { + appointmentCreationResponse.setAppointmentId(application.getAppointmentId()); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.APPOINTMENT_ALREADY_CREATED)); + // return appointmentCreationResponse; + } + + if (application.getNdg() == null && Objects.equals(application.getNdgStatus(), GepafinConstant.NDG_IN_PROGRESS)) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NDG_NOT_FOUND_FOR_APPLICATION)); + } + + // Generate authorization token and fetch template data + String authorizationToken = getBearerToken(hub); + ResponseEntity response = appointmentApiService.getAppointmentTemplateForTemplateCreation(authorizationToken); + + if (response.getStatusCode() != HttpStatus.OK) { + log.error("Failed to retrieve appointment template for appointment creation. Status: {}", response.getStatusCode()); + throw new IllegalStateException("Failed to retrieve appointment template for appointment creation"); + } + + // Parse template data + String responseDataForTemplate = Utils.convertObjectToJson(response.getBody()); + AppointmentCreationRequest templateRichiestaData = parseTemplateResponseData(responseDataForTemplate); + + // Build the appointment request body + AppointmentCreationRequest appointmentCreationRequest = buildAppointmentCreationRequest(applicationId, createAppointmentRequest, hub.getAreaCode(), + templateRichiestaData); + String appointmentRequestBody = Utils.convertObjectToJson(appointmentCreationRequest); + + // Make API call to create the appointment + ResponseEntity appointmentResponse = appointmentApiService.createAppointment(authorizationToken, context, appointmentRequestBody); + String appointmentId = extractAppointmentIdFromResponse(appointmentResponse); + + if (appointmentId != null) { + // Update application with the appointment ID + application.setAppointmentId(appointmentId); + application.setStatus(ApplicationStatusTypeEnum.APPOINTMENT.getValue()); + applicationRepository.save(application); + + // Log version history + loggingUtil.addVersionHistory( + VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationData).newData(application).build()); + } + + appointmentCreationResponse.setAppointmentId(appointmentId); + return appointmentCreationResponse; + + } catch (FeignException.Forbidden forbiddenException) { + log.error("403 Forbidden received while retrieving template. Regenerating token..."); + regenerateTokenAndSave(hub); + return createAppointment(applicationId, createAppointmentRequest); + } + } + + private String extractAppointmentIdFromResponse(ResponseEntity appointmentResponse) { + + if (appointmentResponse.getBody() != null) { + Map responseBody = (Map) appointmentResponse.getBody(); + if (responseBody.containsKey(GepafinConstant.DATA_STRING)) { + Map data = (Map) responseBody.get(GepafinConstant.DATA_STRING); + if (data != null && data.containsKey(GepafinConstant.ID_STRING)) { + return data.get(GepafinConstant.ID_STRING).toString(); + } + } + } + return null; + } + + public AppointmentCreationRequest parseTemplateResponseData(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + JsonNode richiestaClienteArray = rootNode.path(GepafinConstant.DATA_STRING).path(GepafinConstant.RICHIESTA_CLIENTE_STRING); + + AppointmentCreationRequest appointmentCreationRequest = new AppointmentCreationRequest(); + AppointmentCreationRequest.Input input = new AppointmentCreationRequest.Input(); + + // Map `richiestaCliente` array + List richiestaClienteList = new ArrayList<>(); + if (richiestaClienteArray.isArray()) { + for (JsonNode richiestaNode : richiestaClienteArray) { + richiestaClienteList.add(objectMapper.treeToValue(richiestaNode, AppointmentCreationRequest.RichiestaCliente.class)); + } + } + + input.setRichiestaCliente(richiestaClienteList); + appointmentCreationRequest.setInput(input); + return appointmentCreationRequest; + + } catch (Exception e) { + log.error("Error parsing template response: {}", e.getMessage(), e); + throw new IllegalStateException("Failed to parse template response", e); + } + } + + public AppointmentCreationRequest buildAppointmentCreationRequest(Long applicationId, CreateAppointmentRequest createAppointmentRequest, String areaCode, + AppointmentCreationRequest templateRichiestaData) { + + ApplicationEntity application = applicationService.validateApplication(applicationId); + CreateAppointmentRequest.Nota nota = createAppointmentRequest.getNota(); + + AppointmentCreationRequest appointmentCreationRequest = new AppointmentCreationRequest(); + AppointmentCreationRequest.Input input = new AppointmentCreationRequest.Input(); + + // Set Input Fields + input.setId(areaCode); + input.setNdg(application.getNdg()); + + // Populate richiestaCliente from template data + List richiestaClienteList = new ArrayList<>(); + for (AppointmentCreationRequest.RichiestaCliente templateRichiesta : templateRichiestaData.getInput().getRichiestaCliente()) { + AppointmentCreationRequest.RichiestaCliente richiestaCliente = new AppointmentCreationRequest.RichiestaCliente(); + BeanUtils.copyProperties(templateRichiesta, richiestaCliente); + + // Add specific `nota` + AppointmentCreationRequest.Nota requestNota = new AppointmentCreationRequest.Nota(); + requestNota.setTitolo(nota.getTitolo()); + requestNota.setTesto(nota.getTesto()); + richiestaCliente.setNota(requestNota); + + richiestaClienteList.add(richiestaCliente); + } + + input.setRichiestaCliente(richiestaClienteList); + appointmentCreationRequest.setInput(input); + return appointmentCreationRequest; + } + + public DocumentUploadResponse uploadDocumentToExternalSystem(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) { + // Check if the document is already being processed + DocumentEntity systemDoc = documentDao.validateDocument(documentId); + + Claims claims = tokenProvider.getClaimsFromToken(tokenProvider.extractTokenFromRequest(request)); + Long hubId = Utils.extractHubIdFromPayload(claims.getSubject()); + if (systemDoc.getDocumentAttachmentId() != null) { + // If the documentAttachmentId is already set, return the response + log.info("Document already uploaded with documentAttachmentId: {}", systemDoc.getDocumentAttachmentId()); + DocumentUploadResponse response = new DocumentUploadResponse(); + response.setDocumentAttachmentId(systemDoc.getDocumentAttachmentId()); + return response; + } + // Check if a thread is already running for this document upload + if (threadForDocumentMap.containsKey(documentId)) { + log.warn("Document upload already running for documentId: {}", documentId); + throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.DOCUMENT_UPLOADING_IN_PROGRESS)); + } + // Start the upload process in the background + ExecutorService executor = Executors.newSingleThreadExecutor(runnable -> { + Thread thread = new Thread(runnable); + thread.setName(GepafinConstant.ASYNC_DOCUMENT_UPLOAD_NAME + documentId); + return thread; + }); + threadForDocumentMap.put(documentId, executor); + + executor.submit(() -> { + threadLocalHubId.set(hubId); + try { + log.info("Starting async document upload for documentId: {}", documentId); + uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest); + } catch (Exception e) { + log.error("Error in async document upload for documentId: {}", documentId, e); + } finally { + // Cleanup resources + ExecutorService executorToShutdown = threadForDocumentMap.remove(documentId); + if (executorToShutdown != null) { + executorToShutdown.shutdown(); + threadLocalHubId.remove(); + } + log.info("Async document upload completed for documentId: {}", documentId); + } + }); + return null; + // Return an immediate response indicating the process is in progress +// throw new CustomValidationException(Status.SUCCESS, Translator.toLocale(GepafinConstant.DOCUMENT_UPLOADING_IN_PROGRESS)); + } + + private void uploadDocumentToExternalSystemSync(Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) { + // Synchronous upload logic + DocumentEntity systemDoc = documentDao.validateDocument(documentId); + + Long hubId = threadLocalHubId.get(); + HubEntity hub = hubRepository.findByHubId(hubId); + + if (!hub.getUniqueUuid().equals(defaultHubUuid)) { + log.info("Document cannot be uploaded for another Hub, it is default for Gepafin."); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NO_DOCUMENT_UPLOAD_FOR_ANOTHER_HUB)); + } + + log.info("Got Document in system: {}", systemDoc); + String oldUrl = systemDoc.getFilePath(); + String authorizationToken = getBearerToken(hub); + + try { + File localFile = downloadFileFromS3(oldUrl); + MultipartFile multipartFile = convertFileToMultipartFile(localFile); + + UploadDocToExternalSystemRequest externalSystemRequest = new UploadDocToExternalSystemRequest(); + externalSystemRequest.setInput(getUploadDocumentInput(docToExternalSystemRequest)); + + String uploadDocRequest = Utils.convertObjectToJson(externalSystemRequest); + ResponseEntity uploadedDocumentData = appointmentApiService.uploadDocumentToExternalSystemForAppointment(authorizationToken, context, uploadDocRequest, + multipartFile); + + String responseData = Utils.convertObjectToJson(uploadedDocumentData.getBody()); + DocumentUploadResponse parsedResponse = parseDocumentUploadResponse(responseData); + + if (parsedResponse == null) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.ERROR_UPLOADING_DOCUMENT)); + } + + // Save the documentAttachmentId to the database + systemDoc.setDocumentAttachmentId(parsedResponse.getDocumentAttachmentId()); + documentRepository.save(systemDoc); + + log.info("Document uploaded successfully to external system: {}", parsedResponse); + } catch (FeignException.Forbidden forbiddenException) { + log.error("403 Forbidden received while uploading document. Regenerating token..."); + regenerateTokenAndSave(hub); + uploadDocumentToExternalSystemSync(documentId, docToExternalSystemRequest); + } catch (Exception e) { + log.error("Exception during document upload: {}", e.getMessage(), e); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.EXTERNAL_DOCUMENT_UPLOAD_FAILURE_MSG)); + } + } + + private UploadDocToExternalSystemRequest.Input getUploadDocumentInput(UploadDocToExternalSystemRequest docToExternalSystemRequest) { + + UploadDocToExternalSystemRequest.Input input = new UploadDocToExternalSystemRequest.Input(); + input.setIdTipoProtocollo(docToExternalSystemRequest.getInput().getIdTipoProtocollo()); + input.setIdClassificazione(docToExternalSystemRequest.getInput().getIdClassificazione()); + input.setFlagDaFirmare(flagDaFirmare); + input.setDescrizione(docToExternalSystemRequest.getInput().getDescrizione()); + + UploadDocToExternalSystemRequest.Input.Attributes attributes = new UploadDocToExternalSystemRequest.Input.Attributes(); + attributes.setNdg(docToExternalSystemRequest.getInput().getAttributes().getNdg()); + attributes.setEmail(docToExternalSystemRequest.getInput().getAttributes().getEmail()); + + input.setAttributes(attributes); + return input; + } + + public static MultipartFile convertFileToMultipartFile(File file) throws IOException { + + FileInputStream input = new FileInputStream(file); + return new MockMultipartFile(file.getName(), file.getName(), MediaType.APPLICATION_OCTET_STREAM_VALUE, input); + } + + private File downloadFileFromS3(String fileUrl) throws Exception { + + String key = extractS3KeyFromUrl(fileUrl); + File localFile = new File(GepafinConstant.TEMP_FILE_PATH + extractFileName(key)); + + GetObjectRequest getObjectRequest = new GetObjectRequest(OLD_BUCKET, key); + + try (InputStream s3Stream = s3Client.getObject(getObjectRequest).getObjectContent(); FileOutputStream outputStream = new FileOutputStream(localFile)) { + s3Stream.transferTo(outputStream); + } + + log.info("Downloaded file from old S3 bucket: {}", key); + return localFile; + } + + private String extractS3KeyFromUrl(String url) { + + return url.replace(s3Url, ""); + } + + private String extractFileName(String filePath) { + + String[] parts = filePath.split("/"); + return parts[parts.length - 1]; + + } + + public DocumentUploadResponse parseDocumentUploadResponse(String jsonResponse) { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(jsonResponse); + + // Navigate to the "data" node + JsonNode dataNode = rootNode.get(GepafinConstant.DATA_STRING); + if (dataNode != null) { + DocumentUploadResponse response = new DocumentUploadResponse(); + + // Extract "documentAttachmentId" + JsonNode documentAttachmentIdNode = dataNode.get(GepafinConstant.DOCUMENT_ATTACHMENT_ID_STRING); + if (documentAttachmentIdNode != null) { + response.setDocumentAttachmentId(documentAttachmentIdNode.asText()); + } else { + throw new RuntimeException("Invalid JSON structure: Missing 'documentAttachmentId' node."); + } + + return response; + } else { + return null; + } + } catch (Exception e) { + throw new RuntimeException("Failed to parse response: " + e.getMessage(), e); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java b/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java index 628e34b2..cc281df7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/AssignedApplicationsDao.java @@ -5,7 +5,9 @@ import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; +import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.FaqEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; @@ -13,11 +15,14 @@ import net.gepafin.tendermanagement.enums.AssignedApplicationEnum; import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; +import net.gepafin.tendermanagement.model.request.UpdateAssignedApplicationRequest; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository; import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.LoggingUtil; @@ -32,6 +37,7 @@ import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static net.gepafin.tendermanagement.util.Utils.log; @@ -57,6 +63,9 @@ public class AssignedApplicationsDao { @Autowired private ApplicationEvaluationDao applicationEvaluationDao; + + @Autowired + private CompanyService companyService; @Autowired private LoggingUtil loggingUtil; @@ -64,6 +73,9 @@ public class AssignedApplicationsDao { @Autowired private HttpServletRequest request; + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + public AssignedApplicationsResponse createAssignedApplications(Long applicationId, Long userId, UserEntity assignedByUser, AssignedApplicationsRequest assignedApplicationsRequest) { log.info("Assigning application to pre-Instructor with details: {}", applicationId, userId); @@ -89,8 +101,8 @@ public class AssignedApplicationsDao { UserEntity user = userService.validateUser(userId); AssignedApplicationsEntity assignment = createAssignmentEntity(application, user.getId(), assignedByUser, assignedApplicationsRequest); + applicationEvaluationDao.createOrUpdateApplicationEvaluation(user, new ApplicationEvaluationRequest(), assignment.getId()); AssignedApplicationsResponse assignApplicationToInstructorResponse = convertEntityToResponse(assignment); - applicationEvaluationDao.createOrUpdateApplicationEvaluation(user, new ApplicationEvaluationRequest(), assignApplicationToInstructorResponse.getId()); log.info("Application assigned succesfully {}", assignApplicationToInstructorResponse); return assignApplicationToInstructorResponse; } @@ -129,6 +141,7 @@ public class AssignedApplicationsDao { ApplicationEntity application = applicationService.validateApplication(assignedApplications.getApplication().getId()); String callName = application.getCall() != null ? application.getCall().getName() : ""; + Optional applicationEvaluationEntity=applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(application.getId()); LocalDateTime callEndDate = application.getCall().getEndDate(); LocalDateTime callStartDate = application.getCall().getStartDate(); @@ -155,12 +168,15 @@ public class AssignedApplicationsDao { assignedApplicationsResponse.setAssignedAt(assignedApplications.getAssignedAt()); assignedApplicationsResponse.setProtocolNumber(protocolNumber); assignedApplicationsResponse.setCallName(callName); - assignedApplicationsResponse.setCompanyName(application.getCompany().getCompanyName()); + CompanyEntity company=companyService.validateCompany(application.getCompanyId()); + assignedApplicationsResponse.setCompanyName(company.getCompanyName()); assignedApplicationsResponse.setBeneficiaryName(beneficiaryName); assignedApplicationsResponse.setSubmissionDate(submissionDate); assignedApplicationsResponse.setCallEndDate(callEndDate); assignedApplicationsResponse.setCallStartDate(callStartDate); - + if(applicationEvaluationEntity.isPresent()){ + assignedApplicationsResponse.setEvaluationEndDate(applicationEvaluationEntity.get().getEndDate()); + } return assignedApplicationsResponse; } @@ -211,7 +227,7 @@ public class AssignedApplicationsDao { public AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, - Long id, AssignedApplicationsRequest updateRequest) { + Long id, UpdateAssignedApplicationRequest updateRequest) { UserEntity updatedByUser = validator.validateUser(request); log.info("Updating assigned application with ID: {}", id); AssignedApplicationsEntity existingAssignment = validateAssignedApplication(id); @@ -222,7 +238,9 @@ public class AssignedApplicationsDao { setIfUpdated(existingAssignment::getNote, existingAssignment::setNote, updateRequest.getNote()); setIfUpdated(existingAssignment::getStatus, existingAssignment::setStatus, updateRequest.getStatus().name()); setIfUpdated(existingAssignment::getAssignedBy, existingAssignment::setAssignedBy, updatedByUser.getId()); - + setIfUpdated(existingAssignment::getUserId, existingAssignment::setUserId, updateRequest.getUserId()); + Optional entityOptional = applicationEvaluationRepository.findByAssignedApplicationsEntity_IdAndIsDeletedFalse(id); + entityOptional.ifPresent(applicationEvaluationEntity -> setIfUpdated(applicationEvaluationEntity::getUserId, applicationEvaluationEntity::setUserId, updateRequest.getUserId())); existingAssignment.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); AssignedApplicationsEntity updatedAssignment = saveAssignedApplication(existingAssignment, oldAssignedApplicationEntity, VersionActionTypeEnum.UPDATE); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java index 7daa089f..9500e0d1 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/BeneficiaryPreferredCallDao.java @@ -5,6 +5,7 @@ import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.BeneficiaryPreferredCallEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.enums.BeneficiaryCallStatus; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.BeneficiaryPreferredCallReq; @@ -12,6 +13,8 @@ import net.gepafin.tendermanagement.model.request.BeneficiaryPreferredCallReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.BeneficiaryPreferredCallResponseBean; import net.gepafin.tendermanagement.repositories.BeneficiaryPreferredCallRepository; +import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.util.Validator; @@ -41,6 +44,12 @@ public class BeneficiaryPreferredCallDao { @Autowired private Validator validator; + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; + + @Autowired + private CompanyService companyService; + @Autowired private LoggingUtil loggingUtil; @@ -50,16 +59,16 @@ public class BeneficiaryPreferredCallDao { public BeneficiaryPreferredCallResponseBean createBeneficiaryPreferredCall(HttpServletRequest httpServletRequest, BeneficiaryPreferredCallReq request, UserEntity user) { log.info("Creating new beneficiary preferred call with details: {}", request); validator.validateUserWithCompany(httpServletRequest, request.getCompanyId()); - + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(user.getId(), request.getCompanyId()); Optional existingCall = beneficiaryPreferredCallRepository - .findByUserIdAndCallIdAndCompanyIdAndIsDeletedFalse(user.getId(), request.getCallId(), request.getCompanyId()); + .findByUserIdAndCallIdAndUserWithCompanyIdAndIsDeletedFalse(user.getId(), request.getCallId(), userWithCompanyEntity.getId()); if (existingCall.isPresent()) { log.warn("Duplicate beneficiary preferred call detected: {}", existingCall.get()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.DUPLICATE_BENEFICIARY_CALL)); } - BeneficiaryPreferredCallEntity entity = convertRequestToEntity(request, user); + BeneficiaryPreferredCallEntity entity = convertRequestToEntity(request, user,userWithCompanyEntity); entity = beneficiaryPreferredCallRepository.save(entity); /** This code is responsible for adding a version history log for "Create Beneficiary Preferred Call" operation. **/ @@ -69,7 +78,7 @@ public class BeneficiaryPreferredCallDao { return convertEntityToResponse(entity); } - private BeneficiaryPreferredCallEntity convertRequestToEntity(BeneficiaryPreferredCallReq request,UserEntity userEntity) { + private BeneficiaryPreferredCallEntity convertRequestToEntity(BeneficiaryPreferredCallReq request,UserEntity userEntity,UserWithCompanyEntity userWithCompanyEntity) { BeneficiaryPreferredCallEntity entity = new BeneficiaryPreferredCallEntity(); if (userEntity.getBeneficiary()!=null) { entity.setBeneficiaryId(userEntity.getBeneficiary().getId()); @@ -77,7 +86,8 @@ public class BeneficiaryPreferredCallDao { entity.setStatus(BeneficiaryCallStatus.ENABLED.getValue()); entity.setCallId(request.getCallId()); entity.setUserId(userEntity.getId()); - entity.setCompanyId(request.getCompanyId()); + entity.setCompanyId(userWithCompanyEntity.getCompanyId()); + entity.setUserWithCompany(userWithCompanyEntity); entity.setIsDeleted( false); return entity; } @@ -142,6 +152,7 @@ public class BeneficiaryPreferredCallDao { response.setCallId(entity.getCallId()); response.setUserId(entity.getUserId()); response.setCompanyId(entity.getCompanyId()); + response.setUserWithCompanyId(entity.getUserWithCompany().getId()); response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); @@ -160,8 +171,8 @@ public class BeneficiaryPreferredCallDao { log.info("Beneficiary preferred call status updated with ID: {}", existingEntity.getId()); } public List getBeneficiaryPreferredCallByUserId(UserEntity userEntity, Long companyId) { - - List calls = beneficiaryPreferredCallRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), companyId); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyId); + List calls = beneficiaryPreferredCallRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId()); 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 9c33c1fb..7382f1c6 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -15,7 +15,9 @@ import java.util.zip.ZipOutputStream; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; @@ -49,6 +51,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.Status; import static net.gepafin.tendermanagement.enums.RoleStatusEnum.ROLE_SUPER_ADMIN; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; +import static org.hibernate.internal.util.collections.CollectionHelper.listOf; @Component public class CallDao { @@ -99,12 +102,24 @@ public class CallDao { @Autowired private Validator validator; + @Autowired + private CompanyService companyService; + @Autowired private LoggingUtil loggingUtil; @Autowired private HttpServletRequest request; + @Autowired + private NotificationDao notificationDao; + + @Autowired + private BeneficiaryRepository beneficiaryRepository; + + @Autowired + private NotificationTypeRepository notificationTypeRepository; + public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, UserEntity userEntity) { createCallRequest.setRegionId(userEntity.getRoleEntity().getRegion().getId()); CallEntity callEntity = convertToCallEntity(createCallRequest, userEntity); @@ -127,7 +142,7 @@ public class CallDao { ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) { for (DocumentEntity document : documents) { - String s3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.CALL, callId, 0L); + String s3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.CALL, callId, 0L,0L); try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, document.getFilePath())) { String fileName = Utils.extractFileName(document.getFilePath()); ZipEntry zipEntry = new ZipEntry(fileName); @@ -476,8 +491,9 @@ public class CallDao { BeneficiaryPreferredCallEntity preferredCall; if (companyId != null) { validator.validateUserWithCompany(request, companyId); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(user.getId(),companyId); preferredCall = beneficiaryPreferredCallRepository - .findByUserIdAndCallIdAndCompanyIdAndIsDeletedFalse(userId, callId, companyId) + .findByUserIdAndCallIdAndUserWithCompanyIdAndIsDeletedFalse(userId, callId, userWithCompanyEntity.getId()) .orElse(null); } else { preferredCall = beneficiaryPreferredCallRepository @@ -735,8 +751,9 @@ public class CallDao { if (Boolean.TRUE.equals(onlyPreferredCall)) { validator.validateUserWithCompany(request, companyId); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(user.getId(),companyId); List preferredCalls = beneficiaryPreferredCallRepository - .findByUserIdAndCompanyIdAndIsDeletedFalse(user.getId(), companyId); + .findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(user.getId(), userWithCompanyEntity.getId()); List preferredCallIds = preferredCalls.stream() .map(BeneficiaryPreferredCallEntity::getCallId) .collect(Collectors.toList()); @@ -764,10 +781,11 @@ public class CallDao { public Map getBeneficiaryPreferredCallsForUser(HttpServletRequest request, UserEntity user, List callIds, Long companyId) { List beneficiaryPreferredCalls; - if (companyId != null) { + if (companyId != null && Boolean.TRUE.equals(validator.checkIsBeneficiary())) { validator.validateUserWithCompany(request, companyId); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(user.getId(),companyId); beneficiaryPreferredCalls = beneficiaryPreferredCallRepository - .findByUserIdAndCallIdInAndCompanyIdAndIsDeletedFalse(user.getId(), callIds, companyId); + .findByUserIdAndCallIdInAndUserWithCompanyIdAndIsDeletedFalse(user.getId(), callIds, userWithCompanyEntity.getId()); } else { beneficiaryPreferredCalls = beneficiaryPreferredCallRepository .findByUserIdAndCallIdInAndIsDeletedFalse(user.getId(), callIds); @@ -822,10 +840,20 @@ public class CallDao { validateStatusChange(currentStatus, statusReq); callEntity.setStatus(statusReq.getValue()); callEntity = callRepository.save(callEntity); - + + //Creating notification. + List userIds = beneficiaryRepository.findUserIdsByHubIdAndBeneficiaryId(callEntity.getHub().getId()); + Map placeholders = new HashMap<>(); + placeholders.put("{{call_name}}", callEntity.getName()); + userIds.forEach(userId -> { + List companyIds = notificationDao.getAllCompanyIdsForUser(userId); + NotificationReq notificationReq = notificationDao.createNotificationReq(NotificationTypeEnum.CALL_CREATED.getValue(), placeholders, userId, null, companyIds); + notificationDao.sendNotification(notificationReq); + }); + /** This code is responsible for adding a version history log for the "update call status" operation **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCallEntity).newData(callEntity).build()); - + return convertToCallResponseBean(callEntity); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 38e856c0..48ec017b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -1,10 +1,15 @@ package net.gepafin.tendermanagement.dao; +import java.util.EnumSet; import java.util.List; +import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.repositories.ApplicationRepository; @@ -19,8 +24,6 @@ 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; @@ -41,6 +44,15 @@ public class CompanyDao { private ApplicationRepository applicationRepository; @Autowired private FaqRepository faqRepository; + + @Autowired + private BeneficiaryPreferredCallRepository beneficiaryPreferredCallRepository; + + @Autowired + private UserCompanyDelegationRepository userCompanyDelegationRepository; + + @Autowired + private CompanyService companyService; @Autowired private LoggingUtil loggingUtil; @@ -55,7 +67,7 @@ public class CompanyDao { if (existingCompany != null) { UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), existingCompany.getId()).orElse(null); if (existingRelation == null) { - userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant()); + userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant(),companyRequest); /** This code is responsible for adding a version history log for "adding user with company" operation. **/ loggingUtil.addVersionHistory( @@ -72,7 +84,7 @@ public class CompanyDao { /** This code is responsible for adding a version history log for "creating company" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(companyData).build()); - userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant()); + userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant(),companyRequest); return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity); } @@ -96,7 +108,7 @@ public class CompanyDao { } } - private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant) { + private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant,CompanyRequest companyRequest) { UserWithCompanyEntity userWithCompanyEntity = new UserWithCompanyEntity(); if (userEntity.getBeneficiary() != null) { @@ -106,6 +118,11 @@ public class CompanyDao { userWithCompanyEntity.setCompanyId(companyEntity.getId()); userWithCompanyEntity.setUserId(userEntity.getId()); userWithCompanyEntity.setIsLegalRepresentant(isLegalRepresentant); + userWithCompanyEntity.setEmail(companyRequest.getEmail()); + userWithCompanyEntity.setPec(companyRequest.getPec()); + userWithCompanyEntity.setContactName(companyRequest.getContactName()); + userWithCompanyEntity.setContactEmail(companyRequest.getContactEmail()); + userWithCompanyEntity.setJson(Utils.convertMapIntoJsonString(companyRequest.getVatCheckResponse()) ); UserWithCompanyEntity userWithCompany = userWithCompanyRepository.save(userWithCompanyEntity); /** This code is responsible for adding a version history log for the "adding user with company" operation. **/ @@ -124,12 +141,8 @@ public class CompanyDao { 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()); entity.setHub(userEntity.getHub()); return entity; } @@ -146,8 +159,8 @@ public class CompanyDao { response.setProvince(entity.getProvince()); response.setCap(entity.getCap()); response.setCountry(entity.getCountry()); - response.setPec(entity.getPec()); - response.setEmail(entity.getEmail()); + response.setPec(userWithCompanyEntity.getPec()); + response.setEmail(userWithCompanyEntity.getEmail()); response.setNumberOfEmployees(entity.getNumberOfEmployees()); response.setAnnualRevenue(entity.getAnnualRevenue()); if(userWithCompanyEntity!=null) { @@ -155,8 +168,8 @@ public class CompanyDao { } response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); - response.setContactName(entity.getContactName()); - response.setContactEmail(entity.getContactEmail()); + response.setContactName(userWithCompanyEntity.getContactName()); + response.setContactEmail(userWithCompanyEntity.getContactEmail()); return response; } @@ -167,7 +180,6 @@ public class CompanyDao { CompanyEntity oldCompanyData = Utils.getClonedEntityForData(companyEntity); 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()); @@ -175,12 +187,17 @@ public class CompanyDao { 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()); + + if(StringUtils.isNotBlank(companyRequest.getVatNumber())) { + CompanyEntity existingCompany = companyRepository.findByVatNumberAndHubId(companyRequest.getVatNumber(), userEntity.getHub().getId()); + if(existingCompany!=null){ + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.VATNUMBER_ALREADY_EXISTS)); + } + companyEntity.setVatNumber(companyRequest.getVatNumber()); + + } companyRepository.save(companyEntity); /** This code is responsible for adding a version history log for the "Update company" operation. **/ @@ -190,8 +207,15 @@ public class CompanyDao { UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId); //cloned entity for old data UserWithCompanyEntity oldUserWithCompanyData = Utils.getClonedEntityForData(userWithCompanyEntity); - - Utils.setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, companyRequest.getIsLegalRepresentant()); + if(StringUtils.isNotBlank(companyRequest.getVatNumber())) { + String responseJson = companyRequest.getVatCheckResponse() != null ? Utils.convertMapIntoJsonString(companyRequest.getVatCheckResponse()) : null; + setIfUpdated(userWithCompanyEntity::getJson, userWithCompanyEntity::setJson, responseJson); + } + setIfUpdated(userWithCompanyEntity::getPec, userWithCompanyEntity::setPec, userWithCompanyEntity.getPec()); + setIfUpdated(userWithCompanyEntity::getEmail, userWithCompanyEntity::setEmail, userWithCompanyEntity.getEmail()); + setIfUpdated(userWithCompanyEntity::getContactName, userWithCompanyEntity::setContactName, companyRequest.getContactName()); + setIfUpdated(userWithCompanyEntity::getContactEmail, userWithCompanyEntity::setContactEmail, companyRequest.getContactEmail()); + setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, companyRequest.getIsLegalRepresentant()); userWithCompanyEntity = userWithCompanyRepository.save(userWithCompanyEntity); /** This code is responsible for adding a version history log for the "Update company" operation. **/ @@ -243,42 +267,89 @@ public class CompanyDao { 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()))) { + 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=companyService.getUserWithCompany(userEntity.getId(),companyEntity.getId()); + List userApplications = applicationRepository.findByUserWithCompanyIdAndUserIdAndIsDeletedFalse(existingRelation.getId(), userEntity.getId()); + List faqs = faqRepository.findByUserWithCompanyIdAndIsDeletedFalse(existingRelation.getId()); + List preferredCallEntities= beneficiaryPreferredCallRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(userEntity.getId(),existingRelation.getId()); + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository.findByUserIdAndUserWithCompanyIdAndStatus(userEntity.getId(),existingRelation.getId(), UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + List applicationStatusAllowed = List.of( + ApplicationStatusTypeEnum.DRAFT.getValue(), + ApplicationStatusTypeEnum.AWAITING.getValue(), + ApplicationStatusTypeEnum.READY.getValue() + ); + boolean notAllowedStatus = userApplications.stream() + .anyMatch(application -> !applicationStatusAllowed.contains(application.getStatus())); + if (notAllowedStatus) { 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()))) { - //cloned entity for old data - ApplicationEntity oldApplicationData = Utils.getClonedEntityForData(application); - application.setIsDeleted(Boolean.TRUE); - applicationRepository.save(application); + userApplications = userApplications.stream() + .peek(application -> { + ApplicationEntity oldApplication = Utils.getClonedEntityForData(application); + application.setIsDeleted(Boolean.TRUE); - /** This code is responsible for adding a version history log for the "" operation. **/ - loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldApplicationData).newData(application).build()); - } - } - for (FaqEntity faq : faqs) { - //cloned for old data - FaqEntity oldFaqEntityData = Utils.getClonedEntityForData(faq); - faq.setIsDeleted(Boolean.TRUE); - faqRepository.save(faq); + /** This code is responsible for adding a version history log for the "Soft delete Faq" operation. **/ + loggingUtil.addVersionHistory( + VersionHistoryRequest.builder() + .request(request) + .actionType(VersionActionTypeEnum.SOFT_DELETE) + .oldData(oldApplication) + .newData(application) + .build() + ); + }) + .toList(); + applicationRepository.saveAll(userApplications); - /** This code is responsible for adding a version history log for the "soft deleting faq" operation. **/ + faqs = faqs.stream() + .peek(faq -> { + FaqEntity oldFaq = Utils.getClonedEntityForData(faq); + faq.setIsDeleted(Boolean.TRUE); + /** This code is responsible for adding a version history log for the "Soft delete Faq" operation. **/ + loggingUtil.addVersionHistory( + VersionHistoryRequest.builder() + .request(request) + .actionType(VersionActionTypeEnum.SOFT_DELETE) + .oldData(oldFaq) + .newData(faq) + .build() + ); + }) + .toList(); + faqRepository.saveAll(faqs); + + preferredCallEntities = preferredCallEntities.stream() + .peek(beneficiaryPreferredCall -> { + BeneficiaryPreferredCallEntity oldPreferredCall = Utils.getClonedEntityForData(beneficiaryPreferredCall); + beneficiaryPreferredCall.setIsDeleted(Boolean.TRUE); + /** This code is responsible for adding a version history log for the "Soft Delete BeneficiaryPreferredCall" operation. **/ + loggingUtil.addVersionHistory( + VersionHistoryRequest.builder() + .request(request) + .actionType(VersionActionTypeEnum.SOFT_DELETE) + .oldData(oldPreferredCall) + .newData(beneficiaryPreferredCall) + .build() + ); + }) + .toList(); + beneficiaryPreferredCallRepository.saveAll(preferredCallEntities); + + if(userCompanyDelegationEntity!=null){ + UserCompanyDelegationEntity oldUserWithCompanyDelegation = Utils.getClonedEntityForData(userCompanyDelegationEntity); + userCompanyDelegationEntity.setStatus( UserCompanyDelegationStatusEnum.INACTIVE.getValue()); + userCompanyDelegationRepository.save(userCompanyDelegationEntity); + + /** This code is responsible for adding a version history log for the "Update UserWithCompanyDelegation" operation. **/ loggingUtil.addVersionHistory( - VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldFaqEntityData).newData(faq).build()); + VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldUserWithCompanyDelegation).newData(userCompanyDelegationEntity).build()); } UserWithCompanyEntity oldUserWithCompanyData = Utils.getClonedEntityForData(existingRelation); existingRelation.setIsDeleted(Boolean.TRUE); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index c76d14c9..0afc8fc8 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.dao; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; @@ -12,6 +13,7 @@ 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 net.gepafin.tendermanagement.service.CompanyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -31,6 +33,9 @@ public class DashboardDao { @Autowired private CompanyRepository companyRepository; + + @Autowired + private CompanyService companyService; public SuperAdminWidgetResponseBean getDashboardWidget(UserEntity requestedUserEntity) { SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); @@ -108,8 +113,9 @@ public class DashboardDao { if (activeCalls != null) { beneficiaryWidgetResponseBean.setNumberOfCalls(activeCalls); } + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),company.getId()); Long activeApplication = applicationRepository.countSubmittedApplicationsByUserId(userEntity.getId(), - company.getId()); + userWithCompanyEntity.getId()); if (activeApplication != null) { beneficiaryWidgetResponseBean.setNumberOfApplications(activeApplication); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java index 5c2c7e70..670f9444 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java @@ -7,8 +7,13 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Function; +import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; +import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.util.LoggingUtil; @@ -21,10 +26,6 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; -import net.gepafin.tendermanagement.entities.CompanyEntity; -import net.gepafin.tendermanagement.entities.DocumentEntity; -import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; -import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; import net.gepafin.tendermanagement.model.request.CompanyDelegationRequest; import net.gepafin.tendermanagement.model.response.CompanyDelegationResponse; @@ -33,6 +34,7 @@ import net.gepafin.tendermanagement.model.response.UserResponseBean; import net.gepafin.tendermanagement.repositories.DocumentRepository; import net.gepafin.tendermanagement.repositories.UserCompanyDelegationRepository; import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.service.ApplicationEvaluationService; import net.gepafin.tendermanagement.service.UserService; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; @@ -70,15 +72,27 @@ public class DelegationDao { @Autowired private Validator validator; + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; + + @Autowired + private CompanyService companyService; + @Autowired private LoggingUtil loggingUtil; @Autowired private HttpServletRequest request; + @Autowired + private ApplicationService applicationService; + + @Autowired + private ApplicationEvaluationService applicationEvaluationService; + public ByteArrayOutputStream generateDocument(Map placeholders, String templateName) { try { - String s3Folder = s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.TEMPLATE, 0L, 0L); + String s3Folder = s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.TEMPLATE, 0L, 0L,0L); InputStream templateStream = amazonS3Service.getFile(s3Folder ,templateName); XWPFDocument doc = loadTemplate(templateStream); replacePlaceholders(doc, placeholders); @@ -191,20 +205,18 @@ public class DelegationDao { companyDao.validateCompany(companyId); companyDao.getUserWithCompany(userEntity.getId(), companyId); validateFileType(file); - UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository.findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, - UserCompanyDelegationStatusEnum.ACTIVE.getValue()); - UserCompanyDelegationEntity oldUserCompanyDelegationEntity = Utils.getClonedEntityForData(userCompanyDelegationEntity); - if (userCompanyDelegationEntity != null) { - userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.INACTIVE.getValue()); - userCompanyDelegationRepository.save(userCompanyDelegationEntity); + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyId); + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndUserWithCompanyIdAndStatus(userEntity.getId(), userWithCompanyEntity.getId(), + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); - /** This code is responsible for adding a version history log for the "update user company delegation status" operation. **/ - loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldUserCompanyDelegationEntity) - .newData(userCompanyDelegationEntity).build()); + if (userCompanyDelegationEntity != null) { + deleteDelegationFromS3(userCompanyDelegationEntity); } UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = uploadFileOnAmazonS3ForCompanyDelegation(file); userCompanyDelegationEntity = new UserCompanyDelegationEntity(); - userCompanyDelegationEntity.setCompanyId(companyId); + userCompanyDelegationEntity.setUserWithCompany(userWithCompanyEntity); + userCompanyDelegationEntity.setCompanyId(userWithCompanyEntity.getCompanyId()); userCompanyDelegationEntity.setUserId(userEntity.getId()); if (userEntity.getBeneficiary() != null) { userCompanyDelegationEntity.setBeneficiaryId(userEntity.getBeneficiary().getId()); @@ -253,11 +265,12 @@ public class DelegationDao { } } - public CompanyDelegationResponse getCompanyDelegation(UserEntity userEntity, Long companyId) { + public CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId, Long applicationId) { + + UserWithCompanyEntity userWithCompanyEntity= validateUserAndGetUserWithCompany(request, companyId, applicationId); UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository - .findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, + .findByUserIdAndUserWithCompanyIdAndStatus(userWithCompanyEntity.getUserId(), userWithCompanyEntity.getId(), UserCompanyDelegationStatusEnum.ACTIVE.getValue()); - companyDao.getUserWithCompany(userEntity.getId(), companyId); if(userCompanyDelegationEntity == null) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DELEGATION_NOT_FOUND)); @@ -265,20 +278,49 @@ public class DelegationDao { return convertUserCompanyDelegationToCompanyDelegationResponse(userCompanyDelegationEntity); } - public void deleteCompanyDelegation(UserEntity userEntity, Long companyId) { + private UserWithCompanyEntity validateUserAndGetUserWithCompany(HttpServletRequest request, Long companyId, + Long applicationId) { + Long userId = null; + if (companyId == null && applicationId == null) { + throw new CustomValidationException(Status.BAD_REQUEST, + Translator.toLocale(GepafinConstant.ATLEAST_ONE_ID_REQUIRED)); + } + if (applicationId != null) { + ApplicationEntity application = applicationService.validateApplication(applicationId); + userId = application.getUserId(); + companyId = application.getCompanyId(); + } + if (validator.checkIsPreInstructor()) { + ApplicationEvaluationEntity applicationEvaluationEntity = applicationEvaluationService.validateApplicationEvaluationByApplicationId(applicationId); + validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId()); + } else if (validator.checkIsBeneficiary()) { + userId = validator.validateUser(request).getId(); + } + return companyService.getUserWithCompany(userId, companyId); + } - UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository.findByUserIdAndCompanyIdAndStatus(userEntity.getId(), companyId, - UserCompanyDelegationStatusEnum.ACTIVE.getValue()); + public void deleteCompanyDelegation(UserEntity userEntity, Long companyId) { + UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyId); + UserCompanyDelegationEntity userCompanyDelegationEntity = userCompanyDelegationRepository + .findByUserIdAndUserWithCompanyIdAndStatus(userEntity.getId(), userWithCompanyEntity.getId(), + UserCompanyDelegationStatusEnum.ACTIVE.getValue()); companyDao.getUserWithCompany(userEntity.getId(), companyId); - //cloned entity for old data - UserCompanyDelegationEntity oldUserCompanyDelegation = Utils.getClonedEntityForData(userCompanyDelegationEntity); if (userCompanyDelegationEntity == null) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DELEGATION_NOT_FOUND)); } + deleteDelegationFromS3(userCompanyDelegationEntity); + } + + public void deleteDelegationFromS3(UserCompanyDelegationEntity userCompanyDelegationEntity) { + UserCompanyDelegationEntity oldUserCompanyDelegation = Utils.getClonedEntityForData(userCompanyDelegationEntity); + String oldS3Path = userCompanyDelegationEntity.getFilePath(); + String newS3Path = s3ConfigBean.generateDocumentPathForDelegationAndSignedDocument(DocOtherSourceTypeEnum.DELETED_USER_DELEGATION); + UploadFileOnAmazonS3Response response = amazonS3Service.moveFile(userCompanyDelegationEntity.getFileName(), oldS3Path, newS3Path); + userCompanyDelegationEntity.setFileName(response.getFileName()); + userCompanyDelegationEntity.setFilePath(response.getFilePath()); userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.INACTIVE.getValue()); userCompanyDelegationRepository.save(userCompanyDelegationEntity); - /** This code is responsible for adding a version history log for the "Soft Deleting company delegation " operation. **/ loggingUtil.addVersionHistory( VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldUserCompanyDelegation).newData(userCompanyDelegationEntity) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java index 9ff9fd49..e1dbe853 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -1,13 +1,12 @@ package net.gepafin.tendermanagement.dao; +import lombok.extern.slf4j.Slf4j; import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; -import lombok.extern.slf4j.Slf4j; -import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; -import net.gepafin.tendermanagement.enums.UserActionContextEnum; -import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; @@ -18,20 +17,24 @@ import org.springframework.web.multipart.MultipartFile; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.DocumentEntity; -import net.gepafin.tendermanagement.enums.DocumentTypeEnum; import net.gepafin.tendermanagement.model.response.DocumentResponseBean; import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response; +import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; import net.gepafin.tendermanagement.repositories.DocumentRepository; import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService; +import net.gepafin.tendermanagement.service.ApplicationService; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; - +import org.springframework.beans.factory.annotation.Value; import java.util.ArrayList; import java.util.List; + @Slf4j @Component public class DocumentDao { @@ -52,7 +55,22 @@ public class DocumentDao { private S3PathConfig s3ConfigBean; @Autowired - private ApplicationRepository applicationFormRepository; + private ApplicationRepository applicationRepository; + + @Autowired + ApplicationService applicationService; + + @Autowired + ApplicationAmendmentRequestService applicationAmendmentRequestService; + + @Autowired + ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Value("${aws.s3.bucket.name}") + private String bucketName; @Autowired private LoggingUtil loggingUtil; @@ -63,7 +81,7 @@ public class DocumentDao { // @Value("${aws.s3.url.folder}") // private String s3Folder; - public List uploadFiles(List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { + public List uploadFiles(Long userId,List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { List documentEntities = new ArrayList<>(); Long source = resolveSourceId(sourceId, sourceType); @@ -77,6 +95,7 @@ public class DocumentDao { documentEntity.setType(fileType.getValue()); documentEntity.setFilePath(uploadFileOnAmazonS3Response.getFilePath()); documentEntity.setIsDeleted(false); + documentEntity.setUploadedBy(userId); documentEntities.add(documentEntity); } } @@ -102,6 +121,14 @@ public class DocumentDao { userActionContext = UserActionContextEnum.UPLOAD_APPLICATION_DOCUMENT; } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.APPLICATION)) { userActionContext = UserActionContextEnum.UPLOAD_APPLICATION_IMAGES; + }else if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.AMENDMENT)) { + userActionContext = UserActionContextEnum.UPLOAD_AMENDMENT_DOCUMENT; + } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.AMENDMENT)) { + userActionContext = UserActionContextEnum.UPLOAD_AMENDMENT_IMAGES; + }else if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.EVALUATION)) { + userActionContext = UserActionContextEnum.UPLOAD_EVALUATION_DOCUMENT; + } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.EVALUATION)) { + userActionContext = UserActionContextEnum.UPLOAD_EVALUATION_IMAGES; } return userActionContext; @@ -121,28 +148,41 @@ public class DocumentDao { private UploadFileOnAmazonS3Response uploadFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long sourceId) { - Long applicationId = 0L; + Long applicationId = 0L; + Long amendmentId = 0L; + Long evaluationId = 0L; Long callId = sourceId; if (type == DocumentSourceTypeEnum.APPLICATION) { applicationId = sourceId; - callId = applicationFormRepository.findCallIdById(applicationId); + callId = applicationRepository.findCallIdById(applicationId); + } else if (type == DocumentSourceTypeEnum.AMENDMENT) { + amendmentId = sourceId; + ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + }else if (type == DocumentSourceTypeEnum.EVALUATION) { + evaluationId = sourceId; + ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); } try { - String s3Path = generateS3Path(type, callId, applicationId); + String s3Path = generateS3Path(type, callId, applicationId, amendmentId); log.info("Generated S3 path {}", s3Path); return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); } catch (Exception e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); } } - public String generateS3Path(DocumentSourceTypeEnum typeOfDocument, Long callId, Long applicationId) { + public String generateS3Path(DocumentSourceTypeEnum typeOfDocument, Long callId, Long applicationId, Long amendmentId) { try { - return s3ConfigBean.generateDocumentPath(typeOfDocument, callId, applicationId); + return s3ConfigBean.generateDocumentPath(typeOfDocument, callId, applicationId, amendmentId); } catch (IllegalArgumentException e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); } } + private Long resolveSourceId(Long sourceId, DocumentSourceTypeEnum sourceType) { if (sourceType == DocumentSourceTypeEnum.CALL) { @@ -159,26 +199,38 @@ public class DocumentDao { } public void deleteFile(Long documentId) { + DocumentEntity documentEntity = documentRepository.findById(documentId).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND))); + if(Boolean.TRUE.equals(documentEntity.getIsDeleted())){ + return; + } + Long callId = null; + Long applicationId = null; + Long amendmentId = null; + Long evaluationId = null; - DocumentEntity documentEntity = documentRepository.findById(documentId) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND))); - // String fileName= Utils.extractFileName(documentEntity.getFilePath()); - // deleteFileOnAmazonS3(fileName); + if (DocumentSourceTypeEnum.CALL.getValue().equalsIgnoreCase(documentEntity.getSource())) { + callId = documentEntity.getSourceId(); + } else if (DocumentSourceTypeEnum.APPLICATION.getValue().equalsIgnoreCase(documentEntity.getSource())) { + applicationId = documentEntity.getSourceId(); + ApplicationEntity applicationEntity = applicationService.validateApplication(applicationId); + callId = applicationEntity.getCall().getId(); + } + else if(DocumentSourceTypeEnum.AMENDMENT.getValue().equalsIgnoreCase(documentEntity.getSource())){ + amendmentId = documentEntity.getSourceId(); + ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + } else if(DocumentSourceTypeEnum.EVALUATION.getValue().equalsIgnoreCase(documentEntity.getSource())){ + evaluationId = documentEntity.getSourceId(); + ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + } + deleteFileFromS3(documentEntity, callId, applicationId,amendmentId); - //cloned for old data - DocumentEntity oldDocumentEntity = Utils.getClonedEntityForData(documentEntity); - - // String fileName= Utils.extractFileName(documentEntity.getFilePath()); - // deleteFileOnAmazonS3(fileName); - documentEntity.setIsDeleted(true); - documentRepository.save(documentEntity); - - /** This code is responsible for adding a version history log for the "Soft delete document" operation. **/ - loggingUtil.addVersionHistory( - VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldDocumentEntity).newData(documentEntity).build()); } - public DocumentEntity validateDocument(Long id) { return documentRepository.findByIdAndNotDeleted(id).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND))); @@ -206,19 +258,35 @@ public class DocumentDao { } return callDao.convertToDocumentResponseBean(documentEntity); } + private UploadFileOnAmazonS3Response updateFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long id) { try { - Long callId; - Long applicationId; - if(type.equals(DocumentSourceTypeEnum.APPLICATION)){ - callId = applicationFormRepository.findCallIdById(id); + Long callId=null; + Long applicationId=null; + Long amendmentId=null; + Long evaluationId=null; + if (type.equals(DocumentSourceTypeEnum.APPLICATION)) { + callId = applicationRepository.findCallIdById(id); applicationId = id; - }else{ + } + else if(type.equals(DocumentSourceTypeEnum.AMENDMENT)){ + amendmentId = id; + ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + }else if(type.equals(DocumentSourceTypeEnum.EVALUATION)){ + evaluationId = id; + ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + } + + else { callId = id; applicationId = 0L; } - String s3Path = generateS3Path(type, callId, applicationId); + String s3Path = generateS3Path(type, callId, applicationId,amendmentId); log.info("Generated S3 path {}", s3Path); return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); } catch (Exception e) { @@ -229,4 +297,26 @@ public class DocumentDao { DocumentEntity documentEntity = validateDocument(documentId); return callDao.convertToDocumentResponseBean(documentEntity); } + + public void deleteFileFromS3(DocumentEntity documentEntity, Long callId, Long applicationId,Long amendmentId) { + try { + + DocumentEntity oldDocumentEntity = Utils.getClonedEntityForData(documentEntity); + String oldS3Path = documentEntity.getFilePath(); + String newS3Path = s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.valueOf("DELETED_" + documentEntity.getSource().toUpperCase()), callId, applicationId,amendmentId); + UploadFileOnAmazonS3Response response = amazonS3Service.moveFile(documentEntity.getFileName(), oldS3Path, newS3Path); + documentEntity.setFileName(response.getFileName()); + documentEntity.setFilePath(response.getFilePath()); + documentEntity.setIsDeleted(true); + documentRepository.save(documentEntity); + + /** This code is responsible for adding a version history log for the "Soft delete document" operation. **/ + loggingUtil.addVersionHistory( + VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldDocumentEntity).newData(documentEntity).build()); + log.info("File for document ID {} successfully moved to deleted folder.", documentEntity.getId()); + } catch (Exception e) { + log.error("Error moving file for document ID {} to deleted folder: {}", documentEntity.getId(), e.getMessage()); + throw new CustomValidationException(Status.VALIDATION_ERROR, "Error occurred while moving file to deleted folder."); + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java index 855caa2d..88e6954a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/EmailNotificationDao.java @@ -1,23 +1,17 @@ package net.gepafin.tendermanagement.dao; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; -import net.gepafin.tendermanagement.enums.EmailEntityTypeEnum; import net.gepafin.tendermanagement.enums.RecipientTypeEnum; -import net.gepafin.tendermanagement.enums.StatusTypeEnum; -import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.model.request.EmailConfig; import net.gepafin.tendermanagement.model.request.EmailLogRequest; +import net.gepafin.tendermanagement.model.response.AmendmentFormFieldResponse; +import net.gepafin.tendermanagement.model.response.EmailContentResponse; import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse; -import net.gepafin.tendermanagement.repositories.EmailLogRepository; -import net.gepafin.tendermanagement.repositories.HubRepository; -import net.gepafin.tendermanagement.service.ApplicationService; -import net.gepafin.tendermanagement.service.HubService; -import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; -import net.gepafin.tendermanagement.service.UserService; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.service.impl.EmailService; import net.gepafin.tendermanagement.service.impl.EmailServiceFactory; import net.gepafin.tendermanagement.util.DateTimeUtil; @@ -25,11 +19,14 @@ import net.gepafin.tendermanagement.util.Utils; 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.stereotype.Component; import java.time.LocalDateTime; import java.util.*; +import static net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao.filterByName; + @Component public class EmailNotificationDao { @@ -43,7 +40,7 @@ public class EmailNotificationDao { @Autowired private UserService userService; - + @Autowired private HubService hubService; @@ -59,85 +56,180 @@ public class EmailNotificationDao { @Autowired private EmailLogRepository emailLogRepository; + @Autowired + private CompanyService companyService; - private void sendEmail(ApplicationEntity applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType, - Map bodyPlaceholders, List additionalRecipients,Long amendmentId) { + @Autowired + private ApplicationFormRepository applicationFormRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Value("${rinaldo_email}") + private String rinaldoEmail; + + private void sendEmail(ApplicationEntity applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType, Map bodyPlaceholders, + List additionalRecipients, Long amendmentId) { HubEntity hubEntity = hubService.valdateHub(applicationEntity.getHubId()); - String service = determineService(applicationEntity.getHubId()); - String legalMail = service.equals("Gepafin S.p.a.") ? "bandi.gepafin@legalmail.it" : "bandi.sviluppumbria@legalmail.it"; +// String service = determineService(applicationEntity.getHubId()); +// String legalMail = service.equals("Gepafin S.p.a.") ? "bandi.gepafin@legalmail.it" : "bandi.sviluppumbria@legalmail.it"; + EmailContentResponse emailContent = prepareEmailContent(applicationEntity, templateType, hubEntity, bodyPlaceholders); + UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); + sendEmails(applicationEntity, userEntity, additionalRecipients,amendmentId,emailContent.getSystemEmailTemplateResponse(),emailContent.getSubject(),emailContent.getBody()); + } + + public EmailContentResponse prepareEmailContent( + ApplicationEntity applicationEntity, + SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType, + HubEntity hubEntity, + Map bodyPlaceholders + ) { SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall(templateType, hubEntity, null); + Map subjectPlaceholders = new HashMap<>(); + CompanyEntity company = companyService.validateCompany(applicationEntity.getCompanyId()); subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - subjectPlaceholders.put("{{company_name}}", applicationEntity.getCompany().getCompanyName()); - bodyPlaceholders.put("{{legal_mail}}", legalMail); + subjectPlaceholders.put("{{company_name}}", company.getCompanyName()); +// bodyPlaceholders.put("{{legal_mail}}", legalMail); String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders); String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders); - UserEntity userEntity = userService.validateUser(applicationEntity.getUserId()); - List recipientEmails = getRecipientEmails(applicationEntity, userEntity, additionalRecipients); - EmailLogRequest emailLogRequest=emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.BENEFICIARY,userEntity.getBeneficiary().getId(),Utils.listToCommaSeparatedString(recipientEmails),userEntity.getId(),applicationEntity.getId(),amendmentId ,applicationEntity.getCall().getId()); - sendMail(applicationEntity.getHubId(), subject, body, recipientEmails,emailLogRequest); - } - private List getRecipientEmails(ApplicationEntity applicationEntity, UserEntity userEntity, List additionalRecipients) { - List recipientEmails = new ArrayList<>(); - String companyEmail = applicationEntity.getCompany().getEmail(); - String contactEmail = applicationEntity.getCompany().getContactEmail(); - - if (companyEmail != null && !companyEmail.isEmpty()) { - recipientEmails.add(companyEmail); - } - if (contactEmail != null && !contactEmail.isEmpty() && !contactEmail.equals(companyEmail)) { - recipientEmails.add(contactEmail); - } - - if (userEntity.getBeneficiary().getEmail() != null) { - recipientEmails.add(userEntity.getBeneficiary().getEmail()); - } - if (additionalRecipients != null) { - recipientEmails.addAll(additionalRecipients); - } - - return recipientEmails; + return new EmailContentResponse(subject, body, systemEmailTemplateResponse); } + private void sendEmails(ApplicationEntity applicationEntity, UserEntity userEntity, List additionalRecipients,Long amendmentId,SystemEmailTemplateResponse systemEmailTemplateResponse,String subject,String body) { - private String determineService(Long hubId) { + Optional applicationEvaluationEntity = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId()); + CompanyEntity company = companyService.validateCompany(applicationEntity.getCompanyId()); - HubEntity hub = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); - return hub.getEmailServiceType().equalsIgnoreCase("MAILGUN_SERVICE") ? "Gepafin S.p.a." : "Sviluppumbria"; + UserWithCompanyEntity userWithCompany=companyService.getUserWithCompany(userEntity.getId(),company.getId()); + String companyEmail = userWithCompany.getEmail(); + String contactEmail = userWithCompany.getContactEmail(); + + if (companyEmail != null && !companyEmail.isEmpty()) { + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.COMPANY,company.getId() , + companyEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(companyEmail), emailLogRequest); + } + if (contactEmail != null && !contactEmail.isEmpty() && !contactEmail.equals(companyEmail)) { + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.COMPANY,company.getId(), + contactEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(contactEmail), emailLogRequest); + } + + if (userEntity.getBeneficiary().getEmail() != null) { + String beneficiaryEmail = userEntity.getBeneficiary().getEmail(); + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.BENEFICIARY,userEntity.getBeneficiary().getId() , + beneficiaryEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(beneficiaryEmail), emailLogRequest); + } + if(userEntity.getHub().getEmail() != null){ + String hubEmails = userEntity.getHub().getEmail(); + String[] hubEmailArray = hubEmails.split(","); + for (String hubEmail : hubEmailArray) { + hubEmail = hubEmail.trim(); + if (!hubEmail.isEmpty()) { + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.PROPERTIES,null, + hubEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(hubEmail), emailLogRequest); + } + } + } + if (rinaldoEmail != null) { + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.PROPERTIES,null , + rinaldoEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(rinaldoEmail), emailLogRequest); + } + if (applicationEvaluationEntity.isPresent()) { + Long preInstructorId = applicationEvaluationEntity.get().getUserId(); // Assuming UserEntity has an email field + UserEntity instructorUser = userService.validateUser(preInstructorId); + String preInstructorEmail = instructorUser.getEmail(); + if (preInstructorEmail != null && !preInstructorEmail.isEmpty()) { + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.INSTRUCTOR, instructorUser.getId(), + preInstructorEmail, userEntity.getId(), applicationEntity.getId(), amendmentId, applicationEntity.getCall().getId()); + sendMail(applicationEntity.getHubId(), subject, body, List.of(preInstructorEmail), emailLogRequest); + } + } } +// +// private String determineService(Long hubId) { +// +// HubEntity hub = hubRepository.findById(hubId).orElseThrow(() -> new IllegalArgumentException("Invalid Hub ID: " + hubId)); +// return hub.getEmailServiceType().equalsIgnoreCase("MAILGUN_SERVICE") ? "Sviluppumbria" : "Gepafin S.p.a."; +// } - public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequest) { + public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) { - ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequest.getApplicationId()); + ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequestEntity.getApplicationId()); + Map bodyPlaceholders = prepareEmailPlaceholders(applicationEntity, applicationAmendmentRequestEntity); + sendEmail(applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null, + applicationAmendmentRequestEntity.getId()); + } + public Map prepareEmailPlaceholders(ApplicationEntity applicationEntity, ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity){ Map bodyPlaceholders = new HashMap<>(); bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName()); - bodyPlaceholders.put("{{protocol_number}}", applicationAmendmentRequest.getProtocol().getProtocolNumber().toString()); - bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatLocalDateTime(applicationAmendmentRequest.getProtocol().getCreatedDate(), GepafinConstant.DD_MM_YYYY)); - bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationAmendmentRequest.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); - String formFieldsJson = applicationAmendmentRequest.getFormFields(); - ObjectMapper objectMapper = new ObjectMapper(); + bodyPlaceholders.put("{{protocol_number}}", applicationEntity.getProtocol().getProtocolNumber().toString()); + bodyPlaceholders.put("{{protocol_date}}", DateTimeUtil.formatLocalDateTime(applicationEntity.getProtocol().getCreatedDate(), GepafinConstant.DD_MM_YYYY)); + bodyPlaceholders.put("{{protocol_time}}", DateTimeUtil.parseLocalTimeToString(applicationEntity.getProtocol().getTime(), GepafinConstant.HH_MM_SS)); + bodyPlaceholders.put("{{response_days}}", applicationAmendmentRequestEntity.getResponseDays().toString()); try { - List> formFields = objectMapper.readValue(formFieldsJson, new TypeReference>>() { - }); - //• + // Retrieve forms and initialize required collections + List forms = applicationFormRepository.findByApplicationId(applicationEntity.getId()); + List allFormFields = new ArrayList<>(); StringBuilder bulletPoints = new StringBuilder(); - for (Map field : formFields) { - String label = (String) field.get("label"); - boolean selected = (boolean) field.get("selected"); - if (!selected) { - bulletPoints.append("• ").append(label).append("\n"); - } + + // Extract data from forms + for (ApplicationFormEntity form : forms) { + String content = form.getForm().getContent(); + List> result = filterByName(content, "fileupload"); + allFormFields.addAll(getIdAndLabelFromResult(result)); } + + // Process allFormFields and generate bullet points + for (AmendmentFormFieldResponse field : allFormFields) { + // Build bullet points +// bulletPoints.append(field.getLabel()); + bulletPoints.append("
  • ").append(field.getLabel()).append("
  • "); + + } + // Add the generated bullet points to placeholders bodyPlaceholders.put("{{form_dataInput}}", bulletPoints.toString()); } catch (Exception e) { - log.error("Failed to parse form fields JSON: ", e); + log.error("Failed to process form fields: ", e); } - bodyPlaceholders.put("{{note}}", applicationAmendmentRequest.getNote()); - sendEmail(applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null,applicationAmendmentRequest.getId()); + + + bodyPlaceholders.put("{{note}}", applicationAmendmentRequestEntity.getNote()); + return bodyPlaceholders; + } + + public List getIdAndLabelFromResult(List> result) { + List formFieldResponses = new ArrayList<>(); + + for (Map item : result) { + AmendmentFormFieldResponse formFieldResponse = new AmendmentFormFieldResponse(); + formFieldResponse.setFieldId((String) item.get("id")); + + // Extract "label" value from the "settings" array + List> settings = (List>) item.get("settings"); + String label = settings.stream() + .filter(setting -> "label".equals(setting.get("name"))) + .map(setting -> (String) setting.get("value")) + .findFirst() + .orElse(""); // Default to empty string if not found + + if (label == null || label.trim().isEmpty()) { + continue; + } + + formFieldResponse.setLabel(label); // Set the label as fieldValue + formFieldResponses.add(formFieldResponse); + } + + return formFieldResponses; } public void sendApplicationFailureNotificationEmail(ApplicationAmendmentRequestEntity amendmentRequest) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java index 3cad69b9..e5a41e68 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FaqDao.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.dao; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.FaqEntity; import net.gepafin.tendermanagement.entities.UserEntity; @@ -13,6 +14,7 @@ import net.gepafin.tendermanagement.model.request.FaqReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.FaqResponseBean; import net.gepafin.tendermanagement.repositories.FaqRepository; +import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.service.LookUpDataService; @@ -30,6 +32,7 @@ import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; @Component public class FaqDao { @@ -48,6 +51,9 @@ public class FaqDao { @Autowired private CompanyService companyService; + + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; @Autowired HttpServletRequest request; @@ -63,10 +69,15 @@ public class FaqDao { if (validator.checkIsBeneficiary() && companyId == null) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.COMPANY_ID_MANDATORY)); } - if (companyId != null) { - companyService.validateCompany(companyId); - entity.setCompanyId(companyId); + UserWithCompanyEntity userWithCompanyEntity=null; + if(companyId!=null) { + userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),companyId); + companyService.validateCompany(userWithCompanyEntity.getCompanyId()); + entity.setCompanyId(userWithCompanyEntity.getCompanyId()); + } + + entity.setUserWithCompany(userWithCompanyEntity); faqRepository.save(entity); if (entity.getCompanyId() != null) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 4ad912f4..4a42daf7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -3,19 +3,15 @@ package net.gepafin.tendermanagement.dao; import java.util.*; import java.util.stream.Collectors; +import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.CompanyService; 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.entities.ApplicationEntity; -import net.gepafin.tendermanagement.entities.ApplicationFormEntity; -import net.gepafin.tendermanagement.entities.ApplicationFormFieldEntity; -import net.gepafin.tendermanagement.entities.FlowDataEntity; -import net.gepafin.tendermanagement.entities.FlowEdgesEntity; -import net.gepafin.tendermanagement.entities.FormEntity; import net.gepafin.tendermanagement.enums.FormActionEnum; import net.gepafin.tendermanagement.model.response.NextOrPreviousFormResponse; import net.gepafin.tendermanagement.service.FormService; @@ -44,6 +40,8 @@ public class FlowFormDao { private FormService formService; @Autowired private FormDao formDao; + @Autowired + private CompanyService companyService; @@ -290,6 +288,7 @@ public class FlowFormDao { private NextOrPreviousFormResponse setNextOrPreviousResponse(Long calculatedFormId, ApplicationEntity applicationEntity) { NextOrPreviousFormResponse nextOrPreviousFormResponse = new NextOrPreviousFormResponse(); Integer completedSteps=0; + CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId()); FormEntity formEntity = formService.validateForm(calculatedFormId); nextOrPreviousFormResponse.setFormId(calculatedFormId); nextOrPreviousFormResponse.setApplicationStatus(ApplicationStatusTypeEnum.valueOf(applicationEntity.getStatus())); @@ -297,8 +296,8 @@ public class FlowFormDao { applicationDao.processForm(formEntity, applicationEntity)); nextOrPreviousFormResponse.setCallId(applicationEntity.getCall().getId()); nextOrPreviousFormResponse.setCallTitle(applicationEntity.getCall().getName()); - nextOrPreviousFormResponse.setCompanyId(applicationEntity.getCompany().getId()); - nextOrPreviousFormResponse.setCompanyName(applicationEntity.getCompany().getCompanyName()); + nextOrPreviousFormResponse.setCompanyId(applicationEntity.getCompanyId()); + nextOrPreviousFormResponse.setCompanyName(company.getCompanyName()); List flowEdgesList = flowEdgesRepository.findByCallId(applicationEntity.getCall().getId()); Long totalFormSteps = calculateTotalSteps(flowEdgesList); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/NotificationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/NotificationDao.java new file mode 100644 index 00000000..9acacdb0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/NotificationDao.java @@ -0,0 +1,278 @@ +package net.gepafin.tendermanagement.dao; + +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.entities.NotificationEntity; +import net.gepafin.tendermanagement.entities.NotificationTypeEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; +import net.gepafin.tendermanagement.enums.NotificationEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.response.NotificationResponse; +import net.gepafin.tendermanagement.repositories.NotificationRepository; +import net.gepafin.tendermanagement.repositories.NotificationTypeRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.hibernate.internal.util.collections.CollectionHelper.listOf; + +@Component +@Slf4j +public class NotificationDao { + + @Autowired + private SimpMessagingTemplate messagingTemplate; + + @Autowired + private NotificationRepository notificationRepository; + + @Autowired + private NotificationTypeRepository notificationTypeRepository; + + @Autowired + private UserWithCompanyRepository userWithCompanyRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private CompanyDao companyDao; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private UserDao userDao; + + public NotificationResponse sendNotification(NotificationReq notificationReq) { + + // Ensure userId is properly set in notificationReq if not already + Long userId = notificationReq.getUserId(); + if (userId == null) { + log.error("User ID is missing in the notification request."); + return null; + } + NotificationEntity notificationEntity = saveNotification(notificationReq); + log.info("Sending notification to user {} with content: {}", userId, notificationReq.getMessage()); + List companyIds = notificationReq.getCompanyIds(); + + if (companyIds == null || companyIds.isEmpty()) { + sendToUser(userId, notificationEntity); + } else { + sendToCompanies(userId, companyIds, notificationEntity); + } + + return convertNotificationEntityToNotificationResponse(notificationEntity); + } + + private NotificationEntity saveNotification(NotificationReq notificationReq) { + + return notificationRepository.save(convertNotificationRequestToNotificationEntity(notificationReq)); + } + + private void sendToUser(Long userId, NotificationEntity notificationEntity) { + + String userChannel = GepafinConstant.COMMON_SINGLE_CHANNEL_PREFIX + userId; + log.info("Channel for User {}", userChannel); + NotificationResponse notificationResponse = convertNotificationEntityToNotificationResponse(notificationEntity); + messagingTemplate.convertAndSend(userChannel, notificationResponse); + } + + private void sendToCompanies(Long userId, List companyIds, NotificationEntity notificationEntity) { + // Send notification to each company provided in the companyIds list + companyIds.forEach(companyId -> { + UserWithCompanyEntity userWithCompany = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalseForNotification(userId, companyId); + String companyChannel = Utils.createChannelForUserAndCompany(userId, companyId); + log.info("Channel for User and Company {}, {}", userId, companyChannel); + if (userWithCompany == null) { + throw new CustomValidationException(Status.BAD_REQUEST, GepafinConstant.USER_WITH_COMPANY_NOT_FOUND); + } + notificationEntity.setUserWithCompany(userWithCompany); + notificationRepository.save(notificationEntity); + NotificationResponse notificationResponse = convertNotificationEntityToNotificationResponse(notificationEntity); + messagingTemplate.convertAndSend(companyChannel, notificationResponse); + }); + } + + private NotificationResponse convertNotificationEntityToNotificationResponse(NotificationEntity notificationEntity) { + + NotificationResponse notificationResponse = new NotificationResponse(); + notificationResponse.setId(notificationEntity.getId()); + notificationResponse.setUserId(notificationEntity.getUserId()); + notificationResponse.setStatus(notificationEntity.getStatus()); + notificationResponse.setMessage(notificationEntity.getMessage()); + notificationResponse.setCreatedDate(notificationEntity.getCreatedDate()); + notificationResponse.setUpdatedDate(notificationEntity.getUpdatedDate()); + notificationResponse.setRedirectUrl(notificationEntity.getNotificationType()); + notificationResponse.setCompanyId(notificationEntity.getUserWithCompany() != null ? notificationEntity.getUserWithCompany().getCompanyId() : null); + notificationResponse.setNotificationType(notificationEntity.getNotificationType()); + notificationResponse.setTitle(notificationEntity.getTitle()); + return notificationResponse; + } + + private NotificationEntity convertNotificationRequestToNotificationEntity(NotificationReq notificationReq) { + + NotificationEntity notificationEntity = new NotificationEntity(); + String message = notificationReq.getMessage(); + notificationEntity.setNotificationType(notificationReq.getNotificationType()); + notificationEntity.setUserId(notificationReq.getUserId()); + notificationEntity.setStatus(NotificationEnum.UNREAD.getValue()); + notificationEntity.setIsDeleted(Boolean.FALSE); + notificationEntity.setUserWithCompany(notificationReq.getUserWithCompanyEntity() != null ? notificationReq.getUserWithCompanyEntity() : null); + notificationEntity.setMessage(message); + notificationEntity.setTitle(notificationReq.getTitle()); + return notificationEntity; + } + + public NotificationReq createNotificationReq(String notificationType, Map placeholders, Long userId, UserWithCompanyEntity userWithCompanyEntity, + List companyIds) { + // Create NotificationReq object + NotificationReq notificationReq = new NotificationReq(); + NotificationTypeEntity notificationTypeEntity = notificationTypeRepository.findByNotificationNameAndIsDeletedFalse(notificationType); + notificationReq.setNotificationType(notificationType); + String message = Utils.replacePlaceholders(notificationTypeEntity.getJsonTemplate(), placeholders); + notificationReq.setMessage(message); + notificationReq.setUserId(userId); + notificationReq.setCompanyIds(companyIds); + String title = Utils.replacePlaceholders(notificationTypeEntity.getTitle(), placeholders); + notificationReq.setTitle(title); + notificationReq.setUserWithCompanyEntity(userWithCompanyEntity); + return notificationReq; + } + + public Map sendNotificationToBeneficiary(ApplicationEntity application, NotificationTypeEnum notificationTypeEnum) { + + Map placeHolders = new HashMap<>(); + placeHolders.put("{{call_name}}", application.getCall().getName()); + placeHolders.put("{{protocol_number}}", String.valueOf(application.getProtocol().getProtocolNumber())); + NotificationReq notificationReq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, application.getUserId(), application.getUserWithCompany(), + listOf(application.getCompanyId())); + sendNotification(notificationReq); + return placeHolders; + } + + public void sendNotificationToInstructor(Map placeHolders, ApplicationEvaluationEntity applicationEvaluationEntity, NotificationTypeEnum notificationTypeEnum) { + + Long instructorId = applicationEvaluationEntity.getUserId(); + ApplicationEntity application = applicationService.validateApplication(applicationEvaluationEntity.getApplicationId()); + if (instructorId != null) { + NotificationReq notificationreq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, instructorId, application.getUserWithCompany(), + null); + sendNotification(notificationreq); + } + } + public void sendNotificationToSuperUser(ApplicationEntity application, Map placeHolders, NotificationTypeEnum notificationTypeEnum) { + + List user = userRepository.findByRoleEntity_RoleTypeAndHubId(RoleStatusEnum.ROLE_SUPER_ADMIN.getValue(), application.getHubId()); + UserEntity userEntity1 = user.get(0); + if (userEntity1 != null) { + NotificationReq notificationreq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, userEntity1.getId(), application.getUserWithCompany(), + null); + sendNotification(notificationreq); + } + } + + public List getAllCompanyIdsForUser(Long userId) { + + return userWithCompanyRepository.findActiveCompanyIdsByUserId(userId); + } + + public NotificationResponse getNotificationById(Long id) { + + NotificationEntity notificationEntity = validateNotificationEntity(id); + return convertNotificationEntityToNotificationResponse(notificationEntity); + } + + private NotificationEntity validateNotificationEntity(Long id) { + + NotificationEntity notificationEntity = notificationRepository.findByIdAndIsDeletedFalse(id); + if (notificationEntity == null) { + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.NOTIFICATION_NOT_FOUND)); + } + return notificationEntity; + } + + public List getNotificationByUserId(Long userId, Long companyId, List statuses) { + + List notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalse(userId); + UserWithCompanyEntity userWithCompany = null; + List statusStrings = new ArrayList<>(); + if (companyId != null) { + userWithCompany = companyDao.validateUserWithCompny(userId, companyId); + } + + if (statuses != null) { + statusStrings = statuses.stream().map(NotificationEnum::name) // Convert enum to its name as String + .toList(); + notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalseAndStatusIn(userId, statusStrings); + + if (userWithCompany != null) { + notificationEntities = notificationRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(userId, userWithCompany.getId(), statusStrings); + } + } + + return notificationEntities.stream().map(this::convertNotificationEntityToNotificationResponse).collect(Collectors.toList()); + } + + public NotificationResponse updateNotificationStatus(Long id, NotificationEnum status) { + + NotificationEntity notificationEntity = validateNotificationEntity(id); + if (notificationEntity.getStatus().equals(status.getValue())) { + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NOTIFICATION_ALREADY_IN_THAT_STATE)); + } + notificationEntity.setStatus(status.getValue()); + notificationEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + notificationRepository.save(notificationEntity); + return convertNotificationEntityToNotificationResponse(notificationEntity); + } + + public void deleteNotification(Long id) { + + NotificationEntity notificationEntity = validateNotificationEntity(id); + notificationEntity.setIsDeleted(true); + notificationRepository.save(notificationEntity); + } + + public List getNotificationByCompanyIdAndUserId(Long userId, Long companyId, List statuses) { + + List notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalse(userId); + UserWithCompanyEntity userWithCompany = null; + List statusStrings; + if (companyId != null) { + userWithCompany = companyDao.validateUserWithCompny(userId, companyId); + } + + if (statuses != null) { + statusStrings = statuses.stream().map(NotificationEnum::name) + .toList(); + notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalseAndStatusIn(userId, statusStrings); + + if (userWithCompany != null) { + notificationEntities = notificationRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(userId, userWithCompany.getId(), statusStrings); + } + } + + return notificationEntities.stream().map(this::convertNotificationEntityToNotificationResponse).toList(); + } + +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 456a614b..5ec81347 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -57,7 +57,7 @@ public class PdfDao { try { UserEntity userEntity = validator.validateUser(request); ApplicationEntity applicationEntity = applicationDao.validateApplication(applicationId); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); CallEntity call=callService.validateCall(applicationEntity.getCall().getId()); // Create a byte stream to hold the PDF diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java index a7606c9a..4601ef8c 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ProtocolDao.java @@ -4,6 +4,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.ProtocolTypeEnum; import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.util.LoggingUtil; @@ -42,7 +43,7 @@ public class ProtocolDao { return (maxProtocolNumber != null) ? maxProtocolNumber + 1 : startNumber; } - public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Long protocolNumber, Long hubId){ + public ProtocolEntity createProtocolEntity(ApplicationEntity applicationEntity,Long protocolNumber, Long hubId,Boolean isForApplication){ ProtocolEntity protocolEntity=new ProtocolEntity(); protocolEntity.setCall(applicationEntity.getCall().getId()); LocalDateTime utcDateTime = DateTimeUtil.DateServerToUTC(LocalDateTime.now()); @@ -51,6 +52,11 @@ public class ProtocolDao { protocolEntity.setTime(LocalTime.now()); protocolEntity.setApplicationId(applicationEntity.getId()); protocolEntity.setHubId(hubId); + if(Boolean.TRUE.equals(isForApplication)){ + protocolEntity.setType(ProtocolTypeEnum.INPUT.getValue()); + }else { + protocolEntity.setType(ProtocolTypeEnum.OUTPUT.getValue()); + } protocolRepository.save(protocolEntity); /** This code is responsible for adding a version history log for "create protocol" operation. **/ diff --git a/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java b/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java index b127b699..1db01f11 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java @@ -13,25 +13,28 @@ public class S3PathConfig { @Autowired S3ConfigRepository s3ConfigRepository; - public String generateDocumentPath(DocumentSourceTypeEnum type, Long callId, Long applicationId) { + public String generateDocumentPath(DocumentSourceTypeEnum type, Long callId, Long applicationId,Long amendmentId) { S3ConfigEntity config = getDocumentPath(type); - return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId); + return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId,amendmentId); } - public String generateDocumentPathForOther(DocOtherSourceTypeEnum type, Long callId, Long applicationId) { + public String generateDocumentPathForOther(DocOtherSourceTypeEnum type, Long callId, Long applicationId,Long amendmentId) { S3ConfigEntity config = getDocumentPathForOther(type); - return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId); - } - private String buildS3Path(String pathTemplate, Long callId, Long applicationId) { - - return pathTemplate.replace("{call_id}", callId != null && callId != 0L ? "call_" + callId : "").replace("{application_id}", applicationId != null && applicationId != 0L ? "application_" + applicationId : ""); + return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId,amendmentId); } public String generateDocumentPathForDelegationAndSignedDocument(DocOtherSourceTypeEnum type) { S3ConfigEntity config = getDocumentPathForOther(type); return config.getParentFolder() + "/" + config.getPath(); } + private String buildS3Path(String pathTemplate, Long callId, Long applicationId, Long amendmentId) { + return pathTemplate + .replace("{call_id}", callId != null && callId != 0L ? "call_" + callId : "") + .replace("{application_id}", applicationId != null && applicationId != 0L ? "application_" + applicationId : "") + .replace("{amendment_id}", amendmentId != null && amendmentId != 0L ? "amendment_" + amendmentId : ""); + } + private S3ConfigEntity getDocumentPath(DocumentSourceTypeEnum type) { return s3ConfigRepository.getPathByType(type.name()).orElseThrow(() -> new IllegalArgumentException("No path configuration found for type: " + type)); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 41483d36..6622ca95 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -271,7 +271,7 @@ public class UserDao { log.info("Current user details: {}", userEntity); log.info("New user details: {}", userReq); String newStatus = userReq.getStatus() != null ? userReq.getStatus().getValue() : null; - if (Boolean.FALSE.equals(userEntity.getStatus().equals(newStatus))) { + if (newStatus!=null && Boolean.FALSE.equals(userEntity.getStatus().equals(newStatus))) { userEntity.setStatus(newStatus); } setIfUpdated(userEntity::getFirstName, userEntity::setFirstName, userReq.getFirstName()); @@ -280,15 +280,19 @@ public class UserDao { setIfUpdated(userEntity::getAddress, userEntity::setAddress, userReq.getAddress()); setIfUpdated(userEntity::getPhoneNumber, userEntity::setPhoneNumber, userReq.getPhoneNumber()); setIfUpdated(userEntity::getDateOfBirth, userEntity::setDateOfBirth, userReq.getDateOfBirth()); - setIfUpdated(userEntity.getBeneficiary()::getCodiceFiscale, userEntity.getBeneficiary()::setCodiceFiscale, userReq.getCodiceFiscale()); - setIfUpdated(userEntity.getBeneficiary()::getMarketing, userEntity.getBeneficiary()::setMarketing, userReq.getMarketing()); - setIfUpdated(userEntity.getBeneficiary()::getOffers, userEntity.getBeneficiary()::setOffers, userReq.getOffers()); - setIfUpdated(userEntity.getBeneficiary()::getThirdParty, userEntity.getBeneficiary()::setThirdParty, userReq.getThirdParty()); if (userReq.getRoleId() != null) { RoleEntity roleEntity = roleDao.validateRole(userReq.getRoleId()); - setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); + if((userEntity.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()) && roleEntity.getRoleType().equals(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue())) || (userEntity.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue()) && roleEntity.getRoleType().equals(RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()))) { + setIfUpdated(userEntity::getRoleEntity, userEntity::setRoleEntity, roleEntity); + } + } + if(userEntity.getBeneficiary()!=null) { + setIfUpdated(userEntity.getBeneficiary()::getCodiceFiscale, userEntity.getBeneficiary()::setCodiceFiscale, userReq.getCodiceFiscale()); + setIfUpdated(userEntity.getBeneficiary()::getMarketing, userEntity.getBeneficiary()::setMarketing, userReq.getMarketing()); + setIfUpdated(userEntity.getBeneficiary()::getOffers, userEntity.getBeneficiary()::setOffers, userReq.getOffers()); + setIfUpdated(userEntity.getBeneficiary()::getThirdParty, userEntity.getBeneficiary()::setThirdParty, userReq.getThirdParty()); + setIfUpdated(userEntity.getBeneficiary()::getEmailPec, userEntity.getBeneficiary()::setEmailPec, userReq.getEmailPec()); } - setIfUpdated(userEntity.getBeneficiary()::getEmailPec, userEntity.getBeneficiary()::setEmailPec, userReq.getEmailPec()); userEntity = userRepository.save(userEntity); /** This code is responsible for adding a version history log for the "Update user details" operation **/ @@ -569,12 +573,14 @@ public class UserDao { return authService.validateNewUserToken(token); } - public List getAllUsers(UserEntity user, Long roleId) { + public List getAllUsers(UserEntity user, List roleIds) { List users; - if (roleId != null) { - log.info("Fetching users by role ID: {}", roleId); - RoleEntity roleEntity=roleService.validateRole(roleId); - users = userRepository.findByRoleEntityIdAndHubId(roleEntity.getId(), user.getHub().getId()); + if (roleIds != null) { + log.info("Fetching users by role ID: {}", roleIds); + List roleEntities = roleIds.stream() + .map(roleService::validateRole) // Assuming `validateRole` takes an ID and returns a RoleEntity + .collect(Collectors.toList()); + users = userRepository.findByRoleEntityIdInAndHubId(roleIds, user.getHub().getId()); } else { log.info("Fetching all users"); users = userRepository.findByHubId(user.getHub().getId()); @@ -583,7 +589,7 @@ public class UserDao { .map(this::convertUserEntityToUserResponse) .collect(Collectors.toList()); - log.info("Total users found with role ID {}: {}", roleId, userResponseBeans.size()); + log.info("Total users found with role ID {}: {}", roleIds, userResponseBeans.size()); return userResponseBeans; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java index 1a4c110d..85af1388 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java @@ -4,15 +4,11 @@ import feign.FeignException; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; -import net.gepafin.tendermanagement.enums.UserActionContextEnum; -import net.gepafin.tendermanagement.enums.UserActionLogsEnum; -import net.gepafin.tendermanagement.model.request.UserActionRequest; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.model.response.VatCheckResponseBean; import net.gepafin.tendermanagement.service.feignClient.VatCheckService; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; -import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; -import net.gepafin.tendermanagement.web.rest.api.errors.Status; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,10 +45,13 @@ public class VatCheckDao { @Autowired private HttpServletRequest request; - public Map checkVatNumberApi(String vatNumber) { - + public VatCheckResponseBean checkVatNumberApi(String vatNumber) { + VatCheckResponseBean vatCheckResponseBean = new VatCheckResponseBean(); + vatCheckResponseBean.setValid(false); + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); if (Boolean.TRUE.equals(Boolean.parseBoolean(isVatCheckGloballyDisabled))) { - return new HashMap<>(); + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + return vatCheckResponseBean; } Map responseBody = new HashMap<>(); try { @@ -65,9 +64,6 @@ public class VatCheckDao { URI baseUrl = URI.create(GepafinConstant.CHECK_VATNUMBER_V2_NEW_URL); ResponseEntity> response = vatCheckService.checkVatNumber(baseUrl, vatNumber, headers); - /** This code is responsible for creating user action logs for the "Download company delegation" operation. **/ - loggingUtil.logUserAction( - UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.CHECK_COMPANY_VAT_NUMBER).build()); if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) { log.info("Successfully checked vat number"); @@ -80,22 +76,28 @@ public class VatCheckDao { responseBody.remove("id"); Map data = new LinkedHashMap<>(); data.put("data", responseBody); - return data; + vatCheckResponseBean.setValid(true); + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.VALID_VATNUMBER_MSG)); + vatCheckResponseBean.setVatCheckResponse(data); } } } catch (FeignException ex) { log.error("Exception occurred while checking vat number: {0}", ex); Utils.callException(ex.status(), ex); } - return responseBody; + return vatCheckResponseBean; } - public Map checkVatNumber(String vatNumber) { + public VatCheckResponseBean checkVatNumber(String vatNumber) { try { return checkVatNumberApi(vatNumber); } catch (Exception e) { - throw new CustomValidationException(Status.VALIDATION_ERROR, - Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + log.error("Error in checkVatNumber: {}", e.getMessage()); + VatCheckResponseBean vatCheckResponseBean = new VatCheckResponseBean(); + vatCheckResponseBean.setValid(false); + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + return vatCheckResponseBean; } } + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java index 4d2dabf6..8a8701a1 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationAmendmentRequestEntity.java @@ -47,4 +47,10 @@ public class ApplicationAmendmentRequestEntity extends BaseEntity { @JoinColumn(name = "PROTOCOL_Id") private ProtocolEntity protocol; + @Column(name = "end_date") + private LocalDateTime endDate; + + @Column(name = "amendment_document") + private String amendmentDocument; + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java index 68c433e2..39e26f4b 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java @@ -12,10 +12,9 @@ public class ApplicationEntity extends BaseEntity { @Column(name = "USER_ID") private Long userId; - - @ManyToOne - @JoinColumn(name = "COMPANY_ID", nullable = false) - private CompanyEntity company; + + @Column(name = "COMPANY_ID") + private Long companyId; @Column(name = "SUBMISSION_DATE") private LocalDateTime submissionDate; @@ -39,4 +38,21 @@ public class ApplicationEntity extends BaseEntity { @Column(name = "HUB_ID") private Long hubId; + + @ManyToOne + @JoinColumn(name = "USER_WITH_COMPANY_ID") + private UserWithCompanyEntity userWithCompany; + + @Column(name = "NDG") + private String ndg; + + @Column(name = "ID_VISURA") + private String idVisura; + + @Column(name = "NDG_STATUS") + private String ndgStatus; + + @Column(name = "APPOINTMENT_ID") + private String appointmentId; + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java index e2bb27aa..15e3d3d7 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java @@ -3,6 +3,8 @@ package net.gepafin.tendermanagement.entities; import jakarta.persistence.*; import lombok.Data; +import java.time.LocalDateTime; + @Data @Entity @Table(name = "application_evaluation") @@ -20,6 +22,9 @@ public class ApplicationEvaluationEntity extends BaseEntity{ @Column(name = "checklist") private String checklist; + @Column(name = "EVALUATION_DOCUMENT") + private String evaluationDocument; + @Column(name = "file") private String file; @@ -38,5 +43,26 @@ public class ApplicationEvaluationEntity extends BaseEntity{ @ManyToOne @JoinColumn(name = "assigned_applications_id", nullable = true) private AssignedApplicationsEntity assignedApplicationsEntity; - + + @Column(name = "INITIAL_DAYS") + private Long initialDays; + + @Column(name = "REMAINING_DAYS") + private Long remainingDays; + + @Column(name = "SUSPENDED_DAYS") + private Long suspendedDays; + + @Column(name = "START_DATE") + private LocalDateTime startDate; + + @Column(name = "END_DATE") + private LocalDateTime endDate; + + @Column(name = "STOP_DATE_TIME") + private LocalDateTime stopDateTime; + + @Column(name = "CLOSING_DATE") + private LocalDateTime closingDate; + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryPreferredCallEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryPreferredCallEntity.java index 7a30c267..5bbc316d 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryPreferredCallEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/BeneficiaryPreferredCallEntity.java @@ -34,6 +34,11 @@ public class BeneficiaryPreferredCallEntity extends BaseEntity{ @Column(name = "STATUS", length = 255) private String status; + @Column(name="IS_DELETED") private Boolean isDeleted; + + @ManyToOne + @JoinColumn(name = "USER_WITH_COMPANY_ID") + private UserWithCompanyEntity userWithCompany; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java index ed50268f..e7aa0f40 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java @@ -41,26 +41,19 @@ public class CompanyEntity extends BaseEntity{ @Column(name = "COUNTRY") private String country; - @Column(name = "PEC") - private String pec; - - @Column(name = "EMAIL") - private String email; - @Column(name = "NUMBER_OF_EMPLOYEES") private String numberOfEmployees; @Column(name = "ANNUAL_REVENUE") private BigDecimal annualRevenue; - - @Column(name = "CONTACT_NAME") - private String contactName; - - @Column(name = "CONTACT_EMAIL") - private String contactEmail; @ManyToOne @JoinColumn(name = "HUB_ID") private HubEntity hub; - + +// @Column(name = "JSON") +// private String json; + + @Column(name = "NDG") + private String ndg; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java index fc15a82d..08bfd623 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java @@ -29,4 +29,10 @@ public class DocumentEntity extends BaseEntity{ @Column(name ="IS_DELETED", nullable = false) private Boolean isDeleted = false; + @Column(name="DOCUMENT_ATTACHMENT_ID") + private String documentAttachmentId; + + @Column(name="uploaded_by") + private Long uploadedBy; + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java index a476f2c5..46ebff24 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java @@ -45,5 +45,9 @@ public class FaqEntity extends BaseEntity { @Column(name ="COMPANY_ID") private Long companyId; + @ManyToOne + @JoinColumn(name = "USER_WITH_COMPANY_ID") + private UserWithCompanyEntity userWithCompany; + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java index 2e219acf..52aa6cc2 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/HubEntity.java @@ -54,4 +54,13 @@ public class HubEntity extends BaseEntity{ @Column(name = "EMAIL_SERVICE_CONFIG") private String emailServiceConfig; + + @Column(name = "AUTH_TOKEN") + private String authToken; + + @Column(name = "APPOINTMENT_AUTH_TOKEN_ID") + private String appointmentAuthTokenId; + + @Column(name = "AREA_CODE") + private String areaCode; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/NotificationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/NotificationEntity.java new file mode 100644 index 00000000..718a7367 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/NotificationEntity.java @@ -0,0 +1,39 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "NOTIFICATION") +@Data +public class NotificationEntity extends BaseEntity { + + @Column(name = "USER_ID") + private Long userId; + + @Column(name = "MESSAGE") + private String message; + + @Column(name = "TITLE") + private String title; + + @Column(name = "STATUS") + private String status; + + @Column(name = "IS_DELETED") + private Boolean isDeleted; + + @Column(name = "NOTIFICATION_TYPE") + private String notificationType; + + @Column(name = "REDIRECT_LINK") + private String redirectLink; + + @ManyToOne + @JoinColumn(name = "USER_WITH_COMPANY_ID") + private UserWithCompanyEntity userWithCompany; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/NotificationTypeEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/NotificationTypeEntity.java new file mode 100644 index 00000000..40d3f220 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/NotificationTypeEntity.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Data +@Table(name = "NOTIFICATION_TYPE") +public class NotificationTypeEntity extends BaseEntity { + + @Column(name = "NOTIFICATION_NAME") + private String notificationName; + + @Column(name = "JSON_TEMPLATE") + private String jsonTemplate; + + @Column(name = "TITLE") + private String title; + + @Column(name="IS_DELETED") + private Boolean isDeleted; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java index ad57c1ee..47dc5065 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ProtocolEntity.java @@ -28,4 +28,7 @@ public class ProtocolEntity extends BaseEntity { @Column(name="HUB_ID") private Long hubId; + @Column(name = "type") + private String type; + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java index d682747d..9def5dc3 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserCompanyDelegationEntity.java @@ -1,8 +1,6 @@ package net.gepafin.tendermanagement.entities; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.Data; @Data @@ -28,4 +26,7 @@ public class UserCompanyDelegationEntity extends BaseEntity{ @Column(name="STATUS") private String status; + @ManyToOne + @JoinColumn(name = "USER_WITH_COMPANY_ID") + private UserWithCompanyEntity userWithCompany; } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java index 49770356..1f067a90 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/UserWithCompanyEntity.java @@ -22,6 +22,22 @@ public class UserWithCompanyEntity extends BaseEntity{ @Column(name = "IS_LEGAL_REPRESENTANT") private Boolean isLegalRepresentant; + + @Column(name = "CONTACT_NAME") + private String contactName; + + @Column(name = "CONTACT_EMAIL") + private String contactEmail; + + @Column(name = "PEC") + private String pec; + + @Column(name = "EMAIL") + private String email; + + @Column(name = "JSON") + private String json; + @Column(name = "IS_DELETED") private Boolean isDeleted = false; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java index 18cfc30d..59e47f9a 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationEvaluationStatusTypeEnum.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonValue; public enum ApplicationEvaluationStatusTypeEnum { OPEN ("OPEN"), SOCCORSO("SOCCORSO"), + EXPIRED("EXPIRED"), CLOSE("CLOSE"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java index db6fe287..b6fd00b3 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/ApplicationStatusTypeEnum.java @@ -12,7 +12,10 @@ public enum ApplicationStatusTypeEnum { SOCCORSO("SOCCORSO"), APPROVED("APPROVED"), REJECTED("REJECTED"), - EVALUATION("EVALUATION"); + EVALUATION("EVALUATION"), + APPOINTMENT("APPOINTMENT"), + NDG("NDG"), + ADMISSIBLE("ADMISSIBLE"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java index 751dfa92..05b42e3b 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java @@ -3,7 +3,12 @@ package net.gepafin.tendermanagement.enums; public enum DocOtherSourceTypeEnum { USER_SIGNED_DOCUMENT("USER_SIGNED_DOCUMENT"), USER_DELEGATION("USER_DELEGATION"), - TEMPLATE("TEMPLATE"); + TEMPLATE("TEMPLATE"), + DELETED_USER_DELEGATION("DELETED_USER_DELEGATION"), + DELETED_APPLICATION("DELETED_APPLICATION"), + DELETED_EVALUATION("DELETED_EVALUATION"), + DELETED_CALL("DELETED_CALL"), + DELETED_AMENDMENT("DELETED_AMENDMENT"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/DocumentSourceTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/DocumentSourceTypeEnum.java index 123c6f8c..e2b121e7 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/DocumentSourceTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/DocumentSourceTypeEnum.java @@ -3,7 +3,9 @@ package net.gepafin.tendermanagement.enums; public enum DocumentSourceTypeEnum { CALL("CALL"), - APPLICATION("APPLICATION"); + APPLICATION("APPLICATION"), + EVALUATION("EVALUATION"), + AMENDMENT("AMENDMENT"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/NotificationEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/NotificationEnum.java new file mode 100644 index 00000000..5b8bf633 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/NotificationEnum.java @@ -0,0 +1,27 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum NotificationEnum { + //status + READ("READ"), UNREAD("UNREAD"); + + private final String value; + + NotificationEnum(String value) { + + this.value = value; + } + + @JsonValue + public String getValue() { + + return value; + } + + @Override + public String toString() { + + return String.valueOf(value); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java new file mode 100644 index 00000000..54a13768 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum NotificationTypeEnum { + CALL_CREATED("CALL_CREATED"), + APPLICATION_SUBMISSION("APPLICATION_SUBMISSION"), + AMENDMENT_CREATION("AMENDMENT_CREATION"), + EVALUATION_RESULT("EVALUATION_RESULT"), + AMENDMENT_EXPIRED("AMENDMENT_EXPIRED"), + AMENDMENT_CLOSED("AMENDMENT_CLOSED"), + NDG_GENERATION("NDG_GENERATION"), + EVALUATION_CREATION("EVALUATION_CREATION"), + EVALUATION_EXPIRED("EVALUATION_EXPIRED"); + + private final String value; + + NotificationTypeEnum(String value) { + + this.value = value; + } + + @JsonValue + public String getValue() { + + return value; + } + + @Override + public String toString() { + + return String.valueOf(value); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ProtocolTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ProtocolTypeEnum.java new file mode 100644 index 00000000..f890fb42 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ProtocolTypeEnum.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ProtocolTypeEnum { + INPUT("INPUT"), + OUTPUT("OUTPUT"); + + private String value; + + ProtocolTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/RecipientTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/RecipientTypeEnum.java index c4f54175..8f656154 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/RecipientTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/RecipientTypeEnum.java @@ -7,7 +7,8 @@ public enum RecipientTypeEnum { BENEFICIARY ("BENEFICIARY"), USER("USER"), COMPANY("COMPANY"), - PROPERTIES("PROPERTIES"); + PROPERTIES("PROPERTIES"), + INSTRUCTOR("INSTRUCTOR"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/RoleStatusEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/RoleStatusEnum.java index 3659856d..31d3e9b8 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/RoleStatusEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/RoleStatusEnum.java @@ -7,7 +7,8 @@ public enum RoleStatusEnum { ROLE_BENEFICIARY("ROLE_BENEFICIARY"), ROLE_SUPER_ADMIN("ROLE_SUPER_ADMIN"), ROLE_PRE_INSTRUCTOR("ROLE_PRE_INSTRUCTOR"), - ROLE_GEPAFIN_OPERATOR("ROLE_GEPAFIN_OPERATOR"); + ROLE_GEPAFIN_OPERATOR("ROLE_GEPAFIN_OPERATOR"), + ROLE_INSTRUCTOR_MANAGER("ROLE_INSTRUCTOR_MANAGER"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java index a4d7f3c2..8863f715 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java @@ -120,6 +120,10 @@ public enum UserActionContextEnum { UPDATE_DOCUMENT("UPDATE_DOCUEMENT"), UPDATE_IMAGES("UPDATE_IMAGES"), GET_DOCUMENT("GET_DOCUMENT"), + UPLOAD_AMENDMENT_DOCUMENT("UPLOAD_AMENDMENT_DOCUMENT"), + UPLOAD_AMENDMENT_IMAGES("UPLOAD_AMENDMENT_IMAGES"), + UPLOAD_EVALUATION_DOCUMENT("UPLOAD_EVALUATION_DOCUMENT"), + UPLOAD_EVALUATION_IMAGES("UPLOAD_EVALUATION_IMAGES"), /** Assigned flow context **/ CREATE_UPDATE_FLOW("CREATE_UPDATE_FLOW"), @@ -138,6 +142,7 @@ public enum UserActionContextEnum { UPDATE_EVALUATION_CRITERIA("UPDATE_EVALUATION_CRITERIA"), DELETE_EVALUATION_CRITERIA("DELETE_EVALUATION_CRITERIA"), CREATE_EVALUATION_CRITERIA("CREATE_EVALUATION_CRITERIA"), + UPLOAD_EVALUATION_DOC("UPLOAD_EVALUATION_DOC"), /** communication action context **/ ADD_COMMENT_TO_AMENDMENT_REQUEST("ADD_COMMENT_TO_AMENDMENT_REQUEST"), @@ -149,7 +154,16 @@ public enum UserActionContextEnum { GET_FORM("GET_FORM"), CREATE_FORM("CREATE_FORM"), UPDATE_FORM("UPDATE_FORM"), - DELETE_FORM("DELETE_FORM"); + DELETE_FORM("DELETE_FORM"), + + /** scheduler action context **/ + AMENDMENT_EXPIRATION_SCHEDULER("AMENDMENT_EXPIRATION_SCHEDULER"), + EVALUATION_EXPIRATION_SCHEDULER("EVALUATION_EXPIRATION_SCHEDULER"), + + /** appointment action context **/ + CHECK_OR_CREATE_NDG_CODE("CHECK_OR_CREATE_NDG_CODE"), + CREATE_APPOINTMENT("CREATE_APPOINTMENT"), + UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM("UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM"); private final String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/UserActionLogsEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/UserActionLogsEnum.java index f68f6ae9..555d3298 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/UserActionLogsEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/UserActionLogsEnum.java @@ -10,7 +10,9 @@ public enum UserActionLogsEnum { VIEW("VIEW"), INSERT("INSERT"), DOWNLOAD("DOWNLOAD"), - UPLOAD("UPLOAD"); + UPLOAD("UPLOAD"), + SCHEDULER("SCHEDULER"), + SCRIPT("SCRIPT"); private final String value; diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentDetailsRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentDetailsRequest.java new file mode 100644 index 00000000..b0dc2adb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentDetailsRequest.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class AmendmentDetailsRequest { + + private String fieldId; + + private Long amendmentId; + + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFieldRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFieldRequest.java new file mode 100644 index 00000000..b7efa539 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFieldRequest.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class AmendmentFieldRequest { + + private String fieldId; + private String nameValue; + private String fileValue; + private Boolean valid = false; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormField.java b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormField.java index 95f158c3..35b3521a 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormField.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormField.java @@ -9,9 +9,13 @@ public class AmendmentFormField { private String fieldId; + private String label; + private String fieldValue; - private String isUploadedBy; + private Boolean valid; + + public enum AmendmentIsUploadedByEnum { diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormFieldRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormFieldRequest.java new file mode 100644 index 00000000..3376d76c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AmendmentFormFieldRequest.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class AmendmentFormFieldRequest { + + private String fieldId; + + private Object fieldValue; + + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java index 94141ef0..7ab254d8 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationAmendmentRequestBean.java @@ -7,5 +7,7 @@ import lombok.Data; @Data public class ApplicationAmendmentRequestBean { private String note; - private List applicationFormFields; + private List applicationFormFields; + private String amendmentDocuments; + private String amendmentNotes; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java index df29c1d8..6616c288 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java @@ -10,6 +10,8 @@ public class ApplicationEvaluationRequest { private List criteria; private List checklist; private List files; + private List evaluationDocument; + private List amendmentDetails; private String note; private ApplicationStatusForEvaluation applicationStatus; private String motivation; diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentCreationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentCreationRequest.java new file mode 100644 index 00000000..a877a620 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentCreationRequest.java @@ -0,0 +1,42 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +import java.util.List; + +@Data +public class AppointmentCreationRequest { + + private Input input; + + @Data + public static class Input { + private String id; + private String ndg; + private List richiestaCliente; + } + + @Data + public static class RichiestaCliente { + private String codAbi; + private String codCab; + private Integer durataMesiFinanziamento; + private Integer idMotivazione; + private String idNota; + private String importoAgevolato; + private Double importoBreveTermine; + private String importoMedioLungoTermine; + private String codTipoProdotto; + private String codCategoriaProdotto; + private String codFormaTecnica; + private String codProdotto; + private String codOperazione; + private Nota nota; + } + + @Data + public static class Nota { + private String titolo; + private String testo; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentNdgRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentNdgRequest.java new file mode 100644 index 00000000..639c8b5d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentNdgRequest.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class AppointmentNdgRequest { + private Filter filter; + private Pagination pagination; + + @Data + public static class Filter { + private String partitaIva; + } + + @Data + public static class Pagination { + private int targetPage; + private int recordsPerPage; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraListRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraListRequest.java new file mode 100644 index 00000000..da5b8720 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraListRequest.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class AppointmentVisuraListRequest { + + private AppointmentVisuraListRequest.VisuraFilter filter; + + @Data + public static class VisuraFilter { + private String idVisura; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraRequest.java new file mode 100644 index 00000000..59546ee6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/AppointmentVisuraRequest.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.model.request; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.Setter; + +@Data +public class AppointmentVisuraRequest { + private VisuraInput input; + + @Data + public static class VisuraInput { + private String codiceFiscale; + private String partitaIva; + private boolean creaAnagrafica; + private boolean salvaDocumenti; + private String visuraProvider; + private String visuraType; + private String visuraMode; + private String codArea; + private String codAgente; + @JsonProperty("isFromRating") + private boolean isFromRating; + @JsonProperty("isAnagraficaLegame") + private boolean isAnagraficaLegame; + } +} + diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java index b9f43932..22ade9a5 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CompanyRequest.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.model.request; import java.math.BigDecimal; +import java.util.Map; import lombok.Data; @@ -23,4 +24,5 @@ public class CompanyRequest { private Boolean isLegalRepresentant; private String contactName; private String contactEmail; + private Map vatCheckResponse; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CreateAppointmentRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CreateAppointmentRequest.java new file mode 100644 index 00000000..667ba581 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CreateAppointmentRequest.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class CreateAppointmentRequest { + private Double importoBreveTermine; + private Integer durataMesiFinanziamento; + private Nota nota; + + @Data + public static class Nota { + private String titolo; + + private String testo; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationDocumentRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationDocumentRequest.java new file mode 100644 index 00000000..79aed45c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationDocumentRequest.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class EvaluationDocumentRequest { + + private String fieldId; + + private String nameValue; + + private String fileValue; + + private Boolean valid; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/NotificationReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/NotificationReq.java new file mode 100644 index 00000000..9582d700 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/NotificationReq.java @@ -0,0 +1,45 @@ +package net.gepafin.tendermanagement.model.request; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class NotificationReq { + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + Long id; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + Long userId; + + String message; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + String notificationType; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + String status; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private LocalDateTime createdDate; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private LocalDateTime updatedDate; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private String redirectUrl; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private String title; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private List companyIds; + + @JsonIgnore + private UserWithCompanyEntity userWithCompanyEntity; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UpdateAssignedApplicationRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateAssignedApplicationRequest.java new file mode 100644 index 00000000..ac9a176b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UpdateAssignedApplicationRequest.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.AssignedApplicationEnum; +@Data +public class UpdateAssignedApplicationRequest { + private String note; + private AssignedApplicationEnum status; + private Long userId; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/UploadDocToExternalSystemRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/UploadDocToExternalSystemRequest.java new file mode 100644 index 00000000..bd3a3097 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/UploadDocToExternalSystemRequest.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class UploadDocToExternalSystemRequest { + private Input input; + + @Data + public static class Input { + private Long idTipoProtocollo; + private Long idClassificazione; + private Boolean flagDaFirmare; + private String descrizione; + private Attributes attributes; + + @Data + public static class Attributes { + private String ndg; + private String email; + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDetailsResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDetailsResponseBean.java new file mode 100644 index 00000000..eb9ee866 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDetailsResponseBean.java @@ -0,0 +1,12 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.util.List; +@Data +public class AmendmentDetailsResponseBean { + private String amendmentDocuments; + private String amendmentNotes; + private Boolean valid; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDocumentResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDocumentResponseBean.java new file mode 100644 index 00000000..21fc1a09 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AmendmentDocumentResponseBean.java @@ -0,0 +1,15 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class AmendmentDocumentResponseBean { + + private Long amendmentId; + private String fieldId; + private String label; + private Boolean valid; + private List fileDetail ; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java index 76e445de..8e8aeb83 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationAmendmentRequestResponse.java @@ -1,7 +1,6 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; -import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; import java.time.LocalDateTime; @@ -19,12 +18,18 @@ public class ApplicationAmendmentRequestResponse { private Long protocolNumber; private String callName; private String beneficiaryName; + private String companyName; private List formFields; private List applicationFormFields; + private List amendmentDocuments; + private String amendmentNotes; + private Boolean valid; private Long applicationId; private Long applicationEvaluationId; + private LocalDateTime evaluationEndDate; private LocalDateTime expirationDate; private List commentsList; private String internalNote; private ApplicationAmendmentRequestEnum status; + private String emailTemplate; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java index 7f4722e2..7da6d25f 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java @@ -21,13 +21,21 @@ public class ApplicationEvaluationResponse { private List criteria; private List checklist; private List files; + private List evaluationDocument; + private List amendmentDetails; private LocalDateTime createdDate; private LocalDateTime updatedDate; private String beneficiary; + private Long assignedUserId; + private String assignedUserName; private Long protocolNumber; private String callName; private String motivation; private LocalDateTime submissionDate; - private LocalDateTime evaluationDate; + private LocalDateTime evaluationEndDate; private LocalDateTime callEndDate; + private String companyName; + private LocalDateTime assignedAt; + private String ndg; + private String appointmentId; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java index d5df459e..24ad5a34 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java @@ -33,4 +33,8 @@ public class ApplicationResponse{ private Long protocolNumber; + private Long assignedUserId; + + private String assignedUserName; + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentCreationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentCreationResponse.java new file mode 100644 index 00000000..80dd3ba0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentCreationResponse.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class AppointmentCreationResponse { + private String appointmentId; +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentLoginResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentLoginResponse.java new file mode 100644 index 00000000..1d3b9c56 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AppointmentLoginResponse.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class AppointmentLoginResponse { + + private String tokenId; + private String areaCode; + private Long companyId; + private String codecFiscale; + private String vatNumber; + private String ndg; + private String message; + private String idVisura; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/AssignedApplicationsResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/AssignedApplicationsResponse.java index 3affe42f..b975c150 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/AssignedApplicationsResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/AssignedApplicationsResponse.java @@ -21,6 +21,7 @@ public class AssignedApplicationsResponse extends BaseBean { private LocalDateTime callStartDate; private LocalDateTime callEndDate; private String companyName; + private LocalDateTime evaluationEndDate; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryPreferredCallResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryPreferredCallResponseBean.java index 9588b576..aa07ab69 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryPreferredCallResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryPreferredCallResponseBean.java @@ -20,6 +20,7 @@ public class BeneficiaryPreferredCallResponseBean { private BeneficiaryCallStatus status; private LocalDateTime createdDate; private LocalDateTime updatedDate; + private Long userWithCompanyId; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java index f5706b10..307c4982 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java @@ -25,4 +25,6 @@ public class DocumentResponseBean { private LocalDateTime createdDate; private LocalDateTime updatedDate; + + private String documentAttachmentId; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/DocumentUploadResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentUploadResponse.java new file mode 100644 index 00000000..956ef1cb --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentUploadResponse.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class DocumentUploadResponse { + private String documentAttachmentId; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/EmailContentResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/EmailContentResponse.java new file mode 100644 index 00000000..dfeaf074 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/EmailContentResponse.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class EmailContentResponse { + private final String subject; + private final String body; + private final SystemEmailTemplateResponse systemEmailTemplateResponse; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationDocumentResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationDocumentResponse.java new file mode 100644 index 00000000..94a4d881 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationDocumentResponse.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class EvaluationDocumentResponse { + private String fieldId; + private String nameValue; + private Boolean valid; + private List fileValue ; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NdgResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NdgResponse.java new file mode 100644 index 00000000..991828c5 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NdgResponse.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class NdgResponse { + private String ndg; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NotificationResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NotificationResponse.java new file mode 100644 index 00000000..0383cd25 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NotificationResponse.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.model.BaseBean; + +@Data +public class NotificationResponse extends BaseBean { + private Long userId; + + private String title; + + private String message; + + private String status; + + private Long companyId; + + private String redirectUrl; + + private String notificationType; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java index b0a5ef38..c8724d43 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/UserResponseBean.java @@ -40,6 +40,7 @@ public class UserResponseBean extends BaseBean { private List companies; private Boolean privacy; + private Boolean terms; private Boolean marketing; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/VatCheckResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/VatCheckResponseBean.java new file mode 100644 index 00000000..611925d3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/VatCheckResponseBean.java @@ -0,0 +1,12 @@ +package net.gepafin.tendermanagement.model.response; +import lombok.Getter; +import lombok.Setter; +import java.util.Map; + +@Getter +@Setter +public class VatCheckResponseBean { + private Boolean valid; + private Map vatCheckResponse; + private String message; +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java index 57331e43..68133efb 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java @@ -1,13 +1,18 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.Set; public interface ApplicationAmendmentRequestRepository extends JpaRepository, JpaSpecificationExecutor { Optional findByIdAndIsDeletedFalse(Long id); @@ -25,6 +30,7 @@ public interface ApplicationAmendmentRequestRepository extends JpaRepository findAllByApplicationEvaluationIdAndIsDeletedFalse(Long id); @@ -34,4 +40,38 @@ public interface ApplicationAmendmentRequestRepository extends JpaRepository findByApplicationIdAndStatusInAndIsDeletedFalse(Long applicationId, List statuses); + @Query("SELECT app " + + "FROM ApplicationEntity app " + + "WHERE app.id = (SELECT aar.applicationId " + + "FROM ApplicationAmendmentRequestEntity aar " + + "WHERE aar.id = :amendmentId AND aar.isDeleted = false)") + ApplicationEntity findApplicationByAmendmentId(Long amendmentId); + + @Query(value = "SELECT amr " + + "FROM ApplicationAmendmentRequestEntity amr " + + "WHERE amr.applicationEvaluationEntity.id = :id " + + "AND amr.isDeleted = false " + + "AND amr.applicationEvaluationEntity.isDeleted = false " + + "AND amr.status IN (:statuses)") + List findAllByApplicationEvaluationIdAndStatusAndIsDeletedFalse(Long id, List statuses); + + @Query("SELECT a FROM ApplicationAmendmentRequestEntity a " + + "WHERE a.isDeleted = false " + + "AND a.status <> 'CLOSE' " + + "AND a.endDate < :currentTime") + List findAmendmentsDueForExpiration(LocalDateTime currentTime); + + + + @Query("SELECT DISTINCT a.applicationEvaluationEntity " + + "FROM ApplicationAmendmentRequestEntity a " + + "WHERE a.applicationEvaluationEntity.id IN :applicationEvaluationIds " + + "AND a.isDeleted = false " + + "AND NOT EXISTS ( " + + " SELECT 1 FROM ApplicationAmendmentRequestEntity activeAmendment" + + " WHERE activeAmendment.applicationEvaluationEntity.id = a.applicationEvaluationEntity.id " + + " AND activeAmendment.status <> 'CLOSE' " + + " AND activeAmendment.isDeleted = false) ") + Set findEvaluationsWithoutActiveAmendmentsByIds(@Param("applicationEvaluationIds") Set applicationEvaluationIds); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java index 9ec88ffa..f9a7b0ac 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java @@ -1,11 +1,13 @@ package net.gepafin.tendermanagement.repositories; +import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -20,6 +22,13 @@ public interface ApplicationEvaluationRepository extends JpaRepository findFirstByIsDeletedFalseOrderByCreatedDateDesc(); boolean existsByApplicationIdAndIsDeletedFalse(Long applicationId); + @Query("SELECT app " + + "FROM ApplicationEntity app " + + "WHERE app.id = (SELECT aar.applicationId " + + "FROM ApplicationEvaluationEntity aar " + + "WHERE aar.id = :evaluationId AND aar.isDeleted = false)") + ApplicationEntity findApplicationByEvaluationId(Long evaluationId); - + @Query("SELECT a FROM ApplicationEvaluationEntity a WHERE a.isDeleted = false AND a.endDate < :currentDate") + List findAllByIsDeletedFalseAndEndDateBefore(@Param("currentDate") LocalDateTime currentDate); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 38d73e8d..db645f95 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -24,15 +24,17 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndIsDeletedFalse(Long id,Long userId); - Optional findByUserIdAndCompanyIdAndCallIdAndIsDeletedFalse(Long userId, Long companyId, Long callId); + Optional findByUserIdAndUserWithCompanyIdAndCallIdAndIsDeletedFalse(Long userId, Long userWithCompanyId, Long callId); public Optional findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, Long callId); - @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.userId = :userId AND a.company.id = :companyId AND a.status = 'SUBMIT' AND a.isDeleted = false") - Long countSubmittedApplicationsByUserId(@Param("userId") Long userId, @Param("companyId") Long companyId); + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.userId = :userId AND a.userWithCompany.id = :userWithCompanyId AND a.status = 'SUBMIT' AND a.isDeleted = false") + Long countSubmittedApplicationsByUserId(@Param("userId") Long userId, @Param("userWithCompanyId") Long userWithCompanyId); + + + List findByUserWithCompanyIdAndUserIdAndIsDeletedFalse(Long userWithCompanyId, Long userId); - List findByCompanyIdAndUserIdAndIsDeletedFalse(Long companyId,Long userId); @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'SUBMIT' And a.hubId = :hubId AND a.isDeleted = false") public Long countSubmittedApplicationsByHubId(@Param("hubId") Long hubId); @@ -40,6 +42,6 @@ public interface ApplicationRepository extends JpaRepository findByBeneficiaryIdAndIsDeletedFalse(Long beneficiaryId); List findByUserIdAndIsDeletedFalse(Long userId); - @Query("SELECT preferredCall FROM BeneficiaryPreferredCallEntity preferredCall where preferredCall.userId=:userId AND (:companyId is null OR preferredCall.companyId=:companyId) AND isDeleted=false") - List findByUserIdAndCompanyIdAndIsDeletedFalse(@Param("userId") Long userId, @Param("companyId") Long companyId); + @Query("SELECT preferredCall FROM BeneficiaryPreferredCallEntity preferredCall WHERE preferredCall.userId = :userId AND (:userWithCompanyId IS NULL OR preferredCall.userWithCompany.id = :userWithCompanyId) AND isDeleted = false") + List findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(@Param("userId") Long userId, @Param("userWithCompanyId") Long userWithCompanyId); + List findByBeneficiaryIdAndCompanyId(Long beneficiaryId,Long companyId); + List findByUserIdAndCallIdInAndIsDeletedFalse(Long userId, List callIds); Optional findByIdAndIsDeletedFalse(Long id); - Optional findByUserIdAndCallIdAndCompanyIdAndIsDeletedFalse(Long userId, Long callId, Long companyId); - List findByUserIdAndCallIdInAndCompanyIdAndIsDeletedFalse(Long userId, List callIds,Long companyId); + + Optional findByUserIdAndCallIdAndUserWithCompanyIdAndIsDeletedFalse(Long userId, Long callId, Long userWithCompanyId); + + List findByUserIdAndCallIdInAndUserWithCompanyIdAndIsDeletedFalse(Long userId, List callIds, Long userWithCompanyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java index ecb6ed7d..984e477a 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/BeneficiaryRepository.java @@ -1,11 +1,16 @@ package net.gepafin.tendermanagement.repositories; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import net.gepafin.tendermanagement.entities.BeneficiaryEntity; +import java.util.List; + @Repository public interface BeneficiaryRepository extends JpaRepository { + @Query("SELECT u.id FROM UserEntity u JOIN u.beneficiary b WHERE b.id = u.beneficiary.id AND b.hubId = :hubId") + List findUserIdsByHubIdAndBeneficiaryId(Long hubId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 684e2a3b..0ca46f8e 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -28,6 +28,12 @@ public interface DocumentRepository extends JpaRepository @Query("SELECT d FROM DocumentEntity d WHERE d.isDeleted = false") List findAllByIsDeleteFalse(); + + @Query("SELECT d FROM DocumentEntity d WHERE d.isDeleted = true") + List findAllByIsDeleteTrue(); + List findAllByIdInAndIsDeletedFalse(Set documentIds); + + List findBySourceIdInAndSourceAndIsDeletedFalse(Set sourceId, String type); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java index 51642934..a8ada0e1 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java @@ -19,6 +19,8 @@ public interface FaqRepository extends JpaRepository { List findByCallIdAndIsDeletedFalse(Long callId); Optional findByIdAndCallIdAndIsDeletedFalse(Long id, Long callId); - List findByCompanyIdAndUserIdAndIsDeletedFalse(Long companyId,Long userId); + + List findByUserWithCompanyIdAndIsDeletedFalse(Long userWithCompanyId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/HubRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/HubRepository.java index cc54295a..e371d148 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/HubRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/HubRepository.java @@ -1,15 +1,17 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.HubEntity; - import java.util.Optional; - import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository public interface HubRepository extends JpaRepository { - Optional findByUniqueUuid(String hubUuid); - + Optional findByUniqueUuid(String hubUuid); + + @Query("SELECT h FROM HubEntity h WHERE h.id = :hubId") + HubEntity findByHubId(@Param("hubId") Long hubId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/NotificationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/NotificationRepository.java new file mode 100644 index 00000000..bce3ba68 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/NotificationRepository.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.NotificationEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface NotificationRepository extends JpaRepository { + + NotificationEntity findByIdAndIsDeletedFalse(Long id); + + List findByUserIdAndIsDeletedFalse(Long userId); + + List findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(Long userId, Long userWithCompanyId, List statuses); + + List findByUserIdAndIsDeletedFalseAndStatusIn(Long userId, List statuses); + + List findByUserWithCompanyIdAndUserIdAndIsDeletedFalse(Long userWithCompanyId, Long userId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/NotificationTypeRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/NotificationTypeRepository.java new file mode 100644 index 00000000..78cef54d --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/NotificationTypeRepository.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.NotificationTypeEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface NotificationTypeRepository extends JpaRepository { + NotificationTypeEntity findByNotificationNameAndIsDeletedFalse(String value); +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java index 03067c80..4cbe8875 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java @@ -9,7 +9,7 @@ import java.util.List; public interface UserCompanyDelegationRepository extends JpaRepository { - UserCompanyDelegationEntity findByUserIdAndCompanyIdAndStatus(Long userId, Long companyId, String status); + UserCompanyDelegationEntity findByUserIdAndUserWithCompanyIdAndStatus(Long userId, Long userWithCompanyId, String status); @Query("SELECT d FROM UserCompanyDelegationEntity d where d.status = :status") List findAllByStatus(@Param("status") String status); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 3a0cf957..ae41b9b1 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -25,7 +25,7 @@ public interface UserRepository extends JpaRepository { // boolean existsByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid); - List findByRoleEntityIdAndHubId(Long roleId, Long hubId); + List findByRoleEntityIdInAndHubId(List roleIds, Long hubId); List findByHubId(Long hubId); @@ -50,5 +50,8 @@ public interface UserRepository extends JpaRepository { "AND u.roleEntity.roleType = :beneficiaryRoleType") Boolean existsByEmailIgnoreCaseForBeneficiaries(String email, String hubUuid, String beneficiaryRoleType); + // existsByBebooleanneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); + + List findByRoleEntity_RoleTypeAndHubId(String roleType, Long hubId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java index ec93f2f6..13a197f1 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserWithCompanyRepository.java @@ -1,22 +1,23 @@ package net.gepafin.tendermanagement.repositories; -import java.util.List; -import java.util.Optional; - +import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; - +import java.util.List; +import java.util.Optional; public interface UserWithCompanyRepository extends JpaRepository { - void deleteByCompanyIdAndIsDeletedFalse(Long companyId); + void deleteByCompanyIdAndIsDeletedFalse(Long companyId); - @Query("SELECT u.companyId FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.isDeleted = false") - List findActiveCompanyIdsByUserId(@Param("userId") Long userId); + @Query("SELECT u.companyId FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.isDeleted = false") + List findActiveCompanyIdsByUserId(@Param("userId") Long userId); - Optional findByUserIdAndCompanyIdAndIsDeletedFalse(Long userId, Long companyId); + Optional findByUserIdAndCompanyIdAndIsDeletedFalse(Long userId, Long companyId); + + @Query("SELECT u FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.companyId = :companyId AND u.isDeleted = false") + UserWithCompanyEntity findByUserIdAndCompanyIdAndIsDeletedFalseForNotification(Long userId, Long companyId); } diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java new file mode 100644 index 00000000..91cfaf78 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java @@ -0,0 +1,185 @@ +package net.gepafin.tendermanagement.scheduler; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; +import net.gepafin.tendermanagement.dao.NotificationDao; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; +import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; +import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.AssignedApplicationEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; +import net.gepafin.tendermanagement.enums.UserActionContextEnum; +import net.gepafin.tendermanagement.enums.UserActionLogsEnum; +import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.model.request.UserActionRequest; +import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; +import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.LoggingUtil; +import net.gepafin.tendermanagement.util.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class ApplicationAmendmentScheduler { + + @Autowired + private HttpServletRequest httpServletRequest; + + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRepository; + + + @Autowired + private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; + + @Autowired + private LoggingUtil loggingUtil; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private AssignedApplicationsRepository assignedApplicationsRepository; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + private static final Logger log = LoggerFactory.getLogger(ApplicationAmendmentScheduler.class); + + @Scheduled(cron = "0 0 1 * * ?") + public void processAmendmentExpirationScheduler() { + log.info("Starting the Application Amendment Expiration scheduler."); + try { + + Utils.setHttpServletRequestForScheduler(); + + /** This code is responsible for creating user action logs for the "Application Amendment Expiration scheduler" operation. **/ + loggingUtil.logUserActionWithoutToken( + UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.SCHEDULER).actionContext(UserActionContextEnum.AMENDMENT_EXPIRATION_SCHEDULER).build()); + + List amendmentRequestList = applicationAmendmentRepository + .findAmendmentsDueForExpiration( + DateTimeUtil.DateServerToUTC(LocalDateTime.now()).with(LocalTime.MIN).plusSeconds(5)); + processAmendmentsForExpiration(amendmentRequestList); + log.info("Application Amendment Expiration scheduler completed successfully."); + } catch (Exception e) { + log.error("An error occurred during the Application Amendment Expiration scheduler: {}", e.getMessage(), e); + } + Utils.clearHttpServletRequest(); + } + + private void processAmendmentsForExpiration(List amendmentRequests) { + + log.info("Starting the process of expiring application amendments."); + amendmentRequests.forEach(request -> { + try { + ApplicationAmendmentRequestEntity oldAmendmentRequestEntity = Utils.getClonedEntityForData(request); + request.setStatus(ApplicationAmendmentRequestEnum.EXPIRED.getValue()); + ApplicationEntity application=oldAmendmentRequestEntity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication(); + request = applicationAmendmentRepository.save(request); + Map placeHolders=notificationDao.sendNotificationToBeneficiary(application,NotificationTypeEnum.AMENDMENT_EXPIRED); + notificationDao.sendNotificationToInstructor(placeHolders,oldAmendmentRequestEntity.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_EXPIRED); + /** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAmendmentRequestEntity).newData(request).build()); + +// emailNotificationDao.sendApplicationFailureNotificationEmail(request); + log.info("Updated status to EXPIRED for ApplicationAmendmentRequest with ID: {}", request.getId()); + } catch (Exception e) { + log.error("Error expiring ApplicationAmendmentRequest with ID {}: {}", request.getId(), e.getMessage(), + e); + } + }); + log.info("Completed the process of updating expiring application amendments."); + + log.info("Starting the process of updating EndDate in ApplicationEvaluations."); + try { + Set applicationEvaluationIds = amendmentRequests.stream() + .map(request -> request.getApplicationEvaluationEntity().getId()).collect(Collectors.toSet()); + + Set evaluationsWithoutActiveAmendmentList = applicationAmendmentRepository + .findEvaluationsWithoutActiveAmendmentsByIds(applicationEvaluationIds); + evaluationsWithoutActiveAmendmentList.forEach(evaluation -> { + try { + applicationAmendmentRequestDao.calculateEndDateAndSuspensionDays(evaluation); + + updateEvaluationStatus(evaluation); + + // Update AssignedApplicationsEntity status + updateAssignedApplicationStatus(evaluation.getAssignedApplicationsEntity()); + + // Update ApplicationEntity status + updateApplicationStatus(evaluation.getAssignedApplicationsEntity().getApplication()); + + + log.info("Updated EndDate and suspension days for ApplicationEvaluation with ID: {}", + evaluation.getId()); + } catch (Exception e) { + log.error("Error updating EndDate for ApplicationEvaluation with ID {}: {}", evaluation.getId(), + e.getMessage(), e); + } + }); + + log.info("Completed the process of updating EndDate in ApplicationEvaluations."); + } catch (Exception e) { + log.error("An error occurred while updating EndDate in ApplicationEvaluations: {}", e.getMessage(), e); + } + + } + + public void updateAssignedApplicationStatus(AssignedApplicationsEntity assignedApplicationsEntity){ + AssignedApplicationsEntity oldAssignedApplicationEntity = Utils.getClonedEntityForData(assignedApplicationsEntity); + assignedApplicationsEntity.setStatus(AssignedApplicationEnum.OPEN.getValue()); + assignedApplicationsRepository.save(assignedApplicationsEntity); + log.info("Updated status to OPEN for Assigned Application with ID: {}", assignedApplicationsEntity.getId()); + + /** This code is responsible for adding a version history log for the "Update Assigned Application status" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplicationEntity).newData(assignedApplicationsEntity).build()); + + } + + public void updateApplicationStatus(ApplicationEntity applicationEntity){ + ApplicationEntity oldApplicationEntity = Utils.getClonedEntityForData(applicationEntity); + applicationEntity.setStatus(ApplicationStatusTypeEnum.EVALUATION.getValue()); + applicationRepository.save(applicationEntity); + log.info("Updated status to EVALUATION for Application with ID: {}",applicationEntity.getId()); + + /** This code is responsible for adding a version history log for the "Update Application Status" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEntity).newData(applicationEntity).build()); + + } + public void updateEvaluationStatus(ApplicationEvaluationEntity applicationEvaluationEntity){ + ApplicationEvaluationEntity oldApplicationEvaluationEntity = Utils.getClonedEntityForData(applicationEvaluationEntity); + applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.OPEN.getValue()); + applicationEvaluationRepository.save(applicationEvaluationEntity); + log.info("Updated status to OPEN for ApplicationEvaluation with ID: {}", applicationEvaluationEntity.getId()); + + /** This code is responsible for adding a version history log for the "Update Application Status" operation. **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity).newData(applicationEvaluationEntity).build()); + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationEvaluationScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationEvaluationScheduler.java new file mode 100644 index 00000000..e7249645 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationEvaluationScheduler.java @@ -0,0 +1,111 @@ +package net.gepafin.tendermanagement.scheduler; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.dao.NotificationDao; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; +import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; +import net.gepafin.tendermanagement.enums.UserActionContextEnum; +import net.gepafin.tendermanagement.enums.UserActionLogsEnum; +import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.model.request.UserActionRequest; +import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.util.LoggingUtil; +import net.gepafin.tendermanagement.util.Utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.Map; + +@Component +public class ApplicationEvaluationScheduler { + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Autowired + private LoggingUtil loggingUtil; + + @Autowired + private HttpServletRequest httpServletRequest; + + @Autowired + private NotificationDao notificationDao; + + private static final Logger log = LoggerFactory.getLogger(ApplicationEvaluationScheduler.class); + + @Scheduled(cron = "0 0 2 * * ?") // Runs daily at midnight + public void updateExpiredEvaluations() { + log.info("Starting the Application Evaluation Expiration scheduler..."); + try { + + Utils.setHttpServletRequestForScheduler(); + + // Logging user action for the scheduler operation + loggingUtil.logUserActionWithoutToken( + UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.SCHEDULER) + .actionContext(UserActionContextEnum.EVALUATION_EXPIRATION_SCHEDULER).build()); + + + processExpiredEvaluation(); + log.info("Completed the process of updating expiring application evaluations."); + } catch (Exception e) { + log.error("An error occurred during the Application Evaluation Expiration scheduler: {}", e.getMessage(), + e); + } finally { + Utils.clearHttpServletRequest(); + } + } + + private void processExpiredEvaluation() { + log.info("Starting the process of expiring application evaluations."); + + + try { + List evaluations = applicationEvaluationRepository + .findAllByIsDeletedFalseAndEndDateBefore( + DateTimeUtil.DateServerToUTC(LocalDateTime.now()).with(LocalTime.MIN).plusSeconds(5)); + log.info("Found {} evaluations to process for expiration.", evaluations.size()); + + for (ApplicationEvaluationEntity evaluation : evaluations) { + try { + log.debug("Processing evaluation with ID: {}", evaluation.getId()); + + ApplicationEvaluationEntity oldApplicationEvaluationEntity = Utils + .getClonedEntityForData(evaluation); + ApplicationEntity application=evaluation.getAssignedApplicationsEntity().getApplication(); + evaluation.setStatus(ApplicationEvaluationStatusTypeEnum.EXPIRED.getValue()); + evaluation = applicationEvaluationRepository.save(evaluation); + + Map placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_EXPIRED); + notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_EXPIRED); + notificationDao.sendNotificationToInstructor(placeHolders,evaluation,NotificationTypeEnum.EVALUATION_EXPIRED); + + + // Logging version history for the update operation + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest) + .actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity) + .newData(evaluation).build()); + + log.info("Updated evaluation status to EXPIRED for ID: {}", evaluation.getId()); + } catch (Exception e) { + log.error("Error processing evaluation with ID: {}. Error: {}", evaluation.getId(), e.getMessage(), + e); + } + } + } catch (Exception e) { + log.error("An error occurred while fetching evaluations for expiration. Error: {}", e.getMessage(), e); + } + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java deleted file mode 100644 index 69dc05cb..00000000 --- a/src/main/java/net/gepafin/tendermanagement/scheduler/NotificationScheduler.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.gepafin.tendermanagement.scheduler; - -import net.gepafin.tendermanagement.dao.EmailNotificationDao; -import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; -import net.gepafin.tendermanagement.entities.ApplicationEntity; -import net.gepafin.tendermanagement.entities.UserEntity; -import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; -import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; -import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.List; - -@Component -public class NotificationScheduler { - - @Autowired - UserRepository userRepository; - - @Autowired - ApplicationRepository applicationRepository; - - @Autowired - ApplicationAmendmentRequestRepository applicationAmendmentRepository; - - @Autowired - EmailNotificationDao emailNotificationDao; - -// @Scheduled(cron = "0 0 1 * * ?") - void sendNotificationForRejectedApplicationToBeneficiary() { - - List applicationsList = applicationRepository.findByIsDeletedFalse(); - List amendmentRequestList = applicationAmendmentRepository.findByIsDeletedFalse(); - - LocalDateTime today = LocalDateTime.now(); - - for (ApplicationEntity application : applicationsList) { - ApplicationAmendmentRequestEntity amendmentRequest = getAmendmentRequestForApplication(application, amendmentRequestList); - - if (amendmentRequest != null) { - LocalDateTime requestDate = amendmentRequest.getStartDate(); - if (requestDate.plusDays(amendmentRequest.getResponseDays()).isBefore(today)) { - // Update the application status to REJECTED - application.setStatus(ApplicationStatusTypeEnum.REJECTED.getValue()); - applicationRepository.save(application); - amendmentRequest.setStatus(ApplicationAmendmentRequestEnum.CLOSE.getValue()); - applicationAmendmentRepository.save(amendmentRequest); - emailNotificationDao.sendApplicationFailureNotificationEmail(amendmentRequest); - } - } - } - } - - private ApplicationAmendmentRequestEntity getAmendmentRequestForApplication(ApplicationEntity application, List amendmentRequestList) { - - return amendmentRequestList.stream().filter(request -> request.getApplicationId().equals(application.getId())).findFirst().orElse(null); - } -} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java index 6cc27000..f9f22ae1 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java +++ b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java @@ -1,5 +1,4 @@ package net.gepafin.tendermanagement.service; - import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; @@ -9,12 +8,15 @@ import java.io.IOException; import java.io.InputStream; @Component -public interface AmazonS3Service { +public interface +AmazonS3Service { UploadFileOnAmazonS3Response uploadFileOnAmazonS3(String s3Folder, MultipartFile file); Boolean delete(String s3Folder, String filePath); InputStream getFile(String s3Folder, String filePath) throws IOException; - + + UploadFileOnAmazonS3Response moveFile(String fileName, String oldPath, String newPath); + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java index c9f72e6a..454030af 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationEvaluationService.java @@ -2,10 +2,12 @@ package net.gepafin.tendermanagement.service; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; -import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.request.EvaluationDocumentRequest; import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; +import java.util.List; + public interface ApplicationEvaluationService { ApplicationEvaluationResponse createOrUpdateApplicationEvaluation( HttpServletRequest request, @@ -16,4 +18,7 @@ public interface ApplicationEvaluationService { ApplicationEvaluationResponse getApplicationEvaluationByApplicationId(HttpServletRequest request,Long applicationId,Long assignedApplicationId); ApplicationEvaluationEntity validateApplicationEvaluation(Long applicationEvaluationId); + + ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/AppointmentService.java b/src/main/java/net/gepafin/tendermanagement/service/AppointmentService.java new file mode 100644 index 00000000..842901a4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/AppointmentService.java @@ -0,0 +1,16 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest; +import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest; +import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse; +import net.gepafin.tendermanagement.model.response.DocumentUploadResponse; +import net.gepafin.tendermanagement.model.response.NdgResponse; + +public interface AppointmentService { + NdgResponse checkNdgForAppointment(HttpServletRequest request, Long applicationId); + + AppointmentCreationResponse createAppointmentForApplication(HttpServletRequest request, Long applicationId, CreateAppointmentRequest createAppointmentRequest); + + DocumentUploadResponse uploadDocToExternalSystem(HttpServletRequest request, Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java b/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java index f1670687..1a73c674 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/AssignedApplicationsService.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.service; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; +import net.gepafin.tendermanagement.model.request.UpdateAssignedApplicationRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; import java.util.List; @@ -15,7 +16,7 @@ public interface AssignedApplicationsService { void deleteApplication(HttpServletRequest request, Long id); List getAllAssignedApplications(HttpServletRequest request, Long userId); - AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, Long id, AssignedApplicationsRequest assignedApplicationsRequest); + AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, Long id, UpdateAssignedApplicationRequest assignedApplicationsRequest); AssignedApplicationsResponse getAssignedApplicationById(HttpServletRequest request, Long id); AssignedApplicationsEntity validateAssignedApplication(Long assignedApplicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java index f11e0798..da36cc15 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CompanyService.java @@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream; import java.util.List; import java.util.Map; +import net.gepafin.tendermanagement.model.response.VatCheckResponseBean; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletRequest; @@ -26,21 +27,22 @@ public interface CompanyService { List getCompanyByUserId(HttpServletRequest request, Long userId); - Map checkVatNumber(HttpServletRequest request, String vatNumber); + VatCheckResponseBean checkVatNumber(HttpServletRequest request, String vatNumber); CompanyEntity validateCompany(Long companyId); UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId); - + + UserWithCompanyEntity getUserWithCompany(Long userId, Long companyId); + ByteArrayOutputStream downloadCompanyDelegation(HttpServletRequest request, Long companyId, CompanyDelegationRequest companyDelegationRequest); CompanyDelegationResponse uploadCompanyDelegation(HttpServletRequest request, Long companyId, MultipartFile file); - CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId); + CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId,Long applicationId); void deleteCompanyDelegation(HttpServletRequest request, Long companyId); UserWithCompanyEntity getUserWithCompanyEntity(Long userId,Long companyId); void removeCompanyFromList(HttpServletRequest request, Long companyId); - } diff --git a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java index 6012a273..c777f004 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java @@ -11,7 +11,7 @@ import java.util.List; public interface DocumentService { - public List uploadFile(List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType); + public List uploadFile(HttpServletRequest request,List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType); public void deleteFile(Long documentId); diff --git a/src/main/java/net/gepafin/tendermanagement/service/NotificationService.java b/src/main/java/net/gepafin/tendermanagement/service/NotificationService.java new file mode 100644 index 00000000..ca5927c0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/NotificationService.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.NotificationEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.response.NotificationResponse; + +import java.util.List; + +public interface NotificationService { + NotificationResponse sendNotification(Long userId, NotificationReq notificationReq, Long companyId); + + public NotificationResponse getNotificationById(HttpServletRequest servletRequest, Long id); + + public List getNotificationByUserId(HttpServletRequest servletRequest, Long userId, Long companyId, List statuses); + + public NotificationResponse updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum status); + + public void deleteNotification(HttpServletRequest request, Long id); + + public List getNotificationsByCompanyIdAndUserId(Long userId, Long companyId, List statuses); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java index aa534bea..6a92a667 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java @@ -45,6 +45,6 @@ public interface UserService { UserEntity getUserByBeneficiaryId(Long beneficiaryId); public UserEntity getUserEntityById(Long userId); - List getAllUsers(HttpServletRequest request, Long roleId); + List getAllUsers(HttpServletRequest request, List roleIds); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/feignClient/AppointmentApiService.java b/src/main/java/net/gepafin/tendermanagement/service/feignClient/AppointmentApiService.java new file mode 100644 index 00000000..b193713b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/feignClient/AppointmentApiService.java @@ -0,0 +1,44 @@ +package net.gepafin.tendermanagement.service.feignClient; + +import net.gepafin.tendermanagement.constants.AppointmentApiConstant; +import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; + +@FeignClient(value = "appointment-api-service", url = "${appointment.base.url}") +public interface AppointmentApiService { + + @PostMapping(value = AppointmentApiConstant.ODESSA_LOGIN, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity loginWithOdessa(@RequestHeader("auth") String authToken, @RequestHeader("source") String source, @RequestHeader("context") String context, + @RequestHeader("user") String user, @RequestHeader("password") String password, @RequestBody(required = false) Map body); + + @PostMapping(value = AppointmentApiConstant.GET_NDG_BY_VAT_NUMBER, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity getNdgByVatNumber(@RequestBody AppointmentNdgRequest ndgRequest, @RequestHeader("Authorization") String token); + + @PostMapping(value = AppointmentApiConstant.CREATE_VISURA, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity createVisura(@RequestBody String visuraRequest, @RequestHeader("Authorization") String token); + + @GetMapping(value = AppointmentApiConstant.GET_VISURA_LIST, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity getVisuraList(@RequestBody String visuraRequest, @RequestHeader("Authorization") String token); + + @GetMapping(value = AppointmentApiConstant.GET_APPOINTMENT_TEMPLATE, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity getAppointmentTemplateForTemplateCreation(@RequestHeader("Authorization") String token); + + @PostMapping(value = AppointmentApiConstant.CREATE_APPOINTMENT_FROM_TEMPLATE, consumes = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity createAppointment(@RequestHeader("Authorization") String token, @RequestHeader("context") String context, String appointmentCreationRequest); + + @PostMapping(value = AppointmentApiConstant.UPLOAD_APOOINTMENT_DOCUMENT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + ResponseEntity uploadDocumentToExternalSystemForAppointment(@RequestHeader("Authorization") String token, @RequestHeader("context") String context, + @RequestPart("input") String uploadDocumentRequest, @RequestPart("file") MultipartFile file); +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java index 56141be2..8221117a 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java @@ -1,10 +1,17 @@ package net.gepafin.tendermanagement.service.impl; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.*; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.dao.S3PathConfig; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response; import net.gepafin.tendermanagement.service.AmazonS3Service; import net.gepafin.tendermanagement.util.Utils; @@ -22,6 +29,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -45,6 +55,18 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { @Value("${aws.s3.url}") private String s3Url; + @Autowired + private S3PathConfig s3ConfigBean; + + @Autowired + private AmazonS3Client s3Client; + + @Value("${aws.s3.region}") + private String region; + + @Autowired + S3ReUploadMigrationService s3ReUploadMigrationService; + private String upload(String fileName, String s3Folder, MultipartFile file) throws IOException { @@ -68,9 +90,11 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { if(Boolean.FALSE.equals(isTestProfileActivated())) { amazonS3.putObject(bucketName, path, inputStream, objectMetadata); } - path =s3Url + s3Folder +"/"+ fileName; - log.info("File '{}' uploaded successfully to Amazon S3 with URL: {}", fileName, path); - return path; + //getting actual encoded s3 file path + URL amazonS3Url = amazonS3.getUrl(bucketName, path); + String fileUrl = amazonS3Url.toString(); + log.info("File '{}' uploaded successfully to Amazon S3 with URL: {}", fileName, fileUrl); + return fileUrl; } @Override @@ -96,12 +120,15 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { public InputStream getFile(String s3Folder, String filePath) { try { String fileName = Utils.extractFileName(filePath); - String path = s3Folder + "/" + fileName; + // Decode the file name to handle special characters like '+' correctly + String decodedFileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8.toString()); + + String path = s3Folder + "/" + decodedFileName; GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, path); S3Object s3Object = amazonS3.getObject(getObjectRequest); log.info("File fetched successfully from Amazon S3: {}", fileName); return s3Object.getObjectContent(); - } catch (AmazonS3Exception e) { + } catch (Exception e) { log.error("Error occurred while getting file from Amazon S3: {}", e); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.GET_ERROR_S3)); @@ -125,4 +152,39 @@ public class AmazonS3ServiceImpl implements AmazonS3Service { Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); } } + + @Override + public UploadFileOnAmazonS3Response moveFile(String fileName, String oldPath, String newPath) { + try { + newPath = cleanNewPath(oldPath, newPath); + oldPath = cleanOldPath(oldPath); + log.info("Moving file from {} to {} in bucket {}", oldPath, newPath, bucketName); + + CopyObjectRequest copyRequest = new CopyObjectRequest(bucketName, oldPath, bucketName, newPath); + s3Client.copyObject(copyRequest); + log.info("File copied successfully from {} to {}", oldPath, newPath); + + s3Client.deleteObject(bucketName, oldPath); + log.info("Original file deleted successfully: {}", oldPath); + String filePath = s3Url + newPath; + return UploadFileOnAmazonS3Response.builder().fileName(fileName).filePath(filePath).build(); + } catch (AmazonServiceException e) { + log.error("AWS service error while moving file: {}", e.getErrorMessage(), e); + throw e; + } catch (SdkClientException e) { + log.error("SDK client error while moving file: {}", e.getMessage(), e); + throw e; + } catch (Exception e) { + log.error("Unexpected error while moving file: {}", e.getMessage(), e); + throw e; + } + } + + private String cleanNewPath(String oldPath, String newPath) { + return newPath + "/" + oldPath.substring(oldPath.lastIndexOf("/") + 1); + } + + private String cleanOldPath(String oldPath) { + return oldPath.replace(s3Url, ""); + } } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java index 4d3092a3..e2615a71 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationAmendmentRequestServiceImpl.java @@ -20,6 +20,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundExceptio import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -45,6 +46,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationAmendmentRequestResponse createApplicationAmendmentRequest(HttpServletRequest request, Long applicationEvaluationId , ApplicationAmendmentRequest applicationAmendmentRequest) { Optional entityOptional = applicationEvaluationRepository.findByIdAndIsDeletedFalse(applicationEvaluationId); entityOptional.ifPresent(applicationEvaluationEntity -> validator.validatePreInstructor(request, applicationEvaluationEntity.getUserId())); @@ -52,6 +54,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override + @Transactional(rollbackFor = Exception.class) public void deleteApplicationAmendmentRequest(HttpServletRequest request, Long id) { ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, @@ -86,14 +89,8 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationAmendmentRequestResponse updateApplicationAmendment(HttpServletRequest request, Long id, ApplicationAmendmentRequestBean applicationAmendmentRequestBean) { - ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestDao.validateApplicationAmendmentRequest(id); - - if (Boolean.FALSE.equals(validator.checkIsBeneficiary())) { - validator.validatePreInstructor(request, amendment.getApplicationEvaluationEntity().getUserId()); - } else { - validator.validateUserId(request, amendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication().getUserId()); - } return applicationAmendmentRequestDao.updateApplicationAmendment(id,applicationAmendmentRequestBean); } @@ -110,6 +107,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationAmendmentRequestResponse closeAmendmentRequest(HttpServletRequest request, Long id, CloseAmendmentRequest closeAmendmentRequest) { ApplicationAmendmentRequestEntity amendment = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(id) .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, @@ -123,6 +121,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationAmendmentRequestResponse extendResponseDays(HttpServletRequest request, Long id, Long addedDays) { UserEntity user= validator.validateUser(request); return applicationAmendmentRequestDao.extendResponseDays(id, addedDays); @@ -132,6 +131,7 @@ public class ApplicationAmendmentRequestServiceImpl implements ApplicationAmendm return applicationAmendmentRequestDao.getAmendmentByApplicationId(request,applicationId,statuses); } @Override + @Transactional(rollbackFor = Exception.class) public ApplicationAmendmentRequestResponse updateApplicationAmendmentStatus(HttpServletRequest request, Long applicationAmendmentId, ApplicationAmendmentRequestEnum status) { return applicationAmendmentRequestDao.updateApplicationAmendmentStatus(applicationAmendmentId, status); diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java index 30cdaf80..3dd9035f 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationEvaluationServiceImpl.java @@ -1,29 +1,24 @@ package net.gepafin.tendermanagement.service.impl; import jakarta.servlet.http.HttpServletRequest; -import net.gepafin.tendermanagement.config.Translator; -import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.dao.ApplicationEvaluationDao; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.entities.UserEntity; -import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.request.EvaluationDocumentRequest; import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository; import net.gepafin.tendermanagement.service.ApplicationEvaluationService; import net.gepafin.tendermanagement.service.AssignedApplicationsService; 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.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; +import java.util.List; @Service public class ApplicationEvaluationServiceImpl implements ApplicationEvaluationService { @@ -36,6 +31,9 @@ public class ApplicationEvaluationServiceImpl implements ApplicationEvaluationSe private AssignedApplicationsService assignedApplicationsService; @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; + @Autowired + private ApplicationEvaluationService applicationEvaluationService; + @Override @Transactional(rollbackFor = Exception.class) public ApplicationEvaluationResponse createOrUpdateApplicationEvaluation( @@ -54,31 +52,12 @@ public class ApplicationEvaluationServiceImpl implements ApplicationEvaluationSe @Transactional(readOnly = true) public ApplicationEvaluationResponse getApplicationEvaluationByApplicationId( HttpServletRequest request, Long applicationId, Long assignedApplicationId) { - - if (applicationId == null && assignedApplicationId == null) { - throw new CustomValidationException( - Status.BAD_REQUEST, - Translator.toLocale(GepafinConstant.EITHER_APPLICATION_OR_ASSIGNED_APPLICATION_ID_REQUIRED_MSG) - ); - } UserEntity preInstructor = validator.validateUser(request); - Optional assignedApplicationsOptional = - assignedApplicationsRepository.findByApplicationIdOrIdAndIsDeletedFalse(applicationId,assignedApplicationId); - - if (assignedApplicationId != null) { - assignedApplicationsOptional = assignedApplicationsOptional.filter(a -> a.getId().equals(assignedApplicationId)); - } - AssignedApplicationsEntity assignedApplications = assignedApplicationsOptional - .orElseThrow(() -> new CustomValidationException( - Status.BAD_REQUEST, - Translator.toLocale(GepafinConstant.ASSIGNED_APPLICATION_NOT_FOUND_WITH_ID_MSG) - )); - validator.validatePreInstructor(request, assignedApplications.getUserId()); - return applicationEvaluationDao.getApplicationEvaluationByApplicationId( + request, preInstructor, - assignedApplications.getApplication().getId(), - assignedApplications.getId() + applicationId, + assignedApplicationId ); } @@ -93,4 +72,10 @@ public class ApplicationEvaluationServiceImpl implements ApplicationEvaluationSe public ApplicationEvaluationEntity validateApplicationEvaluation(Long applicationEvaluationId) { return applicationEvaluationDao.validateApplicationEvaluation(applicationEvaluationId); } + + @Override + public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) { + return applicationEvaluationDao.validateApplicationEvaluationByApplicationId(applicationId); + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index beaffd36..6a3d827b 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -80,7 +80,7 @@ public class ApplicationServiceImpl implements ApplicationService { public NextOrPreviousFormResponse getNextOrPreviousForm(HttpServletRequest request, Long applicationId, Long formId, FormActionEnum action) { ApplicationEntity applicationEntity = validateApplication(applicationId); - validator.validateUserWithCompany(request, applicationEntity.getCompany().getId()); + validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); return flowFormDao.getNextOrPreviousForm(applicationEntity, formId, action); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AppointmentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AppointmentServiceImpl.java new file mode 100644 index 00000000..2e7960df --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AppointmentServiceImpl.java @@ -0,0 +1,37 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.dao.AppointmentDao; +import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest; +import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest; +import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse; +import net.gepafin.tendermanagement.model.response.DocumentUploadResponse; +import net.gepafin.tendermanagement.model.response.NdgResponse; +import net.gepafin.tendermanagement.service.AppointmentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AppointmentServiceImpl implements AppointmentService { + + @Autowired + private AppointmentDao appointmentDao; + + @Override + public NdgResponse checkNdgForAppointment(HttpServletRequest request, Long applicationId) { + + return appointmentDao.checkNdgForAppointment(applicationId); + } + + @Override + public AppointmentCreationResponse createAppointmentForApplication(HttpServletRequest request, Long applicationId, CreateAppointmentRequest createAppointmentRequest) { + + return appointmentDao.createAppointment(applicationId, createAppointmentRequest); + } + + @Override + public DocumentUploadResponse uploadDocToExternalSystem(HttpServletRequest request, Long documentId, UploadDocToExternalSystemRequest docToExternalSystemRequest) { + + return appointmentDao.uploadDocumentToExternalSystem(documentId, docToExternalSystemRequest); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java index 154e342a..c820d929 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AssignedApplicationsServiceImpl.java @@ -5,6 +5,7 @@ import net.gepafin.tendermanagement.dao.AssignedApplicationsDao; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; +import net.gepafin.tendermanagement.model.request.UpdateAssignedApplicationRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; import net.gepafin.tendermanagement.service.AssignedApplicationsService; import net.gepafin.tendermanagement.util.Validator; @@ -45,7 +46,7 @@ public class AssignedApplicationsServiceImpl implements AssignedApplicationsServ @Override @Transactional(rollbackFor = Exception.class) - public AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, Long id, AssignedApplicationsRequest updatedAssignedApplicationRequest) { + public AssignedApplicationsResponse updateAssignedApplication(HttpServletRequest request, Long id, UpdateAssignedApplicationRequest updatedAssignedApplicationRequest) { return assignedApplicationsDao.updateAssignedApplication(request, id, updatedAssignedApplicationRequest); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java index 1f0194d9..12ea0123 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -208,8 +208,6 @@ public class AuthenticationService { public void logout(HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null) { - String token = tokenProvider.extractTokenFromRequest(request); - tokenProvider.invalidateToken(token); new SecurityContextLogoutHandler().logout(request, response, auth); } SecurityContextHolder.getContext().setAuthentication(null); diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java index c6bcc2f1..092c5102 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CompanyServiceImpl.java @@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream; import java.util.List; import java.util.Map; +import net.gepafin.tendermanagement.model.response.VatCheckResponseBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -78,7 +79,7 @@ public class CompanyServiceImpl implements CompanyService { @Override @Transactional(readOnly = true) - public Map checkVatNumber(HttpServletRequest request, String vatNumber) { + public VatCheckResponseBean checkVatNumber(HttpServletRequest request, String vatNumber) { return vatCheckDao.checkVatNumber(vatNumber); } @Override @@ -90,7 +91,10 @@ public class CompanyServiceImpl implements CompanyService { public UserWithCompanyEntity validateUserWithCompny(Long userId, Long companyId) { return companyDao.validateUserWithCompny(userId, companyId); } - + @Override + public UserWithCompanyEntity getUserWithCompany(Long userId, Long companyId) { + return companyDao.getUserWithCompany(userId, companyId); + } @Override @Transactional(readOnly = true) public ByteArrayOutputStream downloadCompanyDelegation(HttpServletRequest request, Long companyId, CompanyDelegationRequest companyDelegationRequest) { @@ -107,9 +111,8 @@ public class CompanyServiceImpl implements CompanyService { @Override @Transactional - public CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId) { - UserEntity userEntity =validator.validateUser(request); - return delegationDao.getCompanyDelegation(userEntity, companyId); + public CompanyDelegationResponse getCompanyDelegation(HttpServletRequest request, Long companyId,Long applicationId) { + return delegationDao.getCompanyDelegation(request, companyId,applicationId); } @Override @Transactional(rollbackFor = Exception.class) diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java index 505d0da1..d7a46aa6 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java @@ -1,14 +1,17 @@ package net.gepafin.tendermanagement.service.impl; import java.util.List; +import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.DocumentDao; import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentTypeEnum; import net.gepafin.tendermanagement.model.response.DocumentResponseBean; import net.gepafin.tendermanagement.service.DocumentService; +import net.gepafin.tendermanagement.util.Validator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -22,9 +25,13 @@ public class DocumentServiceImpl implements DocumentService { @Autowired private DocumentDao documentDao; + @Autowired + private Validator validator; @Override - public List uploadFile(List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { - return documentDao.uploadFiles(files,sourceId,sourceType,fileType); + public List uploadFile(HttpServletRequest request,List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { + Map userInfo = validator.getUserInfoFromToken(request); + Long userId = validator.getUserId(userInfo); + return documentDao.uploadFiles(userId,files,sourceId,sourceType,fileType); } @Override public void deleteFile(Long documentId) { diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/NotificationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/NotificationServiceImpl.java new file mode 100644 index 00000000..86eaa5cf --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/NotificationServiceImpl.java @@ -0,0 +1,62 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.dao.NotificationDao; +import net.gepafin.tendermanagement.enums.NotificationEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.response.NotificationResponse; +import net.gepafin.tendermanagement.service.NotificationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static org.hibernate.internal.util.collections.CollectionHelper.listOf; + +@Service +@Slf4j +public class NotificationServiceImpl implements NotificationService { + + @Autowired + private NotificationDao notificationDao; + + @Override + public NotificationResponse sendNotification(Long userId, NotificationReq notificationReq, Long companyId) { + + log.info("Sending notification to user {} with content: {}", userId, notificationReq.getMessage()); + notificationReq.setUserId(userId); + notificationReq.setCompanyIds(listOf(companyId)); + return notificationDao.sendNotification(notificationReq); + } + + @Override + public NotificationResponse getNotificationById(HttpServletRequest servletRequest, Long id) { + + return notificationDao.getNotificationById(id); + } + + @Override + public List getNotificationByUserId(HttpServletRequest servletRequest, Long userId, Long companyId, List statuses) { + + return notificationDao.getNotificationByUserId(userId, companyId, statuses); + } + + @Override + public NotificationResponse updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum status) { + + return notificationDao.updateNotificationStatus(id, status); + } + + @Override + public void deleteNotification(HttpServletRequest request, Long id) { + + notificationDao.deleteNotification(id); + return; + } + + @Override + public List getNotificationsByCompanyIdAndUserId(Long userId, Long companyId, List statuses) { + return notificationDao.getNotificationByCompanyIdAndUserId(userId, companyId, statuses); + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java index 4bc59150..dac565e7 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java @@ -7,12 +7,14 @@ import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.dao.DocumentDao; import net.gepafin.tendermanagement.dao.S3PathConfig; +import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.DocumentEntity; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.ApplicationSignedDocumentRepository; -import net.gepafin.tendermanagement.repositories.DocumentRepository; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.service.ApplicationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -50,13 +52,38 @@ public class S3ReUploadMigrationService { @Autowired private AmazonS3 amazonS3; + @Autowired + ApplicationService applicationService; + @Value("${aws.s3.url}") private String s3Url; + @Autowired + AmazonS3Service amazonS3Service; + + @Value("${aws.s3.bucket.name}") + private String bucketName; + + @Value("${aws.s3.region}") + private String region; + + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Autowired + private DocumentDao documentDao; + + private boolean migrationCompleted = false; public String reUploadAndMigrateDocuments(String providedKey) { + Long totalDocuments=0L; + Long failedDocuments=0L; + Long processDocuments=0L; if (migrationCompleted) { return "Migration already completed."; } @@ -66,26 +93,54 @@ public class S3ReUploadMigrationService { return "Invalid or missing migration key."; } - List documents = documentRepository.findAllByIsDeleteFalse(); + List documents = documentRepository.findAllByIsDeleteTrue(); + totalDocuments = Long.valueOf(documents.size()); if (documents.isEmpty()) { return "No documents found to migrate."; } for (DocumentEntity document : documents) { - String oldUrl = document.getFilePath(); // This should contain the full URL - log.info("Processing {}", oldUrl); - + log.info("Processing for the Document id and url:{} ",document.getId(),document.getFilePath()); try { - File localFile = downloadFileFromS3(oldUrl); - String newKey = generateNewS3Path(document); // Make sure this generates the correct new path - String uploadedPath = uploadFileToNewBucket(localFile, newKey); - updateDocumentPathAndNameEntry(document, uploadedPath); + + Long callId = null; + Long applicationId = null; + Long amendmentId = null; + Long evaluationId = null; + if (DocumentSourceTypeEnum.CALL.getValue().equalsIgnoreCase(document.getSource())) { + callId = document.getSourceId(); + } else if (DocumentSourceTypeEnum.APPLICATION.getValue().equalsIgnoreCase(document.getSource())) { + applicationId = document.getSourceId(); + ApplicationEntity applicationEntity = applicationService.validateApplication(applicationId); + callId = applicationEntity.getCall().getId(); + } + else if(DocumentSourceTypeEnum.AMENDMENT.getValue().equalsIgnoreCase(document.getSource())){ + amendmentId = document.getSourceId(); + ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + } else if(DocumentSourceTypeEnum.EVALUATION.getValue().equalsIgnoreCase(document.getSource())){ + evaluationId = document.getSourceId(); + ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); + applicationId = applicationEntity.getId(); + callId = applicationEntity.getCall().getId(); + } + + + documentDao.deleteFileFromS3(document,callId,applicationId,amendmentId); + processDocuments++; + } catch (Exception e) { log.error("Error processing document {}: {}", document.getId(), e.getMessage()); + failedDocuments++; } } + log.info("Total Documents Fetched ",totalDocuments); + log.info("Total Process Documents :{}",processDocuments); + log.info("Total Failed Documents :{}",failedDocuments); return "Migrated Successfully."; + } private boolean isValidKey(String providedKey) { @@ -164,10 +219,10 @@ public class S3ReUploadMigrationService { Long callId; if (sourceType.equals(DocumentSourceTypeEnum.CALL)) { - return s3ConfigBean.generateDocumentPath(sourceType, document.getSourceId(), 0L); + return s3ConfigBean.generateDocumentPath(sourceType, document.getSourceId(), 0L,0L); } else { callId = applicationRepository.findCallIdById(document.getSourceId()); - return s3ConfigBean.generateDocumentPath(sourceType, callId, document.getSourceId()); + return s3ConfigBean.generateDocumentPath(sourceType, callId, document.getSourceId(),0L); } } @@ -177,13 +232,4 @@ public class S3ReUploadMigrationService { return parts[parts.length - 1]; } - - private void updateDocumentPathAndNameEntry(DocumentEntity document, String newPath) { - - String fileName = extractFileName(newPath); - document.setFilePath(newPath); - document.setFileName(fileName); - documentRepository.save(document); - log.info("Migrated document ID: {} to new path: {}", document.getId(), newPath); - } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java index 744fbacb..b959ba61 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -126,8 +126,8 @@ public class UserServiceImpl implements UserService { } @Override @Transactional(readOnly = true) - public List getAllUsers(HttpServletRequest request, Long roleId) { + public List getAllUsers(HttpServletRequest request, List roleIds) { UserEntity user=validator.validateUser(request); - return userDao.getAllUsers(user, roleId); + return userDao.getAllUsers(user, roleIds); } } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java index dbd54afd..d5bd4c3c 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java @@ -6,6 +6,7 @@ import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.dao.DelegationDao; import net.gepafin.tendermanagement.dao.S3PathConfig; import net.gepafin.tendermanagement.entities.ApplicationSignedDocumentEntity; import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; @@ -56,10 +57,16 @@ public class UserSignedAndDelegationServiceImpl { @Value("${aws.s3.url}") private String s3Url; + @Autowired + private DelegationDao delegationDao; + private boolean migrationCompleted = false; public String migrateUserDelegatedDocuments(String providedKey) { + Long totalDocuments=0L; + Long failedDocuments=0L; + Long processDocuments=0L; if (migrationCompleted) { return "Migration already completed."; } @@ -69,25 +76,27 @@ public class UserSignedAndDelegationServiceImpl { return "Invalid or missing migration key."; } - List documents = userCompanyDelegationRepository.findAllByStatus("ACTIVE"); - + List documents = userCompanyDelegationRepository.findAllByStatus("INACTIVE"); + totalDocuments = Long.valueOf(documents.size()); if (documents.isEmpty()) { return "No documents found to migrate."; } for (UserCompanyDelegationEntity document : documents) { String oldUrl = document.getFilePath(); - log.info("Processing user designated document: {}", oldUrl); + log.info("Processing user designated document and old Url: {}", document.getId(),oldUrl); try { - File localFile = downloadFileFromS3(oldUrl); - String newKey = generateNewS3PathForDelegationDoc(); - String uploadedPath = uploadFileToNewBucket(localFile, newKey); - updateDelegatedDocumentPathAndNameEntry(document, uploadedPath); + delegationDao.deleteDelegationFromS3(document); + processDocuments++; } catch (Exception e) { log.error("Error processing user designated document {}: {}", document.getId(), e.getMessage()); + failedDocuments++; } } + log.info("Total Documents Fetched:{} ",totalDocuments); + log.info("Total Process Documents :{}",processDocuments); + log.info("Total Failed Documents :{}",failedDocuments); return "Migrated"; } @@ -130,7 +139,7 @@ public class UserSignedAndDelegationServiceImpl { private String generateNewS3PathForDelegationDoc() { - return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_DELEGATION, 0L, 0L); + return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_DELEGATION, 0L, 0L,0L); } private String generateNewS3PathForUserSignedDoc(ApplicationSignedDocumentEntity document) { diff --git a/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java b/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java index 53ed01cb..e2ab4521 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java @@ -9,7 +9,6 @@ import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.UserActionEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.entities.VersionHistoryEntity; -import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.repositories.UserActionsRepository; @@ -134,8 +133,12 @@ public class LoggingUtil { try { VersionHistoryEntity history = new VersionHistoryEntity(); String token = tokenProvider.extractTokenFromRequest(versionHistoryRequest.getRequest()); - Claims claims = tokenProvider.getClaimsFromToken(token); - Long userId = claims.get(GepafinConstant.USER_ID, Long.class); + if(versionHistoryRequest.getRequest() != null && token != null) + { + Claims claims = tokenProvider.getClaimsFromToken(token); + Long userId = claims.get(GepafinConstant.USER_ID, Long.class); + history.setUserId(userId); + } String oldData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getOldData()); String newData = Utils.convertEntityToJsonForLogging(versionHistoryRequest.getNewData()); history.setUserActionId(userActionId); @@ -144,7 +147,6 @@ public class LoggingUtil { history.setNewData(newData); history.setRecordId(recordId); history.setTableName(tableName); - history.setUserId(userId); versionHistoryRepository.save(history); } catch (Exception e) { log.error("Error logging version history: {}", e.getMessage(), e); diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index b3993900..fb15759f 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -28,7 +28,6 @@ import net.gepafin.tendermanagement.constants.GepafinConstant; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import com.fasterxml.jackson.core.JsonProcessingException; @@ -45,9 +44,12 @@ import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientForbiddenExce import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException; import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException; -import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; import javax.crypto.Cipher; +import javax.crypto.Mac; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; @@ -56,6 +58,9 @@ import static org.apache.commons.lang3.StringUtils.isEmpty; public class Utils { +// @Autowired +// private static TokenProvider tokenProvider; + public static final Logger log = LoggerFactory.getLogger(Utils.class); private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) @@ -571,4 +576,125 @@ public class Utils { return null; } } -} + + public static void setHttpServletRequestForScheduler() { + MockHttpServletRequest mockRequest = new MockHttpServletRequest(); + mockRequest.setRequestURI("/scheduled"); + mockRequest.setMethod("POST"); + ServletRequestAttributes attributes = new ServletRequestAttributes(mockRequest); + RequestContextHolder.setRequestAttributes(attributes); + } + + public static void clearHttpServletRequest() { + // Clear the RequestContextHolder after task execution + RequestContextHolder.resetRequestAttributes(); + } + + public static String generateAuthTokenForLoginToOdessa() { + + try { + // Your weak secret key + String secretKey = GepafinConstant.AUTH_JWT_SECRET_KEY; + + // Header + String header = GepafinConstant.JWT_ALGO_HEADER; + String encodedHeader = Base64.getUrlEncoder().withoutPadding().encodeToString(header.getBytes(StandardCharsets.UTF_8)); + + // Payload + String payload = "{\"iat\":" + (System.currentTimeMillis() / 1000) + "}"; + String encodedPayload = Base64.getUrlEncoder().withoutPadding().encodeToString(payload.getBytes(StandardCharsets.UTF_8)); + + // Combine header and payload + String dataToSign = encodedHeader + "." + encodedPayload; + + // Sign the token manually + Mac mac = Mac.getInstance(GepafinConstant.HMAC_ALGO); + SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), GepafinConstant.HMAC_ALGO); + mac.init(secretKeySpec); + byte[] signatureBytes = mac.doFinal(dataToSign.getBytes(StandardCharsets.UTF_8)); + String signature = Base64.getUrlEncoder().withoutPadding().encodeToString(signatureBytes); + + // Return the final JWT + return dataToSign + "." + signature; + } catch (Exception e) { + throw new RuntimeException("Failed to generate JWT token", e); + } + } + +// public static void setHttpServletRequestForNdgProcess(HttpServletRequest originalRequest) { +// +// // Validate original request +// if (originalRequest == null) { +// throw new IllegalArgumentException("Original request cannot be null."); +// } +// +// // Create a mock request +// Claims tokenClaims = tokenProvider.getClaimsFromToken(tokenProvider.extractTokenFromRequest(originalRequest)); +// MockHttpServletRequest mockRequest = new MockHttpServletRequest(); +// mockRequest.setRequestURI(originalRequest.getRequestURI()); +// mockRequest.setMethod(originalRequest.getMethod()); +// +// // Copy essential headers and attributes from the original request +// Enumeration headerNames = originalRequest.getHeaderNames(); +// while (headerNames.hasMoreElements()) { +// String headerName = headerNames.nextElement(); +// String headerValue = originalRequest.getHeader(headerName); +// if (headerValue != null) { +// mockRequest.addHeader(headerName, headerValue); +// } +// } +// +// // Set a specific attribute if required +// if (originalRequest.getAttribute(GepafinConstant.USER_ACTION_ID) != null) { +// mockRequest.setAttribute(GepafinConstant.USER_ACTION_ID, originalRequest.getAttribute(GepafinConstant.USER_ACTION_ID)); +// } +// +// ServletRequestAttributes attributes = new ServletRequestAttributes(mockRequest); +// RequestContextHolder.setRequestAttributes(attributes); +// // Log successful context setting +// log.info("Successfully set mock request for NDG process with URI: {}", mockRequest.getRequestURI()); +// } + + public static Long extractHubIdFromPayload(String payload) { + + Long hubId; + try { + String[] parts = payload.split(":"); + if (parts.length > 2) { + hubId = Long.valueOf(parts[2]); + return hubId; + } else { + hubId = null; + } + } catch (Exception e) { + throw new RuntimeException("No Hub id present in payload", e); + } + return null; + } + + // Method to convert a JSON string to an object of type T + public static T convertStringToObject(String jsonString, Class clazz) { + try { + return mapper.readValue(jsonString, clazz); + } catch (Exception e) { + e.printStackTrace(); + // Handle the exception appropriately (e.g., throw a custom exception) + return null; + } + } + + // Method to convert an object of type T to a JSON string + public static String convertObjectToString(T object) { + try { + return mapper.writeValueAsString(object); + } catch (Exception e) { + e.printStackTrace(); + // Handle the exception appropriately (e.g., throw a custom exception) + return null; + } + } + + public static String createChannelForUserAndCompany(Long userId, Long companyId) { + return GepafinConstant.COMMON_SINGLE_CHANNEL_PREFIX + userId + GepafinConstant.COMPANY_PREFIX + companyId; + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/util/Validator.java b/src/main/java/net/gepafin/tendermanagement/util/Validator.java index e0814305..4e3335a6 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Validator.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Validator.java @@ -90,6 +90,8 @@ public class Validator { validateHubId(request, companyEntity.getHub().getId()); if (checkIsSuperAdmin()) { return companyEntity; + } else if (checkIsInstructorManager()) { + return companyEntity; } Map userInfo = tokenProvider.getUserInfoAndUserIdFromToken(request); companyService.validateUserWithCompny(getUserId(userInfo), companyId); @@ -105,7 +107,7 @@ public class Validator { } } - private Long getUserId(Map userInfo) { + public Long getUserId(Map userInfo) { return Long.parseLong(userInfo.get("userId").toString()); } @@ -127,8 +129,11 @@ public class Validator { UserEntity requestedUser = userService.validateUser(userId); validateHubId(request, requestedUser.getHub().getId()); - if (Boolean.FALSE.equals(user.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_SUPER_ADMIN.getValue())) - && Boolean.FALSE.equals(user.getId().equals(userId))) { +// if (Boolean.FALSE.equals(user.getRoleEntity().getRoleType().equals(RoleStatusEnum.ROLE_SUPER_ADMIN.getValue())) +// && Boolean.FALSE.equals(user.getId().equals(userId))) + if (checkIsSuperAdmin() || checkIsInstructorManager()) { + + } else if(Boolean.FALSE.equals(user.getId().equals(userId))) { throw new ForbiddenAccessException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PERMISSION_DENIED)); } @@ -164,6 +169,11 @@ public class Validator { validateHubId(request, preInstructorUser.getHub().getId()); } return preInstructorUser; + } else if (checkIsInstructorManager()) { + if (preInstructorUserId != null) { + validateHubId(request, preInstructorUser.getHub().getId()); + } + return preInstructorUser; } else if (checkIsPreInstructor()) { return validateUserId(request, preInstructorUserId); } else { @@ -171,5 +181,18 @@ public class Validator { Translator.toLocale(GepafinConstant.PERMISSION_DENIED)); } } - + + public Boolean checkIsInstructorManager() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + if (authentication != null && authentication.isAuthenticated()) { + // Check if the user has the ROLE_INSTRUCTOR_MANAGER authority + for (GrantedAuthority authority : authentication.getAuthorities()) { + if (RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue().equals(authority.getAuthority())) { + return true; + } + } + } + return false; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java index bc17e345..9d168955 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationEvaluationApi.java @@ -7,8 +7,8 @@ import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; -import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.request.EvaluationDocumentRequest; import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; @@ -16,6 +16,8 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; + public interface ApplicationEvaluationApi { @Operation(summary = "API to create or update ApplicationEvaluation", diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/AppointmentApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/AppointmentApi.java new file mode 100644 index 00000000..5507492a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/AppointmentApi.java @@ -0,0 +1,59 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest; +import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest; +import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse; +import net.gepafin.tendermanagement.model.response.DocumentUploadResponse; +import net.gepafin.tendermanagement.model.response.NdgResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +public interface AppointmentApi { + + @Operation(summary = "API to check or create ndg.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/application/{applicationId}/check-ndg", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> checkNdgForAppointment(HttpServletRequest request, + @Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId); + + @Operation(summary = "API to create appointment.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "/application/{applicationId}", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> createAppointment(HttpServletRequest request, + @Parameter(description = "The application id", required = true) @PathVariable(value = "applicationId", required = true) Long applicationId, + @RequestBody CreateAppointmentRequest createAppointmentRequest); + + @Operation(summary = "API to Upload document to external system.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "/document/{documentId}", produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> uploadDocumentToExternalSystem(HttpServletRequest request, + @Parameter(description = "The document id", required = true) @PathVariable(value = "documentId", required = true) Long documentId, + @RequestBody UploadDocToExternalSystemRequest docToExternalSystemRequest); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/AssignedApplicationsApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/AssignedApplicationsApi.java index 1cfbb5c9..144a20f4 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/AssignedApplicationsApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/AssignedApplicationsApi.java @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; +import net.gepafin.tendermanagement.model.request.UpdateAssignedApplicationRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; @@ -32,7 +33,7 @@ public interface AssignedApplicationsApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "/application/{applicationId}") - @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')|| hasRole('ROLE_INSTRUCTOR_MANAGER')") public ResponseEntity> createAssignedApplications( HttpServletRequest request, @Parameter(description = "ID of the application", required = true) @PathVariable Long applicationId, @@ -50,7 +51,7 @@ public interface AssignedApplicationsApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @DeleteMapping(value = "/{id}") - @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')|| hasRole('ROLE_INSTRUCTOR_MANAGER')") ResponseEntity> deleteAssignedApplication(HttpServletRequest request, @Parameter(description = "The assigned application id", required = true) @PathVariable("id") Long id); @@ -78,10 +79,10 @@ public interface AssignedApplicationsApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) - @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')|| hasRole('ROLE_INSTRUCTOR_MANAGER')") public ResponseEntity> updateAssignedApplication(HttpServletRequest request, @Parameter(description = "The Assigned Application id", required = true) @PathVariable("id") Long id, - @Parameter(description = "Assigned Application request object", required = true) @Valid @RequestBody AssignedApplicationsRequest assignedApplicationsRequest); + @Parameter(description = "Assigned Application request object", required = true) @Valid @RequestBody UpdateAssignedApplicationRequest assignedApplicationsRequest); @Operation(summary = "Api to get an assigned application by id", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java index a648b08b..e50dae85 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CommunicationApi.java @@ -33,7 +33,7 @@ public interface CommunicationApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PostMapping(value = "/{amendmentId}", produces = { "application/json" }) - @PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY')") + @PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY') || hasRole('ROLE_INSTRUCTOR_MANAGER')") ResponseEntity> addCommentToAmendmentRequest(HttpServletRequest request, @RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId); @@ -55,7 +55,7 @@ public interface CommunicationApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{amendmentId}/{commentId}", produces = { "application/json" }) - @PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY')") + @PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY') || hasRole('ROLE_INSTRUCTOR_MANAGER')") ResponseEntity> updateCommunicationAmendment(HttpServletRequest request, @RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId, @PathVariable(value = "commentId") Long commentId); diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java index bc016334..6384f4d7 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CompanyApi.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.web.rest.api; import java.util.List; import java.util.Map; +import net.gepafin.tendermanagement.model.response.VatCheckResponseBean; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; @@ -94,8 +95,8 @@ public interface CompanyApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "/vatNumber", produces = { "application/json" }) - ResponseEntity>> checkVatNumber(HttpServletRequest request, - @Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber); + ResponseEntity> checkVatNumber(HttpServletRequest request, + @Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber); @Operation(summary = "Api to download company delegation template", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @@ -128,9 +129,10 @@ public interface CompanyApi { @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) - @GetMapping(value = "{companyId}/delegation", produces = { "application/json" }) + @GetMapping(value = "delegation", produces = { "application/json" }) ResponseEntity> getCompanyDelegation(HttpServletRequest request, - @Parameter(description = "The company id", required = true) @PathVariable("companyId") Long companyId); + @Parameter(description = "The company ID") @RequestParam(value = "companyId", required = false) Long companyId, + @Parameter(description = "The application ID") @RequestParam(value = "applicationId", required = false) Long applicationId); @Operation(summary = "Api to delete company delegation", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/NotificationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/NotificationApi.java new file mode 100644 index 00000000..ca059499 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/NotificationApi.java @@ -0,0 +1,101 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.NotificationEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.response.NotificationResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +public interface NotificationApi { + @Operation(summary = "Api to send notification.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.NOTFOUND_ERROR_EXAMPLE))), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE))), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value = + ErrorConstants.BADREQUEST_ERROR_EXAMPLE))) }) + @PostMapping(value = "/user/{userId}/sent", consumes = "application/json", produces = "application/json") + ResponseEntity> sendNotification(HttpServletRequest request, @RequestBody NotificationReq notificationReq, + @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId, + @Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId); + + @Operation(summary = "Api to get notification by id", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/{id}", produces = "application/json") + ResponseEntity> getNotificationById(HttpServletRequest request, + @Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id); + + @Operation(summary = "Api to get notification by user id", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/user/{userId}", produces = "application/json") + ResponseEntity>> getNotificationByUserId(HttpServletRequest request, + @Parameter(description = "The user id", required = true) @PathVariable(value = "userId", required = true) Long userId, + @Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId, + @Parameter(description = "The notification status", required = false) @RequestParam(value = "status", required = false) List statuses); + + @Operation(summary = "Api to update notification status", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "/{id}", produces = "application/json") + ResponseEntity> updateNotificationStatus(HttpServletRequest request, + @Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id, + @Parameter(description = "The notification status", required = true) @RequestParam(value = "status", required = true) NotificationEnum status); + + @Operation(summary = "Api to delete notification", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @DeleteMapping(value = "/{id}", produces = "application/json") + ResponseEntity> deleteNotification(HttpServletRequest request, + @Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id); + + @Operation(summary = "API to get notifications by user ID and company ID", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/user/{userId}/company/{companyId}/notifications", produces = "application/json") + ResponseEntity>> getNotificationsByUserIdAndCompanyId(HttpServletRequest request, + @Parameter(description = "The user id", required = true) @PathVariable(value = "userId") Long userId, + @Parameter(description = "The company ID", required = true) @PathVariable(value = "companyId") Long companyId, + @Parameter(description = "The notification status", required = false) @RequestParam(value = "status", required = false) List statuses); + +} + + diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java index 4a4d3eb1..75039427 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java @@ -5,9 +5,10 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import jakarta.validation.Valid; + +import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; -import org.springframework.data.repository.query.Param; + import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PathVariable; @@ -16,7 +17,7 @@ import org.springframework.web.bind.annotation.PutMapping; @Validated public interface S3MigrationApi { - @Operation(summary = "Api to migrate S3 doc to db and update s3 files as per specified folder.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @Operation(summary = "Api to migrate deleted documents to the deleted Folder ", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @@ -24,5 +25,5 @@ public interface S3MigrationApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @PutMapping(value = "/{key}", produces = { "application/json" }) - String reUploadAndMigrateDocuments(@Parameter(description = "The secret key", required = true) @PathVariable("key") String key); + String reUploadAndMigrateDocuments(HttpServletRequest request, @Parameter(description = "The secret key", required = true) @PathVariable("key") String key); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java index 8bf9b780..6dc45bec 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java @@ -59,6 +59,7 @@ public interface UserApi { @RequestMapping(value = "/{userId}", produces = {"application/json"}, method = RequestMethod.PUT) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") default ResponseEntity> updateUser(HttpServletRequest request, @Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId, @Parameter(description = "User request object", required = true) @Valid @RequestBody UpdateUserReq userReq) { @@ -234,9 +235,9 @@ public interface UserApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))}) @RequestMapping(value = "", produces = {"application/json"}, method = RequestMethod.GET) - @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')|| hasRole('ROLE_INSTRUCTOR_MANAGER')") ResponseEntity>> getAllUsers(HttpServletRequest request, - @Parameter( required = false)@RequestParam(value ="roleId", required = false) Long roleId); + @Parameter( required = false)@RequestParam(value ="roleIds", required = false) List roleIds); @RequestMapping("favicon.ico") diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java index 2a3978a1..2cee9b76 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java @@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; import org.springframework.data.repository.query.Param; @@ -16,7 +17,7 @@ import org.springframework.web.bind.annotation.PostMapping; @Validated public interface UserSignedAndDelegationApi { - @Operation(summary = "Api to migrate S3 doc to db and user-delegated folder", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @Operation(summary = "Api to migrate S3 user-delegated deleted doc to deleted folder", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @@ -24,7 +25,7 @@ public interface UserSignedAndDelegationApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "/{key}", produces = { "application/json" }) - String migrateUserDelegatedDocuments(@Parameter(description = "The secret key", required = true) @PathVariable("key") String key); + String migrateUserDelegatedDocuments(HttpServletRequest request, @Parameter(description = "The secret key", required = true) @PathVariable("key") String key); @Operation(summary = "Api to migrate S3 doc to user-signed.", responses = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java index be177bf9..b299ecc2 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationEvaluationApiController.java @@ -3,12 +3,13 @@ package net.gepafin.tendermanagement.web.rest.api.impl; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; -import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; import net.gepafin.tendermanagement.enums.UserActionContextEnum; import net.gepafin.tendermanagement.enums.UserActionLogsEnum; import net.gepafin.tendermanagement.model.request.ApplicationEvaluationRequest; +import net.gepafin.tendermanagement.model.request.EvaluationDocumentRequest; import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.model.response.ApplicationEvaluationResponse; +import net.gepafin.tendermanagement.model.response.EvaluationDocumentResponse; import net.gepafin.tendermanagement.model.util.Response; import net.gepafin.tendermanagement.service.ApplicationEvaluationService; import net.gepafin.tendermanagement.util.LoggingUtil; @@ -20,6 +21,8 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController @RequestMapping("${openapi.gepafin.base-path:/v1/applicationEvaluation}") public class ApplicationEvaluationApiController implements ApplicationEvaluationApi { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AppointmentController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AppointmentController.java new file mode 100644 index 00000000..9264aa3a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AppointmentController.java @@ -0,0 +1,81 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.enums.UserActionContextEnum; +import net.gepafin.tendermanagement.enums.UserActionLogsEnum; +import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest; +import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest; +import net.gepafin.tendermanagement.model.request.UserActionRequest; +import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse; +import net.gepafin.tendermanagement.model.response.DocumentUploadResponse; +import net.gepafin.tendermanagement.model.response.NdgResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.AppointmentService; +import net.gepafin.tendermanagement.util.LoggingUtil; +import net.gepafin.tendermanagement.web.rest.api.AppointmentApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/appointment}") +@Slf4j +public class AppointmentController implements AppointmentApi { + + @Autowired + private AppointmentService appointmentService; + + @Autowired + private LoggingUtil loggingUtil; + + @Override + public ResponseEntity> checkNdgForAppointment(HttpServletRequest request, Long applicationId) { + + /** This code is responsible for creating user action logs for the "checking or creating ndg" operation. **/ + loggingUtil.logUserAction( + UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.CHECK_OR_CREATE_NDG_CODE).build()); + + NdgResponse appointmentLoginResponse = appointmentService.checkNdgForAppointment(request, applicationId); + + return ResponseEntity.status(HttpStatus.OK).body(new Response<>(appointmentLoginResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NDG_FETCH_SUCCESSFULLY))); + } + + @Override + public ResponseEntity> createAppointment(HttpServletRequest request, Long applicationId, + CreateAppointmentRequest createAppointmentRequest) { + + /** This code is responsible for creating user action logs for the "create appointment" operation. **/ + loggingUtil.logUserAction( + UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.CREATE_APPOINTMENT).build()); + + AppointmentCreationResponse appointmentCreationResponse = appointmentService.createAppointmentForApplication(request, applicationId, createAppointmentRequest); + + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(appointmentCreationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPOINTMENT_CREATED))); + } + + @Override + public ResponseEntity> uploadDocumentToExternalSystem(HttpServletRequest request, Long documentId, + UploadDocToExternalSystemRequest docToExternalSystemRequest) { + + /** This code is responsible for creating user action logs for the "Upload document to external system" operation. **/ + loggingUtil.logUserAction( + UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPLOAD).actionContext(UserActionContextEnum.UPLOAD_DOCUMENT_TO_EXTERNAL_SYSTEM).build()); + + DocumentUploadResponse documentUploadResponse = appointmentService.uploadDocToExternalSystem(request, documentId, docToExternalSystemRequest); + + String message = GepafinConstant.DOCUMENT_UPLOADED_SUCCESSFULLY_TO_EXTERNAL_SYSTEM; + if(documentUploadResponse == null) { + message = GepafinConstant.DOCUMENT_UPLOADING_IN_PROGRESS; + } + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(documentUploadResponse, Status.SUCCESS, Translator.toLocale(message))); + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AssignedApplicationsController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AssignedApplicationsController.java index 7f22337a..78cc47dd 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AssignedApplicationsController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/AssignedApplicationsController.java @@ -7,6 +7,7 @@ import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.enums.UserActionContextEnum; import net.gepafin.tendermanagement.enums.UserActionLogsEnum; import net.gepafin.tendermanagement.model.request.AssignedApplicationsRequest; +import net.gepafin.tendermanagement.model.request.UpdateAssignedApplicationRequest; import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.model.response.AssignedApplicationsResponse; import net.gepafin.tendermanagement.model.util.Response; @@ -66,7 +67,7 @@ public class AssignedApplicationsController implements AssignedApplicationsApi { } @Override - public ResponseEntity> updateAssignedApplication(HttpServletRequest request, Long id, AssignedApplicationsRequest updateAssignedApplicationRequest) { + public ResponseEntity> updateAssignedApplication(HttpServletRequest request, Long id, UpdateAssignedApplicationRequest updateAssignedApplicationRequest) { log.info("Update Assigned Application"); /** This code is responsible for "Updating Assigned Applications details" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java index ef73e985..0bfb0e7a 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CompanyApiController.java @@ -7,7 +7,9 @@ import java.util.Map; import net.gepafin.tendermanagement.enums.UserActionContextEnum; import net.gepafin.tendermanagement.enums.UserActionLogsEnum; import net.gepafin.tendermanagement.model.request.UserActionRequest; +import net.gepafin.tendermanagement.model.response.VatCheckResponseBean; import net.gepafin.tendermanagement.util.LoggingUtil; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -111,15 +113,15 @@ public class CompanyApiController implements CompanyApi{ } @Override - public ResponseEntity>> checkVatNumber(HttpServletRequest request, String vatNumber) { + public ResponseEntity> checkVatNumber(HttpServletRequest request, String vatNumber) { log.info("check VatNumber with: {}", vatNumber); /** This code is responsible for creating user action logs for the "Check vat number" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.CHECK_COMPANY_VAT_NUMBER).build()); - Map data = companyService.checkVatNumber(request, vatNumber); + VatCheckResponseBean vatCheckResponseBean = companyService.checkVatNumber(request, vatNumber); return ResponseEntity.status(HttpStatus.OK) - .body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG))); + .body(new Response<>(vatCheckResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG))); } @Override @@ -152,13 +154,13 @@ public class CompanyApiController implements CompanyApi{ @Override public ResponseEntity> getCompanyDelegation(HttpServletRequest request, - Long companyId) { + Long companyId,Long applicationId) { log.info("get company delegation with companyId: {}", companyId); /** This code is responsible for creating user action logs for the "Get company delegation" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_COMPANY_DELEGATION).build()); - - CompanyDelegationResponse companyDelegationResponse = companyService.getCompanyDelegation(request, companyId); + + CompanyDelegationResponse companyDelegationResponse = companyService.getCompanyDelegation(request, companyId,applicationId); return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(companyDelegationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.DELEGATION_FETCH_SUCCESS))); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java index 9d42ab53..123a4620 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java @@ -47,7 +47,7 @@ DocumentApiController implements DocumentApi { /** This code is responsible for creating user action logs for the "upload document for call or application" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.UPLOAD).actionContext(userActionContext).build()); - List responseBeans = documentService.uploadFile(files, sourceId, sourceType, fileType); + List responseBeans = documentService.uploadFile(httpServletRequest,files, sourceId, sourceType, fileType); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response>(responseBeans, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILES_UPLOADED_MSG))); } catch (CustomValidationException ex) { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/NotificationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/NotificationApiController.java new file mode 100644 index 00000000..d2047d7a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/NotificationApiController.java @@ -0,0 +1,74 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.enums.NotificationEnum; +import net.gepafin.tendermanagement.model.request.NotificationReq; +import net.gepafin.tendermanagement.model.response.NotificationResponse; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.NotificationService; +import net.gepafin.tendermanagement.web.rest.api.NotificationApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/notification}") +public class NotificationApiController implements NotificationApi { + + @Autowired + private NotificationService notificationService; + + public ResponseEntity> sendNotification(HttpServletRequest request, NotificationReq notificationReq, Long userId, Long companyId) { + + NotificationResponse notificationData = notificationService.sendNotification(userId, notificationReq, companyId); + + return ResponseEntity.status(HttpStatus.OK).body(new Response<>(notificationData, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_SENT_SUCCESSFULLY))); + } + + @Override + public ResponseEntity> getNotificationById(HttpServletRequest request, Long id) { + + NotificationResponse notificationResponse = notificationService.getNotificationById(request, id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(notificationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY))); + } + + @Override + public ResponseEntity>> getNotificationByUserId(HttpServletRequest request, Long userId, Long companyId, List statuses) { + + List notificationResponses = notificationService.getNotificationByUserId(request, userId, companyId, statuses); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response>(notificationResponses, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY))); + + } + + @Override + public ResponseEntity> updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum notificationEnums) { + + NotificationResponse notificationResponse = notificationService.updateNotificationStatus(request, id, notificationEnums); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(notificationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_UPDATED_SUCCESSFULLY))); + } + + @Override + public ResponseEntity> deleteNotification(HttpServletRequest request, Long id) { + + notificationService.deleteNotification(request, id); + return ResponseEntity.status(HttpStatus.OK).body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_DELETED_SUCCESSFULLY))); + } + + @Override + public ResponseEntity>> getNotificationsByUserIdAndCompanyId(HttpServletRequest request,Long userId, Long companyId, List statuses) { + List notificationResponses = notificationService.getNotificationsByCompanyIdAndUserId(userId, companyId, statuses); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response<>(notificationResponses, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY))); + } + +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java index 7e58800e..c2b5affb 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java @@ -1,6 +1,11 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.UserActionContextEnum; +import net.gepafin.tendermanagement.enums.UserActionLogsEnum; +import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.service.impl.S3ReUploadMigrationService; +import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.web.rest.api.S3MigrationApi; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -12,8 +17,16 @@ public class S3MigrationApiController implements S3MigrationApi { @Autowired S3ReUploadMigrationService s3MigrationService; + + @Autowired + LoggingUtil loggingUtil; + @Override - public String reUploadAndMigrateDocuments(String providedKey) { + public String reUploadAndMigrateDocuments(HttpServletRequest request,String providedKey) { + + /** This code is responsible for creating user action logs for the "upload document for call or application" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.SCRIPT).actionContext(UserActionContextEnum.GET_DOCUMENT).build()); + return s3MigrationService.reUploadAndMigrateDocuments(providedKey); } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java index 061b731b..e18159c6 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java @@ -1,6 +1,11 @@ package net.gepafin.tendermanagement.web.rest.api.impl; +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.UserActionContextEnum; +import net.gepafin.tendermanagement.enums.UserActionLogsEnum; +import net.gepafin.tendermanagement.model.request.UserActionRequest; import net.gepafin.tendermanagement.service.impl.UserSignedAndDelegationServiceImpl; +import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.web.rest.api.UserSignedAndDelegationApi; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -13,8 +18,15 @@ public class S3UserSignedAndDelegationMigrationController implements UserSignedA @Autowired UserSignedAndDelegationServiceImpl userSignedAndDelegationService; + @Autowired + LoggingUtil loggingUtil; + @Override - public String migrateUserDelegatedDocuments(String providedKey) { + public String migrateUserDelegatedDocuments(HttpServletRequest request,String providedKey) { + + /** This code is responsible for creating user action logs for the "upload document for call or application" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.SCRIPT).actionContext(UserActionContextEnum.GET_DOCUMENT).build()); + return userSignedAndDelegationService.migrateUserDelegatedDocuments(providedKey); } @Override diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java index 9f02a8f6..0d649943 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java @@ -231,14 +231,14 @@ public class UserApiController implements UserApi { } @Override - public ResponseEntity>> getAllUsers(HttpServletRequest request, Long roleId) { + public ResponseEntity>> getAllUsers(HttpServletRequest request, List roleIds) { - log.info("Get all Users by Role ID - Role ID: {}", roleId); + log.info("Get all Users by Role ID - Role ID: {}", roleIds); /** This code is responsible for creating user action logs for the "Get all users by role" operation. **/ loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_ALL_USERS_BY_ROLE).build()); - List users = userService.getAllUsers(request, roleId); + List users = userService.getAllUsers(request, roleIds); return ResponseEntity.status(HttpStatus.OK).body(new Response<>(users, Status.SUCCESS, Translator.toLocale(GepafinConstant.GET_USERS_SUCCESS_MSG))); } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 8fa5c7a6..87a38095 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -15,3 +15,19 @@ gepafin_email=rinaldo.bonazzo@bflows.net rinaldo_email=rinaldo.bonazzo@bflows.net carlo_email=test@test.test default.hub.uuid=p4lk3bcx1RStqTaIVVbXs + +#Login to Odessa, Appointment Creation, Upload document Configuration +appointment.base.url=https://demo.galileonetwork.it/gateway/rest +appointment.portal.user=UtenzaAPIPortal@621 +appointment.portal.password=u13nzaAP1P0rtal +appointment.portal.source=GEPAFINPORTAL +appointment.portal.context=GEPAFINPORTAL +flagDaFirmare=false + +# RabbitMQ properties for STOMP broker relay for Notification +#spring.rabbitmq.host=rabbitmq.bflows.ai +spring.rabbitmq.host=172.18.0.7 +spring.rabbitmq.port=61613 +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ \ No newline at end of file diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 76aca344..e52a9577 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -13,4 +13,18 @@ default_System_Receiver_Email=test@test.test gepafin_email=test@test.test rinaldo_email=test@test.test carlo_email=test@test.test -default.hub.uuid=p4lk3bcx1RStqTaIVVbXs \ No newline at end of file +default.hub.uuid=p4lk3bcx1RStqTaIVVbXs + +appointment.base.url=https://demo.galileonetwork.it/gateway/rest +appointment.portal.user=UtenzaAPIPortal@621 +appointment.portal.password=u13nzaAP1P0rtal +appointment.portal.source=GEPAFINPORTAL +appointment.portal.context=GEPAFINPORTAL +flagDaFirmare=false + +# RabbitMQ properties for STOMP broker relay for Notification +spring.rabbitmq.host=localhost +spring.rabbitmq.port=61613 +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ \ No newline at end of file diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index b3704a3d..df295088 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -22,3 +22,18 @@ rinaldo_email=rinaldo.bonazzo@bflows.net carlo_email=carlo.mancosu@bflows.net default.hub.uuid=p4lk3bcx1RStqTaIVVbXs # TEST DEPLOY Configuration + +#Login to Odessa, Appointment Creation, Upload document Configuration +appointment.base.url=https://demo.galileonetwork.it/gateway/rest +appointment.portal.user=UtenzaAPIPortal@621 +appointment.portal.password=u13nzaAP1P0rtal +appointment.portal.source=GEPAFINPORTAL +appointment.portal.context=GEPAFINPORTAL +flagDaFirmare=true + +# RabbitMQ properties for STOMP broker relay for Notification +spring.rabbitmq.host=rabbitmq.bflows.ai +spring.rabbitmq.port=61613 +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ \ No newline at end of file diff --git a/src/main/resources/application-testing.properties b/src/main/resources/application-testing.properties index 1dbc41cc..8ee53329 100644 --- a/src/main/resources/application-testing.properties +++ b/src/main/resources/application-testing.properties @@ -11,4 +11,18 @@ default_System_Receiver_Email=test@test.test gepafin_email=test@test.test rinaldo_email=test@test.test carlo_email=test@test.test -default.hub.uuid=p4lk3bcx1RStqTaIVVbXs \ No newline at end of file +default.hub.uuid=p4lk3bcx1RStqTaIVVbXs + +appointment.base.url=https://demo.galileonetwork.it/gateway/rest +appointment.portal.user=UtenzaAPIPortal@621 +appointment.portal.password=u13nzaAP1P0rtal +appointment.portal.source=GEPAFINPORTAL +appointment.portal.context=GEPAFINPORTAL +flagDaFirmare=false + +# RabbitMQ properties for STOMP broker relay for Notification +spring.rabbitmq.host=rabbitmq.bflows.ai +spring.rabbitmq.port=61613 +spring.rabbitmq.username=guest +spring.rabbitmq.password=guest +spring.rabbitmq.virtual-host=/ \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 19988cf3..d0af99d3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.application.name=tendermanagement spring.servlet.multipart.max-file-size=300MB spring.servlet.multipart.max-request-size=300MB -spring.profiles.active=testing +spring.profiles.active=testing # JPA Configuration @@ -37,8 +37,8 @@ aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ #aws.s3.url.folder.signed.document=gepafin/signed-document # JWT configuration # Ensure these values match your expectations -security.authentication.jwt.secret=my-secret-token-to-change-in-prod-environment-your-super-secure-randomly-generated-key -security.authentication.jwt.token-validity-in-seconds=86400 +security.authentication.jwt.secret=Z3/zjSD96Hdvh/AMyaMLJLWSVF00AOmxxEk4Kv8E+bM3bUW/QXOu45OSgRD6H16RvQ/pWZznDQP3l2ZkPlu9Sg== +security.authentication.jwt.token-validity-in-seconds=7200 # Default system base URLs base-url=https://api-dev-gepafin.memento.credit @@ -65,3 +65,7 @@ default.email.signature=Gepafin S.p.a default.hub.pdf.banner=https://mementoresources.s3.amazonaws.com/gepafin/staging/template/gepafin-logo.jpg +#feign client config +spring.cloud.openfeign.client.config.default.connectTimeout=300000 +spring.cloud.openfeign.client.config.default.readTimeout=300000 +spring.rabbitmq.connection-timeout=120000 \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index cc2ee820..d5ca1304 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -1787,6 +1787,22 @@ + + + + + + + + + + + + + + + + @@ -1858,6 +1874,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1886,4 +1972,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/dump/insert_json_template_for_notification_13_12_2024.sql b/src/main/resources/db/dump/insert_json_template_for_notification_13_12_2024.sql new file mode 100644 index 00000000..9856d855 --- /dev/null +++ b/src/main/resources/db/dump/insert_json_template_for_notification_13_12_2024.sql @@ -0,0 +1,10 @@ +INSERT INTO notification_type (notification_name,title, json_template,created_date,updated_date,is_deleted) VALUES +('CALL_CREATED', 'Un Nuovo Bando È Stato Pubblicato','Un nuovo bando intitolato {{call_name}} è stato pubblicato. Controllalo e invia le candidature prima della scadenza.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('APPLICATION_SUBMISSION','Candidatura Inviata con Successo per la Valutazione', 'La richiesta per {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stata presentata con successo. È ora in fase di valutazione.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('AMENDMENT_CREATION','È Stato Creato un Emendamento per la Richiesta', 'È stato creato un emendamento per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}}. Esamina le modifiche e procedi di conseguenza.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('EVALUATION_RESULT','Il Risultato della Valutazione per la Richiesta È Disponibile','Il risultato della valutazione per la richiesta ai sensi del protocollo n. {{protocol_number}} è ora disponibile.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('AMENDMENT_EXPIRED','L Emendamento per la Richiesta È Scaduto', 'L’emendamento per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è scaduto.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('AMENDMENT_CLOSED','L Emendamento È Stato Chiuso ed È Ora Inattivo','L’emendamento per {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stato chiuso ed è ora inattivo.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('NDG_GENERATION','È Stato Generato un Nuovo NDG per la Richiesta','È stato generato un nuovo NDG per {{call_name}} ai sensi del protocollo n. {{protocol_number}}.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('EVALUATION_CREATION','La Richiesta È Stata Assegnata per la Valutazione','La richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stata assegnata alla fase di valutazione.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'), +('EVALUATION_EXPIRED','La Valutazione per la Richiesta È Scaduta','La valutazione per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è scaduta.','2024-12-19T10:16:26.472Z','2024-12-19T10:16:26.472Z','false'); \ No newline at end of file diff --git a/src/main/resources/db/dump/update_json_template_for_notification_31_12_2024.sql b/src/main/resources/db/dump/update_json_template_for_notification_31_12_2024.sql new file mode 100644 index 00000000..57a01984 --- /dev/null +++ b/src/main/resources/db/dump/update_json_template_for_notification_31_12_2024.sql @@ -0,0 +1,62 @@ +UPDATE notification_type +SET + title = 'Un Nuovo Bando È Stato Pubblicato', + json_template = 'Un nuovo bando intitolato {{call_name}} è stato pubblicato. Controllalo e invia le candidature prima della scadenza.' +WHERE + notification_name = 'CALL_CREATED'; + +UPDATE notification_type +SET + title = 'Richiesta Finanziamento Inviata con Successo per la Valutazione', + json_template = 'La richiesta per {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stata presentata con successo. È ora in fase di valutazione.' +WHERE + notification_name = 'APPLICATION_SUBMISSION'; + +UPDATE notification_type +SET + title = 'È Stato Creato un Soccorso Istruttorio per la Richiesta', + json_template = 'È stato creato un soccorso istruttorio per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}}. Esamina le richieste e procedi di conseguenza.' +WHERE + notification_name = 'AMENDMENT_CREATION'; + +UPDATE notification_type +SET + title = 'Il Risultato della Valutazione per la Richiesta È Disponibile', + json_template = 'Il risultato della valutazione per la richiesta ai sensi del protocollo n. {{protocol_number}} è ora disponibile.' +WHERE + notification_name = 'EVALUATION_RESULT'; + +UPDATE notification_type +SET + title = 'Soccorso Scaduto', + json_template = 'Il soccorso istruttorio per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è scaduto.' +WHERE + notification_name = 'AMENDMENT_EXPIRED'; + +UPDATE notification_type +SET + title = 'Scorso Chiuso ed È Ora Inattivo', + json_template = 'Il soccorso istruttorio per {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stato chiuso ed è ora inattivo.' +WHERE + notification_name = 'AMENDMENT_CLOSED'; + +UPDATE notification_type +SET + title = 'NDG creato per la Richiesta', + json_template = 'È stato generato un nuovo NDG per {{call_name}} ai sensi del protocollo n. {{protocol_number}}.' +WHERE + notification_name = 'NDG_GENERATION'; + +UPDATE notification_type +SET + title = 'La domanda è stata assegnata per la Valutazione', + json_template = 'La richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è stata assegnata alla fase di valutazione.' +WHERE + notification_name = 'EVALUATION_CREATION'; + +UPDATE notification_type +SET + title = 'La Valutazione per la Richiesta È Scaduta', + json_template = 'La valutazione per la richiesta in {{call_name}} ai sensi del protocollo n. {{protocol_number}} è scaduta.' +WHERE + notification_name = 'EVALUATION_EXPIRED'; diff --git a/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_03_12_2024_1.sql b/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_03_12_2024_1.sql new file mode 100644 index 00000000..3e4e8e30 --- /dev/null +++ b/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_03_12_2024_1.sql @@ -0,0 +1,26 @@ +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
    +

    RICHIESTA INTEGRAZIONE DOCUMENTALE

    +

    Buongiorno,

    +

    In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui al Protocollo n. {{protocol_number}} del + {{protocol_date}} e {{protocol_time}}, alla luce dell''attività istruttoria svolta, + segnaliamo quanto segue:

    +
      +
    • {{form_dataInput}}
    • +
    +

    {{note}}

    +

    Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all''interno dello sportello + online {{platform_link}} che inviandola a mezzo PEC all''indirizzo + {{legal_mail}} entro e non oltre 10 giorni dal ricevimento della presente comunicazione, + precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.

    +

    Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito + dell''invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.

    +

    Distinti Saluti,

    +

    {{email_signature}}

    +
    + + ' +WHERE "type" = 'DOCUMENTATION_INTEGRATION_REQUEST' AND "system" = true; \ No newline at end of file diff --git a/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_04_12_2024_1.sql b/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_04_12_2024_1.sql new file mode 100644 index 00000000..564d855d --- /dev/null +++ b/src/main/resources/db/dump/update_system_email_template_for_updating_amendment_mail_notification_mail_04_12_2024_1.sql @@ -0,0 +1,26 @@ +UPDATE gepafin_schema.system_email_template +SET html_content = ' + +
    +

    RICHIESTA INTEGRAZIONE DOCUMENTALE

    +

    Buongiorno,

    +

    In riferimento alla domanda di concessione di Finanziamento agevolato a valere sul Fondo prestiti + {{call_name}} di cui al Protocollo n. {{protocol_number}} del + {{protocol_date}} e {{protocol_time}}, alla luce dell''attività istruttoria svolta, + segnaliamo quanto segue:

    +
      +
    • {{form_dataInput}}
    • +
    +

    {{note}}

    +

    Vi invitiamo a fornire quanto sopra richiesto integrando la documentazione sia caricandola all''interno dello sportello + online {{platform_link}} che inviandola a mezzo PEC all''indirizzo + bandi.gepafin@legalmail.it entro e non oltre {{response_days}} giorni dal ricevimento della presente comunicazione, + precisando che, in caso di mancata ricezione nei termini indicati, saremo costretti a non prendere in considerazione la Vostra richiesta di finanziamento.

    +

    Vi informiamo che per la ricezione della PEC farà fede la ricevuta di avvenuta consegna che attesterà il buon esito + dell''invio. La documentazione trasmessa e le informazioni fornite saranno processate dall''istruttore assegnatario della pratica.

    +

    Distinti Saluti,

    +

    {{email_signature}}

    +
    + + ' +WHERE "type" = 'DOCUMENTATION_INTEGRATION_REQUEST' AND "system" = true; \ No newline at end of file diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 5c8345ed..44a27275 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -310,3 +310,39 @@ application.documents.not.found=No documents found for the application. beneficiary.call.duplicate = A preferred call with this call ID and company ID already exists for this user. user.must.be.associated.with.company.to.create.application=You must be associated with a company to apply for this application. company.id.required.for.preferred.call=Company ID is required when requesting only preferred calls. + +response.days.not.null=Response days should not be null and greater than zero. +application.cannot.approved.or.rejected=Application cannot be approved and rejected because amendment is active. +valid.vatnumber.message=The VAT number is valid. + +atleast.one.id.required=At least one of companyId or applicationId must be provided + +#Appointment flow messages +ndg.generated = NDG Generated. +ndg.available = NDG Available. +ndg.generation.in.progress = NDG generation is in progress. +ndg.fetch.successfully = NDG fetched successfully. +appointment.already.created = Appointment Already Created. +ndg.not.found.for.this.application.or.invalid = Ndg not found for this application or invalid. +provide.valid.application.document.id = Provide valid application document id. +document.uploaded.successfully.to.external.system = Document uploaded successfully to external system. +error.in.uploading.document.check.input = Error in uploading document check input data or try again. +document.already.uploaded = Document already uploaded. +document.not.uploaded.to.external.system.please.try.again = Document not uploaded to external system, please try again. +ndg.not.found.or.not.matched = The provided NDG does not match the application NDG, or the NDG has not been generated. +ndg.generation.is.only.for.gepafin = NDG generation is only available for GEPAFIN Hub. +appointment.creation.is.only.for.gepafin = Appointment creation is only allowed for GEPAFIN Hub. +upload.document.is.only.for.gepafin = Document cant be uploaded, this is only available for GEPAFIN Hub. +appointment.created.successfully = Appointment created successfully. +error.try.again = Service call error while performing the operation. Please try again. +document.uploading.is.in.progress = Document uploading is in progress. +all.document.checked.and.one.checklist.checked=All document should be checked and at least one checklist should be checked. + +#notification messsages +notification.already.in.state=Notification is already in provided status. +notification.fetched.successfully=Notification fetched successfully. +notification.not.found=Notification not found. +notification.sent.successfully=Notification sent successfully. +notification.deleted.successfully=Notification deleted successfully. +notification.updated.successfully=Notification updated successfully. +user.with.company.not.found = User with company not found for user or company. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 1aaaf17d..0b22e9e3 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -2,14 +2,14 @@ user.created.success=Utente creato con successo. user.updated.success=Utente aggiornato con successo. user.deleted.success=Utente eliminato con successo. user.not.found=Utente non trovato. -create_user_error_msg=Si � verificato un errore durante la creazione dell'utente. -update_user_error_msg=Si � verificato un errore durante l'aggiornamento dell'utente. -delete_user_error_msg=Si � verificato un errore durante l'eliminazione dell'utente. +create_user_error_msg=Si ? verificato un errore durante la creazione dell'utente. +update_user_error_msg=Si ? verificato un errore durante l'aggiornamento dell'utente. +delete_user_error_msg=Si ? verificato un errore durante l'eliminazione dell'utente. get_user_success_msg=Utente recuperato con successo. -get_user_error_msg=Si � verificato un errore durante il recupero dell'utente. +get_user_error_msg=Si ? verificato un errore durante il recupero dell'utente. user.not.active=Utente non attivo. Si prega di contattare il supporto. -user.already.exist.msg=L'utente esiste gi� per questo codice fiscale. -validate.email=L'email � obbligatoria e deve essere nel formato corretto. Si prega di verificare e riprovare. +user.already.exist.msg=L'utente esiste gi? per questo codice fiscale. +validate.email=L'email ? obbligatoria e deve essere nel formato corretto. Si prega di verificare e riprovare. validate.password=La password e confPassword sono obbligatorie. Verifica e riprova. # Role-related messages role.created.success=Ruolo creato con successo. @@ -20,7 +20,7 @@ create.role.error=Errore durante la creazione del ruolo. update.role.error=Errore durante l'aggiornamento del ruolo. role.fetch.success=Ruolo recuperato con successo. delete.role.error=Errore durante l'eliminazione del ruolo. -role.id.mandatory=L'ID del ruolo � obbligatorio. +role.id.mandatory=L'ID del ruolo ? obbligatorio. # Region-related messages region.created.success=Regione creata con successo. @@ -35,42 +35,42 @@ password.doesnt.match=La password e la conferma della password non corrispondono #call related messages user.not.exist=L'utente non esiste. region.not.found=Regione non trovata. -user.id.not.null=L'ID utente non pu� essere nullo. -question.not.empty=La domanda non pu� essere vuota. -name.not.empty=Il nome non pu� essere vuoto. -type.not.empty=Il tipo non pu� essere vuoto. -region.not.null=L'ID regione non pu� essere nullo. +user.id.not.null=L'ID utente non pu? essere nullo. +question.not.empty=La domanda non pu? essere vuota. +name.not.empty=Il nome non pu? essere vuoto. +type.not.empty=Il tipo non pu? essere vuoto. +region.not.null=L'ID regione non pu? essere nullo. amount.greater.than.zero=L'importo del finanziamento deve essere maggiore di zero. -look.up.data.not.valid=L'entit� dati di ricerca non � valida. +look.up.data.not.valid=L'entit? dati di ricerca non ? valida. files.uploaded=File caricati correttamente. call.created.successfully=Chiamata creata correttamente. file.deleted.successfully=File eliminato con successo. document.not.found=Documento non trovato. document.id.not.found=ID documento non trovato. call.invalid.date=Data di inizio o fine non valida. -call.id.not.null=L'ID della chiamata non pu� essere nullo. +call.id.not.null=L'ID della chiamata non pu? essere nullo. call.update.successfully=Chiamata aggiornata con successo. call.fetch.success=Dettagli della chiamata recuperati con successo. call.not.found=Chiamata non trovata. -score.not.null=Il punteggio non pu� essere nullo o zero. -field.not.null={0} non pu� essere nullo. -field.not.empty=la {0} non pu� essere vuota. -update_call_status_success_msg=Lo stato della chiamata � stato aggiornato con successo. -status.same.error=Lo stato � gi� impostato. -invalid.status.change.from.draft=Lo stato non pu� essere cambiato in READY_TO_PUBLISH o PUBLISH da DRAFT. -status.cannot.be.changed=Lo stato non pu� essere cambiato. -published.call.not.update=Il bando pubblicato non pu� essere aggiornato. -invalid.status.change.from.publish=Lo stato non pu� essere modificato in READY_TO_PUBLISH o DRAFT da PUBLISH. +score.not.null=Il punteggio non pu? essere nullo o zero. +field.not.null={0} non pu? essere nullo. +field.not.empty=la {0} non pu? essere vuota. +update_call_status_success_msg=Lo stato della chiamata ? stato aggiornato con successo. +status.same.error=Lo stato ? gi? impostato. +invalid.status.change.from.draft=Lo stato non pu? essere cambiato in READY_TO_PUBLISH o PUBLISH da DRAFT. +status.cannot.be.changed=Lo stato non pu? essere cambiato. +published.call.not.update=Il bando pubblicato non pu? essere aggiornato. +invalid.status.change.from.publish=Lo stato non pu? essere modificato in READY_TO_PUBLISH o DRAFT da PUBLISH. # Login-related messages login.successfully=Accesso effettuato con successo. pass.min.len.msg=La password deve essere lunga almeno 8 caratteri. -email.already.exists=Esiste gi� un utente con questa email. +email.already.exists=Esiste gi? un utente con questa email. invalid_user=Validazione utente fallita. Controlla le informazioni, lo stato dell'account e la scadenza del token. #Global messages -common_message=qualcosa é andato storto. Per favore riprova +common_message=qualcosa � andato storto. Per favore riprova invalid_signature=Gettone non valido. invalid_login=Nome utente o password errati req_validation_er=Errore di convalida @@ -119,26 +119,26 @@ lookupdata.created.successfully=LookUpData creato correttamente. lookupdata.fetched.successfully=LookUpData recuperato correttamente. lookupdata.updated.successfully=LookUpData aggiornato correttamente. lookupdata.deleted.successfully=LookUpData eliminato correttamente. -lookupdata.value.cannot.be.empty=Il campo valore non pu� essere vuoto +lookupdata.value.cannot.be.empty=Il campo valore non pu? essere vuoto #Document-related message document.updated.successfully=Documento aggiornato con successo. document.fetched.successfully=Documento recuperato con successo. # Password reset messages password.reset.initiated=Reimpostazione della password avviata. -password.reset.success=La password � stata reimpostata con successo. -invalid.token.msg=Il token fornito � invalido o scaduto. Si prega di richiedere un nuovo token. -current.password.incorrect = La password attuale non � corretta. +password.reset.success=La password ? stata reimpostata con successo. +invalid.token.msg=Il token fornito ? invalido o scaduto. Si prega di richiedere un nuovo token. +current.password.incorrect = La password attuale non ? corretta. success.password.changed=Password cambiata con successo. logout.successful.msg=Logout riuscito. Sei stato disconnesso con successo. -update.user.status.success=Lo stato dell'utente � stato aggiornato con successo. +update.user.status.success=Lo stato dell'utente ? stato aggiornato con successo. #Flow-related message flow.created.successfully=Flusso creato con successo. flow.fetched.successfully=Flusso recuperato con successo. -flow.already.exists= Il flusso esiste gi� per questa chiamata. -flow.request.not.complete=La richiesta di flusso non � completa. +flow.already.exists= Il flusso esiste gi? per questa chiamata. +flow.request.not.complete=La richiesta di flusso non ? completa. initial.and.final.form.cannot.null=La forma iniziale e finale non possono essere nulle. # Application related messages @@ -149,25 +149,25 @@ application.get.success=Dettagli dell'applicazione recuperati con successo. application.not.found=Applicazione non trovata con l'ID fornito. application.form.field.not.found=Campo del modulo di domanda non trovato. Form.not.matches.to.call.initial.form=L'ID del modulo non corrisponde all'ID del modulo iniziale della chiamata. -application.already.exists=L'applicazione esiste gi� per questa chiamata. -application.already.submitted=La domanda � gi� stata inviata. +application.already.exists=L'applicazione esiste gi? per questa chiamata. +application.already.submitted=La domanda ? gi? stata inviata. #Validation related messages -validation.field.required=Il campo {0} � obbligatorio. +validation.field.required=Il campo {0} ? obbligatorio. validation.field.min_length=Il campo {0} deve essere lungo almeno {1} caratteri. validation.field.max_length=Il campo {0} deve essere lungo al massimo {1} caratteri. validation.field.pattern=Il campo {0} non corrisponde al modello richiesto. validation.field.not_null=Il campo {0} non deve essere nullo. validation.field.not_empty=Il campo {0} non deve essere vuoto. -current.form.incomplete=il modulo corrente non � compilato +current.form.incomplete=il modulo corrente non ? compilato flow.not.found=Flow not found. validation.message=Messaggi di convalida. action.required=Campo azione obbligatorio. -call.not.published=La chiamata non � stata pubblicata. +call.not.published=La chiamata non ? stata pubblicata. application.form.not.found=Modulo di domanda non trovato. -application.is.incomplete = L'applicazione � incompleta. -updating.form.value.impact.on.flow=L'aggiornamento di questo valore del modulo {0} pu� avere un impatto sul flusso. +application.is.incomplete = L'applicazione ? incompleta. +updating.form.value.impact.on.flow=L'aggiornamento di questo valore del modulo {0} pu? avere un impatto sul flusso. validation.field.custom=Il valore per il campo {0} non soddisfa la regola di convalida personalizzata. validation.codice.fiscale=Il campo {0} deve essere un Codice Fiscale valido con esattamente 16 caratteri: 6 lettere, 2 cifre, 1 lettera, 2 cifre, 1 lettera, 3 cifre e 1 lettera. @@ -178,13 +178,13 @@ validation.email.pec=Il campo {0} deve essere un indirizzo email PEC valido. validation.url=Il campo {0} deve essere un URL valido. validation.marca.da.bollo=Il campo {0} deve essere una Marca Da Bollo valida con esattamente 14 cifre. validation.piva=Il numero di partita IVA per {0} deve essere lungo fino a 11 cifre. -valid.vat.number=Il numero di partita IVA non � valido per il campo {0}. +valid.vat.number=Il numero di partita IVA non ? valido per il campo {0}. failed.retain.field=Impossibile conservare campi specifici. token.validate.success=Token convalidato con successo. invalid.request=Richiesta non valida. -codice.fiscale.exists=Questo codice fiscale � gi� associato ad un altro utente. +codice.fiscale.exists=Questo codice fiscale ? gi? associato ad un altro utente. -total.steps.not.zero=Il totale dei passaggi non pu� essere zero. +total.steps.not.zero=Il totale dei passaggi non pu? essere zero. completed.steps.not.valid=I passaggi completati devono essere compresi tra 0 e il totale dei passaggi. field.id.not.found=L'ID campo {0} non esiste nella struttura del modulo. company.created.success=Azienda creata con successo. @@ -194,39 +194,37 @@ company.get.success=Azienda recuperata con successo. company.not.found=Azienda non trovata. check.vatnumber.success=Numero di partita IVA verificato con successo. invalid.vatnumber=Numero di partita IVA non valido. -vatnumber.mandatory=Il numero di partita IVA � obbligatorio. -vatnumber.already.exists=Il numero di partita IVA esiste gi�. +vatnumber.mandatory=Il numero di partita IVA ? obbligatorio. +vatnumber.already.exists=Il numero di partita IVA esiste gi?. invalid.email=Email non valida. -company.id.mandatory=L'ID dell'azienda � obbligatorio. -user.already.connected.to.company=L'utente � gi� collegato a questa azienda. -validation.error.missing.firstName=Il nome � obbligatorio. -validation.error.missing.lastName=Il cognome � obbligatorio. -validation.error.missing.codiceFiscale=Il Codice Fiscale � obbligatorio. +validation.error.missing.firstName=Il nome ? obbligatorio. +validation.error.missing.lastName=Il cognome ? obbligatorio. +validation.error.missing.codiceFiscale=Il Codice Fiscale ? obbligatorio. delegation.file.upload.success=File di delega caricato con successo. delegation.fetch.success=Delega recuperata con successo. -delegation.template.generation.error=Si � verificato un errore durante la generazione del modello di delega. -validation.error.file.empty=Il file caricato � vuoto. +delegation.template.generation.error=Si ? verificato un errore durante la generazione del modello di delega. +validation.error.file.empty=Il file caricato ? vuoto. validation.error.file.invalidType=Sono accettati solo file .p7m. upload.error.s3=Impossibile caricare il file su S3. -company.id.mandatory=L'ID dell'azienda � obbligatorio. -user.already.connected.to.company=L'utente � gi� collegato a questa azienda. -call.not.started.yet = La chiamata non � ancora iniziata. Attendere fino alla data e all'ora di inizio specificate. -call.already.ended = La chiamata � gi� terminata. Non � possibile inviare l'applicazione dopo la scadenza. +company.id.mandatory=L'ID dell'azienda ? obbligatorio. +user.already.connected.to.company=L'utente ? gi? collegato a questa azienda. +call.not.started.yet = La chiamata non ? ancora iniziata. Attendere fino alla data e all'ora di inizio specificate. +call.already.ended = La chiamata ? gi? terminata. Non ? possibile inviare l'applicazione dopo la scadenza. status.updated.successfully=Stato aggiornato con successo. application.status.updated.successfully = Stato dell'applicazione aggiornato con successo. -application.already.in.provided.status=L'applicazione � gi� nello stato fornito. +application.already.in.provided.status=L'applicazione ? gi? nello stato fornito. delegation.not.found=Delega non trovata. user.company.relation.not.found=Relazione utente con l'azienda specificata non trovata. delegation.delete.success=Delega eliminata con successo. user.not.authorized.create.application=L'utente deve essere un rappresentante legale o avere una delega. -application.submitted.cannot.change=La domanda inviata non pu� essere modificata. +application.submitted.cannot.change=La domanda inviata non pu? essere modificata. # Call Document Messages call.documents.fetch.success=Documenti recuperati con successo. call.documents.not.found=Nessun documento trovato per la chiamata specificata. # Beneficiary Preferred Call messages -beneficiary.preferred.call.status.updated.success=Lo stato della chiamata preferita del beneficiario � stato aggiornato con successo. +beneficiary.preferred.call.status.updated.success=Lo stato della chiamata preferita del beneficiario ? stato aggiornato con successo. beneficiary.preferred.calls.get.all.success=Tutte le chiamate preferite del beneficiario sono state recuperate con successo. beneficiary.preferred.call.created.success=Chiamata preferita del beneficiario creata con successo. beneficiary.preferred.call.get.success=Chiamata preferita del beneficiario recuperata con successo. @@ -235,7 +233,7 @@ beneficiary.preferred.calls.get.success=Tutte le chiamate preferite del benefici beneficiary.preferred.call.updated.success=Chiamata preferita del beneficiario aggiornata con successo. beneficiary.preferred.call.not.found=Chiamata preferita del beneficiario non trovata. either.user.or.beneficiary.id.required = ID utente o ID beneficiario non presente. -userId.and.beneficiaryId.error = Non � possibile fornire contemporaneamente sia userId che beneficiaryId. +userId.and.beneficiaryId.error = Non ? possibile fornire contemporaneamente sia userId che beneficiaryId. User.not.found.with.the.given.beneficiaryID=Utente non trovato con l'ID beneficiario fornito. permission.denied=Non sei autorizzato ad accedere a questi dati. signed.document.file.upload.success=File del documento firmato caricato con successo. @@ -246,10 +244,10 @@ delete.signed.document.file.success=Documento firmato eliminato con successo. dashboard.widget.fetched.successfully=Widget dashboard recuperato correttamente. login_attempt_successfully_created= Tentativo di login creato con successo. get_login_attempt_se_msg=Lista dei tentativi di accesso recuperata correttamente. -application.in.submit.status.cannot.delete.company=Non � possibile eliminare l'azienda perch� ci sono domande attive con stato SUBMITTED. +application.in.submit.status.cannot.delete.company=Non ? possibile eliminare l'azienda perch? ci sono domande attive con stato SUBMITTED. get.users.success.msg = Utenti recuperati con successo -cannot.create.beneficiary.user = La creazione di un utente beneficiario non � consentita. Si prega di assegnare il ruolo appropriato. +cannot.create.beneficiary.user = La creazione di un utente beneficiario non ? consentita. Si prega di assegnare il ruolo appropriato. evaluationCriteria.invalid=Questo criterio di valutazione non appartiene alla chiamata corrente. application.evaluation.not.found=Valutazione dell'applicazione non trovata con ID: {0} @@ -260,11 +258,11 @@ evaluation.deleted.successfully = Valutazione dell'applicazione eliminata con su evaluations.fetched.successfully = Tutte le valutazioni delle applicazioni recuperate con successo. application.evaluation.status.updated.successfully=Stato della valutazione dell'applicazione aggiornato con successo. assigned.application.not.found.with.id=Applicazione assegnata con questo ID dell'applicazione non trovata -either.application.or.assigned.application.id.required=� richiesto almeno uno tra applicationId o assignedApplicationId. -evaluation.already.exists=Una valutazione dell'applicazione esiste gi� per questo ID applicazione. +either.application.or.assigned.application.id.required=? richiesto almeno uno tra applicationId o assignedApplicationId. +evaluation.already.exists=Una valutazione dell'applicazione esiste gi? per questo ID applicazione. application.assigned.success.msg =Domanda assegnata con successo -application.already.assigned.msg =La domanda � gi� assegnata +application.already.assigned.msg =La domanda ? gi? assegnata aasigned.application.not.found = Applicazione assegnata non trovata con l'ID specificato. assigned.application.deleted.success =Applicazione assegnata eliminata con successo. assigned.application.get.success =Dettagli dell'applicazione assegnata recuperati correttamente. @@ -279,7 +277,7 @@ hub_get_all_success=Hub recuperati con successo hub_delete_success=Hub eliminato con successo hub_not_found=Hub non trovato -application.not.in.draft.status=La domanda non � in stato DRAFT. +application.not.in.draft.status=La domanda non ? in stato DRAFT. get.error.s3=Impossibile recuperare il file da S3. application.data.amendment.success = Recupero riuscito dei dati dell'applicazione per il processo di modifica @@ -294,14 +292,52 @@ added.comment.to.amendment.request.success = Commento aggiunto con successo alla comment.not.found = Commento non trovato. comment.updated.successfully = Commento aggiornato con successo. comment.deleted.successfully = Commento eliminato con successo. -comment.not.associate.with.amendment = Il commento non � associato alla richiesta di emendamento. +comment.not.associate.with.amendment = Il commento non ? associato alla richiesta di emendamento. amendment.found.success = Richiesta di emendamento trovata con successo. invalid.amendment.for.comment = Richiesta di emendamento non valida per il commento fornito. DD_MM_YYYY_HH_MM = dd_MM_yyyy HH:mm create.application.data.amendment.msg =Emendamento alla domanda inviato con successo -beneficiary.email.not.found.msg=L'indirizzo email per il beneficiario non � stato trovato. Si prega di assicurarsi che il beneficiario abbia un indirizzo email valido. +beneficiary.email.not.found.msg=L'indirizzo email per il beneficiario non ? stato trovato. Si prega di assicurarsi che il beneficiario abbia un indirizzo email valido. reminder.email.sent.success.msg=Email di promemoria inviata con successo! application.documents.not.found=Nessun documento trovato per la domanda. -beneficiary.call.duplicate = Una chiamata preferita con questo ID di chiamata e ID azienda esiste gi� per questo utente. +beneficiary.call.duplicate = Una chiamata preferita con questo ID di chiamata e ID azienda esiste gi? per questo utente. user.must.be.associated.with.company.to.create.application=Devi essere associato a un'azienda per poter presentare domanda per questa applicazione. company.id.required.for.preferred.call=ID azienda obbligatorio quando si richiedono solo chiamate preferite. +response.days.not.null=I giorni di risposta non devono essere nulli e maggiori di zero. +application.cannot.approved.or.rejected=La domanda non pu� essere approvata o rifiutata perch� l'emendamento � attivo. +valid.vatnumber.message=Il numero di partita IVA � valido. +application.cannot.approved.or.rejected=La domanda non pu? essere approvata o rifiutata perch? l'emendamento ? attivo. + +atleast.one.id.required=Almeno uno tra companyId o applicationId deve essere fornito. + +#Appointment flow messages +ndg.available = NDG disponibile. +ndg.generation.in.progress = La generazione NDG ? in corso. +ndg.fetch.successfully = NDG recuperato con successo. +appointment.already.created = Appuntamento gi? creato. +ndg.not.found.for.this.application.or.invalid = NDG non trovato per questa applicazione o non valido. +provide.valid.application.document.id = Fornisci un ID documento applicativo valido. +document.uploaded.successfully.to.external.system = Documento caricato con successo nel sistema esterno. +error.in.uploading.document.check.input = Errore nel caricamento del documento. Controlla i dati inseriti o riprova. +document.already.uploaded = Documento gi? caricato. +document.not.uploaded.to.external.system.please.try.again = Documento non caricato nel sistema esterno, riprova. +ndg.not.found.or.not.matched = L'NDG fornito non corrisponde all'NDG dell'applicazione o non ? stato generato. +ndg.generation.is.only.for.gepafin = La generazione dell'NDG ? disponibile solo per GEPAFIN. +appointment.creation.is.only.for.gepafin = La creazione degli appuntamenti ? consentita solo per GEPAFIN. +upload.document.is.only.for.gepafin = Il documento non pu? essere caricato, questa operazione ? disponibile solo per il Hub GEPAFIN. +appointment.created.successfully = Appuntamento creato con successo. +error.try.again = Errore di chiamata di servizio durante l'esecuzione dell'operazione. Riprovare. +document.uploading.is.in.progress = Il documento ? in fase di caricamento. +all.document.checked.and.one.checklist.checked=Tutti i documenti devono essere controllati e almeno una checklist deve essere controllata. +<<<<<<< HEAD + +#notification messsages +notification.already.in.state=La notifica � gi� nello stato fornito. +notification.fetched.successfully=Notifica recuperata con successo. +notification.not.found=Notifica non trovata. +notification.sent.successfully=Notifica inviata con successo. +notification.deleted.successfully=Notifica eliminata con successo. +notification.updated.successfully=Notifica aggiornata con successo. +user.with.company.not.found = Utente con azienda non trovato per utente o azienda. +======= +>>>>>>> 832666a4d412c2c81f5c1dfb5b1866aba2c40bdd