From cac4a7efacd6d975697199197217e57ff2409d4c Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 2 Dec 2024 18:20:08 +0530 Subject: [PATCH 01/31] User management --- .../config/SamlSuccessHandler.java | 2 +- .../constants/GepafinConstant.java | 1 + .../gepafin/tendermanagement/dao/UserDao.java | 195 ++++++++++++++---- .../entities/SystemEmailTemplatesEntity.java | 2 + .../enums/EmailScenarioTypeEnum.java | 2 + .../enums/UserActionContextEnum.java | 4 +- .../repositories/UserRepository.java | 32 ++- .../tendermanagement/service/UserService.java | 2 +- .../service/impl/AuthenticationService.java | 19 +- .../service/impl/UserServiceImpl.java | 4 +- .../gepafin/tendermanagement/util/Utils.java | 11 +- .../web/rest/api/UserApi.java | 4 +- .../api/impl/CustomUserDetailsService.java | 6 +- .../web/rest/api/impl/UserApiController.java | 23 ++- .../db/changelog/db.changelog-1.0.0.xml | 12 +- ...template_for_reset_password_28_11_2024.sql | 65 ++++++ ...tem_email_template_for_user_28_11_2024.sql | 29 +++ 17 files changed, 351 insertions(+), 62 deletions(-) create mode 100644 src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql create mode 100644 src/main/resources/db/dump/insert_system_email_template_for_user_28_11_2024.sql diff --git a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java index 14f2b1bf..850d2451 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SamlSuccessHandler.java @@ -63,7 +63,7 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler { Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal(); Map> userAttributes = principal.getAttributes(); - String token = Utils.generateSecureToken(); + String token = Utils.generateSecureSamlToken(); logger.info("SAML User Attributes: " + userAttributes); // Extracting raw SAML response diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 97730f80..aaa3279b 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -302,5 +302,6 @@ public class GepafinConstant { public static final String USER_ID = "userId"; 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"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index da5c6f07..41483d36 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -6,21 +6,15 @@ import net.gepafin.tendermanagement.config.SamlSuccessHandler; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; -import net.gepafin.tendermanagement.enums.RoleStatusEnum; -import net.gepafin.tendermanagement.enums.UserActionContextEnum; -import net.gepafin.tendermanagement.enums.UserActionLogsEnum; -import net.gepafin.tendermanagement.enums.UserStatusEnum; -import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.*; -import net.gepafin.tendermanagement.model.response.CompanyResponse; -import net.gepafin.tendermanagement.model.response.RoleResponseBean; -import net.gepafin.tendermanagement.model.response.UserSamlResponse; -import net.gepafin.tendermanagement.model.response.UserResponseBean; +import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.model.util.JWTToken; import net.gepafin.tendermanagement.repositories.BeneficiaryRepository; import net.gepafin.tendermanagement.repositories.UserRepository; import net.gepafin.tendermanagement.service.HubService; import net.gepafin.tendermanagement.service.RoleService; +import net.gepafin.tendermanagement.service.SystemEmailTemplatesService; import net.gepafin.tendermanagement.service.impl.AuthenticationService; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; @@ -39,6 +33,7 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; @@ -90,6 +85,18 @@ public class UserDao { @Autowired private HttpServletRequest request; + @Autowired + private SystemEmailTemplatesService systemEmailTemplatesService; + + @Autowired + private EmailLogDao emailLogDao; + + @Autowired + private EmailNotificationDao emailNotificationDao; + + @Value("${fe.base.url}") + private String feBaseUrl; + public JWTToken createUser(HttpServletRequest request, String tempToken, UserReq userReq) { if (StringUtils.isEmpty(userReq.getHubUuid())) { @@ -120,9 +127,35 @@ public class UserDao { /** This code is responsible for adding a version history log for the "Create user" operation. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).newData(userEntity).build()); + if(beneficiary == null){ + sendEmailToOnboardingUser(userEntity); + } return token; } - + public void sendEmailToOnboardingUser(UserEntity userEntity){ + SystemEmailTemplateResponse emailTemplate = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( + SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.USER_ONBOARDING, userEntity.getHub(), null); + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(emailTemplate.getEmailScenario(), RecipientTypeEnum.USER, userEntity.getId(), userEntity.getEmail(), + userEntity.getId(), null, null, null); + String firstName = userEntity.getFirstName() != null ? userEntity.getFirstName() : ""; + String lastName = userEntity.getLastName() != null ? userEntity.getLastName() : ""; + String userName = String.join(" ", firstName, lastName).trim(); + String subject = Utils.replacePlaceholders(emailTemplate.getSubject(), Map.of( + "{{user_name}}", userName + )); + String body = Utils.replacePlaceholders(emailTemplate.getHtmlContent(), Map.of( + "{{user_name}}", userName, + "{{user_email}}", userEntity.getEmail() + )); + + emailNotificationDao.sendMail( + userEntity.getHub().getId(), + subject, + body, + List.of(userEntity.getEmail()), + emailLogRequest + ); + } private BeneficiaryEntity createBeneficiary(RoleEntity roleEntity, UserReq userReq, HubEntity hub) { BeneficiaryEntity beneficiaryEntity = null; if (RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleEntity.getRoleType())) { @@ -164,12 +197,10 @@ public class UserDao { Translator.toLocale(GepafinConstant.VALIDATE_EMAIL)); } log.info("Creating user with email: {}", userReq.getEmail()); - if (userRepository.existsByEmailIgnoreCaseAndHubUniqueUuid(userReq.getEmail(), userReq.getHubUuid())) { - log.error("User creation failed: Email {} already exists", userReq.getEmail()); - throw new CustomValidationException(Status.VALIDATION_ERROR, - Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); - } - if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) + RoleEntity roleEntity = roleService.validateRole(userReq.getRoleId()); + validateDuplicateEmail(userReq.getEmail(), userReq.getHubUuid(), roleEntity.getRoleType()); + + if (Boolean.FALSE.equals(StringUtils.isEmpty(userReq.getCodiceFiscale())) && userRepository.existsByBeneficiaryCodiceFiscaleAndHubId(userReq.getCodiceFiscale(), hub.getId())) { log.error("User creation failed: CodiceFiscale {} already exists", userReq.getCodiceFiscale()); throw new CustomValidationException(Status.VALIDATION_ERROR, @@ -191,8 +222,29 @@ public class UserDao { } } } + private void validateDuplicateEmail(String email, String hubUuid, String roleType) { + Boolean existsForNonBeneficiaries = userRepository.existsByEmailIgnoreCaseForNonBeneficiaries( + email, hubUuid, RoleStatusEnum.ROLE_BENEFICIARY.getValue()); - private void validatePassword(String password, String confirmPassword, String tempToken) { + Boolean beneficiaryExistsInHub = userRepository.existsByEmailIgnoreCaseForBeneficiaries( + email, hubUuid, RoleStatusEnum.ROLE_BENEFICIARY.getValue()); + + if (Boolean.TRUE.equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleType))) { + if (beneficiaryExistsInHub) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); + } + } + else { + if (existsForNonBeneficiaries) { + throw new CustomValidationException(Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); + } + } + } + + + private void validatePassword(String password, String confirmPassword, String tempToken) { if (StringUtils.isEmpty(password) || StringUtils.isEmpty(confirmPassword)) { if(tempToken == null) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.VALIDATE_PASSWORD)); @@ -263,7 +315,7 @@ public class UserDao { userEntity.setAddress(userReq.getAddress()); userEntity.setPhoneNumber(userReq.getPhoneNumber()); userEntity.setDateOfBirth(userReq.getDateOfBirth()); - } + } return userRepository.save(userEntity); } @@ -362,25 +414,83 @@ public class UserDao { return user; } - public String initiatePasswordReset(InitiatePasswordResetReq resetReq) { - UserEntity user = userRepository - .findByEmailIgnoreCaseAndHubUniqueUuid(resetReq.getEmail(), resetReq.getHubUuid()) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + public void initiatePasswordReset(InitiatePasswordResetReq resetReq) { + UserEntity user = userRepository.findUserExcludingRoleType( + resetReq.getEmail(), + resetReq.getHubUuid(), + RoleStatusEnum.ROLE_BENEFICIARY.getValue() + ).orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG) + )); + UserEntity oldUserEntity = Utils.getClonedEntityForData(user); String token = Utils.generateSecureToken(); user.setResetPasswordToken(token); userRepository.save(user); + + /** This code is responsible for adding a version history log for the "Initiate password reset request" operation **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldUserEntity).newData(user).build()); + log.info("Password reset token generated for user: {}", resetReq.getEmail()); - return token; + + sendResetPasswordTokenEmail(user, token); + } + public void sendResetPasswordTokenEmail(UserEntity user, String token) { + + SystemEmailTemplateResponse emailTemplate = systemEmailTemplatesService.retrieveTemplateByTypeAndCall( + SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.PASSWORD_RESET, user.getHub(), null); + String redirectUrl = feBaseUrl; + if (Boolean.FALSE.equals(StringUtils.isEmpty(user.getHub().getDomainName()))) { + redirectUrl = user.getHub().getDomainName(); + } + + EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest( + emailTemplate.getEmailScenario(), + RecipientTypeEnum.USER, + user.getId(), + user.getEmail(), + user.getId(), + null, + null, + null); + redirectUrl = String.format( + user.getHub().getDomainName() + GepafinConstant.RESET_PASSWORD_URL_FORMAT, + token, + user.getEmail() + ); + String firstName = user.getFirstName() != null ? user.getFirstName() : ""; + String lastName = user.getLastName() != null ? user.getLastName() : ""; + String userName = String.join(" ", firstName, lastName).trim(); + String subject = Utils.replacePlaceholders(emailTemplate.getSubject(), Map.of( + "{{user_name}}", userName + )); + String body = Utils.replacePlaceholders(emailTemplate.getHtmlContent(), Map.of( + "{{user_name}}", userName, + "{{reset_password_link}}", redirectUrl + )); + emailNotificationDao.sendMail( + user.getHub().getId(), + subject, + body, + List.of(user.getEmail()), + emailLogRequest + ); + + log.info("Password reset token email sent to: {}", user.getEmail()); } public Boolean resetPassword(ResetPasswordReq resetPasswordReq) { - UserEntity user = userRepository - .findByEmailIgnoreCaseAndHubUniqueUuid(resetPasswordReq.getEmail(), resetPasswordReq.getHubUuid()) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); - + UserEntity user = userRepository.findUserExcludingRoleType( + resetPasswordReq.getEmail(), + resetPasswordReq.getHubUuid(), + RoleStatusEnum.ROLE_BENEFICIARY.getValue() + ).orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG) + )); + + UserEntity oldUserEntity = Utils.getClonedEntityForData(user); if (!resetPasswordReq.getNewPassword().equals(resetPasswordReq.getConfirmPassword())) { log.info("User creation failed: Passwords do not match for email {}", user.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); @@ -395,25 +505,36 @@ public class UserDao { user.setPassword(passwordEncoder.encode(resetPasswordReq.getNewPassword())); user.setResetPasswordToken(null); userRepository.save(user); + + /** This code is responsible for adding a version history log for the "Reset Password " operation **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldUserEntity).newData(user).build()); + log.info("Password successfully reset for user: {}", resetPasswordReq.getEmail()); return true; } - public Boolean changePassword(UserEntity userEntity, ChangePasswordRequest request) { + public Boolean changePassword(UserEntity userEntity, ChangePasswordRequest changePasswordRequest) { UserEntity user = userRepository - .findByEmailIgnoreCaseAndHubUniqueUuid(request.getEmail(), userEntity.getHub().getUniqueUuid()) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); - - if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) { + .findUserExcludingRoleType(changePasswordRequest.getEmail(), userEntity.getHub().getUniqueUuid(),RoleStatusEnum.ROLE_BENEFICIARY.getValue()) + .orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG) + )); + UserEntity oldUserEntity = Utils.getClonedEntityForData(userEntity); + if (!passwordEncoder.matches(changePasswordRequest.getPassword(), user.getPassword())) { throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.CURRENT_PASSWORD_INCORRECT)); } - if (!request.getNewPassword().equals(request.getConfirmPassword())) { + if (!changePasswordRequest.getNewPassword().equals(changePasswordRequest.getConfirmPassword())) { log.info("User creation failed: Passwords do not match for email {}", user.getEmail()); throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.PASSWORD_DOESNT_MATCH)); } - user.setPassword(passwordEncoder.encode(request.getNewPassword())); + user.setPassword(passwordEncoder.encode(changePasswordRequest.getNewPassword())); userRepository.save(user); + + /** This code is responsible for adding a version history log for the "Change user password" operation **/ + loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldUserEntity).newData(user).build()); + + return true; } public void logout(HttpServletRequest request, HttpServletResponse response) { diff --git a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java index f7974eca..dac3a432 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/SystemEmailTemplatesEntity.java @@ -47,6 +47,8 @@ public class SystemEmailTemplatesEntity extends BaseEntity { INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE("INADMISSIBILITY_NOTIFICATION_DUE_TO_FAILURE"), ADMISSIBILITY_NOTIFICATION("ADMISSIBILITY_NOTIFICATION"), AMENDMENT_REMINDER("AMENDMENT_REMINDER"), + USER_ONBOARDING("USER_ONBOARDING"), + PASSWORD_RESET("PASSWORD_RESET"), INADMISSIBILITY_TEMPLATE("INADMISSIBILITY_NOTIFICATION"); private String value; diff --git a/src/main/java/net/gepafin/tendermanagement/enums/EmailScenarioTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/EmailScenarioTypeEnum.java index 493f987c..415f1dd2 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/EmailScenarioTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/EmailScenarioTypeEnum.java @@ -9,6 +9,8 @@ public enum EmailScenarioTypeEnum { APPLICATION_AMENDMENT_EXPIRED("APPLICATION_AMENDMENT_EXPIRED"), APPLICATION_AMENDMENT_REMINDER("APPLICATION_AMENDMENT_REMINDER"), APPLICATION_APPROVED("APPLICATION_APPROVED"), + USER_CREATION("USER_CREATION"), + PASSWORD_RESET_REQUEST("PASSWORD_RESET_REQUEST"), APPLICATION_REJECTED("APPLICATION_REJECTED"); private final 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 0a92143b..a4d7f3c2 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java @@ -24,7 +24,9 @@ public enum UserActionContextEnum { VALIDATE_EXISTING_USER_WITH_SPID_TOKEN("VALIDATE_EXISTING_USER_WITH_SPID_TOKEN"), GET_VALID_USER_DETAILS("GET_VALID_USER_DETAILS"), GET_ALL_USERS_BY_ROLE("GET_ALL_USERS_BY_ROLE"), - + CHANGE_USER_PASSWORD("CHANGE_USER_PASSWORD"), + INITIATE_PASSWORD_RESET_REQUEST("INITIATE_PASSWORD_RESET_REQUEST"), + RESET_USER_PASSWORD("RESET_USER_PASSWORD"), /** application action context **/ GET_APPLICATION("GET_APPLICATION"), CREATE_UPDATE_APPLICATION_FORM("CREATE_UPDATE_APPLICATION_FORM"), diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 47ab16b8..3a0cf957 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -2,6 +2,8 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.UserEntity; 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.util.List; @@ -12,9 +14,16 @@ public interface UserRepository extends JpaRepository { UserEntity findByBeneficiaryId(Long beneficiaryId); - Optional findByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid); +// Optional findByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid); - boolean existsByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid); + @Query("SELECT u FROM UserEntity u WHERE LOWER(u.email) = LOWER(:email) AND u.hub.uniqueUuid = :hubUuid AND u.roleEntity.roleType <> :roleType") + Optional findUserExcludingRoleType( + @Param("email") String email, + @Param("hubUuid") String hubUuid, + @Param("roleType") String roleType + ); + +// boolean existsByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid); List findByRoleEntityIdAndHubId(Long roleId, Long hubId); @@ -24,5 +33,22 @@ public interface UserRepository extends JpaRepository { Optional findByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); - boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); + Boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); + + @Query("SELECT COUNT(u) > 0 " + + "FROM UserEntity u " + + "WHERE u.email = :email " + + "AND u.hub.uniqueUuid = :hubUuid " + + "AND u.roleEntity.roleType <> :beneficiaryRoleType") + Boolean existsByEmailIgnoreCaseForNonBeneficiaries(@Param("email") String email, + @Param("hubUuid") String hubUuid, + @Param("beneficiaryRoleType") String beneficiaryRoleType); + + @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END " + + "FROM UserEntity u " + + "WHERE LOWER(u.email) = LOWER(:email) AND u.hub.uniqueUuid = :hubUuid " + + "AND u.roleEntity.roleType = :beneficiaryRoleType") + Boolean existsByEmailIgnoreCaseForBeneficiaries(String email, String hubUuid, String beneficiaryRoleType); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java index 21109a5e..aa534bea 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java @@ -27,7 +27,7 @@ public interface UserService { UserEntity validateUser(Long userId); - String initiatePasswordReset(InitiatePasswordResetReq resetReq); + void initiatePasswordReset(InitiatePasswordResetReq resetReq); Boolean resetPassword(ResetPasswordReq resetPasswordReq); 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 d4dab052..1f0194d9 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java @@ -12,10 +12,7 @@ import net.gepafin.tendermanagement.entities.HubEntity; import net.gepafin.tendermanagement.entities.LoginAttemptEntity; import net.gepafin.tendermanagement.entities.SamlResponseEntity; import net.gepafin.tendermanagement.entities.UserEntity; -import net.gepafin.tendermanagement.enums.LoginAttemptResultEnum; -import net.gepafin.tendermanagement.enums.LoginAttemptTypeEnum; -import net.gepafin.tendermanagement.enums.UserStatusEnum; -import net.gepafin.tendermanagement.enums.VersionActionTypeEnum; +import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.LoginReq; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.model.response.CompanyResponse; @@ -40,6 +37,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Service; @@ -95,15 +93,22 @@ public class AuthenticationService { LoginAttemptEntity loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request); try { log.info("Attempting login for email: {}", loginReq.getEmail()); + user = userRepository.findUserExcludingRoleType( + loginReq.getEmail(), + loginReq.getHubUuid(), + RoleStatusEnum.ROLE_BENEFICIARY.getValue() + ).orElseThrow(() -> new ResourceNotFoundException( + Status.NOT_FOUND, + Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG) + )); + String emailWithHubId = loginReq.getEmail()+":"+loginReq.getHubUuid(); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( emailWithHubId, loginReq.getPassword()); Authentication authentication = this.authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Authentication successful for email: {}", loginReq.getEmail()); - user = userRepository.findByEmailIgnoreCaseAndHubUniqueUuid(loginReq.getEmail(), loginReq.getHubUuid()) - .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, - Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG))); + loginAttemptEntity.setUserId(user.getId()); if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) { throw new ResourceNotFoundException(Status.NOT_FOUND, 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 9f95b830..744fbacb 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java @@ -77,8 +77,8 @@ public class UserServiceImpl implements UserService { } @Override - public String initiatePasswordReset(InitiatePasswordResetReq resetReq) { - return userDao.initiatePasswordReset(resetReq); + public void initiatePasswordReset(InitiatePasswordResetReq resetReq) { + userDao.initiatePasswordReset(resetReq); } @Override diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 4949e5d5..b3993900 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -201,7 +201,7 @@ public class Utils { return new String(decodedBytes, StandardCharsets.UTF_8); } - public static String generateSecureToken() { + public static String generateSecureSamlToken() { SecureRandom secureRandom = new SecureRandom(); byte[] tokenBytes = new byte[24]; secureRandom.nextBytes(tokenBytes); @@ -209,7 +209,14 @@ public class Utils { log.debug("Generated secure token: {}", token); return token; } - + public static String generateSecureToken() { + SecureRandom secureRandom = new SecureRandom(); + byte[] tokenBytes = new byte[5]; + secureRandom.nextBytes(tokenBytes); + String token = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes); + log.debug("Generated secure token: {}", token); + return token; + } public static Map> convertStringIntoMap(String jsonString) { try { return mapper.readValue(jsonString, new TypeReference>>() { 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 c7b8e530..8bf9b780 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 @@ -118,7 +118,7 @@ public interface UserApi { @RequestMapping(value = "/reset-password/initiate", produces = {"application/json"}, method = RequestMethod.POST) - ResponseEntity> initiatePasswordReset( + ResponseEntity> initiatePasswordReset(HttpServletRequest request, @Parameter(description = "Initiate password reset request object", required = true) @Valid @RequestBody InitiatePasswordResetReq initiatePasswordResetReq); @Operation(summary = "Api to reset password", @@ -131,7 +131,7 @@ public interface UserApi { @RequestMapping(value = "/reset-password", produces = {"application/json"}, method = RequestMethod.POST) - ResponseEntity> resetPassword( + ResponseEntity> resetPassword(HttpServletRequest request, @Parameter(description = "Reset password request object", required = true) @Valid @RequestBody ResetPasswordReq resetPasswordReq); @Operation(summary = "Api to change user password", responses = { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java index d26ab560..dd6ef1ae 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CustomUserDetailsService.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.web.rest.api.impl; import net.gepafin.tendermanagement.entities.RoleEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.repositories.UserRepository; import org.slf4j.Logger; @@ -35,7 +36,10 @@ public class CustomUserDetailsService implements UserDetailsService { String email = loginParts[0]; String hubId = loginParts[1]; - UserEntity user = userRepository.findByEmailIgnoreCaseAndHubUniqueUuid(email, hubId) + UserEntity user = userRepository.findUserExcludingRoleType( + email, + hubId, + RoleStatusEnum.ROLE_BENEFICIARY.getValue()) .orElseThrow( () -> new UsernameNotFoundException("User " + email + " was not found in the database")); return createSpringSecurityUser(user); 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 7ff12c2a..9f02a8f6 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 @@ -125,20 +125,35 @@ public class UserApiController implements UserApi { @Override public ResponseEntity> changePassword(HttpServletRequest httpServletRequest, @Valid @RequestBody ChangePasswordRequest request) { log.info("Change Password attempt for email: {}", request.getEmail()); + + /** This code is responsible for "Change user password" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.UPDATE) + .actionContext(UserActionContextEnum.CHANGE_USER_PASSWORD).build()); + userService.changePassword(httpServletRequest, request); return ResponseEntity.ok(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.SUCCESS_PASSWORD_CHANGED))); } @Override - public ResponseEntity> initiatePasswordReset(InitiatePasswordResetReq request) { + public ResponseEntity> initiatePasswordReset(HttpServletRequest httpServletRequest,InitiatePasswordResetReq request) { log.info("Initiating password reset for email: {}", request.getEmail()); - String resetToken = userService.initiatePasswordReset(request); + + /** This code is responsible for "Initiating Password Reset Request" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.UPDATE) + .actionContext(UserActionContextEnum.INITIATE_PASSWORD_RESET_REQUEST).build()); + + userService.initiatePasswordReset(request); log.info("Password reset token generated for email: {}", request.getEmail()); - return ResponseEntity.ok(new Response<>(resetToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.RESET_PASSWORD_INITIATED))); + return ResponseEntity.ok(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.RESET_PASSWORD_INITIATED))); } @Override - public ResponseEntity> resetPassword(ResetPasswordReq request) { + public ResponseEntity> resetPassword(HttpServletRequest httpServletRequest,ResetPasswordReq request) { log.info("Resetting password for username: {}", request.getEmail()); + + /** This code is responsible for "Resest user password" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(httpServletRequest).actionType(UserActionLogsEnum.UPDATE) + .actionContext(UserActionContextEnum.RESET_USER_PASSWORD).build()); + Boolean success = userService.resetPassword(request); if (success) { log.info("Password reset successfully for username: {}", request.getEmail()); 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 c209f76a..cc2ee820 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 @@ -1875,5 +1875,15 @@ - + + select + setval('gepafin_schema.system_email_template_id_seq', (select + max(id)+1 + from gepafin_schema.system_email_template), false) + + + + diff --git a/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql new file mode 100644 index 00000000..facb4fdf --- /dev/null +++ b/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql @@ -0,0 +1,65 @@ +INSERT INTO gepafin_schema.system_email_template +(template_name, "type", html_content, subject, "json", "system", is_deleted, created_date, updated_date,email_scenario) +VALUES +( + 'Password Reset Link Email (Italian)', + 'PASSWORD_RESET', + ' + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+

Richiesta di Reimpostazione Password

+
+

Gentile {{user_name}},

+

Hai richiesto di reimpostare la tua password. Puoi farlo cliccando sul link sottostante:

+
+ {{reset_password_link}} +
+

Cordiali saluti,

+

{{email_signature}}

+
+ + Reimposta la Password +
+
', + 'Richiesta di Reimpostazione Password', + NULL, + true, + false, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP, + 'PASSWORD_RESET_REQUEST'); diff --git a/src/main/resources/db/dump/insert_system_email_template_for_user_28_11_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_user_28_11_2024.sql new file mode 100644 index 00000000..cfe54849 --- /dev/null +++ b/src/main/resources/db/dump/insert_system_email_template_for_user_28_11_2024.sql @@ -0,0 +1,29 @@ +INSERT INTO gepafin_schema.system_email_template +(template_name, "type", html_content, subject, "json", "system", is_deleted, created_date, updated_date, email_scenario) +VALUES +( + 'Welcome Email for New User', + 'USER_ONBOARDING', + ' + +
+

Benvenuto!

+

Ciao {{user_name}},

+

Siamo lieti di averti con noi. Di seguito trovi alcune informazioni utili:

+
    +
  • Nome Utente: {{user_email}}
  • +
+

Per accedere, utilizza il tuo indirizzo email registrato. Se hai bisogno di supporto, non esitare a contattarci.

+

Distinti saluti,

+

{{email_signature}}

+
+ + ', + 'Welcome - {{user_name}}', + NULL, + true, + false, + CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP, + 'USER_CREATION' +); From 034d17d1fb689a27b74d1c398609e56da31bcda0 Mon Sep 17 00:00:00 2001 From: nisha Date: Tue, 24 Dec 2024 18:20:53 +0530 Subject: [PATCH 02/31] Amendment Scheduler updates --- .../dao/ApplicationEvaluationDao.java | 1 + .../entities/ApplicationEvaluationEntity.java | 3 + .../ApplicationAmendmentScheduler.java | 75 ++++++++++++++++--- .../db/changelog/db.changelog-1.0.0.xml | 5 ++ 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 50fdb16d..aad85864 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -1775,6 +1775,7 @@ public class ApplicationEvaluationDao { 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); diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java index 45a8c842..15e3d3d7 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java @@ -62,4 +62,7 @@ public class ApplicationEvaluationEntity extends BaseEntity{ @Column(name = "STOP_DATE_TIME") private LocalDateTime stopDateTime; + @Column(name = "CLOSING_DATE") + private LocalDateTime closingDate; + } diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java index 56cb3663..b9d63acd 100644 --- a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java @@ -6,24 +6,24 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; +import net.gepafin.tendermanagement.enums.*; +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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; + import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; -import net.gepafin.tendermanagement.dao.EmailNotificationDao; import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; -import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum; -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; @@ -40,8 +40,6 @@ public class ApplicationAmendmentScheduler { @Autowired private ApplicationAmendmentRequestRepository applicationAmendmentRepository; - @Autowired - private EmailNotificationDao emailNotificationDao; @Autowired private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; @@ -49,6 +47,18 @@ public class ApplicationAmendmentScheduler { @Autowired private LoggingUtil loggingUtil; + @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 * * ?") @@ -79,14 +89,14 @@ public class ApplicationAmendmentScheduler { amendmentRequests.forEach(request -> { try { ApplicationAmendmentRequestEntity oldAmendmentRequestEntity = Utils.getClonedEntityForData(request); - request.setStatus(ApplicationAmendmentRequestEnum.CLOSE.getValue()); + request.setStatus(ApplicationAmendmentRequestEnum.EXPIRED.getValue()); request = applicationAmendmentRepository.save(request); /** 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 CLOSED for ApplicationAmendmentRequest with ID: {}", request.getId()); + 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); @@ -104,6 +114,16 @@ public class ApplicationAmendmentScheduler { 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) { @@ -119,4 +139,35 @@ public class ApplicationAmendmentScheduler { } + 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/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 6eee497f..90ab3ca8 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 @@ -2064,5 +2064,10 @@ + + + + + From 178d36ab42259d41b3bba629111de450a5b4e7b6 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Thu, 2 Jan 2025 12:20:34 +0530 Subject: [PATCH 03/31] Done ticket GEPAFINBE-131 --- .../gepafin/tendermanagement/dao/UserDao.java | 18 +++++++++++------- .../tendermanagement/web/rest/api/UserApi.java | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 7e35957b..e37873f3 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -219,7 +219,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()); @@ -228,15 +228,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 **/ 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 86122344..f2010e90 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) { From 252a019d5f839108a403bca69c747ada387271e4 Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 2 Jan 2025 15:08:20 +0530 Subject: [PATCH 04/31] Changes in beneficiary dashboard api --- .../tendermanagement/dao/DashboardDao.java | 38 ++++++++++++------- .../repositories/CallRepository.java | 2 + 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index 0afc8fc8..c87c863a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -1,23 +1,20 @@ 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.entities.*; import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.Widget1; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.CallRepository; -import net.gepafin.tendermanagement.repositories.CompanyRepository; -import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CompanyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; @Component public class DashboardDao { @@ -33,9 +30,12 @@ public class DashboardDao { @Autowired private CompanyRepository companyRepository; - + @Autowired private CompanyService companyService; + @Autowired + private BeneficiaryPreferredCallRepository beneficiaryPreferredCallRepository; + public SuperAdminWidgetResponseBean getDashboardWidget(UserEntity requestedUserEntity) { SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); @@ -106,14 +106,26 @@ public class DashboardDao { } public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(UserEntity userEntity, - CompanyEntity company) { + CompanyEntity company) { BeneficiaryWidgetResponseBean beneficiaryWidgetResponseBean = BeneficiaryWidgetResponseBean.builder() .numberOfApplications(0L).numberOfCalls(0L).numberOfIntegratedDocuments(0L).build(); - Long activeCalls = callRepository.countByStatusAndHubId(CallStatusEnum.PUBLISH.getValue(), userEntity.getHub().getId()); - if (activeCalls != null) { - beneficiaryWidgetResponseBean.setNumberOfCalls(activeCalls); + UserWithCompanyEntity userWithCompanyEntity = companyService.getUserWithCompany(userEntity.getId(), company.getId()); + + List preferredCalls = beneficiaryPreferredCallRepository + .findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId()); + + if (preferredCalls != null && !preferredCalls.isEmpty()) { + List callIds = preferredCalls.stream() + .map(BeneficiaryPreferredCallEntity::getCallId) + .collect(Collectors.toList()); + List callEntities = callRepository.findByIdIn(callIds); + long activeCallsCount = callEntities.stream() + .filter(call -> CallStatusEnum.PUBLISH.getValue().equals(call.getStatus()) + && userEntity.getHub().getId().equals(call.getHub().getId())) + .count(); + + beneficiaryWidgetResponseBean.setNumberOfCalls(activeCallsCount); } - UserWithCompanyEntity userWithCompanyEntity=companyService.getUserWithCompany(userEntity.getId(),company.getId()); Long activeApplication = applicationRepository.countSubmittedApplicationsByUserId(userEntity.getId(), userWithCompanyEntity.getId()); if (activeApplication != null) { diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java index 833e1d68..938f19f6 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -47,4 +47,6 @@ public interface CallRepository extends JpaRepository { BigDecimal findTotalAmountOfPublishedCallsAndHubId(@Param("hubId") Long hubId); @Query("SELECT c FROM CallEntity c WHERE c.id IN :ids AND c.status IN :status") List findByIdInAndStatusIn(@Param("ids") List ids, @Param("status") List status); + List findByIdIn(@Param("ids") List ids); + } From ab1afaf90aab375fdb9d31380813581160db80ff Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 2 Jan 2025 17:36:05 +0530 Subject: [PATCH 05/31] Updated code --- .../gepafin/tendermanagement/dao/UserDao.java | 20 ++++++----- .../repositories/UserRepository.java | 34 +++++++++++-------- ...template_for_reset_password_28_11_2024.sql | 7 +--- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 6622ca95..1c06ccaf 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -222,21 +222,23 @@ public class UserDao { } } } + private void validateDuplicateEmail(String email, String hubUuid, String roleType) { - Boolean existsForNonBeneficiaries = userRepository.existsByEmailIgnoreCaseForNonBeneficiaries( - email, hubUuid, RoleStatusEnum.ROLE_BENEFICIARY.getValue()); + String beneficiaryRoleType = RoleStatusEnum.ROLE_BENEFICIARY.getValue(); - Boolean beneficiaryExistsInHub = userRepository.existsByEmailIgnoreCaseForBeneficiaries( - email, hubUuid, RoleStatusEnum.ROLE_BENEFICIARY.getValue()); + if (beneficiaryRoleType.equals(roleType)) { + Boolean beneficiaryExistsInHub = userRepository.existsByEmailIgnoreCaseForBeneficiaries( + email, hubUuid, beneficiaryRoleType); - if (Boolean.TRUE.equals(RoleStatusEnum.ROLE_BENEFICIARY.getValue().equals(roleType))) { - if (beneficiaryExistsInHub) { + if (Boolean.TRUE.equals(beneficiaryExistsInHub)) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); } - } - else { - if (existsForNonBeneficiaries) { + } else { + Boolean existsForNonBeneficiaries = userRepository.existsByEmailIgnoreCaseForNonBeneficiaries( + email, hubUuid, beneficiaryRoleType); + + if (Boolean.TRUE.equals(existsForNonBeneficiaries)) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS)); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index ae41b9b1..ab00d3e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -33,24 +33,28 @@ public interface UserRepository extends JpaRepository { Optional findByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); - Boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); +// Boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); - @Query("SELECT COUNT(u) > 0 " + - "FROM UserEntity u " + - "WHERE u.email = :email " + - "AND u.hub.uniqueUuid = :hubUuid " + - "AND u.roleEntity.roleType <> :beneficiaryRoleType") - Boolean existsByEmailIgnoreCaseForNonBeneficiaries(@Param("email") String email, - @Param("hubUuid") String hubUuid, - @Param("beneficiaryRoleType") String beneficiaryRoleType); + @Query("SELECT COUNT(u) > 0 " + + "FROM UserEntity u " + + "WHERE LOWER(u.email) = LOWER(:email) " + + "AND u.hub.uniqueUuid = :hubUuid " + + "AND u.roleEntity.roleType <> :beneficiaryRoleType") + Boolean existsByEmailIgnoreCaseForNonBeneficiaries(@Param("email") String email, + @Param("hubUuid") String hubUuid, + @Param("beneficiaryRoleType") String beneficiaryRoleType); - @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END " + - "FROM UserEntity u " + - "WHERE LOWER(u.email) = LOWER(:email) AND u.hub.uniqueUuid = :hubUuid " + - "AND u.roleEntity.roleType = :beneficiaryRoleType") - Boolean existsByEmailIgnoreCaseForBeneficiaries(String email, String hubUuid, String beneficiaryRoleType); + @Query("SELECT COUNT(u) > 0 " + + "FROM UserEntity u " + + "WHERE LOWER(u.email) = LOWER(:email) " + + "AND u.hub.uniqueUuid = :hubUuid " + + "AND u.roleEntity.roleType = :beneficiaryRoleType") + Boolean existsByEmailIgnoreCaseForBeneficiaries(@Param("email") String email, + @Param("hubUuid") String hubUuid, + @Param("beneficiaryRoleType") String beneficiaryRoleType); - // existsByBebooleanneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); + + boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId); List findByRoleEntity_RoleTypeAndHubId(String roleType, Long hubId); diff --git a/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql b/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql index facb4fdf..927345b0 100644 --- a/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql +++ b/src/main/resources/db/dump/insert_system_email_template_for_reset_password_28_11_2024.sql @@ -20,12 +20,7 @@ VALUES

Gentile {{user_name}},

-

Hai richiesto di reimpostare la tua password. Puoi farlo cliccando sul link sottostante:

- - - - - {{reset_password_link}} +

Hai richiesto di reimpostare la tua password.

From 3a7ca2b2224b083ffa30956a60fb7b030d00626c Mon Sep 17 00:00:00 2001 From: rajesh Date: Thu, 2 Jan 2025 19:22:58 +0530 Subject: [PATCH 06/31] Updated code --- .../tendermanagement/dao/CompanyDao.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 48ec017b..6c5f0856 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -189,15 +189,15 @@ public class CompanyDao { setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry()); setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees, companyRequest.getNumberOfEmployees()); setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, companyRequest.getAnnualRevenue()); - - 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()); - - } +// +// 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. **/ From 0445a371333cbb0128173f2300bcbd0f094893fb Mon Sep 17 00:00:00 2001 From: nisha Date: Fri, 3 Jan 2025 13:15:07 +0530 Subject: [PATCH 07/31] Updated form field data --- .../db/changelog/db.changelog-1.0.0.xml | 7 ++ .../update_form_field_data_03_01_2025.sql | 101 ++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/main/resources/db/dump/update_form_field_data_03_01_2025.sql 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 cf3c3987..1a25de27 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 @@ -2139,5 +2139,12 @@ + + + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + + + diff --git a/src/main/resources/db/dump/update_form_field_data_03_01_2025.sql b/src/main/resources/db/dump/update_form_field_data_03_01_2025.sql new file mode 100644 index 00000000..c3c08ca7 --- /dev/null +++ b/src/main/resources/db/dump/update_form_field_data_03_01_2025.sql @@ -0,0 +1,101 @@ +INSERT INTO FORM_FIELD (SORT_ORDER, NAME, LABEL, DESCRIPTION, SETTINGS, VALIDATORS, CREATED_DATE, UPDATED_DATE) +VALUES +(1, 'textinput', 'Testo Breve', 'Per risposte concise (nomi, titoli, brevi descrizioni)', + '[{"name": "label", "value": "Testo Breve"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(2, 'textarea', 'Testo Lungo', 'Campo di testo esteso per paragrafi, descrizioni, proposte', + '[{"name": "label", "value": "Testo Lungo"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(3, 'wysiwyg', 'Campo di Testo Formattato', 'Editor avanzato per testo con formattazione', + '[{"name": "label", "value": "Testo Formattato"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "minLength": null, "maxLength": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(4, 'numberinput', 'Campo Numerico', 'Per l''inserimento di valori numerici (quantità, importi, percentuali)', + '[{"name": "label", "value": "Numero"}, {"name": "placeholder", "value": "0"}, {"name": "step", "value": "0"},{"name": "isRequestedAmount","value": false}]', + '{"isRequired": false, "min": null, "max": null, "pattern": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(5, 'radio', 'Scelta Singola', 'Gruppo di opzioni per selezione singola', + '[{"name": "label", "value": "Scelta Singola"}, {"name": "options", "value": []}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(6, 'select', 'Menu a Tendina', 'Selezione da opzioni predefinite', + '[{"name": "label", "value": "Menu a Tendina"}, {"name": "options", "value": []}]', + '{"isRequired": false, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(7, 'checkboxes', 'Scelta Multipla', 'Gruppo di opzioni per selezione singola o multipla', + '[{"name": "label", "value": "Scelta Multipla"}, {"name": "options", "value": []}]', + '{"isRequired": false, "min": null, "max": null, "custom": null}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(8, 'switch', 'Casella di Spunta', 'Per selezioni binarie, accettazioni, conferme', + '[{"name": "label", "value": "Casella di Spunta"}]', + '{"isRequired": false}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(9, 'datepicker', 'Data', 'Selezione di data', + '[{"name": "label", "value": "Data"}]', + '{"isRequired": false}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(10, 'fileupload', 'Caricamento File', 'Per l''upload di documenti o immagini', + '[{"name": "label", "value": "Caricamento File"}, {"name": "mime", "value": []}]', + '{"isRequired": false, "maxSize": 100000}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(11, 'textinput', 'Campo Partita IVA', 'Specifico per l''inserimento del numero di Partita IVA', + '[{"name": "label", "value": "Partita IVA"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isPIVA"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(12, 'textinput', 'Campo Codice Fiscale','Specifico per l''inserimento del Codice Fiscale italiano per persone fisiche e giuridiche', + '[{"name": "label", "value": "Codice Fiscale"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCodiceFiscale"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(13, 'textinput', 'Campo CAP','Per l''inserimento del Codice di Avviamento Postale', + '[{"name": "label", "value": "CAP"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isCAP"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(14, 'textinput', 'Campo IBAN', 'Per l''inserimento del codice IBAN', + '[{"name": "label", "value": "IBAN"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": true, "custom": "isIBAN"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(15, 'textinput', 'Campo Email', 'Per l''inserimento di indirizzi email standard (non PEC)', + '[{"name": "label", "value": "Campo Email"}, {"name": "placeholder", "value": "nome@esempio.it"}]', + '{"isRequired": false, "custom": "isEmail"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(16, 'textinput', 'Campo PEC', 'Specifico per l''inserimento di un indirizzo di Posta Elettronica Certificata', + '[{"name": "label", "value": "Campo PEC"}, {"name": "placeholder", "value": "nome@pec.it"}]', + '{"isRequired": false, "custom": "isEmailPEC"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(17, 'textinput', 'Campo URL', 'Per l''inserimento di indirizzi web', + '[{"name": "label", "value": "Indirizzo URL"}, {"name": "placeholder", "value": ""}]', + '{"isRequired": false, "custom": "isUrl"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(18, 'textinput', 'Marca da bollo', 'Per inserire codice di marca da bollo', + '[{"name": "label", "value": "Marca da bollo"}, {"name": "placeholder", "value": "Numero identificativo"}]', + '{"isRequired": false, "custom": "isMarcaDaBollo"}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(19, 'paragraph', 'Paragrafo', 'Semplice testo formattato', + '[{"name": "text", "value": ""}]', + '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +(20, 'table', 'Tabella', 'Tabella', + '[{"name": "label", "value": "Tabella"}, {"name": "table_columns", "value": []}]', + '{}', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); From dd5cf63a16d2a2647f55d0d0f109bb9e415f58ed Mon Sep 17 00:00:00 2001 From: piyushkag Date: Fri, 3 Jan 2025 15:12:44 +0530 Subject: [PATCH 08/31] Websocket config fix. --- .../gepafin/tendermanagement/TendermanagementApplication.java | 3 ++- .../net/gepafin/tendermanagement/config/WebSocketConfig.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java index c220b176..6cdd9142 100644 --- a/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java +++ b/src/main/java/net/gepafin/tendermanagement/TendermanagementApplication.java @@ -23,7 +23,8 @@ 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", "http://127.0.0.1:5500", "https://bandi-staging.memento.credit", "https://bandi.gepafin.it") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD").allowCredentials(true); } } diff --git a/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java b/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java index 1b90a882..0212f720 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/WebSocketConfig.java @@ -33,7 +33,7 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @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/**") + registry.addEndpoint("/wss").setAllowedOrigins("http://localhost:3000", "http://127.0.0.1:5500", "https://bandi-staging.memento.credit", "https://bandi.gepafin.it") .withSockJS(); } } From c687849c933898647988687bccd5c1cf52f06d55 Mon Sep 17 00:00:00 2001 From: rajesh Date: Fri, 3 Jan 2025 19:17:11 +0530 Subject: [PATCH 09/31] Done ticket GEPAFINBE-129 --- .../dao/ApplicationAmendmentRequestDao.java | 2 +- .../dao/ApplicationEvaluationDao.java | 7 ++ .../tendermanagement/dao/DashboardDao.java | 79 ++++++++++++++++++- .../entities/ApplicationEvaluationEntity.java | 3 + .../enums/UserActionContextEnum.java | 1 + .../ApplicationWidgetResponseBean.java | 23 ++++++ .../ApplicationEvaluationRepository.java | 25 ++++++ .../repositories/ApplicationRepository.java | 16 ++++ .../service/DashboardService.java | 3 +- .../service/impl/DashboardServiceImpl.java | 7 ++ .../web/rest/api/DashboardApi.java | 14 +++- .../rest/api/impl/DashboardApiController.java | 10 +++ .../db/changelog/db.changelog-1.0.0.xml | 6 +- 13 files changed, 188 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/ApplicationWidgetResponseBean.java diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java index 2937da2c..e478061e 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationAmendmentRequestDao.java @@ -298,7 +298,7 @@ public class ApplicationAmendmentRequestDao { ApplicationAmendmentRequestEntity applicationAmendment = saveApplicationAmendmentRequestEntity(applicationAmendmentRequestEntity, null, VersionActionTypeEnum.INSERT); String evaluationStatusType = applicationEvaluationEntity.getStatus(); if (Boolean.FALSE.equals(evaluationStatusType.equals((ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue())))){ - applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); +// applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); //Set Status applicationEvaluationEntity.setStatus(ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index aad85864..29fa8814 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -24,7 +24,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import java.time.Duration; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -1778,6 +1780,11 @@ public class ApplicationEvaluationDao { existingEntity.setClosingDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); assignedApplicationsEntity.setStatus(AssignedApplicationEnum.CLOSE.getValue()); } + if (existingEntity.getStartDate() != null && existingEntity.getClosingDate() != null) { + long activeDays = ChronoUnit.DAYS.between(existingEntity.getStartDate(), existingEntity.getClosingDate()); + activeDays -= existingEntity.getSuspendedDays() != null ? existingEntity.getSuspendedDays() : 0; + existingEntity.setActiveDays(activeDays); + } entity = applicationEvaluationRepository.save(existingEntity); assignedApplicationsRepository.save(assignedApplicationsEntity); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index 0afc8fc8..a9caba7b 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -6,18 +6,20 @@ import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.enums.CallStatusEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserStatusEnum; +import net.gepafin.tendermanagement.model.response.ApplicationWidgetResponseBean; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.Widget1; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.CallRepository; -import net.gepafin.tendermanagement.repositories.CompanyRepository; -import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CompanyService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; @Component public class DashboardDao { @@ -37,6 +39,9 @@ public class DashboardDao { @Autowired private CompanyService companyService; + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + public SuperAdminWidgetResponseBean getDashboardWidget(UserEntity requestedUserEntity) { SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); widgetResponseBean.setWidget1(createWidget1(requestedUserEntity)); @@ -121,4 +126,70 @@ public class DashboardDao { } return beneficiaryWidgetResponseBean; } + + public ApplicationWidgetResponseBean getApplicationDetails(UserEntity userEntity) { + ApplicationWidgetResponseBean applicationWidgetResponseBean = initializeResponseBean(); + + Long hubId = userEntity.getHub().getId(); + + setApplicationCounts(applicationWidgetResponseBean, hubId); + calculateEvaluationAverageTime(applicationWidgetResponseBean, hubId); + + return applicationWidgetResponseBean; + } + + private ApplicationWidgetResponseBean initializeResponseBean() { + return ApplicationWidgetResponseBean.builder() + .numberOfApplication(0L) + .numberOfAssignedApplication(0L) + .numberOfAcceptedApplication(0L) + .numberOfApplicationInAmendmentState(0L) + .numberOfDueApplication(0L) + .evaluationAverageTime(BigDecimal.ZERO) + .build(); + } + + private void setApplicationCounts(ApplicationWidgetResponseBean responseBean, Long hubId) { + Long activeApplications = applicationRepository.countApplicationsByHubId(hubId); + if (activeApplications != null) { + responseBean.setNumberOfApplication(activeApplications); + } + + Long assignedApplications = applicationRepository.countAssignedApplicationsByHubId(hubId); + if (assignedApplications != null) { + responseBean.setNumberOfAssignedApplication(assignedApplications); + } + + Long approvedApplications = applicationRepository.countApprovedApplicationsByHubId(hubId); + if (approvedApplications != null) { + responseBean.setNumberOfAcceptedApplication(approvedApplications); + } + + Long soccorsoApplications = applicationRepository.countSoccorsoApplicationsByHubId(hubId); + if (soccorsoApplications != null) { + responseBean.setNumberOfApplicationInAmendmentState(soccorsoApplications); + } + } + + private void calculateEvaluationAverageTime(ApplicationWidgetResponseBean responseBean, Long hubId) { + List applicationIds = applicationRepository.findApplicationIdsByHubId(hubId); + + if (Boolean.FALSE.equals(applicationIds.isEmpty())) { + BigDecimal averageTime = applicationEvaluationRepository.findAverageEvaluationTimeByApplicationIds(applicationIds); + responseBean.setEvaluationAverageTime(averageTime != null ? averageTime : BigDecimal.ZERO); + } + LocalDate twoDaysLater = LocalDate.now().plusDays(2); + + Long dueApplications = applicationEvaluationRepository.countDueApplicationsBetween( + applicationIds, + LocalDate.now(), + twoDaysLater + ); + + if (dueApplications != null) { + responseBean.setNumberOfDueApplication(dueApplications); + } + } + + } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java index 15e3d3d7..6ab7b72c 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEvaluationEntity.java @@ -65,4 +65,7 @@ public class ApplicationEvaluationEntity extends BaseEntity{ @Column(name = "CLOSING_DATE") private LocalDateTime closingDate; + @Column(name = "ACTIVE_DAYS") + private Long activeDays; + } diff --git a/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java index 20f917fe..4a992e31 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/UserActionContextEnum.java @@ -134,6 +134,7 @@ public enum UserActionContextEnum { /** Dashboard action context **/ GET_DASHBOARD_WIDGET_FOR_SUPER_ADMIN("GET_DASHBOARD_WIDGET_FOR_SUPER_ADMIN"), GET_DASHBOARD_WIDGET_FOR_BENEFICIARY("GET_DASHBOARD_WIDGET_FOR_BENEFICIARY"), + GET_APPLICATION_DETAILS("GET_APPLICATION_DETAILS"), /** Evaluation criteria action context **/ GET_EVALUATION_CRITERIA("GET_EVALUATION_CRITERIA"), diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationWidgetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationWidgetResponseBean.java new file mode 100644 index 00000000..c119121b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationWidgetResponseBean.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Builder; +import lombok.Data; + +import java.math.BigDecimal; + +@Builder +@Data +public class ApplicationWidgetResponseBean { + + private Long numberOfApplication; + + private Long numberOfAssignedApplication; + + private Long numberOfAcceptedApplication; + + private Long numberOfApplicationInAmendmentState; + + private Long numberOfDueApplication; + + private BigDecimal evaluationAverageTime; +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java index f9a7b0ac..daaae5a8 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java @@ -7,6 +7,8 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.math.BigDecimal; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -31,4 +33,27 @@ public interface ApplicationEvaluationRepository extends JpaRepository findAllByIsDeletedFalseAndEndDateBefore(@Param("currentDate") LocalDateTime currentDate); +// @Query("SELECT AVG(DATEDIFF(DAY, e.startDate, e.endDate)) FROM ApplicationEvaluationEntity e WHERE e.applicationId IN :applicationIds AND e.startDate IS NOT NULL AND e.endDate IS NOT NULL AND e.isDeleted = false ") + @Query(""" + SELECT AVG(e.activeDays) + FROM ApplicationEvaluationEntity e + WHERE e.applicationId IN :applicationIds + AND e.activeDays IS NOT NULL + AND e.isDeleted = false + """) + BigDecimal findAverageEvaluationTimeByApplicationIds(@Param("applicationIds") List applicationIds); + @Query(""" + SELECT COUNT(e) + FROM ApplicationEvaluationEntity e + WHERE e.applicationId IN :applicationIds + AND FUNCTION('DATE', e.endDate) BETWEEN :startDate AND :endDate + AND e.isDeleted = false +""") + Long countDueApplicationsBetween( + @Param("applicationIds") List applicationIds, + @Param("startDate") LocalDate startDate, + @Param("endDate") LocalDate endDate + ); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index db645f95..3b35e921 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -44,4 +44,20 @@ public interface ApplicationRepository extends JpaRepository findApplicationIdsByHubId(@Param("hubId") Long hubId); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java b/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java index 6328ca6e..0e34c1b6 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.service; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.response.ApplicationWidgetResponseBean; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; @@ -9,5 +10,5 @@ public interface DashboardService { public SuperAdminWidgetResponseBean getDashboardWidgetForSuperAdmin(HttpServletRequest request); public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(HttpServletRequest request, Long companyId); - + public ApplicationWidgetResponseBean getApplicationDetails(HttpServletRequest request); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java index 1a6cd6fd..e578a3dc 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.dao.DashboardDao; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.model.response.ApplicationWidgetResponseBean; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; import net.gepafin.tendermanagement.service.DashboardService; @@ -32,4 +33,10 @@ public class DashboardServiceImpl implements DashboardService { CompanyEntity company = validator.validateUserWithCompany(request, companyId); return dashboardDao.getDashboardWidgetForBeneficiary(userEntity, company); } + + @Override + public ApplicationWidgetResponseBean getApplicationDetails(HttpServletRequest request) { + UserEntity userEntity=validator.validateUser(request); + return dashboardDao.getApplicationDetails(userEntity); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java index 753473f2..e8e99aff 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java @@ -6,6 +6,7 @@ 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.response.ApplicationWidgetResponseBean; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; import net.gepafin.tendermanagement.model.util.Response; @@ -46,7 +47,18 @@ public interface DashboardApi { produces = { "application/json" }) ResponseEntity> getDashboardWidgetForBeneficiary(HttpServletRequest request, @Parameter(description = "The company id", required = true) @PathVariable(value = "companyId", required = true) Long companyId); - + @Operation(summary = "Api to get Application details", + 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", + produces = { "application/json" }) + ResponseEntity> getApplicationDetails(HttpServletRequest request); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java index 7ff7be61..ed1f3d68 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java @@ -6,6 +6,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.UserActionRequest; +import net.gepafin.tendermanagement.model.response.ApplicationWidgetResponseBean; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; import net.gepafin.tendermanagement.model.util.Response; @@ -49,5 +50,14 @@ public class DashboardApiController implements DashboardApi { return ResponseEntity.status(HttpStatus.CREATED) .body(new Response<>(widgetResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY))); } + @Override + public ResponseEntity> getApplicationDetails(HttpServletRequest request) { + /** This code is responsible for creating user action logs for the "Get complete application page" operation. **/ + loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_APPLICATION_DETAILS).build()); + + ApplicationWidgetResponseBean widgetResponseBean= dashboardService.getApplicationDetails(request); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(widgetResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY))); + } } 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 90ab3ca8..f4ad96e7 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 @@ -2069,5 +2069,9 @@ - + + + + + From a63e1bd640e390885fbda00345dbab8777d850f5 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 6 Jan 2025 12:53:01 +0530 Subject: [PATCH 10/31] Done ticket GEPAFINBE-135 --- .../net/gepafin/tendermanagement/dao/ApplicationDao.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 0b0edf19..e281615f 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -295,7 +295,12 @@ public class ApplicationDao { log.info("Deleting application with ID: {}", id); ApplicationEntity applicationEntity= validateApplication(id); - + if (Boolean.FALSE.equals(ApplicationStatusTypeEnum.DRAFT.getValue().equals(applicationEntity.getStatus()))) { + throw new CustomValidationException( + Status.VALIDATION_ERROR, + Translator.toLocale(GepafinConstant.APPLICATION_NOT_IN_DRAFT_STATUS) + ); + } ApplicationEntity oldApplicationDataEntity = Utils.getClonedEntityForData(applicationEntity); validator.validateUserWithCompany(request, applicationEntity.getCompanyId()); From de8196c4617c726a9e9017690555dbb87223859b Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 6 Jan 2025 13:11:02 +0530 Subject: [PATCH 11/31] Updated code --- .../net/gepafin/tendermanagement/web/rest/api/DashboardApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java index e8e99aff..31ae1be3 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java @@ -59,6 +59,7 @@ public interface DashboardApi { @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) @GetMapping(value = "/application", produces = { "application/json" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN') || hasRole('ROLE_INSTRUCTOR_MANAGER')") ResponseEntity> getApplicationDetails(HttpServletRequest request); } From 5e293c43e68d457a161eb00abd26c47ca74d7db2 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Mon, 6 Jan 2025 15:57:30 +0530 Subject: [PATCH 12/31] Added prod config for NDG. --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index df295088..07dd31ff 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -24,7 +24,7 @@ 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.base.url=https://prd.galileonetwork.it/gateway/rest appointment.portal.user=UtenzaAPIPortal@621 appointment.portal.password=u13nzaAP1P0rtal appointment.portal.source=GEPAFINPORTAL From de85d6ba90d535b3ab326f4c10761c71bf825393 Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 6 Jan 2025 17:20:42 +0530 Subject: [PATCH 13/31] Done ticket GEPAFINBE-138 --- .../tendermanagement/dao/VatCheckDao.java | 51 +++++++++++++------ .../gepafin/tendermanagement/util/Utils.java | 19 +++++++ 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java index 85af1388..4d74fb71 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/VatCheckDao.java @@ -68,25 +68,46 @@ public class VatCheckDao { if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) { log.info("Successfully checked vat number"); Map responseMap = response.getBody(); - if (responseMap != null && responseMap.containsKey("data")) { - responseBody = (Map) responseMap.get("data"); - responseBody.remove("timestamp_creation"); - responseBody.remove("timestamp_last_update"); - responseBody.remove("data_iscrizione"); - responseBody.remove("id"); - Map data = new LinkedHashMap<>(); - data.put("data", responseBody); - vatCheckResponseBean.setValid(true); - vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.VALID_VATNUMBER_MSG)); - vatCheckResponseBean.setVatCheckResponse(data); - } + processValidResponse(responseMap, vatCheckResponseBean); } } catch (FeignException ex) { - log.error("Exception occurred while checking vat number: {0}", ex); - Utils.callException(ex.status(), ex); - } + if (ex.status() == 406) { + try { + Map errorResponse = Utils.parseErrorResponse(ex.contentUTF8()); + processValidResponse(errorResponse, vatCheckResponseBean); + } catch (Exception parseEx) { + log.error("Failed to parse 406 error response: {0}", parseEx); + } + } else { + log.error("Exception occurred while checking vat number: {0}", ex); + Utils.callException(ex.status(), ex); + } + } return vatCheckResponseBean; } + public static void processValidResponse(Map responseMap, VatCheckResponseBean vatCheckResponseBean) { + if (responseMap != null && responseMap.containsKey("data")) { + Map responseBody = (Map) responseMap.get("data"); + + if (responseBody != null) { + responseBody.remove("timestamp_creation"); + responseBody.remove("timestamp_last_update"); + responseBody.remove("data_iscrizione"); + responseBody.remove("id"); + + Map data = new LinkedHashMap<>(); + data.put("data", responseBody); + + vatCheckResponseBean.setValid(true); + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.VALID_VATNUMBER_MSG)); + vatCheckResponseBean.setVatCheckResponse(data); + } else { + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + } + } else { + vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + } + } public VatCheckResponseBean checkVatNumber(String vatNumber) { try { diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index fb15759f..40f95e3b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -24,6 +24,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; @@ -697,4 +698,22 @@ public class Utils { public static String createChannelForUserAndCompany(Long userId, Long companyId) { return GepafinConstant.COMMON_SINGLE_CHANNEL_PREFIX + userId + GepafinConstant.COMPANY_PREFIX + companyId; } + + public static Map parseErrorResponse(String responseBody) { + if (StringUtils.isBlank(responseBody)) { + return defaultErrorResponse(); + } + try { + return mapper.readValue(responseBody, Map.class); + } catch (Exception e) { + log.error("Failed to parse error response: {}", e.getMessage(), e); + return defaultErrorResponse(); + } + } + + private static Map defaultErrorResponse() { + return Collections.singletonMap("message", Translator.toLocale(GepafinConstant.INVALID_VATNUMBER)); + } + + } \ No newline at end of file From 184cda9fd24c3203cd85bf6b0973832fb99a73a1 Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 7 Jan 2025 12:25:28 +0530 Subject: [PATCH 14/31] removed code smells --- .../ApplicationAmendmentScheduler.java | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java index 045dfd45..6a4c7b81 100644 --- a/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/ApplicationAmendmentScheduler.java @@ -6,29 +6,23 @@ import net.gepafin.tendermanagement.dao.NotificationDao; 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; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.AssignedApplicationsEntity; -import net.gepafin.tendermanagement.enums.*; 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 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 jakarta.servlet.http.HttpServletRequest; -import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; 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; @@ -40,25 +34,9 @@ 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 { @@ -82,9 +60,6 @@ public class ApplicationAmendmentScheduler { @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; - @Autowired - private ApplicationService applicationService; - @Autowired private ApplicationRepository applicationRepository; From af5d31b9fe46f31d8607899f18ab37df9027a242 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Tue, 7 Jan 2025 13:15:25 +0530 Subject: [PATCH 15/31] Done ticket GEPAFINBE-133 User action api response. --- pom.xml | 6 + .../config/JacksonConfig.java | 20 +++ .../constants/GepafinConstant.java | 5 + .../repositories/UserActionsRepository.java | 2 +- .../tendermanagement/util/LoggingUtil.java | 40 ++++- .../util/UserActionAspect.java | 148 ++++++++++++++++++ .../gepafin/tendermanagement/util/Utils.java | 3 + 7 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/util/UserActionAspect.java diff --git a/pom.xml b/pom.xml index c463be91..02b5fb51 100644 --- a/pom.xml +++ b/pom.xml @@ -245,6 +245,12 @@ reactor-netty + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.15.2 + + diff --git a/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java b/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java new file mode 100644 index 00000000..51ad3191 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new JavaTimeModule()); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + return mapper; + } +} + diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 42853112..5869fc81 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -355,5 +355,10 @@ public class GepafinConstant { 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"; + + //action log response + public static final String STATUS_CODE_STRING = "statusCode"; + public static final String GET_STATUS_CODE_STRING = "status"; + public static final String MESSAGE_STRING = "message"; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java index f0163c47..804fdb9b 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java @@ -6,5 +6,5 @@ import org.springframework.stereotype.Repository; @Repository public interface UserActionsRepository extends JpaRepository { - UserActionEntity findUserActionById(Long id); + UserActionEntity findUserActionByIdAndIsDeletedFalse(Long id); } diff --git a/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java b/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java index e2ab4521..90b7a052 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java +++ b/src/main/java/net/gepafin/tendermanagement/util/LoggingUtil.java @@ -41,6 +41,8 @@ public class LoggingUtil { @Autowired private TokenProvider tokenProvider; + private static final ThreadLocal userActionIdHolder = new ThreadLocal<>(); + public UserActionEntity logUserAction(UserActionRequest userActionRequest) { UserActionEntity userAction = new UserActionEntity(); try { @@ -83,12 +85,22 @@ public class LoggingUtil { userAction.setResponse(response); userActionsRepository.save(userAction); userActionRequest.getRequest().setAttribute(GepafinConstant.USER_ACTION_ID, userAction.getId()); + userActionIdHolder.set(userAction.getId()); } catch (Exception e) { log.error("Error logging user action: {}", e.getMessage(), e); } return userAction; } + public Long getUserActionId() { + return userActionIdHolder.get(); + } + + public void clearUserActionId() { + userActionIdHolder.remove(); + log.info("UserActionId cleared from ThreadLocal"); + } + private String normalizeUrl(String url) { url = url.replaceAll("(? getVersionHistoryLogById(Long id) { return versionHistoryRepository.findVersionHistoryByUserActionId(id); } + + public void updateUserActionWithError(Long userActionId, String errorDetails) { + if (userActionId == null) { + return; + } + + UserActionEntity userAction = userActionsRepository.findUserActionByIdAndIsDeletedFalse(userActionId); + if (userAction != null) { + userAction.setResponse(errorDetails); + userActionsRepository.save(userAction); + } + } + + public void updateUserActionWithResponse(Long userActionId, String response) { + if (userActionId == null) { + return; + } + + UserActionEntity userAction = userActionsRepository.findUserActionByIdAndIsDeletedFalse(userActionId); + if (userAction != null) { + userAction.setResponse(response); + userActionsRepository.save(userAction); + } + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/util/UserActionAspect.java b/src/main/java/net/gepafin/tendermanagement/util/UserActionAspect.java new file mode 100644 index 00000000..0064bb82 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/util/UserActionAspect.java @@ -0,0 +1,148 @@ +package net.gepafin.tendermanagement.util; + +import com.amazonaws.services.alexaforbusiness.model.UnauthorizedException; +import jakarta.persistence.EntityNotFoundException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.constants.GepafinConstant; +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.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.server.ResponseStatusException; + +import java.lang.reflect.InvocationTargetException; +import java.nio.file.AccessDeniedException; +import java.util.LinkedHashMap; +import java.util.Map; + +@Aspect +@Component +@Slf4j +public class UserActionAspect { + + @Autowired + private LoggingUtil loggingUtil; + + @Around("execution(public * net.gepafin.tendermanagement.web.rest.api.impl..*(..))") + public Object logApiResponse(ProceedingJoinPoint joinPoint) throws Throwable { + + Object result; + + HttpServletRequest request = getRequestFromContext(); + try { + Long userActionId = getUserActionIdFromRequest(request); + + if (userActionId != null) { + request.setAttribute(GepafinConstant.USER_ACTION_ID, userActionId); + log.info("Stored userActionId in RequestContext: {}", userActionId); + } else { + userActionId = loggingUtil.getUserActionId(); + if (userActionId != null) { + request.setAttribute(GepafinConstant.USER_ACTION_ID, userActionId); + } + } + + result = joinPoint.proceed(); + + if (result instanceof ResponseEntity) { + Long storedUserActionId = (Long) request.getAttribute(GepafinConstant.USER_ACTION_ID); + handleSuccessResponse((ResponseEntity) result, storedUserActionId == null ? userActionId : storedUserActionId); + } + } catch (Exception ex) { + log.error("Exception occurred: ", ex); + handleError(ex, getUserActionIdFromRequest(request)); + throw ex; + } finally { + loggingUtil.clearUserActionId(); + } + + return result; + } + + private void handleSuccessResponse(ResponseEntity responseEntity, Long userActionId) { + + if (userActionId != null) { + Map responseWithUserAction = new LinkedHashMap<>(); + responseWithUserAction.put(GepafinConstant.STATUS_CODE_STRING, responseEntity.getStatusCode().value()); + + // Log and update user action + loggingUtil.updateUserActionWithResponse(userActionId, Utils.convertMapIntoJsonString(responseWithUserAction)); + log.info("Updated userActionId with response: {}", userActionId); + } + } + + private void handleError(Throwable ex, Long userActionId) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { + + HttpStatus status = getStatusCodeFromException(ex); + log.info("Status Code received from exception : {}", status); + String errorMessage = ex.getMessage(); + + Map errorResponse = new LinkedHashMap<>(); + errorResponse.put(GepafinConstant.STATUS_CODE_STRING, status.value()); + errorResponse.put(GepafinConstant.GET_STATUS_CODE_STRING, status); + errorResponse.put(GepafinConstant.MESSAGE_STRING, errorMessage); + + if (userActionId != null) { + String errorDetails = Utils.convertMapIntoJsonString(errorResponse); + loggingUtil.updateUserActionWithError(userActionId, errorDetails); + log.info("Updated userActionId with error details: {}", userActionId); + } + } + + private HttpServletRequest getRequestFromContext() { + + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + return attributes != null ? attributes.getRequest() : null; + } + + private Long getUserActionIdFromRequest(HttpServletRequest request) { + + if (request != null) { + Object userActionIdAttr = request.getAttribute(GepafinConstant.USER_ACTION_ID); + return userActionIdAttr != null ? Long.valueOf(userActionIdAttr.toString()) : null; + } + return null; + } + + private HttpStatus getStatusCodeFromException(Throwable ex) { + + if (ex instanceof ResourceNotFoundException) { + return HttpStatus.NOT_FOUND; + } + + if (ex instanceof ResponseStatusException responseStatusException) { + return (HttpStatus) responseStatusException.getStatusCode(); + } + + if (ex instanceof CustomValidationException) { + return HttpStatus.BAD_REQUEST; + } + + if (ex instanceof EntityNotFoundException) { + return HttpStatus.NOT_FOUND; + } + if (ex instanceof IllegalArgumentException || ex instanceof MissingServletRequestParameterException || ex instanceof MethodArgumentNotValidException) { + return HttpStatus.BAD_REQUEST; + } + if (ex instanceof AccessDeniedException) { + return HttpStatus.FORBIDDEN; + } + if (ex instanceof UnauthorizedException) { + return HttpStatus.UNAUTHORIZED; + } + + return HttpStatus.INTERNAL_SERVER_ERROR; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index 40f95e3b..0770bce5 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -154,6 +154,9 @@ public class Utils { public static String convertMapIntoJsonString(Map map) { try { ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new JavaTimeModule()); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.INDENT_OUTPUT); if (MapUtils.isNotEmpty(map)) { return mapper.writeValueAsString(map); } From b4d8ad45f2b79b20fc56a3fedb665c792def2430 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Tue, 7 Jan 2025 14:10:53 +0530 Subject: [PATCH 16/31] Added config for frame error on FE. --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 8c11eac2..61f84825 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -12,6 +12,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @@ -97,7 +98,9 @@ public class SecurityConfig { } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(auth -> auth + http.csrf(AbstractHttpConfigurer::disable).headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin) + .contentSecurityPolicy(csp -> csp.policyDirectives("frame-ancestors 'self' https://bandi-staging.memento.credit, https://bandi.gepafin.it"))) + .authorizeHttpRequests(auth -> auth // Allow public access to the login endpoints .requestMatchers("/v1/user/login").permitAll() // JWT-based login .requestMatchers("/v1/user").permitAll() // User registration From c53b7e59d3e380087dd5df27da5722619c1f930d Mon Sep 17 00:00:00 2001 From: piyushkag Date: Tue, 7 Jan 2025 14:14:54 +0530 Subject: [PATCH 17/31] Updated cnfig code. --- .../net/gepafin/tendermanagement/config/SecurityConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java index 61f84825..462d5cc9 100644 --- a/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java +++ b/src/main/java/net/gepafin/tendermanagement/config/SecurityConfig.java @@ -99,7 +99,7 @@ public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable).headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin) - .contentSecurityPolicy(csp -> csp.policyDirectives("frame-ancestors 'self' https://bandi-staging.memento.credit, https://bandi.gepafin.it"))) + .contentSecurityPolicy(csp -> csp.policyDirectives("frame-ancestors 'self' https://bandi-staging.memento.credit https://bandi.gepafin.it"))) .authorizeHttpRequests(auth -> auth // Allow public access to the login endpoints .requestMatchers("/v1/user/login").permitAll() // JWT-based login From e28a9f2662e1a1f59f7a57a59bf25df8389c7805 Mon Sep 17 00:00:00 2001 From: Piyush Date: Tue, 7 Jan 2025 17:29:05 +0530 Subject: [PATCH 18/31] Done ticket GEPAFINBE-89 --- .../entities/ExpirationConfigEntity.java | 21 +++ .../enums/ExpirationTypeEnum.java | 20 +++ .../enums/NotificationTypeEnum.java | 4 +- ...ApplicationAmendmentRequestRepository.java | 6 + .../ApplicationEvaluationRepository.java | 7 + .../ExpirationConfigRepository.java | 13 ++ .../scheduler/ExpirationScheduler.java | 125 ++++++++++++++++++ .../db/changelog/db.changelog-1.0.0.xml | 25 ++++ ...t_expiration_scheduler_data_07_01_2025.sql | 9 ++ ...n_template_for_notification_03_01_2025.sql | 3 + 10 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/ExpirationConfigEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/ExpirationTypeEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/ExpirationConfigRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/scheduler/ExpirationScheduler.java create mode 100644 src/main/resources/db/dump/insert_expiration_scheduler_data_07_01_2025.sql create mode 100644 src/main/resources/db/dump/update_json_template_for_notification_03_01_2025.sql diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ExpirationConfigEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ExpirationConfigEntity.java new file mode 100644 index 00000000..83159e3a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/ExpirationConfigEntity.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "expiration_config") +@Data +public class ExpirationConfigEntity extends BaseEntity { + + @Column(name="INTERVAL_DAYS") + private Long intervalDays; + + @Column(name="TYPE") + private String type; + + @Column(name="IS_DELETED") + private Boolean isDeleted; +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/ExpirationTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/ExpirationTypeEnum.java new file mode 100644 index 00000000..2aaa1ae2 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/ExpirationTypeEnum.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ExpirationTypeEnum { + + AMENDMENT("AMENDMENT"), + EVALUATION("EVALUATION"); + + private String value; + + ExpirationTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java index 54a13768..96d89e91 100644 --- a/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java +++ b/src/main/java/net/gepafin/tendermanagement/enums/NotificationTypeEnum.java @@ -11,7 +11,9 @@ public enum NotificationTypeEnum { AMENDMENT_CLOSED("AMENDMENT_CLOSED"), NDG_GENERATION("NDG_GENERATION"), EVALUATION_CREATION("EVALUATION_CREATION"), - EVALUATION_EXPIRED("EVALUATION_EXPIRED"); + EVALUATION_EXPIRED("EVALUATION_EXPIRED"), + AMENDMENT_EXPIRATION_REMINDER("AMENDMENT_EXPIRATION_REMINDER"), + EVALUATION_EXPIRATION_REMINDER("EVALUATION_EXPIRATION_REMINDER"); private final String value; diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java index 68133efb..3c89993c 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationAmendmentRequestRepository.java @@ -74,4 +74,10 @@ public interface ApplicationAmendmentRequestRepository extends JpaRepository findEvaluationsWithoutActiveAmendmentsByIds(@Param("applicationEvaluationIds") Set applicationEvaluationIds); + @Query("SELECT a FROM ApplicationAmendmentRequestEntity a " + + "WHERE a.isDeleted = false " + + "AND a.status NOT IN ('CLOSE', 'EXPIRED') " + + "AND a.endDate BETWEEN :startTime AND :endTime") + List findExpiringBetween(LocalDateTime startTime, LocalDateTime endTime); + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java index f9a7b0ac..e5373f5c 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationEvaluationRepository.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.ApplicationEntity; +import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity; import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -31,4 +32,10 @@ public interface ApplicationEvaluationRepository extends JpaRepository findAllByIsDeletedFalseAndEndDateBefore(@Param("currentDate") LocalDateTime currentDate); + + @Query("SELECT a FROM ApplicationEvaluationEntity a " + + "WHERE a.isDeleted = false " + + "AND a.status NOT IN ('CLOSE', 'EXPIRED') " + + "AND a.endDate BETWEEN :startTime AND :endTime") + List findExpiringBetween(LocalDateTime startTime, LocalDateTime endTime); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ExpirationConfigRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ExpirationConfigRepository.java new file mode 100644 index 00000000..21c7b975 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ExpirationConfigRepository.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.ExpirationConfigEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ExpirationConfigRepository extends JpaRepository { + List findByTypeAndIsDeletedFalse(String type); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/scheduler/ExpirationScheduler.java b/src/main/java/net/gepafin/tendermanagement/scheduler/ExpirationScheduler.java new file mode 100644 index 00000000..60025630 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/scheduler/ExpirationScheduler.java @@ -0,0 +1,125 @@ +package net.gepafin.tendermanagement.scheduler; + +import net.gepafin.tendermanagement.dao.ApplicationAmendmentRequestDao; +import net.gepafin.tendermanagement.dao.ApplicationEvaluationDao; +import net.gepafin.tendermanagement.dao.NotificationDao; +import net.gepafin.tendermanagement.entities.*; +import net.gepafin.tendermanagement.enums.ExpirationTypeEnum; +import net.gepafin.tendermanagement.enums.NotificationTypeEnum; +import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; +import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; +import net.gepafin.tendermanagement.repositories.ExpirationConfigRepository; +import net.gepafin.tendermanagement.service.ApplicationService; +import net.gepafin.tendermanagement.service.CompanyService; +import net.gepafin.tendermanagement.service.UserService; +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.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ExpirationScheduler { + + @Autowired + private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; + + @Autowired + private ApplicationEvaluationRepository applicationEvaluationRepository; + + @Autowired + private ExpirationConfigRepository expirationNotificationConfigRepository; + + @Autowired + private ApplicationEvaluationDao applicationEvaluationDao; + + @Autowired + private ApplicationAmendmentRequestDao applicationAmendmentRequestDao; + + @Autowired + private UserService userService; + + @Autowired + private ApplicationService applicationService; + + @Autowired + private NotificationDao notificationDao; + + @Autowired + private CompanyService companyService; + + private static final Logger log = LoggerFactory.getLogger(ExpirationScheduler.class); + + @Scheduled(cron = "0 0 3 * * ?") + public void processExpiration(){ + log.info("Starting the Expiration scheduler..."); + try { + Utils.setHttpServletRequestForScheduler(); + + log.info("Starting processing expiration notifications for Amendment"); + processExpiration(ExpirationTypeEnum.AMENDMENT); + + log.info("Starting processing expiration notifications for Evaluation"); + processExpiration(ExpirationTypeEnum.EVALUATION); + + log.info("Expiration scheduler completed successfully."); + + } + catch (Exception e){ + log.error("An error occurred during the Notification Expiration Scheduler: {}", e.getMessage(), e); + } + } + + private void processExpiration(ExpirationTypeEnum type) { + List configEntities = expirationNotificationConfigRepository.findByTypeAndIsDeletedFalse(type.getValue()); + + for (ExpirationConfigEntity config : configEntities) { + Long daysBefore = config.getIntervalDays(); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime startDate = now.plusDays(daysBefore).withHour(0).withMinute(0).withSecond(0).withNano(0); + LocalDateTime endDate = startDate.plusDays(1).minusNanos(1).withNano(0); + + if (ExpirationTypeEnum.AMENDMENT.equals(type)) { + processAmendmentExpiration(startDate, endDate, daysBefore); + } else if (ExpirationTypeEnum.EVALUATION.equals(type)) { + processEvaluationExpiration(startDate, endDate, daysBefore); + } + } + } + + private void processAmendmentExpiration(LocalDateTime startDate, LocalDateTime endDate, Long daysBefore) { + List amendmentEntities = applicationAmendmentRequestRepository.findExpiringBetween(startDate, endDate); + + for (ApplicationAmendmentRequestEntity entity : amendmentEntities) { + ApplicationEntity application = entity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication(); + Map placeHolders = replacePlaceholders(application,daysBefore); + notificationDao.sendNotificationToInstructor(placeHolders,entity.getApplicationEvaluationEntity(), NotificationTypeEnum.AMENDMENT_EXPIRATION_REMINDER); + } + } + + private Map replacePlaceholders (ApplicationEntity application, Long daysBefore){ + Long companyId = application.getCompanyId(); + CompanyEntity company = companyService.validateCompany(companyId); + Map placeHolders = new HashMap<>(); + placeHolders.put("{{call_name}}",application.getCall().getName()); + placeHolders.put("{{company_name}}", company.getCompanyName()); + placeHolders.put("{{days_before}}", daysBefore.toString()); + return placeHolders; + } + + private void processEvaluationExpiration(LocalDateTime startDate, LocalDateTime endDate, Long daysBefore) { + List evaluationEntities = applicationEvaluationRepository.findExpiringBetween(startDate, endDate); + + for (ApplicationEvaluationEntity entity : evaluationEntities) { + ApplicationEntity application = entity.getAssignedApplicationsEntity().getApplication(); + Map placeHolders = replacePlaceholders(application,daysBefore); + notificationDao.sendNotificationToInstructor(placeHolders,entity,NotificationTypeEnum.EVALUATION_EXPIRATION_REMINDER); + } + } +} 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 cf3c3987..b62336e2 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 @@ -2140,4 +2140,29 @@ path="db/dump/update_json_template_for_notification_31_12_2024.sql"/> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/dump/insert_expiration_scheduler_data_07_01_2025.sql b/src/main/resources/db/dump/insert_expiration_scheduler_data_07_01_2025.sql new file mode 100644 index 00000000..dca8f3a1 --- /dev/null +++ b/src/main/resources/db/dump/insert_expiration_scheduler_data_07_01_2025.sql @@ -0,0 +1,9 @@ + +INSERT INTO expiration_config (interval_days, type, created_date, updated_date) +VALUES +(5, 'AMENDMENT', '2024-12-03T11:00:51', '2024-12-03T11:00:51'), +(2, 'AMENDMENT', '2024-12-03T11:00:51', '2024-12-03T11:00:51'), +(0, 'AMENDMENT', '2024-12-03T11:00:51', '2024-12-03T11:00:51'), +(5, 'EVALUATION', '2024-12-03T11:00:51', '2024-12-03T11:00:51'), +(2, 'EVALUATION', '2024-12-03T11:00:51', '2024-12-03T11:00:51'), +(0, 'EVALUATION', '2024-12-03T11:00:51', '2024-12-03T11:00:51'); diff --git a/src/main/resources/db/dump/update_json_template_for_notification_03_01_2025.sql b/src/main/resources/db/dump/update_json_template_for_notification_03_01_2025.sql new file mode 100644 index 00000000..06bf6aa0 --- /dev/null +++ b/src/main/resources/db/dump/update_json_template_for_notification_03_01_2025.sql @@ -0,0 +1,3 @@ +INSERT INTO notification_type (notification_name,title, json_template,created_date,updated_date,is_deleted) VALUES +('AMENDMENT_EXPIRATION_REMINDER','Lemendamento sta per scadere','Lemendamento per {{call_name}} - {{company_name}} scadrà tra {{days_before}} giorni. Assicurati che tutte le azioni necessarie siano completate prima della scadenza.','2025-01-03T10:16:26.472Z','2025-01-03T10:16:26.472Z','false'), +('EVALUATION_EXPIRATION_REMINDER','La valutazione sta per scadere','Lemendamento per {{call_name}} - {{company_name}} scadrà tra {{days_before}} giorni. Assicurati che tutte le azioni necessarie siano completate prima della scadenza.','2025-01-03T10:16:26.472Z','2025-01-03T10:16:26.472Z','false'); \ No newline at end of file From 887100ed74eb05b4dceb2234b15ad3581c8718be Mon Sep 17 00:00:00 2001 From: rajesh Date: Tue, 7 Jan 2025 18:17:23 +0530 Subject: [PATCH 19/31] Fixed issue during user creation from SPID --- src/main/java/net/gepafin/tendermanagement/dao/UserDao.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java index 1c06ccaf..0ffa0b42 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java @@ -190,6 +190,8 @@ public class UserDao { userReq.setHubUuid(userEntity.getHub().getUniqueUuid()); }else { samlSuccessHandler.validateToken(tempToken, userReq.getCodiceFiscale(), userReq.getHubUuid()); + RoleEntity roleEntity = roleDao.getRoleByType(RoleStatusEnum.ROLE_BENEFICIARY); + userReq.setRoleId(roleEntity.getId()); } if (Boolean.FALSE.equals(Utils.isValidEmail(userReq.getEmail()))) { From 8bb1ec0d02616642d919af2f64f1060b6bc9859a Mon Sep 17 00:00:00 2001 From: rajesh Date: Wed, 8 Jan 2025 15:58:25 +0530 Subject: [PATCH 20/31] Updated jackson config --- pom.xml | 6 ------ .../config/JacksonConfig.java | 20 ------------------- 2 files changed, 26 deletions(-) delete mode 100644 src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java diff --git a/pom.xml b/pom.xml index 02b5fb51..c463be91 100644 --- a/pom.xml +++ b/pom.xml @@ -245,12 +245,6 @@ reactor-netty - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - 2.15.2 - - diff --git a/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java b/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java deleted file mode 100644 index 51ad3191..00000000 --- a/src/main/java/net/gepafin/tendermanagement/config/JacksonConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.gepafin.tendermanagement.config; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class JacksonConfig { - - @Bean - public ObjectMapper objectMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new JavaTimeModule()); - mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); - return mapper; - } -} - From 179b076a8f4f3dee06e9f5b7aca6c234d2ef3f68 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Wed, 8 Jan 2025 17:11:45 +0530 Subject: [PATCH 21/31] Added RabbitMQ config for production. --- src/main/resources/application-production.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 07dd31ff..2cbd72a3 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -32,7 +32,8 @@ appointment.portal.context=GEPAFINPORTAL flagDaFirmare=true # RabbitMQ properties for STOMP broker relay for Notification -spring.rabbitmq.host=rabbitmq.bflows.ai +#spring.rabbitmq.host=rabbitmq.bflows.ai +spring.rabbitmq.host=172.21.0.2 spring.rabbitmq.port=61613 spring.rabbitmq.username=guest spring.rabbitmq.password=guest From 3cf0e1dfef1eb792c64d4befbe8726ef2d9d65f3 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Wed, 8 Jan 2025 19:06:56 +0530 Subject: [PATCH 22/31] Updated rabbitMq config. --- src/main/resources/application-production.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 2cbd72a3..c6a9cce8 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -33,7 +33,7 @@ flagDaFirmare=true # RabbitMQ properties for STOMP broker relay for Notification #spring.rabbitmq.host=rabbitmq.bflows.ai -spring.rabbitmq.host=172.21.0.2 +spring.rabbitmq.host=172.18.0.5 spring.rabbitmq.port=61613 spring.rabbitmq.username=guest spring.rabbitmq.password=guest From 609bb7d99aa549c6cf974ba4b48f8ba0fbc56360 Mon Sep 17 00:00:00 2001 From: nisha Date: Wed, 8 Jan 2025 20:09:47 +0530 Subject: [PATCH 23/31] Code for dashbaord API --- .../tendermanagement/dao/DashboardDao.java | 67 +++++++++++++++++-- .../SuperAdminWidgetResponseBean.java | 7 +- .../model/response/Widget1.java | 4 ++ .../repositories/ApplicationRepository.java | 13 +++- .../repositories/CallRepository.java | 5 ++ .../repositories/UserActionsRepository.java | 28 ++++++++ .../db/changelog/db.changelog-1.0.0.xml | 8 +++ 7 files changed, 123 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index 0afc8fc8..05bf687d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -1,6 +1,7 @@ package net.gepafin.tendermanagement.dao; import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.UserActionEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.enums.CallStatusEnum; @@ -9,15 +10,18 @@ import net.gepafin.tendermanagement.enums.UserStatusEnum; import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; import net.gepafin.tendermanagement.model.response.Widget1; import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; -import net.gepafin.tendermanagement.repositories.ApplicationRepository; -import net.gepafin.tendermanagement.repositories.CallRepository; -import net.gepafin.tendermanagement.repositories.CompanyRepository; -import net.gepafin.tendermanagement.repositories.UserRepository; +import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CompanyService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Component public class DashboardDao { @@ -37,11 +41,15 @@ public class DashboardDao { @Autowired private CompanyService companyService; + @Autowired + private UserActionsRepository userActionsRepository; + public SuperAdminWidgetResponseBean getDashboardWidget(UserEntity requestedUserEntity) { SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); widgetResponseBean.setWidget1(createWidget1(requestedUserEntity)); -// List widgetBars = callRepository.findApplicationsPerCall(); -// widgetResponseBean.setWidgetBars(widgetBars); + Map widgetBars =getStatistics(requestedUserEntity); + widgetResponseBean.setWidgetBars(widgetBars); + widgetResponseBean.setUserActionWidgetList(getUserAction(requestedUserEntity)); return widgetResponseBean; } @@ -54,7 +62,8 @@ public class DashboardDao { setSubmittedApplications(widget1, requestedUserEntity); setDraftApplications(widget1, requestedUserEntity); setNumberOfCompanies(widget1, requestedUserEntity); - + setAmountRequested(widget1,requestedUserEntity); + setAmountAccepted(widget1,requestedUserEntity); return widget1; } @@ -71,6 +80,20 @@ public class DashboardDao { } } + private void setAmountRequested(Widget1 widget1, UserEntity requestedUserEntity) { + BigDecimal amountRequested = callRepository.findTotalAmountOfPublishedCalls(requestedUserEntity.getHub().getId()); + if (amountRequested != null) { + widget1.setAmountRequested(amountRequested); + } + } + + private void setAmountAccepted(Widget1 widget1, UserEntity requestedUserEntity) { + BigDecimal amountAccepted = applicationRepository.findTotalApprovedApplicationAmount(requestedUserEntity.getHub().getId()); + if (amountAccepted != null) { + widget1.setAmountAccepted(amountAccepted); + } + } + private void setRegisteredUsers(Widget1 widget1, UserEntity requestedUserEntity) { Long activeUsers = userRepository.countByStatusAndRoleEntityRoleTypeAndHubId(UserStatusEnum.ACTIVE.getValue(), RoleStatusEnum.ROLE_BENEFICIARY.getValue(), requestedUserEntity.getHub().getId()); @@ -121,4 +144,34 @@ public class DashboardDao { } return beneficiaryWidgetResponseBean; } + + public Map getStatistics(UserEntity requestedUser) { + Map stats = new HashMap<>(); + + // Get applications per call + List applicationsPerCall = applicationRepository.findApplicationsPerCallWithName(requestedUser.getHub().getId()); + stats.put("APPLICATION_PER_CALL", applicationsPerCall.stream().map(result -> { + Map callData = new HashMap<>(); + callData.put("CALL", result[0]); // Call name + callData.put("APPLICATIONS", result[1]); // Application count + return callData; + }).toList()); + + // Get applications grouped by status + List applicationsByStatus = applicationRepository.findApplicationsByStatus(requestedUser.getHub().getId()); + stats.put("APPLICATION_STATUSES", applicationsByStatus.stream().map(result -> { + Map statusData = new HashMap<>(); + statusData.put("STATUS", result[0]); // Application status + statusData.put("COUNT", result[1]); // Count of applications + return statusData; + }).toList()); + + return stats; + } + public Page getUserAction(UserEntity requestedUserEntity){ + Pageable pageable = PageRequest.of(0, 20); // Get the first 20 records + List roles=List.of(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue(),RoleStatusEnum.ROLE_GEPAFIN_OPERATOR.getValue(),RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()); + Page userActionEntities=userActionsRepository.findActionsByRoleNamesAndHubId(roles,requestedUserEntity.getHub().getId(),pageable); + return userActionEntities; + } } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java index 6ed30e56..405a92ac 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java @@ -1,14 +1,19 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; +import net.gepafin.tendermanagement.entities.UserActionEntity; +import org.springframework.data.domain.Page; import java.util.List; +import java.util.Map; @Data public class SuperAdminWidgetResponseBean { private Widget1 widget1; -// private List widgetBars; + private Map widgetBars; + + Page userActionWidgetList; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java index 75c68758..0d82d0be 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java @@ -23,4 +23,8 @@ public class Widget1 { private BigDecimal totalActiveFinancing; + private BigDecimal amountRequested; + + private BigDecimal amountAccepted; + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index db645f95..560acd09 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.math.BigDecimal; import java.util.List; import java.util.Optional; @@ -24,7 +25,6 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndIsDeletedFalse(Long id,Long userId); - Optional findByUserIdAndUserWithCompanyIdAndCallIdAndIsDeletedFalse(Long userId, Long userWithCompanyId, Long callId); public Optional findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, Long callId); @@ -44,4 +44,15 @@ public interface ApplicationRepository extends JpaRepository findApplicationsPerCallWithName(@Param("hubId") Long hubId); + + // Count Applications by Status by Hub ID + @Query("SELECT a.status, COUNT(a.id) FROM ApplicationEntity a WHERE a.isDeleted = false AND a.call.hub.id = :hubId GROUP BY a.status") + List findApplicationsByStatus(@Param("hubId") Long hubId); + + // Total Amount of Approved Applications by Hub ID + @Query("SELECT SUM(a.call.amount) FROM ApplicationEntity a WHERE a.status = 'APPROVED' AND a.isDeleted = false AND a.call.hub.id = :hubId") + BigDecimal findTotalApprovedApplicationAmount(@Param("hubId") Long hubId); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java index 833e1d68..2a311ca2 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -47,4 +47,9 @@ public interface CallRepository extends JpaRepository { BigDecimal findTotalAmountOfPublishedCallsAndHubId(@Param("hubId") Long hubId); @Query("SELECT c FROM CallEntity c WHERE c.id IN :ids AND c.status IN :status") List findByIdInAndStatusIn(@Param("ids") List ids, @Param("status") List status); + + @Query("SELECT SUM(c.amount) FROM CallEntity c WHERE c.hub.id = :hubId AND c.status = 'PUBLISH'") + BigDecimal findTotalAmountOfPublishedCalls(@Param("hubId") Long hubId); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java index f0163c47..7bfea91b 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserActionsRepository.java @@ -1,10 +1,38 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.UserActionEntity; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; 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.util.List; + @Repository public interface UserActionsRepository extends JpaRepository { UserActionEntity findUserActionById(Long id); + +// +// @Query("SELECT ua FROM UserActionEntity ua " + +// "JOIN ua.user u " + +// "WHERE u.roleEntity.roleType IN :roleNames " + +// "AND ua.hub.id = :hubId " + +// "AND ua.isDeleted = false") +// Page findActionsByRoleNamesAndHubId( +// @Param("roleNames") List roleNames, +// @Param("hubId") Long hubId, Pageable pageable); + + @Query("SELECT ua FROM UserActionEntity ua " + + "JOIN UserEntity u ON ua.userId = u.id " + // Join on userId field + "JOIN u.roleEntity r " + // Join the RoleEntity via the UserEntity + "WHERE r.roleType IN :roleNames " + // Filter by role name + "AND ua.hubId = :hubId " + // Filter by hubId + "AND ua.isDeleted = false") + Page findActionsByRoleNamesAndHubId( + @Param("roleNames") List roleNames, + @Param("hubId") Long hubId, + Pageable pageable); + } 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 6eee497f..764a5377 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 @@ -2065,4 +2065,12 @@ + + + + + + + + From f9c228f0c9ecb037a8713fd813e725976fdf7286 Mon Sep 17 00:00:00 2001 From: nisha Date: Thu, 9 Jan 2025 15:21:59 +0530 Subject: [PATCH 24/31] Updated code --- .../tendermanagement/dao/ApplicationDao.java | 18 +++++++++++++++++- .../dao/ApplicationEvaluationDao.java | 10 +++++++++- .../tendermanagement/dao/DashboardDao.java | 4 ++-- .../entities/ApplicationEntity.java | 15 ++++++++++++++- .../request/ApplicationEvaluationRequest.java | 2 ++ .../repositories/ApplicationRepository.java | 12 +++++++++--- .../db/changelog/db.changelog-1.0.0.xml | 8 ++++---- 7 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 45a69384..cfb2e530 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -46,6 +46,7 @@ import jakarta.servlet.http.HttpServletRequest; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.math.BigDecimal; import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.*; @@ -449,7 +450,22 @@ public class ApplicationDao { List newDocumentIds = validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity); validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity); VersionActionTypeEnum actionType = VersionActionTypeEnum.INSERT; - + List contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + for (ContentResponseBean contentResponseBean:contentResponseBeans){ + if(Boolean.TRUE.equals(contentResponseBean.getName().equals("numberinput"))) { + List settingResponseBeans=contentResponseBean.getSettings(); + for(SettingResponseBean settingResponseBean:settingResponseBeans){ + if(settingResponseBean.getName().equals("isRequestedAmount")){ + Object value=settingResponseBean.getValue(); + if (value instanceof Boolean) { + if(Boolean.TRUE.equals(value)) + { + applicationFormEntity.getApplication().setAmountRequested((BigDecimal) applicationFormFieldRequestBean.getFieldValue()); + } + } + } + } + }} ApplicationFormFieldEntity oldApplicationFormFieldData = null; if (applicationFormFieldEntities == null || applicationFormFieldEntities.isEmpty()) { diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 50fdb16d..2c2e0bee 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -579,6 +579,7 @@ public class ApplicationEvaluationDao { Optional assignedApplications = assignedApplicationsRepository.findByIdAndIsDeletedFalse(assignedApplicationId); ApplicationEvaluationEntity oldApplicationEvaluation = null; + ApplicationEntity application = applicationService.validateApplication(assignedApplications.get().getApplication().getId()); VersionActionTypeEnum actionType = VersionActionTypeEnum.INSERT; if (existingEntityOptional.isPresent()) { entity = existingEntityOptional.get(); @@ -595,6 +596,7 @@ public class ApplicationEvaluationDao { entity.setIsDeleted(false); setIfUpdated(entity::getNote, entity::setNote, req.getNote()); setIfUpdated(entity::getMotivation, entity::setMotivation, req.getMotivation()); + application.setAmountAccepted(req.getAmountAccepted()); actionType = VersionActionTypeEnum.UPDATE; } else { entity = convertToEntity(user, req, assignedApplicationId); @@ -620,7 +622,6 @@ public class ApplicationEvaluationDao { loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(actionType).oldData(oldApplicationEvaluation).newData(entity).build()); if (status != null) { - ApplicationEntity application = applicationService.validateApplication(assignedApplications.get().getApplication().getId()); AssignedApplicationsEntity assignedApplicationsEntity = assignedApplications.get(); return updateApplicationEvaluationStatus(application, assignedApplicationsEntity, status); } else { @@ -1791,11 +1792,18 @@ public class ApplicationEvaluationDao { if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.APPROVED.getValue())))) { + application.setDateAccepted(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + application.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + application = applicationRepository.save(application); emailNotificationDao.sendAdmissibilityNotificationEmailForApprovedApplication(application); } if (Boolean.TRUE.equals(statusType.equals((ApplicationStatusTypeEnum.REJECTED.getValue())))) { + application.setDateRejected(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + application.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + application = applicationRepository.save(application); emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(application,existingEntity); } + return convertToResponse(entity); } return null; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index 05bf687d..1957d676 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -81,14 +81,14 @@ public class DashboardDao { } private void setAmountRequested(Widget1 widget1, UserEntity requestedUserEntity) { - BigDecimal amountRequested = callRepository.findTotalAmountOfPublishedCalls(requestedUserEntity.getHub().getId()); + BigDecimal amountRequested = applicationRepository.findTotalAmountRequestedOfApplication(requestedUserEntity.getHub().getId()); if (amountRequested != null) { widget1.setAmountRequested(amountRequested); } } private void setAmountAccepted(Widget1 widget1, UserEntity requestedUserEntity) { - BigDecimal amountAccepted = applicationRepository.findTotalApprovedApplicationAmount(requestedUserEntity.getHub().getId()); + BigDecimal amountAccepted = applicationRepository.findTotalAmountAcceptedOfApplication(requestedUserEntity.getHub().getId()); if (amountAccepted != null) { widget1.setAmountAccepted(amountAccepted); } diff --git a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java index 39e26f4b..c6880af4 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/ApplicationEntity.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.entities; import jakarta.persistence.*; import lombok.*; +import java.math.BigDecimal; import java.time.LocalDateTime; @Entity @@ -55,4 +56,16 @@ public class ApplicationEntity extends BaseEntity { @Column(name = "APPOINTMENT_ID") private String appointmentId; - } \ No newline at end of file + @Column(name="AMOUNT_REQUESTED") + private BigDecimal amountRequested; + + @Column(name="AMOUNT_ACCEPTED") + private BigDecimal amountAccepted; + + @Column(name="DATE_ACCEPTED") + private LocalDateTime dateAccepted; + + @Column(name="DATE_REJECTED") + private LocalDateTime dateRejected; + +} \ No newline at end of file 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 6616c288..bd63054c 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java +++ b/src/main/java/net/gepafin/tendermanagement/model/request/ApplicationEvaluationRequest.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.model.request; import lombok.Data; import net.gepafin.tendermanagement.enums.ApplicationStatusForEvaluation; +import java.math.BigDecimal; import java.util.List; @Data public class ApplicationEvaluationRequest { @@ -15,4 +16,5 @@ public class ApplicationEvaluationRequest { private String note; private ApplicationStatusForEvaluation applicationStatus; private String motivation; + private BigDecimal amountAccepted; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 560acd09..9922e009 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -52,7 +52,13 @@ public interface ApplicationRepository extends JpaRepository findApplicationsByStatus(@Param("hubId") Long hubId); - // Total Amount of Approved Applications by Hub ID - @Query("SELECT SUM(a.call.amount) FROM ApplicationEntity a WHERE a.status = 'APPROVED' AND a.isDeleted = false AND a.call.hub.id = :hubId") - BigDecimal findTotalApprovedApplicationAmount(@Param("hubId") Long hubId); + @Query("SELECT SUM(a.amountRequested) " + + "FROM ApplicationEntity a " + + "WHERE a.hubId = :hubId AND a.status = 'SUBMIT'") + BigDecimal findTotalAmountRequestedOfApplication(@Param("hubId") Long hubId); + + @Query("SELECT SUM(a.amountAccepted) " + + "FROM ApplicationEntity a " + + "WHERE a.hubId = :hubId AND a.status = 'APPROVED'") + BigDecimal findTotalAmountAcceptedOfApplication(@Param("hubId") Long hubId); } 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 764a5377..9fc242e2 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 @@ -2067,10 +2067,10 @@ - - - - + + + + From 4cfe02f5ad6675b1029925529cd4ce9af4b3e35a Mon Sep 17 00:00:00 2001 From: nisha Date: Thu, 9 Jan 2025 18:10:31 +0530 Subject: [PATCH 25/31] Removed delega check from create application API --- .../java/net/gepafin/tendermanagement/dao/ApplicationDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index e281615f..c8185408 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -219,7 +219,7 @@ public class ApplicationDao { } public ApplicationEntity createApplicationEntity(UserEntity user, CallEntity call, UserWithCompanyEntity userWithCompany) { - validateDelegation(user,userWithCompany); +// validateDelegation(user,userWithCompany); ApplicationEntity entity = new ApplicationEntity(); entity.setUserId(user.getId()); entity.setCompanyId(userWithCompany.getCompanyId()); From 6e092bd5341c0205e2bab3e0339b537981458576 Mon Sep 17 00:00:00 2001 From: nisha Date: Fri, 10 Jan 2025 15:41:37 +0530 Subject: [PATCH 26/31] Resolved null issue in pdf --- .../gepafin/tendermanagement/dao/PdfDao.java | 88 +++---------------- 1 file changed, 13 insertions(+), 75 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java index 5ec81347..a2e437cd 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/PdfDao.java @@ -109,76 +109,7 @@ public class PdfDao { document.add(new Paragraph(" ")); // Add line break } document.add(new Paragraph("\n")); // Add line break - Font boldSmallFont = new Font(Font.FontFamily.HELVETICA, 10, Font.BOLD,new BaseColor(105, 105, 105)); - // Adding the "Documenti Allegati" section title -// document.add(new Paragraph(" ")); -// -//// pageEvent.setTotalPages(writer.getPageNumber()); -// document.newPage(); -//// pageEvent.setTotalPages(writer.getPageNumber()); -// document.add(new Paragraph("Documenti Allegati", sectionFont)); -// document.add(new Paragraph(" ")); -// -// -//// 1. Autocertificazione possesso Requisiti -// Paragraph p1 = new Paragraph(); -// p1.add(new Chunk("1. ", boldSmallFont)); -// p1.add(new Chunk("Autocertificazione possesso Requisiti ", boldSmallFont)); -// p1.add(new Chunk("ai sensi degli artt. 46 e 47 del DPR 445/2000", smallFont)); -// document.add(p1); -// document.add(new Paragraph(" ")); -// -// -// -//// 2. Informativa Privacy relativa al trattamento dei dati personali -// Paragraph p2 = new Paragraph(); -// p2.add(new Chunk("2. ", boldSmallFont)); -// p2.add(new Chunk("Informativa Privacy relativa al trattamento dei dati personali", boldSmallFont)); -// document.add(p2); -// document.add(new Paragraph(" ")); -// -// -//// 3. Dati richiesti per la valutazione dell’adeguatezza dei flussi finanziari -// Paragraph p3 = new Paragraph(); -// p3.add(new Chunk("3. ", boldSmallFont)); -// p3.add(new Chunk("Dati richiesti per la valutazione dell’adeguatezza dei flussi finanziari prospettici come da tabella di cui all’Appendice 9", boldSmallFont)); -// document.add(p3); -// document.add(new Paragraph(" ")); -// -// -//// 4. Rilevazione Centrale dei Rischi -// Paragraph p4 = new Paragraph(); -// p4.add(new Chunk("4. ", boldSmallFont)); -// p4.add(new Chunk("Rilevazione Centrale dei Rischi riferita agli ultimi 36 mesi disponibili alla data di presentazione della Domanda", boldSmallFont)); -// document.add(p4); -// document.add(new Paragraph(" ")); -// -// -//// 5. Schema di presentazione dei dati di bilancio -// Paragraph p5 = new Paragraph(); -// p5.add(new Chunk("5. ", boldSmallFont)); -// p5.add(new Chunk("Schema di presentazione dei dati di bilancio", boldSmallFont)); -// document.add(p5); -// document.add(new Paragraph(" ")); -// -// -//// 6. Dettagli bilanci in forma abbreviata -// Paragraph p6 = new Paragraph(); -// p6.add(new Chunk("6. ", boldSmallFont)); -// p6.add(new Chunk("Dettagli bilanci in forma abbreviata", boldSmallFont)); -// document.add(p6); -// document.add(new Paragraph(" ")); -// -// -//// 7. Relazione aziendale illustrativa -// Paragraph p7 = new Paragraph(); -// p7.add(new Chunk("7. ", boldSmallFont)); -// p7.add(new Chunk("Relazione aziendale illustrativa", boldSmallFont)); -// document.add(p7); -// document.add(new Paragraph(" ")); -// -// addColoredLines(writer,document,greenColor); document.close(); @@ -488,12 +419,19 @@ public class PdfDao { .orElse(null); // If no match is found, set label to null // Find the form field in the response that matches the contentId if (name.equals("paragraph")){ - String paragraph = content.getSettings().stream() - .filter(setting -> "text".equals(setting.getName())) // Filter settings by name - .map(SettingResponseBean::getValue) // Extract the value from the matching setting - .map(Object::toString) // Convert the value to a string - .findFirst() // Get the first matching value - .orElse(null); +// String paragraph = content.getSettings().stream() +// .filter(setting -> "text".equals(setting.getName())) // Filter settings by name +// .map(SettingResponseBean::getValue) // Extract the value from the matching setting +// .map(Object::toString) // Convert the value to a string +// .findFirst() // Get the first matching value +// .orElse(null); + String paragraph = content.getSettings().stream() + .filter(setting -> "text".equals(setting.getName())) // Filter settings by name + .map(SettingResponseBean::getValue) // Extract the value from the matching setting + .map(value -> value != null ? value.toString() : " ") // Replace null with an empty string + .findFirst() // Get the first matching value + .orElse(null); // Return null if no value is found + Paragraph labelParagraph = new Paragraph(); PdfPCell labelCell = new PdfPCell(PdfUtils.htmlToPdfPCell(paragraph,labelFont)); labelCell.setBorder(Rectangle.NO_BORDER); From e39bbcd5725b006259d13e52d0a944fc73c9c7e9 Mon Sep 17 00:00:00 2001 From: piyushkag Date: Fri, 10 Jan 2025 16:00:38 +0530 Subject: [PATCH 27/31] Updated application submission date to protocol creation date. --- .../tendermanagement/dao/ApplicationEvaluationDao.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index c264a078..019eadf3 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -558,7 +558,7 @@ public class ApplicationEvaluationDao { response.setBeneficiary(beneficiary); response.setNdg(application.getNdg() != null ? application.getNdg() : null); response.setAppointmentId(application.getAppointmentId() != null ? application.getAppointmentId() : null); - response.setSubmissionDate(application.getSubmissionDate()); + response.setSubmissionDate(application.getProtocol().getCreatedDate()); 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); @@ -1386,7 +1386,7 @@ public class ApplicationEvaluationDao { String beneficiary = String.join(" ", firstName, lastName).trim(); response.setBeneficiary(beneficiary); - response.setSubmissionDate(application.getSubmissionDate()); + response.setSubmissionDate(application.getProtocol().getCreatedDate()); 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); From b4877b588c6ce8ecbb8ed21d1cc1acf796a2d0c3 Mon Sep 17 00:00:00 2001 From: nisha Date: Mon, 13 Jan 2025 13:00:04 +0530 Subject: [PATCH 28/31] Updated code --- .../constants/GepafinConstant.java | 1 + .../tendermanagement/dao/ApplicationDao.java | 49 +++++++++++++------ .../dao/ApplicationEvaluationDao.java | 13 ++++- .../tendermanagement/dao/DashboardDao.java | 17 +++---- .../tendermanagement/dao/FlowFormDao.java | 4 ++ .../ApplicationEvaluationResponse.java | 5 ++ .../response/ApplicationGetResponseBean.java | 10 ++++ .../model/response/ApplicationResponse.java | 9 ++++ .../response/ApplicationResponseBean.java | 9 ++++ .../response/NextOrPreviousFormResponse.java | 11 +++++ .../SuperAdminWidgetResponseBean.java | 2 - .../model/response/Widget1.java | 4 +- .../repositories/ApplicationRepository.java | 3 +- .../repositories/UserActionsRepository.java | 23 +-------- src/main/resources/message_en.properties | 1 + src/main/resources/message_it.properties | 4 +- 16 files changed, 110 insertions(+), 55 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 5869fc81..f984d0e0 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -360,5 +360,6 @@ public class GepafinConstant { public static final String STATUS_CODE_STRING = "statusCode"; public static final String GET_STATUS_CODE_STRING = "status"; public static final String MESSAGE_STRING = "message"; + public static final String AMOUNT_ACCEPTED_REQUIRED_WHILE_APPROVING_APPLICATION="amount.accepted.required"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 82595964..2877a59d 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -424,6 +424,10 @@ public class ApplicationDao { if(applicationEntity.getProtocol() != null) { responseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } + responseBean.setAmountAccepted(applicationEntity.getAmountAccepted()); + responseBean.setAmountRequested(applicationEntity.getAmountRequested()); + responseBean.setDateAccepted(applicationEntity.getDateAccepted()); + responseBean.setDateRejected(applicationEntity.getDateRejected()); return responseBean; } @@ -443,6 +447,10 @@ public class ApplicationDao { response.setCallId(entity.getCall().getId()); response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); + response.setAmountAccepted(entity.getAmountAccepted()); + response.setAmountRequested(entity.getAmountRequested()); + response.setDateAccepted(entity.getDateAccepted()); + response.setDateRejected(entity.getDateRejected()); if(entity.getProtocol() != null) { response.setProtocolNumber(entity.getProtocol().getProtocolNumber()); } @@ -481,22 +489,31 @@ public class ApplicationDao { List newDocumentIds = validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity); validateFileUploadDocuments(applicationFormFieldRequestBean, formEntity); VersionActionTypeEnum actionType = VersionActionTypeEnum.INSERT; - List contentResponseBeans=formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); - for (ContentResponseBean contentResponseBean:contentResponseBeans){ - if(Boolean.TRUE.equals(contentResponseBean.getName().equals("numberinput"))) { - List settingResponseBeans=contentResponseBean.getSettings(); - for(SettingResponseBean settingResponseBean:settingResponseBeans){ - if(settingResponseBean.getName().equals("isRequestedAmount")){ - Object value=settingResponseBean.getValue(); - if (value instanceof Boolean) { - if(Boolean.TRUE.equals(value)) - { - applicationFormEntity.getApplication().setAmountRequested((BigDecimal) applicationFormFieldRequestBean.getFieldValue()); + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + + contentResponseBeans.stream() + .filter(content -> "numberinput".equals(content.getName())) + .map(ContentResponseBean::getSettings) + .flatMap(List::stream) + .filter(setting -> "isRequestedAmount".equals(setting.getName()) && Boolean.TRUE.equals(setting.getValue())) + .findFirst() + .ifPresent(setting -> { + Object fieldValue = applicationFormFieldRequestBean.getFieldValue(); + if(fieldValue!=null) { + if (fieldValue instanceof String) { + try { + BigDecimal amountRequested = new BigDecimal((String) fieldValue); + applicationFormEntity.getApplication().setAmountRequested(amountRequested); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Field value is not a valid number: " + fieldValue, e); + } + } else { + throw new IllegalArgumentException("Field value is not a String: " + fieldValue); } } - } - } - }} + }); + + ApplicationFormFieldEntity oldApplicationFormFieldData = null; if (applicationFormFieldEntities == null || applicationFormFieldEntities.isEmpty()) { @@ -827,6 +844,10 @@ public class ApplicationDao { applicationGetResponseBean.setCallId(applicationEntity.getCall().getId()); applicationGetResponseBean.setCallTitle(applicationEntity.getCall().getName()); applicationGetResponseBean.setCompanyId(applicationEntity.getCompanyId()); + applicationGetResponseBean.setAmountAccepted(applicationEntity.getAmountAccepted()); + applicationGetResponseBean.setAmountRequested(applicationEntity.getAmountRequested()); + applicationGetResponseBean.setDateAccepted(applicationEntity.getDateAccepted()); + applicationGetResponseBean.setDateRejected(applicationEntity.getDateRejected()); if(applicationEntity.getProtocol() != null) { applicationGetResponseBean.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index acac1b39..7cced04a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import java.math.BigDecimal; import java.time.Duration; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; @@ -582,6 +583,10 @@ public class ApplicationEvaluationDao { CompanyEntity company = companyService.validateCompany(application.getCompanyId()); response.setCompanyName(company.getCompanyName()); } + response.setAmountAccepted(application.getAmountAccepted()); + response.setAmountRequested(application.getAmountRequested()); + response.setDateAccepted(application.getDateAccepted()); + response.setDateRejected(application.getDateRejected()); } @@ -613,11 +618,15 @@ public class ApplicationEvaluationDao { entity.setIsDeleted(false); setIfUpdated(entity::getNote, entity::setNote, req.getNote()); setIfUpdated(entity::getMotivation, entity::setMotivation, req.getMotivation()); - application.setAmountAccepted(req.getAmountAccepted()); + if(Boolean.TRUE.equals(req.getApplicationStatus().equals(ApplicationStatusForEvaluation.APPROVED)) && (req.getAmountAccepted()==null || req.getAmountAccepted().compareTo(BigDecimal.ZERO) < 0)){ + throw new CustomValidationException(Status.BAD_REQUEST,Translator.toLocale(GepafinConstant.AMOUNT_ACCEPTED_REQUIRED_WHILE_APPROVING_APPLICATION)); + } + if (req.getAmountAccepted() != null && req.getAmountAccepted().compareTo(BigDecimal.ZERO) > 0) { + application.setAmountAccepted(req.getAmountAccepted()); + } actionType = VersionActionTypeEnum.UPDATE; } else { AssignedApplicationsEntity assignedApplicationsEntity = assignedApplicationsService.validateAssignedApplication(assignedApplicationId); - ApplicationEntity application = applicationService.validateApplication(assignedApplicationsEntity.getApplication().getId()); entity = convertToEntity(user, req, assignedApplicationId); actionType = VersionActionTypeEnum.INSERT; diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index ba0b5630..91b94b90 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -63,7 +63,6 @@ public class DashboardDao { widgetResponseBean.setWidget1(createWidget1(requestedUserEntity)); Map widgetBars =getStatistics(requestedUserEntity); widgetResponseBean.setWidgetBars(widgetBars); - widgetResponseBean.setUserActionWidgetList(getUserAction(requestedUserEntity)); return widgetResponseBean; } @@ -97,14 +96,14 @@ public class DashboardDao { private void setAmountRequested(Widget1 widget1, UserEntity requestedUserEntity) { BigDecimal amountRequested = applicationRepository.findTotalAmountRequestedOfApplication(requestedUserEntity.getHub().getId()); if (amountRequested != null) { - widget1.setAmountRequested(amountRequested); + widget1.setTotalAmountRequested(amountRequested); } } private void setAmountAccepted(Widget1 widget1, UserEntity requestedUserEntity) { BigDecimal amountAccepted = applicationRepository.findTotalAmountAcceptedOfApplication(requestedUserEntity.getHub().getId()); if (amountAccepted != null) { - widget1.setAmountAccepted(amountAccepted); + widget1.setTotalAmountAccepted(amountAccepted); } } @@ -194,12 +193,12 @@ public class DashboardDao { return stats; } - public Page getUserAction(UserEntity requestedUserEntity){ - Pageable pageable = PageRequest.of(0, 20); // Get the first 20 records - List roles=List.of(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue(),RoleStatusEnum.ROLE_GEPAFIN_OPERATOR.getValue(),RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()); - Page userActionEntities=userActionsRepository.findActionsByRoleNamesAndHubId(roles,requestedUserEntity.getHub().getId(),pageable); - return userActionEntities; - } +// public Page getUserAction(UserEntity requestedUserEntity){ +// Pageable pageable = PageRequest.of(0, 20); // Get the first 20 records +// List roles=List.of(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue(),RoleStatusEnum.ROLE_GEPAFIN_OPERATOR.getValue(),RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()); +// Page userActionEntities=userActionsRepository.findActionsByRoleNamesAndHubId(roles,requestedUserEntity.getHub().getId(),pageable); +// return userActionEntities; +// } public ApplicationWidgetResponseBean getApplicationDetails(UserEntity userEntity) { ApplicationWidgetResponseBean applicationWidgetResponseBean = initializeResponseBean(); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java index 4a42daf7..faec3489 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/FlowFormDao.java @@ -309,6 +309,10 @@ public class FlowFormDao { if(applicationEntity.getProtocol() != null) { nextOrPreviousFormResponse.setProtocolNumber(applicationEntity.getProtocol().getProtocolNumber()); } + nextOrPreviousFormResponse.setAmountAccepted(applicationEntity.getAmountAccepted()); + nextOrPreviousFormResponse.setAmountRequested(applicationEntity.getAmountRequested()); + nextOrPreviousFormResponse.setDateAccepted(applicationEntity.getDateAccepted()); + nextOrPreviousFormResponse.setDateRejected(applicationEntity.getDateRejected()); return nextOrPreviousFormResponse; } 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 7da6d25f..c2fcd6cb 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationEvaluationResponse.java @@ -4,6 +4,7 @@ import lombok.Data; import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -38,4 +39,8 @@ public class ApplicationEvaluationResponse { private LocalDateTime assignedAt; private String ndg; private String appointmentId; + private BigDecimal amountRequested; + private BigDecimal amountAccepted; + private LocalDateTime dateAccepted; + private LocalDateTime dateRejected; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java index aa686023..77048d15 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationGetResponseBean.java @@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -26,6 +27,15 @@ public class ApplicationGetResponseBean { private Long protocolNumber; + private BigDecimal amountRequested; + + private BigDecimal amountAccepted; + + private LocalDateTime dateAccepted; + + private LocalDateTime dateRejected; + + private List form; } 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 24ad5a34..1aae69e2 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponse.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; import net.gepafin.tendermanagement.model.response.ApplicationFormFieldResponseBean; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -37,4 +38,12 @@ public class ApplicationResponse{ private String assignedUserName; + private BigDecimal amountRequested; + + private BigDecimal amountAccepted; + + private LocalDateTime dateAccepted; + + private LocalDateTime dateRejected; + } \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java index 6b99961f..3c9016bd 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/ApplicationResponseBean.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; import net.gepafin.tendermanagement.model.BaseBean; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; @@ -19,6 +20,14 @@ public class ApplicationResponseBean extends BaseBean { private Long protocolNumber; + private BigDecimal amountRequested; + + private BigDecimal amountAccepted; + + private LocalDateTime dateAccepted; + + private LocalDateTime dateRejected; + private List formFields; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java index 8925e7f6..bea417a1 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/NextOrPreviousFormResponse.java @@ -3,6 +3,9 @@ package net.gepafin.tendermanagement.model.response; import lombok.Data; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import java.math.BigDecimal; +import java.time.LocalDateTime; + @Data public class NextOrPreviousFormResponse { @@ -25,6 +28,14 @@ public class NextOrPreviousFormResponse { private Long protocolNumber; private ApplicationStatusTypeEnum applicationStatus; + + private BigDecimal amountRequested; + + private BigDecimal amountAccepted; + + private LocalDateTime dateAccepted; + + private LocalDateTime dateRejected; private FormApplicationResponse applicationFormResponse; diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java index 405a92ac..02744ace 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java @@ -14,6 +14,4 @@ public class SuperAdminWidgetResponseBean { private Map widgetBars; - Page userActionWidgetList; - } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java index 0d82d0be..a6b1ad88 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java @@ -23,8 +23,8 @@ public class Widget1 { private BigDecimal totalActiveFinancing; - private BigDecimal amountRequested; + private BigDecimal totalAmountRequested; - private BigDecimal amountAccepted; + private BigDecimal totalAmountAccepted; } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 542c8cdf..c46c52c7 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -54,13 +54,14 @@ public interface ApplicationRepository extends JpaRepository { UserActionEntity findUserActionById(Long id); - -// -// @Query("SELECT ua FROM UserActionEntity ua " + -// "JOIN ua.user u " + -// "WHERE u.roleEntity.roleType IN :roleNames " + -// "AND ua.hub.id = :hubId " + -// "AND ua.isDeleted = false") -// Page findActionsByRoleNamesAndHubId( -// @Param("roleNames") List roleNames, -// @Param("hubId") Long hubId, Pageable pageable); - - @Query("SELECT ua FROM UserActionEntity ua " + - "JOIN UserEntity u ON ua.userId = u.id " + // Join on userId field - "JOIN u.roleEntity r " + // Join the RoleEntity via the UserEntity - "WHERE r.roleType IN :roleNames " + // Filter by role name - "AND ua.hubId = :hubId " + // Filter by hubId - "AND ua.isDeleted = false") - Page findActionsByRoleNamesAndHubId( - @Param("roleNames") List roleNames, - @Param("hubId") Long hubId, - Pageable pageable); - + UserActionEntity findUserActionByIdAndIsDeletedFalse(Long id); } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 44a27275..c743b3fa 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -346,3 +346,4 @@ 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. +amount.accepted.required=Amount accepted is required while approving the application. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 0b22e9e3..14a5dbb5 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -329,7 +329,6 @@ 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. @@ -339,5 +338,4 @@ 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 +amount.accepted.required=L'importo accettato è obbligatorio durante l'approvazione della domanda. From baba46dc1f680ed7f19d27c44511585ade09fcfb Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 13 Jan 2025 13:09:22 +0530 Subject: [PATCH 29/31] Updated code --- .../java/net/gepafin/tendermanagement/dao/ApplicationDao.java | 2 +- .../tendermanagement/dao/ApplicationEvaluationDao.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index c8185408..77177bc8 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -870,7 +870,7 @@ public class ApplicationDao { 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.setSubmissionDate(protocolEntity.getCreatedDate()); applicationEntity = applicationRepository.save(applicationEntity); Map placeHolders=notificationDao.sendNotificationToBeneficiary(applicationEntity,NotificationTypeEnum.APPLICATION_SUBMISSION); notificationDao.sendNotificationToSuperUser(applicationEntity,placeHolders,NotificationTypeEnum.APPLICATION_SUBMISSION); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java index 019eadf3..c264a078 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationEvaluationDao.java @@ -558,7 +558,7 @@ public class ApplicationEvaluationDao { response.setBeneficiary(beneficiary); response.setNdg(application.getNdg() != null ? application.getNdg() : null); response.setAppointmentId(application.getAppointmentId() != null ? application.getAppointmentId() : null); - response.setSubmissionDate(application.getProtocol().getCreatedDate()); + 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); @@ -1386,7 +1386,7 @@ public class ApplicationEvaluationDao { String beneficiary = String.join(" ", firstName, lastName).trim(); response.setBeneficiary(beneficiary); - response.setSubmissionDate(application.getProtocol().getCreatedDate()); + 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); From aec649564975ab593a18606a0bf6a4e25c548ca9 Mon Sep 17 00:00:00 2001 From: nisha Date: Mon, 13 Jan 2025 15:53:28 +0530 Subject: [PATCH 30/31] Updated changes for GEPAFINBE-127 --- .../tendermanagement/constants/GepafinConstant.java | 8 ++++++++ .../gepafin/tendermanagement/dao/DashboardDao.java | 13 +++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index f984d0e0..7fe87275 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -361,5 +361,13 @@ public class GepafinConstant { public static final String GET_STATUS_CODE_STRING = "status"; public static final String MESSAGE_STRING = "message"; public static final String AMOUNT_ACCEPTED_REQUIRED_WHILE_APPROVING_APPLICATION="amount.accepted.required"; + public static final String CALL_NAME="callName"; + public static final String NUMBER_OF_APPLICATIONS="numberOfApplications"; + public static final String STATUS="status"; + public static final String COUNT="count"; + public static final String APPLICATION_PER_CALL="applicationPerCall"; + public static final String APPLICATION_PER_STATUS="applicationPerStatus"; + + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java index 91b94b90..8f3a55f1 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -1,5 +1,6 @@ package net.gepafin.tendermanagement.dao; +import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserActionEntity; import net.gepafin.tendermanagement.entities.UserEntity; @@ -175,19 +176,19 @@ public class DashboardDao { // Get applications per call List applicationsPerCall = applicationRepository.findApplicationsPerCallWithName(requestedUser.getHub().getId()); - stats.put("APPLICATION_PER_CALL", applicationsPerCall.stream().map(result -> { + stats.put(GepafinConstant.APPLICATION_PER_CALL, applicationsPerCall.stream().map(result -> { Map callData = new HashMap<>(); - callData.put("CALL", result[0]); // Call name - callData.put("APPLICATIONS", result[1]); // Application count + callData.put(GepafinConstant.CALL_NAME, result[0]); // Call name + callData.put(GepafinConstant.NUMBER_OF_APPLICATIONS, result[1]); // Application count return callData; }).toList()); // Get applications grouped by status List applicationsByStatus = applicationRepository.findApplicationsByStatus(requestedUser.getHub().getId()); - stats.put("APPLICATION_STATUSES", applicationsByStatus.stream().map(result -> { + stats.put(GepafinConstant.APPLICATION_PER_STATUS, applicationsByStatus.stream().map(result -> { Map statusData = new HashMap<>(); - statusData.put("STATUS", result[0]); // Application status - statusData.put("COUNT", result[1]); // Count of applications + statusData.put(GepafinConstant.STATUS, result[0]); // Application status + statusData.put(GepafinConstant.NUMBER_OF_APPLICATIONS, result[1]); // Count of applications return statusData; }).toList()); From 7953ba0838bf48f9eedeb837e31da392688ed06e Mon Sep 17 00:00:00 2001 From: rajesh Date: Mon, 13 Jan 2025 19:17:39 +0530 Subject: [PATCH 31/31] Done ticket GEPAFINBE-140 --- .../tendermanagement/dao/CompanyDao.java | 18 +++++++++++++++++- .../entities/CompanyEntity.java | 3 +++ .../model/response/CompanyResponse.java | 1 + .../db/changelog/db.changelog-1.0.0.xml | 6 ++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java index 6c5f0856..1b3a6798 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CompanyDao.java @@ -124,7 +124,6 @@ public class CompanyDao { 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. **/ loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(userWithCompany).build()); return userWithCompany; @@ -144,6 +143,22 @@ public class CompanyDao { entity.setNumberOfEmployees(request.getNumberOfEmployees()); entity.setAnnualRevenue(request.getAnnualRevenue()); entity.setHub(userEntity.getHub()); + Map vatCheckResponse = request.getVatCheckResponse(); + if (request.getVatCheckResponse() != null) { + if (vatCheckResponse.containsKey("dettaglio")) { + Map dettaglio = (Map) vatCheckResponse.get("dettaglio"); + if (dettaglio != null) { + if (dettaglio.containsKey("codice_ateco")) { + Object codiceAtecoObj = dettaglio.get("codice_ateco"); + String codiceAteco = (codiceAtecoObj != null) ? codiceAtecoObj.toString() : null; + + if (codiceAteco != null) { + entity.setCodiceAteco(codiceAteco); + } + } + } + } + } return entity; } @@ -165,6 +180,7 @@ public class CompanyDao { response.setAnnualRevenue(entity.getAnnualRevenue()); if(userWithCompanyEntity!=null) { response.setIsLegalRepresentant(userWithCompanyEntity.getIsLegalRepresentant()); + response.setCodiceAteco(entity.getCodiceAteco()); } response.setCreatedDate(entity.getCreatedDate()); response.setUpdatedDate(entity.getUpdatedDate()); diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java index e7aa0f40..932a8758 100644 --- a/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java +++ b/src/main/java/net/gepafin/tendermanagement/entities/CompanyEntity.java @@ -56,4 +56,7 @@ public class CompanyEntity extends BaseEntity{ @Column(name = "NDG") private String ndg; + + @Column(name = "CODICE_ATECO") + private String codiceAteco; } diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java index e54b040f..ddd62f38 100644 --- a/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CompanyResponse.java @@ -24,4 +24,5 @@ public class CompanyResponse extends BaseBean{ private Boolean isLegalRepresentant; private String contactName; private String contactEmail; + private String codiceAteco; } 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 4b73b739..1ec8f742 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 @@ -2188,5 +2188,11 @@ + + + + + +