Resolved conflicts

This commit is contained in:
nisha
2025-01-09 15:29:14 +05:30
93 changed files with 2958 additions and 510 deletions

View File

@@ -23,8 +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);
}
}

View File

@@ -63,7 +63,7 @@ public class SamlSuccessHandler implements AuthenticationSuccessHandler {
Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) samlAuth.getPrincipal();
Map<String, List<Object>> userAttributes = principal.getAttributes();
String token = Utils.generateSecureToken();
String token = Utils.generateSecureSamlToken();
logger.info("SAML User Attributes: " + userAttributes);
// Extracting raw SAML response

View File

@@ -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
@@ -109,6 +112,7 @@ public class SecurityConfig {
.requestMatchers("/v1/api-docs/**").permitAll() // API docs
.requestMatchers("/v1/user/reset-password/initiate").permitAll()
.requestMatchers("/v1/user/reset-password").permitAll()
.requestMatchers("/wss/**").permitAll() // if this is not running use this /gs-guide-websocket
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
.exceptionHandling(exceptionHandling -> exceptionHandling

View File

@@ -0,0 +1,39 @@
package net.gepafin.tendermanagement.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Value("${spring.rabbitmq.host}")
private String relayHost;
@Value("${spring.rabbitmq.port}")
private int relayPort;
@Value("${spring.rabbitmq.username}")
private String clientUserName;
@Value("${spring.rabbitmq.password}")
private String clientPassword;
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay("/topic").setRelayHost(relayHost).setRelayPort(relayPort).setClientLogin(clientUserName).setClientPasscode(clientPassword);
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/wss").setAllowedOrigins("http://localhost:3000", "http://127.0.0.1:5500", "https://bandi-staging.memento.credit", "https://bandi.gepafin.it")
.withSockJS();
}
}

View File

@@ -305,6 +305,8 @@ 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";
public static final String VALID_VATNUMBER_MSG = "valid.vatnumber.message";
public static final String ATLEAST_ONE_ID_REQUIRED="atleast.one.id.required";
//Appointment
@@ -342,5 +344,21 @@ public class GepafinConstant {
public static final String DOCUMENT_UPLOADING_IN_PROGRESS = "document.uploading.is.in.progress";
public static final String ASYNC_DOCUMENT_UPLOAD_NAME = "AsyncDocumentUpload-";
public static final String All_DOCUMENT_CHECKED_AND_ONE_CHECKLIST_CHECKED="all.document.checked.and.one.checklist.checked";
//Notification
public static final String COMMON_SINGLE_CHANNEL_PREFIX = "/topic/notifications_user_";
public static final String COMPANY_PREFIX = "_company_";
public static final String NOTIFICATION_SENT_SUCCESSFULLY = "notification.sent.successfully";
public static final String NOTIFICATION_FETCHED_SUCCESSFULLY= "notification.fetched.successfully";
public static final String NOTIFICATION_NOT_FOUND= "notification.not.found";
public static final String NOTIFICATION_ALREADY_IN_THAT_STATE="notification.already.in.state";
public static final String NOTIFICATION_DELETED_SUCCESSFULLY="notification.deleted.successfully";
public static final String NOTIFICATION_UPDATED_SUCCESSFULLY="notification.updated.successfully";
public static final String USER_WITH_COMPANY_NOT_FOUND = "user.with.company.not.found";
//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";
}

View File

@@ -110,6 +110,14 @@ public class ApplicationAmendmentRequestDao {
@Autowired
private DocumentRepository documentRepository;
@Autowired
private CompanyService companyService;
@Autowired
private NotificationDao notificationDao;
@Autowired
private UserRepository userRepository;
public ApplicationAmendmentRequestResponse getApplicationDataForAmendment(Long applicationEvaluationId) {
log.info("Fetching the application data for the Amendment process {}", applicationEvaluationId);
@@ -231,7 +239,7 @@ public class ApplicationAmendmentRequestDao {
log.info("Submiting application data for amendment Process with details: {}", applicationEvaluationId);
ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = createApplicationAmendmentRequestEntity(applicationAmendmentRequest, applicationEvaluationId);
ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = convertEntityToResponse(applicationAmendmentRequestEntity);
ApplicationAmendmentRequestResponse applicationAmendmentRequestResponse = convertEntityToResponse(applicationAmendmentRequestEntity,false);
log.info("Application submitted successfully for amendment", applicationAmendmentRequestResponse);
if (Boolean.TRUE.equals(applicationAmendmentRequestResponse.getIsSendEmail())) {
emailNotificationDao.sendMailToNotifyBeneficiaryRegardingNewAmendment(applicationAmendmentRequestEntity);
@@ -298,7 +306,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());
@@ -326,6 +334,10 @@ public class ApplicationAmendmentRequestDao {
assignedApplicationsEntity.setStatus(AssignedApplicationEnum.SOCCORSO.getValue());
assignedApplicationsRepository.save(assignedApplicationsEntity);
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(applicationEntity, NotificationTypeEnum.AMENDMENT_CREATION);
notificationDao.sendNotificationToInstructor(placeHolders,applicationAmendmentRequestEntity.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_CREATION);
/** This code is responsible for adding a version history log for the "Update Assigned Application" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAssignedApplication).newData(assignedApplicationsEntity).build());
}
@@ -362,8 +374,8 @@ public class ApplicationAmendmentRequestDao {
return applicationAmendmentRequest;
}
public ApplicationAmendmentRequestResponse convertEntityToResponse(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) {
ApplicationAmendmentRequestResponse response = initializeBasicResponse(applicationAmendmentRequestEntity);
public ApplicationAmendmentRequestResponse convertEntityToResponse(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity,boolean includeEmailContent) {
ApplicationAmendmentRequestResponse response = initializeBasicResponse(applicationAmendmentRequestEntity,includeEmailContent);
List<ApplicationFormEntity> forms = applicationFormRepository.findByApplicationId(applicationAmendmentRequestEntity.getApplicationId());
Map<String, String> fieldIdToLabelMap = extractFieldIdToLabelMap(forms);
@@ -431,8 +443,12 @@ public class ApplicationAmendmentRequestDao {
}
private ApplicationAmendmentRequestResponse initializeBasicResponse(ApplicationAmendmentRequestEntity entity) {
private ApplicationAmendmentRequestResponse initializeBasicResponse(ApplicationAmendmentRequestEntity entity,boolean includeEmailContent) {
ApplicationAmendmentRequestResponse response = new ApplicationAmendmentRequestResponse();
ApplicationEntity applicationEntity = entity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication();
Long hubId = applicationEntity.getHubId();
HubEntity hubEntity = hubService.valdateHub(hubId);
response.setId(entity.getId());
response.setApplicationId(entity.getApplicationId());
response.setApplicationEvaluationId(entity.getApplicationEvaluationEntity().getId());
@@ -454,10 +470,17 @@ public class ApplicationAmendmentRequestDao {
UserEntity userEntity = userService.validateUser(application.getUserId());
response.setBeneficiaryName(buildBeneficiaryName(userEntity));
CompanyEntity company = companyService.validateCompany(application.getCompanyId());
response.setCompanyName(company.getCompanyName());
Long protocolNumber = entity.getProtocol() != null ? entity.getProtocol().getProtocolNumber() : null;
response.setProtocolNumber(protocolNumber);
if (includeEmailContent) {
Map<String, String> bodyPlaceholders = emailNotificationDao.prepareEmailPlaceholders(applicationEntity, entity);
EmailContentResponse emailContent = emailNotificationDao.prepareEmailContent(applicationEntity, SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, hubEntity, bodyPlaceholders);
String body = emailContent.getBody();
response.setEmailTemplate(body);
}
return response;
}
@@ -564,7 +587,7 @@ public class ApplicationAmendmentRequestDao {
public ApplicationAmendmentRequestResponse getApplicationAmendmentRequestById(Long id) {
log.info("Fetching application amendment with ID: {}", id);
ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(applicationAmendmentRequestEntity,true);
log.info("Application Amendment fetched successfully by ID: {}", response);
return response;
}
@@ -581,7 +604,7 @@ public class ApplicationAmendmentRequestDao {
applicationAmendmentRequestRepository.findAll(spec);
return applicationAmendmentRequestEntities.stream()
.map(this::convertEntityToResponse)
.map(entity -> convertEntityToResponse(entity, false))
.collect(Collectors.toList());
}
@@ -641,7 +664,7 @@ public class ApplicationAmendmentRequestDao {
setAmendmentDocuments(updateRequest.getAmendmentNotes(),updateRequest.getAmendmentDocuments(), existingApplicationAmendment);
}
ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment,oldApplicationAmendmentEntity,VersionActionTypeEnum.UPDATE);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment,false);
log.info("Application Amendment updated successfully: {}", response);
return response;
}
@@ -942,7 +965,7 @@ public class ApplicationAmendmentRequestDao {
applicationAmendmentRequestRepository.findByUserId(beneficiaryUserId);
return entities.stream()
.map(this::convertEntityToResponse)
.map(entity -> convertEntityToResponse(entity, false))
.collect(Collectors.toList());
}
@@ -952,8 +975,7 @@ public class ApplicationAmendmentRequestDao {
ApplicationAmendmentRequestEntity existingApplicationAmendment = validateApplicationAmendmentRequest(id);
//cloned entity for old data and versioning
ApplicationAmendmentRequestEntity oldApplicationAmendmentEntity = Utils.getClonedEntityForData(existingApplicationAmendment);
List<ApplicationAmendmentRequestEntity> amendmentRequestList = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(
List<ApplicationAmendmentRequestEntity> amendmentRequestList = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(
existingApplicationAmendment.getApplicationEvaluationEntity().getId()
);
@@ -971,7 +993,7 @@ public class ApplicationAmendmentRequestDao {
ApplicationAmendmentRequestEntity updatedApplicationAmendment = saveApplicationAmendmentRequestEntity(existingApplicationAmendment, oldApplicationAmendmentEntity,
VersionActionTypeEnum.UPDATE);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(updatedApplicationAmendment,false);
List<ApplicationAmendmentRequestEntity> amendmentRequests = applicationAmendmentRequestRepository.findAllByApplicationEvaluationIdAndIsDeletedFalse(
existingApplicationAmendment.getApplicationEvaluationEntity().getId());
@@ -998,6 +1020,11 @@ public class ApplicationAmendmentRequestDao {
AssignedApplicationsEntity oldAssignedApplicationData = Utils.getClonedEntityForData(assignedApplicationsEntity);
assignedApplicationsEntity = assignedApplicationsRepository.save(existingApplicationAmendment.getApplicationEvaluationEntity().getAssignedApplicationsEntity());
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.AMENDMENT_CLOSED);
notificationDao.sendNotificationToInstructor(placeHolders,existingApplicationAmendment.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_CLOSED);
/** This code is responsible for adding a version history log for the "Update Application Evaluation" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity)
.newData(existingApplicationEvaluationEntity).build());
@@ -1017,6 +1044,7 @@ public class ApplicationAmendmentRequestDao {
return response;
}
public ApplicationAmendmentRequestResponse extendResponseDays(Long id, Long newResponseDays) {
ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = validateApplicationAmendmentRequest(id);
@@ -1030,7 +1058,7 @@ public class ApplicationAmendmentRequestDao {
/** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationAmendmentEntity).newData(applicationAmendmentRequestEntity).build());
}
return convertEntityToResponse(applicationAmendmentRequestEntity);
return convertEntityToResponse(applicationAmendmentRequestEntity,false);
}
public List<ApplicationAmendmentRequestResponse> getAmendmentByApplicationId(HttpServletRequest request, Long applicationId, List<ApplicationAmendmentRequestEnum> statuses) {
@@ -1055,7 +1083,7 @@ public class ApplicationAmendmentRequestDao {
List<ApplicationAmendmentRequestResponse> response = new ArrayList<>();
if (applicationAmendmentRequestEntity != null) {
response = applicationAmendmentRequestEntity.stream()
.map(this::convertEntityToResponse)
.map(entity -> convertEntityToResponse(entity, false))
.collect(Collectors.toList());
}
return response;
@@ -1075,7 +1103,7 @@ public class ApplicationAmendmentRequestDao {
/** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationAmendmentEntity).newData(existingApplicationAmendment).build());
}
ApplicationAmendmentRequestResponse response = convertEntityToResponse(existingApplicationAmendment);
ApplicationAmendmentRequestResponse response = convertEntityToResponse(existingApplicationAmendment,false);
log.info("Amendment status updated successfully: {}", response);
return response;
}

View File

@@ -10,6 +10,7 @@ import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBea
import net.gepafin.tendermanagement.model.request.ApplicationRequest;
import net.gepafin.tendermanagement.model.request.ApplicationRequestBean;
import net.gepafin.tendermanagement.model.request.EmailLogRequest;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.repositories.*;
@@ -163,6 +164,21 @@ public class ApplicationDao {
@Autowired
private ApplicationEvaluationService applicationEvaluationService;
@Autowired
private NotificationDao notificationDao;
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository;
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) {
FormEntity formEntity = formService.validateForm(formId);
// callService.validatePublishedCall(formEntity.getCall().getId());
@@ -280,7 +296,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());
@@ -388,6 +409,16 @@ public class ApplicationDao {
responseBean.setStatus(applicationEntity.getStatus());
responseBean.setComments(applicationEntity.getComments());
responseBean.setCompanyId(applicationEntity.getCompanyId());
Optional<AssignedApplicationsEntity> assignedApplicationsOptional =
assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId());
if(assignedApplicationsOptional.isPresent()){
responseBean.setAssignedUserId(assignedApplicationsOptional.get().getUserId());
UserEntity user = userService.validateUser(assignedApplicationsOptional.get().getUserId());
String firstName = user.getFirstName() != null ? user.getFirstName() : "";
String lastName = user.getLastName() != null ? user.getLastName() : "";
String userName = String.join(" ", firstName, lastName).trim();
responseBean.setAssignedUserName(userName);
}
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
responseBean.setCompanyName(company.getCompanyName());
if(applicationEntity.getProtocol() != null) {
@@ -857,6 +888,8 @@ public class ApplicationDao {
applicationEntity.setStatus(ApplicationStatusTypeEnum.SUBMIT.getValue());
applicationEntity.setSubmissionDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
applicationEntity = applicationRepository.save(applicationEntity);
Map<String ,String> placeHolders=notificationDao.sendNotificationToBeneficiary(applicationEntity,NotificationTypeEnum.APPLICATION_SUBMISSION);
notificationDao.sendNotificationToSuperUser(applicationEntity,placeHolders,NotificationTypeEnum.APPLICATION_SUBMISSION);
/** This code is responsible for adding a version history log for "Update application status" operation. **/
loggingUtil.addVersionHistory(
@@ -969,7 +1002,8 @@ public class ApplicationDao {
private void sendMailToUserAndCompany(UserEntity userEntity, ApplicationEntity applicationEntity) {
CallEntity call =applicationEntity.getCall();
CompanyEntity company=companyService.validateCompany(applicationEntity.getCompanyId());
ProtocolEntity protocol = applicationEntity.getProtocol();
UserWithCompanyEntity userWithCompany=companyService.getUserWithCompany(userEntity.getId(),company.getId());
ProtocolEntity protocol= applicationEntity.getProtocol();
HubEntity hub = hubService.valdateHub(applicationEntity.getHubId());
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService
.retrieveTemplateByTypeAndCall(SystemEmailTemplatesEntityTypeEnum.APPLICATION_SUBMISSION_TO_USER_AND_COMPANY,
@@ -1000,8 +1034,8 @@ public class ApplicationDao {
emailNotificationDao.sendMail(hub.getId(), subject, body, List.of(email),emailLogRequest);
List<String> recipientEmails = new ArrayList<>();
// recipientEmails.add(email);
String companyEmail = company.getEmail();
String contactEmail = company.getContactEmail();
String companyEmail = userWithCompany.getEmail();
String contactEmail = userWithCompany.getContactEmail();
if (companyEmail != null && !companyEmail.isEmpty()) {
recipientEmails.add(companyEmail);
@@ -1219,90 +1253,121 @@ public class ApplicationDao {
}
public byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId) {
ApplicationEntity applicationEntity = validateApplication(applicationId);
validateAssignedUser(request, applicationId);
Set<Long> documentIds = extractDocumentIdsFromApplicationForms(applicationId);
List<DocumentEntity> documents = documentRepository.findAllByIdInAndIsDeletedFalse(documentIds);
ApplicationSignedDocumentEntity signedDocument = applicationSignedDocumentRepository
.findByApplicationIdAndStatus(applicationId, ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
if (documents.isEmpty() && signedDocument == null) {
ApplicationSignedDocumentEntity signedDocument = applicationSignedDocumentRepository.findByApplicationIdAndStatus(applicationId,
ApplicationSignedDocumentStatusEnum.ACTIVE.getValue());
List<DocumentEntity> amendmentDocuments = fetchAmendmentDocuments(applicationId);
List<DocumentEntity> evaluationDocuments = fetchEvaluationDocuments(applicationId);
if (documents.isEmpty() && signedDocument == null && amendmentDocuments.isEmpty() && evaluationDocuments.isEmpty()) {
throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND));
}
return createZipWithDocuments(applicationEntity, documents, signedDocument, applicationId);
return createZipWithDocuments(applicationEntity, documents, signedDocument, amendmentDocuments, evaluationDocuments, applicationId);
}
private void validateAssignedUser(HttpServletRequest request, Long applicationId) {
AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository
.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null);
AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null);
if (assignedApplications != null) {
validator.validatePreInstructor(request, assignedApplications.getUserId());
}
}
private Set<Long> extractDocumentIdsFromApplicationForms(Long applicationId) {
Set<Long> documentIds = new HashSet<>();
List<ApplicationFormEntity> applicationForms = applicationFormRepository.findByApplicationId(applicationId);
applicationForms.forEach(applicationForm -> {
FormEntity formEntity = applicationForm.getForm();
if (formEntity != null) {
List<ContentResponseBean> contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent();
contentResponseBeans.stream()
.filter(content -> "fileupload".equals(content.getName()))
.forEach(content -> {
Optional<ApplicationFormFieldEntity> formField = applicationFormFieldRepository
.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(
content.getId(), applicationForm.getId(), applicationId);
formField.ifPresent(field -> {
if (field.getFieldValue() != null) {
Arrays.stream(field.getFieldValue().split(","))
.map(String::trim)
.map(Long::valueOf)
.forEach(documentIds::add);
}
});
});
contentResponseBeans.stream().filter(content -> "fileupload".equals(content.getName())).forEach(content -> {
Optional<ApplicationFormFieldEntity> formField = applicationFormFieldRepository.findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId(
content.getId(), applicationForm.getId(), applicationId);
formField.ifPresent(field -> {
if (field.getFieldValue() != null) {
Arrays.stream(field.getFieldValue().split(",")).map(String::trim).map(Long::valueOf).forEach(documentIds::add);
}
});
});
}
});
return documentIds;
}
private void addDocumentToZip(ZipOutputStream zos, String s3Folder, String filePath, String fileName) {
private List<DocumentEntity> fetchAmendmentDocuments(Long applicationId) {
List<ApplicationAmendmentRequestEntity> amendmentRequests = applicationAmendmentRequestRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
Set<Long> amendmentIds = amendmentRequests.stream().map(ApplicationAmendmentRequestEntity::getId).collect(Collectors.toSet());
return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(amendmentIds, DocumentSourceTypeEnum.AMENDMENT.getValue());
}
private List<DocumentEntity> fetchEvaluationDocuments(Long applicationId) {
Optional<ApplicationEvaluationEntity> evaluationEntity = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationId);
if (evaluationEntity.isPresent()) {
Long evaluationId = evaluationEntity.get().getId();
return documentRepository.findBySourceIdInAndSourceAndIsDeletedFalse(Collections.singleton(evaluationId), DocumentSourceTypeEnum.EVALUATION.getValue());
}
return Collections.emptyList();
}
private String fetchProtocolNumberForAmendment(Long amendmentRequestId) {
ApplicationAmendmentRequestEntity amendmentRequest = applicationAmendmentRequestRepository.findByIdAndIsDeletedFalse(amendmentRequestId).orElse(null);
if (amendmentRequest != null && amendmentRequest.getProtocol() != null) {
return amendmentRequest.getProtocol().getProtocolNumber().toString();
}
return "unknown";
}
private void addDocumentToZip(ZipOutputStream zos, String s3Folder, String filePath, String fullPath) {
try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, filePath)) {
zos.putNextEntry(new ZipEntry(fileName));
zos.putNextEntry(new ZipEntry(fullPath));
IOUtils.copy(fileInputStream, zos);
zos.closeEntry();
} catch (IOException e) {
throw new RuntimeException("Error downloading or adding document to ZIP: " + fileName, e);
throw new RuntimeException("Error downloading or adding document to ZIP: " + fullPath, e);
}
}
private byte[] createZipWithDocuments(ApplicationEntity applicationEntity, List<DocumentEntity> documents, ApplicationSignedDocumentEntity signedDocument,
List<DocumentEntity> amendmentDocuments, List<DocumentEntity> evaluationDocuments, Long applicationId) {
private byte[] createZipWithDocuments(ApplicationEntity applicationEntity, List<DocumentEntity> documents,
ApplicationSignedDocumentEntity signedDocument, Long applicationId) {
try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
String s3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, applicationEntity.getCall().getId(), applicationId,0L);
try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
Long callId = applicationEntity.getCall().getId();
// Add Application Documents
String appS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, callId, applicationId, 0L);
for (DocumentEntity document : documents) {
String fileName = Utils.extractFileName(document.getFilePath());
addDocumentToZip(zos, s3Folder, document.getFilePath(), fileName);
addDocumentToZip(zos, appS3Folder, document.getFilePath(), fileName);
}
// Add Signed Document
if (signedDocument != null) {
String signedDocS3Folder = s3PathConfig.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, applicationEntity.getCall().getId(), applicationId,0L);
String signedDocFileName = signedDocument.getFileName();
addDocumentToZip(zos, signedDocS3Folder, signedDocument.getFilePath(), signedDocFileName);
String signedFolder = "SIGNED_DOCUMENT/";
String signedDocS3Folder = s3PathConfig.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId, 0L);
String fileName = signedDocument.getFileName();
addDocumentToZip(zos, signedDocS3Folder, signedDocument.getFilePath(), signedFolder + fileName);
}
// Add Amendment (Soccorso) Documents
for (DocumentEntity amendmentDocument : amendmentDocuments) {
String protocolNumber = fetchProtocolNumberForAmendment(amendmentDocument.getSourceId());
String amendmentFolder = "SOCCORSO_" + protocolNumber + "/";
String amendmentS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.AMENDMENT, callId, applicationId, amendmentDocument.getSourceId());
String fileName = Utils.extractFileName(amendmentDocument.getFilePath());
addDocumentToZip(zos, amendmentS3Folder, amendmentDocument.getFilePath(), amendmentFolder + fileName);
}
// Add Evaluation Documents
for (DocumentEntity evaluationDocument : evaluationDocuments) {
String evaluationFolder = "EVALUATION/";
String evaluationS3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.EVALUATION, callId, applicationId, evaluationDocument.getSourceId());
String fileName = Utils.extractFileName(evaluationDocument.getFilePath());
addDocumentToZip(zos, evaluationS3Folder, evaluationDocument.getFilePath(), evaluationFolder + fileName);
}
zos.finish();
return zipOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error while creating ZIP file", e);
}
}
}

View File

@@ -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;
@@ -94,6 +96,12 @@ public class ApplicationEvaluationDao {
@Autowired
private CompanyService companyService;
@Autowired
private NotificationDao notificationDao;
@Autowired
private UserRepository userRepository;
@Autowired
private Validator validator;
@@ -558,7 +566,16 @@ public class ApplicationEvaluationDao {
response.setAssignedAt(assignedApplications.getAssignedAt());
}
response.setEvaluationEndDate(entity.getEndDate());
Optional<AssignedApplicationsEntity> assignedApplicationsOptional =
assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(application.getId());
if(assignedApplicationsOptional.isPresent()){
response.setAssignedUserId(assignedApplicationsOptional.get().getUserId());
UserEntity assignedUser = userService.validateUser(assignedApplicationsOptional.get().getUserId());
String assignedUserFirstName = assignedUser.getFirstName() != null ? assignedUser.getFirstName() : "";
String assignedUserLastName = assignedUser.getLastName() != null ? assignedUser.getLastName() : "";
String userName = String.join(" ", assignedUserFirstName, assignedUserLastName).trim();
response.setAssignedUserName(userName);
}
LocalDateTime callEndDate = application.getCall().getEndDate();
response.setCallEndDate(callEndDate);
if (application.getCompanyId() != null) {
@@ -599,8 +616,15 @@ public class ApplicationEvaluationDao {
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;
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_CREATION);
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_CREATION);
notificationDao.sendNotificationToInstructor(placeHolders,entity,NotificationTypeEnum.EVALUATION_CREATION);
}
ApplicationStatusForEvaluation status = req.getApplicationStatus();
// Fetch all amendment request entities associated with the evaluation ID
@@ -1776,8 +1800,14 @@ 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());
}
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);
@@ -1804,12 +1834,16 @@ public class ApplicationEvaluationDao {
emailNotificationDao.sendInadmissibilityEmailForRejectedApplication(application,existingEntity);
}
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_RESULT);
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_RESULT);
notificationDao.sendNotificationToInstructor(placeHolders,existingEntity,NotificationTypeEnum.EVALUATION_RESULT);
return convertToResponse(entity);
}
return null;
}
public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) {
public ApplicationEvaluationEntity validateApplicationEvaluationByApplicationId(Long applicationId) {
return applicationEvaluationRepository
.findByApplicationIdAndIsDeletedFalse(applicationId)
.orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,

View File

@@ -16,14 +16,18 @@ import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.CompanyEntity;
import net.gepafin.tendermanagement.entities.DocumentEntity;
import net.gepafin.tendermanagement.entities.HubEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
import net.gepafin.tendermanagement.enums.RoleStatusEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.AppointmentCreationRequest;
import net.gepafin.tendermanagement.model.request.AppointmentNdgRequest;
import net.gepafin.tendermanagement.model.request.AppointmentVisuraListRequest;
import net.gepafin.tendermanagement.model.request.AppointmentVisuraRequest;
import net.gepafin.tendermanagement.model.request.CreateAppointmentRequest;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.request.UploadDocToExternalSystemRequest;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.AppointmentCreationResponse;
@@ -34,6 +38,7 @@ import net.gepafin.tendermanagement.repositories.ApplicationRepository;
import net.gepafin.tendermanagement.repositories.CompanyRepository;
import net.gepafin.tendermanagement.repositories.DocumentRepository;
import net.gepafin.tendermanagement.repositories.HubRepository;
import net.gepafin.tendermanagement.repositories.UserRepository;
import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.service.CompanyService;
import net.gepafin.tendermanagement.service.feignClient.AppointmentApiService;
@@ -58,6 +63,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -130,6 +136,12 @@ public class AppointmentDao {
@Autowired
private TokenProvider tokenProvider;
@Autowired
private NotificationDao notificationDao;
@Autowired
private UserRepository userRepository;
private final Map<Long, ExecutorService> executorMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Long, ExecutorService> threadForDocumentMap = new ConcurrentHashMap<>();
@@ -312,6 +324,8 @@ public class AppointmentDao {
company.setNdg(ndg);
companyRepository.save(company);
applicationRepository.save(application);
Map<String ,String> placeHolders=notificationDao.sendNotificationToBeneficiary(application,NotificationTypeEnum.NDG_GENERATION);
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.NDG_GENERATION);
// /** This code is responsible for adding a version history log for the "update application ndg code, status, and Id visura" operation. **/
// loggingUtil.addVersionHistory(

View File

@@ -15,7 +15,9 @@ import java.util.zip.ZipOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.entities.*;
import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum;
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.*;
import net.gepafin.tendermanagement.repositories.*;
@@ -49,6 +51,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import static net.gepafin.tendermanagement.enums.RoleStatusEnum.ROLE_SUPER_ADMIN;
import static net.gepafin.tendermanagement.util.Utils.setIfUpdated;
import static org.hibernate.internal.util.collections.CollectionHelper.listOf;
@Component
public class CallDao {
@@ -108,6 +111,15 @@ public class CallDao {
@Autowired
private HttpServletRequest request;
@Autowired
private NotificationDao notificationDao;
@Autowired
private BeneficiaryRepository beneficiaryRepository;
@Autowired
private NotificationTypeRepository notificationTypeRepository;
public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, UserEntity userEntity) {
createCallRequest.setRegionId(userEntity.getRoleEntity().getRegion().getId());
CallEntity callEntity = convertToCallEntity(createCallRequest, userEntity);
@@ -828,10 +840,20 @@ public class CallDao {
validateStatusChange(currentStatus, statusReq);
callEntity.setStatus(statusReq.getValue());
callEntity = callRepository.save(callEntity);
//Creating notification.
List<Long> userIds = beneficiaryRepository.findUserIdsByHubIdAndBeneficiaryId(callEntity.getHub().getId());
Map<String, String> placeholders = new HashMap<>();
placeholders.put("{{call_name}}", callEntity.getName());
userIds.forEach(userId -> {
List<Long> companyIds = notificationDao.getAllCompanyIdsForUser(userId);
NotificationReq notificationReq = notificationDao.createNotificationReq(NotificationTypeEnum.CALL_CREATED.getValue(), placeholders, userId, null, companyIds);
notificationDao.sendNotification(notificationReq);
});
/** This code is responsible for adding a version history log for the "update call status" operation **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCallEntity).newData(callEntity).build());
return convertToCallResponseBean(callEntity);
}

View File

@@ -2,6 +2,7 @@ package net.gepafin.tendermanagement.dao;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.entities.*;
@@ -66,7 +67,7 @@ public class CompanyDao {
if (existingCompany != null) {
UserWithCompanyEntity existingRelation = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userEntity.getId(), existingCompany.getId()).orElse(null);
if (existingRelation == null) {
userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant());
userWithCompanyEntity = createUserWithCompanyRelation(userEntity, existingCompany, companyRequest.getIsLegalRepresentant(),companyRequest);
/** This code is responsible for adding a version history log for "adding user with company" operation. **/
loggingUtil.addVersionHistory(
@@ -83,7 +84,7 @@ public class CompanyDao {
/** This code is responsible for adding a version history log for "creating company" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(companyData).build());
userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant());
userWithCompanyEntity = createUserWithCompanyRelation(userEntity, companyEntity, companyRequest.getIsLegalRepresentant(),companyRequest);
return convertCompanyEntityToCompanyResponse(companyEntity, userWithCompanyEntity);
}
@@ -107,7 +108,7 @@ public class CompanyDao {
}
}
private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant) {
private UserWithCompanyEntity createUserWithCompanyRelation(UserEntity userEntity, CompanyEntity companyEntity, Boolean isLegalRepresentant,CompanyRequest companyRequest) {
UserWithCompanyEntity userWithCompanyEntity = new UserWithCompanyEntity();
if (userEntity.getBeneficiary() != null) {
@@ -117,6 +118,11 @@ public class CompanyDao {
userWithCompanyEntity.setCompanyId(companyEntity.getId());
userWithCompanyEntity.setUserId(userEntity.getId());
userWithCompanyEntity.setIsLegalRepresentant(isLegalRepresentant);
userWithCompanyEntity.setEmail(companyRequest.getEmail());
userWithCompanyEntity.setPec(companyRequest.getPec());
userWithCompanyEntity.setContactName(companyRequest.getContactName());
userWithCompanyEntity.setContactEmail(companyRequest.getContactEmail());
userWithCompanyEntity.setJson(Utils.convertMapIntoJsonString(companyRequest.getVatCheckResponse()) );
UserWithCompanyEntity userWithCompany = userWithCompanyRepository.save(userWithCompanyEntity);
/** This code is responsible for adding a version history log for the "adding user with company" operation. **/
@@ -135,12 +141,8 @@ public class CompanyDao {
entity.setProvince(request.getProvince());
entity.setCap(request.getCap());
entity.setCountry(request.getCountry());
entity.setPec(request.getPec());
entity.setEmail(request.getEmail());
entity.setNumberOfEmployees(request.getNumberOfEmployees());
entity.setAnnualRevenue(request.getAnnualRevenue());
entity.setContactName(request.getContactName());
entity.setContactEmail(request.getContactEmail());
entity.setHub(userEntity.getHub());
return entity;
}
@@ -157,8 +159,8 @@ public class CompanyDao {
response.setProvince(entity.getProvince());
response.setCap(entity.getCap());
response.setCountry(entity.getCountry());
response.setPec(entity.getPec());
response.setEmail(entity.getEmail());
response.setPec(userWithCompanyEntity.getPec());
response.setEmail(userWithCompanyEntity.getEmail());
response.setNumberOfEmployees(entity.getNumberOfEmployees());
response.setAnnualRevenue(entity.getAnnualRevenue());
if(userWithCompanyEntity!=null) {
@@ -166,8 +168,8 @@ public class CompanyDao {
}
response.setCreatedDate(entity.getCreatedDate());
response.setUpdatedDate(entity.getUpdatedDate());
response.setContactName(entity.getContactName());
response.setContactEmail(entity.getContactEmail());
response.setContactName(userWithCompanyEntity.getContactName());
response.setContactEmail(userWithCompanyEntity.getContactEmail());
return response;
}
@@ -178,7 +180,6 @@ public class CompanyDao {
CompanyEntity oldCompanyData = Utils.getClonedEntityForData(companyEntity);
setIfUpdated(companyEntity::getCompanyName, companyEntity::setCompanyName, companyRequest.getCompanyName());
setIfUpdated(companyEntity::getVatNumber, companyEntity::setVatNumber, companyRequest.getVatNumber());
setIfUpdated(companyEntity::getCodiceFiscale, companyEntity::setCodiceFiscale, companyRequest.getCodiceFiscale());
setIfUpdated(companyEntity::getAddress, companyEntity::setAddress, companyRequest.getAddress());
setIfUpdated(companyEntity::getPhoneNumber, companyEntity::setPhoneNumber, companyRequest.getPhoneNumber());
@@ -186,12 +187,17 @@ public class CompanyDao {
setIfUpdated(companyEntity::getProvince, companyEntity::setProvince, companyRequest.getProvince());
setIfUpdated(companyEntity::getCap, companyEntity::setCap, companyRequest.getCap());
setIfUpdated(companyEntity::getCountry, companyEntity::setCountry, companyRequest.getCountry());
setIfUpdated(companyEntity::getPec, companyEntity::setPec, companyRequest.getPec());
setIfUpdated(companyEntity::getEmail, companyEntity::setEmail, companyRequest.getEmail());
setIfUpdated(companyEntity::getNumberOfEmployees, companyEntity::setNumberOfEmployees, companyRequest.getNumberOfEmployees());
setIfUpdated(companyEntity::getAnnualRevenue, companyEntity::setAnnualRevenue, companyRequest.getAnnualRevenue());
setIfUpdated(companyEntity::getContactName, companyEntity::setContactName, companyRequest.getContactName());
setIfUpdated(companyEntity::getContactEmail, companyEntity::setContactEmail, companyRequest.getContactEmail());
//
// if(StringUtils.isNotBlank(companyRequest.getVatNumber())) {
// CompanyEntity existingCompany = companyRepository.findByVatNumberAndHubId(companyRequest.getVatNumber(), userEntity.getHub().getId());
// if(existingCompany!=null){
// throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.VATNUMBER_ALREADY_EXISTS));
// }
// companyEntity.setVatNumber(companyRequest.getVatNumber());
//
// }
companyRepository.save(companyEntity);
/** This code is responsible for adding a version history log for the "Update company" operation. **/
@@ -201,8 +207,15 @@ public class CompanyDao {
UserWithCompanyEntity userWithCompanyEntity = getUserWithCompany(userEntity.getId(), companyId);
//cloned entity for old data
UserWithCompanyEntity oldUserWithCompanyData = Utils.getClonedEntityForData(userWithCompanyEntity);
Utils.setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, companyRequest.getIsLegalRepresentant());
if(StringUtils.isNotBlank(companyRequest.getVatNumber())) {
String responseJson = companyRequest.getVatCheckResponse() != null ? Utils.convertMapIntoJsonString(companyRequest.getVatCheckResponse()) : null;
setIfUpdated(userWithCompanyEntity::getJson, userWithCompanyEntity::setJson, responseJson);
}
setIfUpdated(userWithCompanyEntity::getPec, userWithCompanyEntity::setPec, userWithCompanyEntity.getPec());
setIfUpdated(userWithCompanyEntity::getEmail, userWithCompanyEntity::setEmail, userWithCompanyEntity.getEmail());
setIfUpdated(userWithCompanyEntity::getContactName, userWithCompanyEntity::setContactName, companyRequest.getContactName());
setIfUpdated(userWithCompanyEntity::getContactEmail, userWithCompanyEntity::setContactEmail, companyRequest.getContactEmail());
setIfUpdated(userWithCompanyEntity::getIsLegalRepresentant, userWithCompanyEntity::setIsLegalRepresentant, companyRequest.getIsLegalRepresentant());
userWithCompanyEntity = userWithCompanyRepository.save(userWithCompanyEntity);
/** This code is responsible for adding a version history log for the "Update company" operation. **/
@@ -254,7 +267,7 @@ public class CompanyDao {
return userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userId, companyId).orElseThrow(() -> new ForbiddenAccessException(Status.FORBIDDEN,
Translator.toLocale(GepafinConstant.PERMISSION_DENIED)));
}
public UserWithCompanyEntity getUserWithCompany(Long userId, Long compnayId) {
return userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userId, compnayId).orElseThrow(
() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.USER_COMPANY_RELATION_NOT_FOUND)));
@@ -277,39 +290,59 @@ public class CompanyDao {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.CANNOT_DELETE_COMPANY_WITH_APPLICATION_SUBMITT));
}
for(ApplicationEntity application:userApplications){
ApplicationEntity oldApplication = Utils.getClonedEntityForData(application);
application.setIsDeleted(Boolean.TRUE);
userApplications = userApplications.stream()
.peek(application -> {
ApplicationEntity oldApplication = Utils.getClonedEntityForData(application);
application.setIsDeleted(Boolean.TRUE);
/** This code is responsible for adding a version history log for the "Soft delete application" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldApplication).newData(application).build());
}
/** This code is responsible for adding a version history log for the "Soft delete Faq" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder()
.request(request)
.actionType(VersionActionTypeEnum.SOFT_DELETE)
.oldData(oldApplication)
.newData(application)
.build()
);
})
.toList();
applicationRepository.saveAll(userApplications);
for(FaqEntity faq:faqs){
FaqEntity oldFaq = Utils.getClonedEntityForData(faq);
faq.setIsDeleted(Boolean.TRUE);
/** This code is responsible for adding a version history log for the "Soft delete Faq" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldFaq).newData(faq).build());
}
faqs = faqs.stream()
.peek(faq -> {
FaqEntity oldFaq = Utils.getClonedEntityForData(faq);
faq.setIsDeleted(Boolean.TRUE);
/** This code is responsible for adding a version history log for the "Soft delete Faq" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder()
.request(request)
.actionType(VersionActionTypeEnum.SOFT_DELETE)
.oldData(oldFaq)
.newData(faq)
.build()
);
})
.toList();
faqRepository.saveAll(faqs);
for(BeneficiaryPreferredCallEntity beneficiaryPreferredCall:preferredCallEntities){
BeneficiaryPreferredCallEntity oldPreferredCall = Utils.getClonedEntityForData(beneficiaryPreferredCall);
beneficiaryPreferredCall.setIsDeleted(Boolean.TRUE);
/** This code is responsible for adding a version history log for the "Soft Delete BeneficiaryPreferredCall" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldPreferredCall).newData(beneficiaryPreferredCall).build());
}
preferredCallEntities = preferredCallEntities.stream()
.peek(beneficiaryPreferredCall -> {
BeneficiaryPreferredCallEntity oldPreferredCall = Utils.getClonedEntityForData(beneficiaryPreferredCall);
beneficiaryPreferredCall.setIsDeleted(Boolean.TRUE);
/** This code is responsible for adding a version history log for the "Soft Delete BeneficiaryPreferredCall" operation. **/
loggingUtil.addVersionHistory(
VersionHistoryRequest.builder()
.request(request)
.actionType(VersionActionTypeEnum.SOFT_DELETE)
.oldData(oldPreferredCall)
.newData(beneficiaryPreferredCall)
.build()
);
})
.toList();
beneficiaryPreferredCallRepository.saveAll(preferredCallEntities);
if(userCompanyDelegationEntity!=null){
if(userCompanyDelegationEntity!=null){
UserCompanyDelegationEntity oldUserWithCompanyDelegation = Utils.getClonedEntityForData(userCompanyDelegationEntity);
userCompanyDelegationEntity.setStatus( UserCompanyDelegationStatusEnum.INACTIVE.getValue());
userCompanyDelegationRepository.save(userCompanyDelegationEntity);

View File

@@ -4,9 +4,11 @@ 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.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.ApplicationWidgetResponseBean;
import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean;
import net.gepafin.tendermanagement.model.response.Widget1;
import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean;
@@ -22,6 +24,12 @@ import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class DashboardDao {
@@ -37,9 +45,15 @@ public class DashboardDao {
@Autowired
private CompanyRepository companyRepository;
@Autowired
private CompanyService companyService;
@Autowired
private BeneficiaryPreferredCallRepository beneficiaryPreferredCallRepository;
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
@Autowired
private UserActionsRepository userActionsRepository;
@@ -129,14 +143,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<BeneficiaryPreferredCallEntity> preferredCalls = beneficiaryPreferredCallRepository
.findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId());
if (preferredCalls != null && !preferredCalls.isEmpty()) {
List<Long> callIds = preferredCalls.stream()
.map(BeneficiaryPreferredCallEntity::getCallId)
.collect(Collectors.toList());
List<CallEntity> 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) {
@@ -174,4 +200,69 @@ public class DashboardDao {
Page<UserActionEntity> userActionEntities=userActionsRepository.findActionsByRoleNamesAndHubId(roles,requestedUserEntity.getHub().getId(),pageable);
return userActionEntities;
}
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<Long> 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);
}
}
}

View File

@@ -8,6 +8,7 @@ import net.gepafin.tendermanagement.enums.RecipientTypeEnum;
import net.gepafin.tendermanagement.model.request.EmailConfig;
import net.gepafin.tendermanagement.model.request.EmailLogRequest;
import net.gepafin.tendermanagement.model.response.AmendmentFormFieldResponse;
import net.gepafin.tendermanagement.model.response.EmailContentResponse;
import net.gepafin.tendermanagement.model.response.SystemEmailTemplateResponse;
import net.gepafin.tendermanagement.repositories.*;
import net.gepafin.tendermanagement.service.*;
@@ -61,9 +62,6 @@ public class EmailNotificationDao {
@Autowired
private ApplicationFormRepository applicationFormRepository;
@Autowired
private ApplicationFormFieldRepository applicationFormFieldRepository;
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
@@ -77,7 +75,19 @@ public class EmailNotificationDao {
// String service = determineService(applicationEntity.getHubId());
// String legalMail = service.equals("Gepafin S.p.a.") ? "bandi.gepafin@legalmail.it" : "bandi.sviluppumbria@legalmail.it";
EmailContentResponse emailContent = prepareEmailContent(applicationEntity, templateType, hubEntity, bodyPlaceholders);
UserEntity userEntity = userService.validateUser(applicationEntity.getUserId());
sendEmails(applicationEntity, userEntity, additionalRecipients,amendmentId,emailContent.getSystemEmailTemplateResponse(),emailContent.getSubject(),emailContent.getBody());
}
public EmailContentResponse prepareEmailContent(
ApplicationEntity applicationEntity,
SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum templateType,
HubEntity hubEntity,
Map<String, String> bodyPlaceholders
) {
SystemEmailTemplateResponse systemEmailTemplateResponse = systemEmailTemplatesService.retrieveTemplateByTypeAndCall(templateType, hubEntity, null);
Map<String, String> subjectPlaceholders = new HashMap<>();
CompanyEntity company = companyService.validateCompany(applicationEntity.getCompanyId());
subjectPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName());
@@ -85,15 +95,18 @@ public class EmailNotificationDao {
// bodyPlaceholders.put("{{legal_mail}}", legalMail);
String subject = Utils.replacePlaceholders(systemEmailTemplateResponse.getSubject(), subjectPlaceholders);
String body = Utils.replacePlaceholders(systemEmailTemplateResponse.getHtmlContent(), bodyPlaceholders);
UserEntity userEntity = userService.validateUser(applicationEntity.getUserId());
sendEmails(applicationEntity, userEntity, additionalRecipients,amendmentId,systemEmailTemplateResponse,subject,body);
return new EmailContentResponse(subject, body, systemEmailTemplateResponse);
}
private void sendEmails(ApplicationEntity applicationEntity, UserEntity userEntity, List<String> additionalRecipients,Long amendmentId,SystemEmailTemplateResponse systemEmailTemplateResponse,String subject,String body) {
Optional<ApplicationEvaluationEntity> applicationEvaluationEntity = applicationEvaluationRepository.findByApplicationIdAndIsDeletedFalse(applicationEntity.getId());
CompanyEntity company = companyService.validateCompany(applicationEntity.getCompanyId());
String companyEmail = company.getEmail();
String contactEmail = company.getContactEmail();
UserWithCompanyEntity userWithCompany=companyService.getUserWithCompany(userEntity.getId(),company.getId());
String companyEmail = userWithCompany.getEmail();
String contactEmail = userWithCompany.getContactEmail();
if (companyEmail != null && !companyEmail.isEmpty()) {
EmailLogRequest emailLogRequest = emailLogDao.createEmailLogRequest(systemEmailTemplateResponse.getEmailScenario(), RecipientTypeEnum.COMPANY,company.getId() ,
@@ -150,6 +163,11 @@ public class EmailNotificationDao {
public void sendMailToNotifyBeneficiaryRegardingNewAmendment(ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity) {
ApplicationEntity applicationEntity = applicationService.validateApplication(applicationAmendmentRequestEntity.getApplicationId());
Map<String, String> bodyPlaceholders = prepareEmailPlaceholders(applicationEntity, applicationAmendmentRequestEntity);
sendEmail(applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null,
applicationAmendmentRequestEntity.getId());
}
public Map<String, String> prepareEmailPlaceholders(ApplicationEntity applicationEntity, ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity){
Map<String, String> bodyPlaceholders = new HashMap<>();
bodyPlaceholders.put("{{call_name}}", applicationEntity.getCall().getName());
bodyPlaceholders.put("{{protocol_number}}", applicationEntity.getProtocol().getProtocolNumber().toString());
@@ -185,8 +203,7 @@ public class EmailNotificationDao {
bodyPlaceholders.put("{{note}}", applicationAmendmentRequestEntity.getNote());
sendEmail(applicationEntity, SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum.DOCUMENTATION_INTEGRATION_REQUEST, bodyPlaceholders, null,
applicationAmendmentRequestEntity.getId());
return bodyPlaceholders;
}
public List<AmendmentFormFieldResponse> getIdAndLabelFromResult(List<Map<String, Object>> result) {

View File

@@ -0,0 +1,278 @@
package net.gepafin.tendermanagement.dao;
import lombok.extern.slf4j.Slf4j;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
import net.gepafin.tendermanagement.entities.NotificationEntity;
import net.gepafin.tendermanagement.entities.NotificationTypeEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.entities.UserWithCompanyEntity;
import net.gepafin.tendermanagement.enums.NotificationEnum;
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
import net.gepafin.tendermanagement.enums.RoleStatusEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.response.NotificationResponse;
import net.gepafin.tendermanagement.repositories.NotificationRepository;
import net.gepafin.tendermanagement.repositories.NotificationTypeRepository;
import net.gepafin.tendermanagement.repositories.UserRepository;
import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository;
import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.util.DateTimeUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.hibernate.internal.util.collections.CollectionHelper.listOf;
@Component
@Slf4j
public class NotificationDao {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@Autowired
private NotificationRepository notificationRepository;
@Autowired
private NotificationTypeRepository notificationTypeRepository;
@Autowired
private UserWithCompanyRepository userWithCompanyRepository;
@Autowired
private UserRepository userRepository;
@Autowired
private CompanyDao companyDao;
@Autowired
private ApplicationService applicationService;
@Autowired
private UserDao userDao;
public NotificationResponse sendNotification(NotificationReq notificationReq) {
// Ensure userId is properly set in notificationReq if not already
Long userId = notificationReq.getUserId();
if (userId == null) {
log.error("User ID is missing in the notification request.");
return null;
}
NotificationEntity notificationEntity = saveNotification(notificationReq);
log.info("Sending notification to user {} with content: {}", userId, notificationReq.getMessage());
List<Long> companyIds = notificationReq.getCompanyIds();
if (companyIds == null || companyIds.isEmpty()) {
sendToUser(userId, notificationEntity);
} else {
sendToCompanies(userId, companyIds, notificationEntity);
}
return convertNotificationEntityToNotificationResponse(notificationEntity);
}
private NotificationEntity saveNotification(NotificationReq notificationReq) {
return notificationRepository.save(convertNotificationRequestToNotificationEntity(notificationReq));
}
private void sendToUser(Long userId, NotificationEntity notificationEntity) {
String userChannel = GepafinConstant.COMMON_SINGLE_CHANNEL_PREFIX + userId;
log.info("Channel for User {}", userChannel);
NotificationResponse notificationResponse = convertNotificationEntityToNotificationResponse(notificationEntity);
messagingTemplate.convertAndSend(userChannel, notificationResponse);
}
private void sendToCompanies(Long userId, List<Long> companyIds, NotificationEntity notificationEntity) {
// Send notification to each company provided in the companyIds list
companyIds.forEach(companyId -> {
UserWithCompanyEntity userWithCompany = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalseForNotification(userId, companyId);
String companyChannel = Utils.createChannelForUserAndCompany(userId, companyId);
log.info("Channel for User and Company {}, {}", userId, companyChannel);
if (userWithCompany == null) {
throw new CustomValidationException(Status.BAD_REQUEST, GepafinConstant.USER_WITH_COMPANY_NOT_FOUND);
}
notificationEntity.setUserWithCompany(userWithCompany);
notificationRepository.save(notificationEntity);
NotificationResponse notificationResponse = convertNotificationEntityToNotificationResponse(notificationEntity);
messagingTemplate.convertAndSend(companyChannel, notificationResponse);
});
}
private NotificationResponse convertNotificationEntityToNotificationResponse(NotificationEntity notificationEntity) {
NotificationResponse notificationResponse = new NotificationResponse();
notificationResponse.setId(notificationEntity.getId());
notificationResponse.setUserId(notificationEntity.getUserId());
notificationResponse.setStatus(notificationEntity.getStatus());
notificationResponse.setMessage(notificationEntity.getMessage());
notificationResponse.setCreatedDate(notificationEntity.getCreatedDate());
notificationResponse.setUpdatedDate(notificationEntity.getUpdatedDate());
notificationResponse.setRedirectUrl(notificationEntity.getNotificationType());
notificationResponse.setCompanyId(notificationEntity.getUserWithCompany() != null ? notificationEntity.getUserWithCompany().getCompanyId() : null);
notificationResponse.setNotificationType(notificationEntity.getNotificationType());
notificationResponse.setTitle(notificationEntity.getTitle());
return notificationResponse;
}
private NotificationEntity convertNotificationRequestToNotificationEntity(NotificationReq notificationReq) {
NotificationEntity notificationEntity = new NotificationEntity();
String message = notificationReq.getMessage();
notificationEntity.setNotificationType(notificationReq.getNotificationType());
notificationEntity.setUserId(notificationReq.getUserId());
notificationEntity.setStatus(NotificationEnum.UNREAD.getValue());
notificationEntity.setIsDeleted(Boolean.FALSE);
notificationEntity.setUserWithCompany(notificationReq.getUserWithCompanyEntity() != null ? notificationReq.getUserWithCompanyEntity() : null);
notificationEntity.setMessage(message);
notificationEntity.setTitle(notificationReq.getTitle());
return notificationEntity;
}
public NotificationReq createNotificationReq(String notificationType, Map<String, String> placeholders, Long userId, UserWithCompanyEntity userWithCompanyEntity,
List<Long> companyIds) {
// Create NotificationReq object
NotificationReq notificationReq = new NotificationReq();
NotificationTypeEntity notificationTypeEntity = notificationTypeRepository.findByNotificationNameAndIsDeletedFalse(notificationType);
notificationReq.setNotificationType(notificationType);
String message = Utils.replacePlaceholders(notificationTypeEntity.getJsonTemplate(), placeholders);
notificationReq.setMessage(message);
notificationReq.setUserId(userId);
notificationReq.setCompanyIds(companyIds);
String title = Utils.replacePlaceholders(notificationTypeEntity.getTitle(), placeholders);
notificationReq.setTitle(title);
notificationReq.setUserWithCompanyEntity(userWithCompanyEntity);
return notificationReq;
}
public Map<String, String> sendNotificationToBeneficiary(ApplicationEntity application, NotificationTypeEnum notificationTypeEnum) {
Map<String, String> placeHolders = new HashMap<>();
placeHolders.put("{{call_name}}", application.getCall().getName());
placeHolders.put("{{protocol_number}}", String.valueOf(application.getProtocol().getProtocolNumber()));
NotificationReq notificationReq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, application.getUserId(), application.getUserWithCompany(),
listOf(application.getCompanyId()));
sendNotification(notificationReq);
return placeHolders;
}
public void sendNotificationToInstructor(Map<String, String> placeHolders, ApplicationEvaluationEntity applicationEvaluationEntity, NotificationTypeEnum notificationTypeEnum) {
Long instructorId = applicationEvaluationEntity.getUserId();
ApplicationEntity application = applicationService.validateApplication(applicationEvaluationEntity.getApplicationId());
if (instructorId != null) {
NotificationReq notificationreq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, instructorId, application.getUserWithCompany(),
null);
sendNotification(notificationreq);
}
}
public void sendNotificationToSuperUser(ApplicationEntity application, Map<String, String> placeHolders, NotificationTypeEnum notificationTypeEnum) {
List<UserEntity> user = userRepository.findByRoleEntity_RoleTypeAndHubId(RoleStatusEnum.ROLE_SUPER_ADMIN.getValue(), application.getHubId());
UserEntity userEntity1 = user.get(0);
if (userEntity1 != null) {
NotificationReq notificationreq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, userEntity1.getId(), application.getUserWithCompany(),
null);
sendNotification(notificationreq);
}
}
public List<Long> getAllCompanyIdsForUser(Long userId) {
return userWithCompanyRepository.findActiveCompanyIdsByUserId(userId);
}
public NotificationResponse getNotificationById(Long id) {
NotificationEntity notificationEntity = validateNotificationEntity(id);
return convertNotificationEntityToNotificationResponse(notificationEntity);
}
private NotificationEntity validateNotificationEntity(Long id) {
NotificationEntity notificationEntity = notificationRepository.findByIdAndIsDeletedFalse(id);
if (notificationEntity == null) {
throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.NOTIFICATION_NOT_FOUND));
}
return notificationEntity;
}
public List<NotificationResponse> getNotificationByUserId(Long userId, Long companyId, List<NotificationEnum> statuses) {
List<NotificationEntity> notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalse(userId);
UserWithCompanyEntity userWithCompany = null;
List<String> statusStrings = new ArrayList<>();
if (companyId != null) {
userWithCompany = companyDao.validateUserWithCompny(userId, companyId);
}
if (statuses != null) {
statusStrings = statuses.stream().map(NotificationEnum::name) // Convert enum to its name as String
.toList();
notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalseAndStatusIn(userId, statusStrings);
if (userWithCompany != null) {
notificationEntities = notificationRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(userId, userWithCompany.getId(), statusStrings);
}
}
return notificationEntities.stream().map(this::convertNotificationEntityToNotificationResponse).collect(Collectors.toList());
}
public NotificationResponse updateNotificationStatus(Long id, NotificationEnum status) {
NotificationEntity notificationEntity = validateNotificationEntity(id);
if (notificationEntity.getStatus().equals(status.getValue())) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.NOTIFICATION_ALREADY_IN_THAT_STATE));
}
notificationEntity.setStatus(status.getValue());
notificationEntity.setUpdatedDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
notificationRepository.save(notificationEntity);
return convertNotificationEntityToNotificationResponse(notificationEntity);
}
public void deleteNotification(Long id) {
NotificationEntity notificationEntity = validateNotificationEntity(id);
notificationEntity.setIsDeleted(true);
notificationRepository.save(notificationEntity);
}
public List<NotificationResponse> getNotificationByCompanyIdAndUserId(Long userId, Long companyId, List<NotificationEnum> statuses) {
List<NotificationEntity> notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalse(userId);
UserWithCompanyEntity userWithCompany = null;
List<String> statusStrings;
if (companyId != null) {
userWithCompany = companyDao.validateUserWithCompny(userId, companyId);
}
if (statuses != null) {
statusStrings = statuses.stream().map(NotificationEnum::name)
.toList();
notificationEntities = notificationRepository.findByUserIdAndIsDeletedFalseAndStatusIn(userId, statusStrings);
if (userWithCompany != null) {
notificationEntities = notificationRepository.findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(userId, userWithCompany.getId(), statusStrings);
}
}
return notificationEntities.stream().map(this::convertNotificationEntityToNotificationResponse).toList();
}
}

View File

@@ -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())) {
@@ -157,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()))) {
@@ -164,12 +199,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,
@@ -192,7 +225,30 @@ public class UserDao {
}
}
private void validatePassword(String password, String confirmPassword, String tempToken) {
private void validateDuplicateEmail(String email, String hubUuid, String roleType) {
String beneficiaryRoleType = RoleStatusEnum.ROLE_BENEFICIARY.getValue();
if (beneficiaryRoleType.equals(roleType)) {
Boolean beneficiaryExistsInHub = userRepository.existsByEmailIgnoreCaseForBeneficiaries(
email, hubUuid, beneficiaryRoleType);
if (Boolean.TRUE.equals(beneficiaryExistsInHub)) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.EMAIL_ALREADY_EXISTS));
}
} 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));
}
}
}
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));
@@ -219,7 +275,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 +284,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 **/
@@ -263,7 +323,7 @@ public class UserDao {
userEntity.setAddress(userReq.getAddress());
userEntity.setPhoneNumber(userReq.getPhoneNumber());
userEntity.setDateOfBirth(userReq.getDateOfBirth());
}
}
return userRepository.save(userEntity);
}
@@ -362,25 +422,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 +513,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) {

View File

@@ -4,15 +4,11 @@ import feign.FeignException;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.model.request.UserActionRequest;
import net.gepafin.tendermanagement.entities.CompanyEntity;
import net.gepafin.tendermanagement.model.response.VatCheckResponseBean;
import net.gepafin.tendermanagement.service.feignClient.VatCheckService;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,10 +45,13 @@ public class VatCheckDao {
@Autowired
private HttpServletRequest request;
public Map<String, Object> checkVatNumberApi(String vatNumber) {
public VatCheckResponseBean checkVatNumberApi(String vatNumber) {
VatCheckResponseBean vatCheckResponseBean = new VatCheckResponseBean();
vatCheckResponseBean.setValid(false);
vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
if (Boolean.TRUE.equals(Boolean.parseBoolean(isVatCheckGloballyDisabled))) {
return new HashMap<>();
vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
return vatCheckResponseBean;
}
Map<String, Object> responseBody = new HashMap<>();
try {
@@ -69,30 +68,57 @@ public class VatCheckDao {
if (response.getStatusCode() == HttpStatus.OK && response.hasBody()) {
log.info("Successfully checked vat number");
Map<String, Object> responseMap = response.getBody();
if (responseMap != null && responseMap.containsKey("data")) {
responseBody = (Map<String, Object>) responseMap.get("data");
responseBody.remove("timestamp_creation");
responseBody.remove("timestamp_last_update");
responseBody.remove("data_iscrizione");
responseBody.remove("id");
Map<String, Object> data = new LinkedHashMap<>();
data.put("data", responseBody);
return 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<String, Object> 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<String, Object> responseMap, VatCheckResponseBean vatCheckResponseBean) {
if (responseMap != null && responseMap.containsKey("data")) {
Map<String, Object> responseBody = (Map<String, Object>) responseMap.get("data");
if (responseBody != null) {
responseBody.remove("timestamp_creation");
responseBody.remove("timestamp_last_update");
responseBody.remove("data_iscrizione");
responseBody.remove("id");
Map<String, Object> 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));
}
return responseBody;
}
public Map<String, Object> checkVatNumber(String vatNumber) {
public VatCheckResponseBean checkVatNumber(String vatNumber) {
try {
return checkVatNumberApi(vatNumber);
} catch (Exception e) {
throw new CustomValidationException(Status.VALIDATION_ERROR,
Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
log.error("Error in checkVatNumber: {}", e.getMessage());
VatCheckResponseBean vatCheckResponseBean = new VatCheckResponseBean();
vatCheckResponseBean.setValid(false);
vatCheckResponseBean.setMessage(Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
return vatCheckResponseBean;
}
}
}

View File

@@ -62,4 +62,10 @@ public class ApplicationEvaluationEntity extends BaseEntity{
@Column(name = "STOP_DATE_TIME")
private LocalDateTime stopDateTime;
@Column(name = "CLOSING_DATE")
private LocalDateTime closingDate;
@Column(name = "ACTIVE_DAYS")
private Long activeDays;
}

View File

@@ -41,28 +41,19 @@ public class CompanyEntity extends BaseEntity{
@Column(name = "COUNTRY")
private String country;
@Column(name = "PEC")
private String pec;
@Column(name = "EMAIL")
private String email;
@Column(name = "NUMBER_OF_EMPLOYEES")
private String numberOfEmployees;
@Column(name = "ANNUAL_REVENUE")
private BigDecimal annualRevenue;
@Column(name = "CONTACT_NAME")
private String contactName;
@Column(name = "CONTACT_EMAIL")
private String contactEmail;
@ManyToOne
@JoinColumn(name = "HUB_ID")
private HubEntity hub;
// @Column(name = "JSON")
// private String json;
@Column(name = "NDG")
private String ndg;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,39 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Data;
@Entity
@Table(name = "NOTIFICATION")
@Data
public class NotificationEntity extends BaseEntity {
@Column(name = "USER_ID")
private Long userId;
@Column(name = "MESSAGE")
private String message;
@Column(name = "TITLE")
private String title;
@Column(name = "STATUS")
private String status;
@Column(name = "IS_DELETED")
private Boolean isDeleted;
@Column(name = "NOTIFICATION_TYPE")
private String notificationType;
@Column(name = "REDIRECT_LINK")
private String redirectLink;
@ManyToOne
@JoinColumn(name = "USER_WITH_COMPANY_ID")
private UserWithCompanyEntity userWithCompany;
}

View File

@@ -0,0 +1,24 @@
package net.gepafin.tendermanagement.entities;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.Data;
@Entity
@Data
@Table(name = "NOTIFICATION_TYPE")
public class NotificationTypeEntity extends BaseEntity {
@Column(name = "NOTIFICATION_NAME")
private String notificationName;
@Column(name = "JSON_TEMPLATE")
private String jsonTemplate;
@Column(name = "TITLE")
private String title;
@Column(name="IS_DELETED")
private Boolean isDeleted;
}

View File

@@ -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;

View File

@@ -22,6 +22,22 @@ public class UserWithCompanyEntity extends BaseEntity{
@Column(name = "IS_LEGAL_REPRESENTANT")
private Boolean isLegalRepresentant;
@Column(name = "CONTACT_NAME")
private String contactName;
@Column(name = "CONTACT_EMAIL")
private String contactEmail;
@Column(name = "PEC")
private String pec;
@Column(name = "EMAIL")
private String email;
@Column(name = "JSON")
private String json;
@Column(name = "IS_DELETED")
private Boolean isDeleted = false;

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -0,0 +1,27 @@
package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum NotificationEnum {
//status
READ("READ"), UNREAD("UNREAD");
private final String value;
NotificationEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}

View File

@@ -0,0 +1,36 @@
package net.gepafin.tendermanagement.enums;
import com.fasterxml.jackson.annotation.JsonValue;
public enum NotificationTypeEnum {
CALL_CREATED("CALL_CREATED"),
APPLICATION_SUBMISSION("APPLICATION_SUBMISSION"),
AMENDMENT_CREATION("AMENDMENT_CREATION"),
EVALUATION_RESULT("EVALUATION_RESULT"),
AMENDMENT_EXPIRED("AMENDMENT_EXPIRED"),
AMENDMENT_CLOSED("AMENDMENT_CLOSED"),
NDG_GENERATION("NDG_GENERATION"),
EVALUATION_CREATION("EVALUATION_CREATION"),
EVALUATION_EXPIRED("EVALUATION_EXPIRED"),
AMENDMENT_EXPIRATION_REMINDER("AMENDMENT_EXPIRATION_REMINDER"),
EVALUATION_EXPIRATION_REMINDER("EVALUATION_EXPIRATION_REMINDER");
private final String value;
NotificationTypeEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}

View File

@@ -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"),
@@ -134,6 +136,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"),

View File

@@ -1,6 +1,7 @@
package net.gepafin.tendermanagement.model.request;
import java.math.BigDecimal;
import java.util.Map;
import lombok.Data;
@@ -23,4 +24,5 @@ public class CompanyRequest {
private Boolean isLegalRepresentant;
private String contactName;
private String contactEmail;
private Map<String, Object> vatCheckResponse;
}

View File

@@ -0,0 +1,45 @@
package net.gepafin.tendermanagement.model.request;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import net.gepafin.tendermanagement.entities.UserWithCompanyEntity;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class NotificationReq {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Long id;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
Long userId;
String message;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
String notificationType;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
String status;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private LocalDateTime createdDate;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private LocalDateTime updatedDate;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private String redirectUrl;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private String title;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private List<Long> companyIds;
@JsonIgnore
private UserWithCompanyEntity userWithCompanyEntity;
}

View File

@@ -1,7 +1,6 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
import java.time.LocalDateTime;
@@ -19,6 +18,7 @@ public class ApplicationAmendmentRequestResponse {
private Long protocolNumber;
private String callName;
private String beneficiaryName;
private String companyName;
private List<AmendmentFormFieldResponse> formFields;
private List<ApplicationFormFieldResponseBean> applicationFormFields;
private List<DocumentResponseBean> amendmentDocuments;
@@ -31,4 +31,5 @@ public class ApplicationAmendmentRequestResponse {
private List<CommunicationResponseBean> commentsList;
private String internalNote;
private ApplicationAmendmentRequestEnum status;
private String emailTemplate;
}

View File

@@ -26,6 +26,8 @@ public class ApplicationEvaluationResponse {
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
private String beneficiary;
private Long assignedUserId;
private String assignedUserName;
private Long protocolNumber;
private String callName;
private String motivation;

View File

@@ -33,4 +33,8 @@ public class ApplicationResponse{
private Long protocolNumber;
private Long assignedUserId;
private String assignedUserName;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,10 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
@Data
public class EmailContentResponse {
private final String subject;
private final String body;
private final SystemEmailTemplateResponse systemEmailTemplateResponse;
}

View File

@@ -0,0 +1,21 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Data;
import net.gepafin.tendermanagement.model.BaseBean;
@Data
public class NotificationResponse extends BaseBean {
private Long userId;
private String title;
private String message;
private String status;
private Long companyId;
private String redirectUrl;
private String notificationType;
}

View File

@@ -40,6 +40,7 @@ public class UserResponseBean extends BaseBean {
private List<CompanyResponse> companies;
private Boolean privacy;
private Boolean terms;
private Boolean marketing;

View File

@@ -0,0 +1,12 @@
package net.gepafin.tendermanagement.model.response;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
@Getter
@Setter
public class VatCheckResponseBean {
private Boolean valid;
private Map<String, Object> vatCheckResponse;
private String message;
}

View File

@@ -74,4 +74,10 @@ public interface ApplicationAmendmentRequestRepository extends JpaRepository<App
" AND activeAmendment.isDeleted = false) ")
Set<ApplicationEvaluationEntity> findEvaluationsWithoutActiveAmendmentsByIds(@Param("applicationEvaluationIds") Set<Long> 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<ApplicationAmendmentRequestEntity> findExpiringBetween(LocalDateTime startTime, LocalDateTime endTime);
}

View File

@@ -1,12 +1,15 @@
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;
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 +34,33 @@ public interface ApplicationEvaluationRepository extends JpaRepository<Applicati
@Query("SELECT a FROM ApplicationEvaluationEntity a WHERE a.isDeleted = false AND a.endDate < :currentDate")
List<ApplicationEvaluationEntity> 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<ApplicationEvaluationEntity> findExpiringBetween(LocalDateTime startTime, LocalDateTime endTime);
// @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<Long> 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<Long> applicationIds,
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate
);
}

View File

@@ -61,4 +61,19 @@ public interface ApplicationRepository extends JpaRepository<ApplicationEntity,
"FROM ApplicationEntity a " +
"WHERE a.hubId = :hubId AND a.status = 'APPROVED'")
BigDecimal findTotalAmountAcceptedOfApplication(@Param("hubId") Long hubId);
@Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.hubId = :hubId AND a.status = 'SUBMIT' AND a.isDeleted = false")
public Long countApplicationsByHubId(@Param("hubId") Long hubId);
@Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.hubId = :hubId AND a.status = 'EVALUATION' AND a.isDeleted = false")
Long countAssignedApplicationsByHubId(@Param("hubId") Long hubId);
@Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.hubId = :hubId AND a.status = 'APPROVED' AND a.isDeleted = false")
Long countApprovedApplicationsByHubId(@Param("hubId") Long hubId);
@Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.hubId = :hubId AND a.status = 'SOCCORSO' AND a.isDeleted = false")
Long countSoccorsoApplicationsByHubId(@Param("hubId") Long hubId);
@Query("SELECT a.id FROM ApplicationEntity a WHERE a.hubId = :hubId AND a.isDeleted = false")
List<Long> findApplicationIdsByHubId(@Param("hubId") Long hubId);
}

View File

@@ -1,11 +1,16 @@
package net.gepafin.tendermanagement.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import net.gepafin.tendermanagement.entities.BeneficiaryEntity;
import java.util.List;
@Repository
public interface BeneficiaryRepository extends JpaRepository<BeneficiaryEntity, Long> {
@Query("SELECT u.id FROM UserEntity u JOIN u.beneficiary b WHERE b.id = u.beneficiary.id AND b.hubId = :hubId")
List<Long> findUserIdsByHubIdAndBeneficiaryId(Long hubId);
}

View File

@@ -51,5 +51,6 @@ public interface CallRepository extends JpaRepository<CallEntity, Long> {
@Query("SELECT SUM(c.amount) FROM CallEntity c WHERE c.hub.id = :hubId AND c.status = 'PUBLISH'")
BigDecimal findTotalAmountOfPublishedCalls(@Param("hubId") Long hubId);
List<CallEntity> findByIdIn(@Param("ids") List<Long> ids);
}

View File

@@ -33,5 +33,7 @@ public interface DocumentRepository extends JpaRepository<DocumentEntity, Long>
List<DocumentEntity> findAllByIsDeleteTrue();
List<DocumentEntity> findAllByIdInAndIsDeletedFalse(Set<Long> documentIds);
List<DocumentEntity> findBySourceIdInAndSourceAndIsDeletedFalse(Set<Long> sourceId, String type);
}

View File

@@ -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<ExpirationConfigEntity, Long> {
List<ExpirationConfigEntity> findByTypeAndIsDeletedFalse(String type);
}

View File

@@ -0,0 +1,20 @@
package net.gepafin.tendermanagement.repositories;
import net.gepafin.tendermanagement.entities.NotificationEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface NotificationRepository extends JpaRepository<NotificationEntity, Long> {
NotificationEntity findByIdAndIsDeletedFalse(Long id);
List<NotificationEntity> findByUserIdAndIsDeletedFalse(Long userId);
List<NotificationEntity> findByUserIdAndUserWithCompanyIdAndIsDeletedFalseAndStatusIn(Long userId, Long userWithCompanyId, List<String> statuses);
List<NotificationEntity> findByUserIdAndIsDeletedFalseAndStatusIn(Long userId, List<String> statuses);
List<NotificationEntity> findByUserWithCompanyIdAndUserIdAndIsDeletedFalse(Long userWithCompanyId, Long userId);
}

View File

@@ -0,0 +1,8 @@
package net.gepafin.tendermanagement.repositories;
import net.gepafin.tendermanagement.entities.NotificationTypeEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface NotificationTypeRepository extends JpaRepository<NotificationTypeEntity, Long> {
NotificationTypeEntity findByNotificationNameAndIsDeletedFalse(String value);
}

View File

@@ -35,4 +35,5 @@ public interface UserActionsRepository extends JpaRepository<UserActionEntity, L
@Param("hubId") Long hubId,
Pageable pageable);
UserActionEntity findUserActionByIdAndIsDeletedFalse(Long id);
}

View File

@@ -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, Long> {
UserEntity findByBeneficiaryId(Long beneficiaryId);
Optional<UserEntity> findByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid);
// Optional<UserEntity> 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<UserEntity> findUserExcludingRoleType(
@Param("email") String email,
@Param("hubUuid") String hubUuid,
@Param("roleType") String roleType
);
// boolean existsByEmailIgnoreCaseAndHubUniqueUuid(String email, String hubUuid);
List<UserEntity> findByRoleEntityIdInAndHubId(List<Long> roleIds, Long hubId);
@@ -24,5 +33,29 @@ public interface UserRepository extends JpaRepository<UserEntity, Long> {
Optional<UserEntity> 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 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 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);
boolean existsByBeneficiaryCodiceFiscaleAndHubId(String codiceFiscale, Long hubId);
List<UserEntity> findByRoleEntity_RoleTypeAndHubId(String roleType, Long hubId);
}

View File

@@ -1,22 +1,23 @@
package net.gepafin.tendermanagement.repositories;
import java.util.List;
import java.util.Optional;
import net.gepafin.tendermanagement.entities.UserWithCompanyEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import net.gepafin.tendermanagement.entities.UserWithCompanyEntity;
import java.util.List;
import java.util.Optional;
public interface UserWithCompanyRepository extends JpaRepository<UserWithCompanyEntity, Long> {
void deleteByCompanyIdAndIsDeletedFalse(Long companyId);
void deleteByCompanyIdAndIsDeletedFalse(Long companyId);
@Query("SELECT u.companyId FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.isDeleted = false")
List<Long> findActiveCompanyIdsByUserId(@Param("userId") Long userId);
@Query("SELECT u.companyId FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.isDeleted = false")
List<Long> findActiveCompanyIdsByUserId(@Param("userId") Long userId);
Optional<UserWithCompanyEntity> findByUserIdAndCompanyIdAndIsDeletedFalse(Long userId, Long companyId);
Optional<UserWithCompanyEntity> findByUserIdAndCompanyIdAndIsDeletedFalse(Long userId, Long companyId);
@Query("SELECT u FROM UserWithCompanyEntity u WHERE u.userId = :userId AND u.companyId = :companyId AND u.isDeleted = false")
UserWithCompanyEntity findByUserIdAndCompanyIdAndIsDeletedFalseForNotification(Long userId, Long companyId);
}

View File

@@ -1,26 +1,33 @@
package net.gepafin.tendermanagement.scheduler;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
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.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.repositories.ApplicationEvaluationRepository;
import net.gepafin.tendermanagement.repositories.ApplicationRepository;
import net.gepafin.tendermanagement.repositories.AssignedApplicationsRepository;
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 net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity;
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
import net.gepafin.tendermanagement.enums.ApplicationAmendmentRequestEnum;
import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.AssignedApplicationEnum;
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
@@ -40,8 +47,6 @@ public class ApplicationAmendmentScheduler {
@Autowired
private ApplicationAmendmentRequestRepository applicationAmendmentRepository;
@Autowired
private EmailNotificationDao emailNotificationDao;
@Autowired
private ApplicationAmendmentRequestDao applicationAmendmentRequestDao;
@@ -49,6 +54,18 @@ public class ApplicationAmendmentScheduler {
@Autowired
private LoggingUtil loggingUtil;
@Autowired
private NotificationDao notificationDao;
@Autowired
private AssignedApplicationsRepository assignedApplicationsRepository;
@Autowired
private ApplicationRepository applicationRepository;
@Autowired
private ApplicationEvaluationRepository applicationEvaluationRepository;
private static final Logger log = LoggerFactory.getLogger(ApplicationAmendmentScheduler.class);
@Scheduled(cron = "0 0 1 * * ?")
@@ -79,14 +96,16 @@ public class ApplicationAmendmentScheduler {
amendmentRequests.forEach(request -> {
try {
ApplicationAmendmentRequestEntity oldAmendmentRequestEntity = Utils.getClonedEntityForData(request);
request.setStatus(ApplicationAmendmentRequestEnum.CLOSE.getValue());
request.setStatus(ApplicationAmendmentRequestEnum.EXPIRED.getValue());
ApplicationEntity application=oldAmendmentRequestEntity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication();
request = applicationAmendmentRepository.save(request);
Map<String ,String> placeHolders=notificationDao.sendNotificationToBeneficiary(application,NotificationTypeEnum.AMENDMENT_EXPIRED);
notificationDao.sendNotificationToInstructor(placeHolders,oldAmendmentRequestEntity.getApplicationEvaluationEntity(),NotificationTypeEnum.AMENDMENT_EXPIRED);
/** This code is responsible for adding a version history log for the "Update Application Amendment" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest).actionType(VersionActionTypeEnum.UPDATE).oldData(oldAmendmentRequestEntity).newData(request).build());
// emailNotificationDao.sendApplicationFailureNotificationEmail(request);
log.info("Updated status to 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 +123,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 +148,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());
}
}

View File

@@ -1,8 +1,11 @@
package net.gepafin.tendermanagement.scheduler;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.dao.NotificationDao;
import net.gepafin.tendermanagement.entities.ApplicationEntity;
import net.gepafin.tendermanagement.entities.ApplicationEvaluationEntity;
import net.gepafin.tendermanagement.enums.ApplicationEvaluationStatusTypeEnum;
import net.gepafin.tendermanagement.enums.NotificationTypeEnum;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
@@ -22,6 +25,7 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
@Component
public class ApplicationEvaluationScheduler {
@@ -35,6 +39,9 @@ public class ApplicationEvaluationScheduler {
@Autowired
private HttpServletRequest httpServletRequest;
@Autowired
private NotificationDao notificationDao;
private static final Logger log = LoggerFactory.getLogger(ApplicationEvaluationScheduler.class);
@Scheduled(cron = "0 0 2 * * ?") // Runs daily at midnight
@@ -76,10 +83,15 @@ public class ApplicationEvaluationScheduler {
ApplicationEvaluationEntity oldApplicationEvaluationEntity = Utils
.getClonedEntityForData(evaluation);
ApplicationEntity application=evaluation.getAssignedApplicationsEntity().getApplication();
evaluation.setStatus(ApplicationEvaluationStatusTypeEnum.EXPIRED.getValue());
evaluation = applicationEvaluationRepository.save(evaluation);
Map<String, String> placeHolders = notificationDao.sendNotificationToBeneficiary(application, NotificationTypeEnum.EVALUATION_EXPIRED);
notificationDao.sendNotificationToSuperUser(application,placeHolders,NotificationTypeEnum.EVALUATION_EXPIRED);
notificationDao.sendNotificationToInstructor(placeHolders,evaluation,NotificationTypeEnum.EVALUATION_EXPIRED);
// Logging version history for the update operation
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(httpServletRequest)
.actionType(VersionActionTypeEnum.UPDATE).oldData(oldApplicationEvaluationEntity)

View File

@@ -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<ExpirationConfigEntity> 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<ApplicationAmendmentRequestEntity> amendmentEntities = applicationAmendmentRequestRepository.findExpiringBetween(startDate, endDate);
for (ApplicationAmendmentRequestEntity entity : amendmentEntities) {
ApplicationEntity application = entity.getApplicationEvaluationEntity().getAssignedApplicationsEntity().getApplication();
Map<String, String> placeHolders = replacePlaceholders(application,daysBefore);
notificationDao.sendNotificationToInstructor(placeHolders,entity.getApplicationEvaluationEntity(), NotificationTypeEnum.AMENDMENT_EXPIRATION_REMINDER);
}
}
private Map<String, String> replacePlaceholders (ApplicationEntity application, Long daysBefore){
Long companyId = application.getCompanyId();
CompanyEntity company = companyService.validateCompany(companyId);
Map<String, String> 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<ApplicationEvaluationEntity> evaluationEntities = applicationEvaluationRepository.findExpiringBetween(startDate, endDate);
for (ApplicationEvaluationEntity entity : evaluationEntities) {
ApplicationEntity application = entity.getAssignedApplicationsEntity().getApplication();
Map<String, String> placeHolders = replacePlaceholders(application,daysBefore);
notificationDao.sendNotificationToInstructor(placeHolders,entity,NotificationTypeEnum.EVALUATION_EXPIRATION_REMINDER);
}
}
}

View File

@@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import net.gepafin.tendermanagement.model.response.VatCheckResponseBean;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletRequest;
@@ -26,7 +27,7 @@ public interface CompanyService {
List<CompanyResponse> getCompanyByUserId(HttpServletRequest request, Long userId);
Map<String, Object> checkVatNumber(HttpServletRequest request, String vatNumber);
VatCheckResponseBean checkVatNumber(HttpServletRequest request, String vatNumber);
CompanyEntity validateCompany(Long companyId);
@@ -44,5 +45,4 @@ public interface CompanyService {
UserWithCompanyEntity getUserWithCompanyEntity(Long userId,Long companyId);
void removeCompanyFromList(HttpServletRequest request, Long companyId);
}

View File

@@ -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);
}

View File

@@ -0,0 +1,23 @@
package net.gepafin.tendermanagement.service;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.enums.NotificationEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.response.NotificationResponse;
import java.util.List;
public interface NotificationService {
NotificationResponse sendNotification(Long userId, NotificationReq notificationReq, Long companyId);
public NotificationResponse getNotificationById(HttpServletRequest servletRequest, Long id);
public List<NotificationResponse> getNotificationByUserId(HttpServletRequest servletRequest, Long userId, Long companyId, List<NotificationEnum> statuses);
public NotificationResponse updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum status);
public void deleteNotification(HttpServletRequest request, Long id);
public List<NotificationResponse> getNotificationsByCompanyIdAndUserId(Long userId, Long companyId, List<NotificationEnum> statuses);
}

View File

@@ -27,7 +27,7 @@ public interface UserService {
UserEntity validateUser(Long userId);
String initiatePasswordReset(InitiatePasswordResetReq resetReq);
void initiatePasswordReset(InitiatePasswordResetReq resetReq);
Boolean resetPassword(ResetPasswordReq resetPasswordReq);

View File

@@ -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,

View File

@@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import net.gepafin.tendermanagement.model.response.VatCheckResponseBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -78,7 +79,7 @@ public class CompanyServiceImpl implements CompanyService {
@Override
@Transactional(readOnly = true)
public Map<String, Object> checkVatNumber(HttpServletRequest request, String vatNumber) {
public VatCheckResponseBean checkVatNumber(HttpServletRequest request, String vatNumber) {
return vatCheckDao.checkVatNumber(vatNumber);
}
@Override

View File

@@ -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);
}
}

View File

@@ -0,0 +1,62 @@
package net.gepafin.tendermanagement.service.impl;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import net.gepafin.tendermanagement.dao.NotificationDao;
import net.gepafin.tendermanagement.enums.NotificationEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.response.NotificationResponse;
import net.gepafin.tendermanagement.service.NotificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import static org.hibernate.internal.util.collections.CollectionHelper.listOf;
@Service
@Slf4j
public class NotificationServiceImpl implements NotificationService {
@Autowired
private NotificationDao notificationDao;
@Override
public NotificationResponse sendNotification(Long userId, NotificationReq notificationReq, Long companyId) {
log.info("Sending notification to user {} with content: {}", userId, notificationReq.getMessage());
notificationReq.setUserId(userId);
notificationReq.setCompanyIds(listOf(companyId));
return notificationDao.sendNotification(notificationReq);
}
@Override
public NotificationResponse getNotificationById(HttpServletRequest servletRequest, Long id) {
return notificationDao.getNotificationById(id);
}
@Override
public List<NotificationResponse> getNotificationByUserId(HttpServletRequest servletRequest, Long userId, Long companyId, List<NotificationEnum> statuses) {
return notificationDao.getNotificationByUserId(userId, companyId, statuses);
}
@Override
public NotificationResponse updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum status) {
return notificationDao.updateNotificationStatus(id, status);
}
@Override
public void deleteNotification(HttpServletRequest request, Long id) {
notificationDao.deleteNotification(id);
return;
}
@Override
public List<NotificationResponse> getNotificationsByCompanyIdAndUserId(Long userId, Long companyId, List<NotificationEnum> statuses) {
return notificationDao.getNotificationByCompanyIdAndUserId(userId, companyId, statuses);
}
}

View File

@@ -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

View File

@@ -41,6 +41,8 @@ public class LoggingUtil {
@Autowired
private TokenProvider tokenProvider;
private static final ThreadLocal<Long> 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("(?<!:)//+", "/");
@@ -263,6 +275,7 @@ public class LoggingUtil {
userAction.setResponse(response);
userActionsRepository.save(userAction);
userActionRequest.getRequest().setAttribute(GepafinConstant.USER_ACTION_ID, userAction.getId());
} catch (Exception e) {
log.error("Error logging user action: {}", e.getMessage(), e);
}
@@ -323,10 +336,35 @@ public class LoggingUtil {
public UserActionEntity getUserActionLogById(Long id) {
return userActionsRepository.findUserActionById(id);
return userActionsRepository.findUserActionByIdAndIsDeletedFalse(id);
}
public List<VersionHistoryEntity> 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);
}
}
}

View File

@@ -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<String, Object> 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<String, Object> 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;
}
}

View File

@@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.jsonwebtoken.Claims;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
@@ -27,11 +26,9 @@ import jakarta.persistence.OneToOne;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -48,7 +45,6 @@ import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientForbiddenExce
import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientNotFoundException;
import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientUnauthorizedException;
import net.gepafin.tendermanagement.web.rest.api.errors.FeignClientValidationException;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -158,6 +154,9 @@ public class Utils {
public static String convertMapIntoJsonString(Map<String, Object> 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);
}
@@ -211,7 +210,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);
@@ -219,7 +218,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<String, List<Object>> convertStringIntoMap(String jsonString) {
try {
return mapper.readValue(jsonString, new TypeReference<Map<String, List<Object>>>() {
@@ -691,4 +697,26 @@ public class Utils {
return null;
}
}
public static String createChannelForUserAndCompany(Long userId, Long companyId) {
return GepafinConstant.COMMON_SINGLE_CHANNEL_PREFIX + userId + GepafinConstant.COMPANY_PREFIX + companyId;
}
public static Map<String, Object> 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<String, Object> defaultErrorResponse() {
return Collections.singletonMap("message", Translator.toLocale(GepafinConstant.INVALID_VATNUMBER));
}
}

View File

@@ -33,7 +33,7 @@ public interface CommunicationApi {
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PostMapping(value = "/{amendmentId}", produces = { "application/json" })
@PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY')")
@PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY') || hasRole('ROLE_INSTRUCTOR_MANAGER')")
ResponseEntity<Response<CommunicationResponseBean>> addCommentToAmendmentRequest(HttpServletRequest request,
@RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId);
@@ -55,7 +55,7 @@ public interface CommunicationApi {
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PutMapping(value = "/{amendmentId}/{commentId}", produces = { "application/json" })
@PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY')")
@PreAuthorize("hasRole('ROLE_PRE_INSTRUCTOR') || hasRole('ROLE_BENEFICIARY') || hasRole('ROLE_INSTRUCTOR_MANAGER')")
ResponseEntity<Response<CommunicationResponseBean>> updateCommunicationAmendment(HttpServletRequest request,
@RequestBody @Parameter CommunicationRequestBean communicationResponseBean, @PathVariable(value = "amendmentId") Long amendmentId, @PathVariable(value = "commentId") Long commentId);

View File

@@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.web.rest.api;
import java.util.List;
import java.util.Map;
import net.gepafin.tendermanagement.model.response.VatCheckResponseBean;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -94,8 +95,8 @@ public interface CompanyApi {
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/vatNumber", produces = { "application/json" })
ResponseEntity<Response<Map<String,Object>>> checkVatNumber(HttpServletRequest request,
@Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber);
ResponseEntity<Response<VatCheckResponseBean>> checkVatNumber(HttpServletRequest request,
@Parameter(description = "The vatNumber of company", required = true) @RequestParam("vatNumber") String vatNumber);
@Operation(summary = "Api to download company delegation template", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {

View File

@@ -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,19 @@ public interface DashboardApi {
produces = { "application/json" })
ResponseEntity<Response<BeneficiaryWidgetResponseBean>> 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" })
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN') || hasRole('ROLE_INSTRUCTOR_MANAGER')")
ResponseEntity<Response<ApplicationWidgetResponseBean>> getApplicationDetails(HttpServletRequest request);
}

View File

@@ -0,0 +1,101 @@
package net.gepafin.tendermanagement.web.rest.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.enums.NotificationEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.response.NotificationResponse;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
public interface NotificationApi {
@Operation(summary = "Api to send notification.", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value =
ErrorConstants.NOTFOUND_ERROR_EXAMPLE))),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value =
ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE))),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = @ExampleObject(value =
ErrorConstants.BADREQUEST_ERROR_EXAMPLE))) })
@PostMapping(value = "/user/{userId}/sent", consumes = "application/json", produces = "application/json")
ResponseEntity<Response<NotificationResponse>> sendNotification(HttpServletRequest request, @RequestBody NotificationReq notificationReq,
@Parameter(description = "The user id", required = true) @PathVariable("userId") Long userId,
@Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId);
@Operation(summary = "Api to get notification by id", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/{id}", produces = "application/json")
ResponseEntity<Response<NotificationResponse>> getNotificationById(HttpServletRequest request,
@Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id);
@Operation(summary = "Api to get notification by user id", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/user/{userId}", produces = "application/json")
ResponseEntity<Response<List<NotificationResponse>>> getNotificationByUserId(HttpServletRequest request,
@Parameter(description = "The user id", required = true) @PathVariable(value = "userId", required = true) Long userId,
@Parameter(description = "The company id", required = false) @RequestParam(value = "companyId", required = false) Long companyId,
@Parameter(description = "The notification status", required = false) @RequestParam(value = "status", required = false) List<NotificationEnum> statuses);
@Operation(summary = "Api to update notification status", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@PutMapping(value = "/{id}", produces = "application/json")
ResponseEntity<Response<NotificationResponse>> updateNotificationStatus(HttpServletRequest request,
@Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id,
@Parameter(description = "The notification status", required = true) @RequestParam(value = "status", required = true) NotificationEnum status);
@Operation(summary = "Api to delete notification", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@DeleteMapping(value = "/{id}", produces = "application/json")
ResponseEntity<Response<Void>> deleteNotification(HttpServletRequest request,
@Parameter(description = "The notification id", required = true) @PathVariable(value = "id", required = true) Long id);
@Operation(summary = "API to get notifications by user ID and company ID", responses = { @ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
@ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) })
@GetMapping(value = "/user/{userId}/company/{companyId}/notifications", produces = "application/json")
ResponseEntity<Response<List<NotificationResponse>>> getNotificationsByUserIdAndCompanyId(HttpServletRequest request,
@Parameter(description = "The user id", required = true) @PathVariable(value = "userId") Long userId,
@Parameter(description = "The company ID", required = true) @PathVariable(value = "companyId") Long companyId,
@Parameter(description = "The notification status", required = false) @RequestParam(value = "status", required = false) List<NotificationEnum> statuses);
}

View File

@@ -59,6 +59,7 @@ public interface UserApi {
@RequestMapping(value = "/{userId}",
produces = {"application/json"},
method = RequestMethod.PUT)
@PreAuthorize("hasRole('ROLE_SUPER_ADMIN')")
default ResponseEntity<Response<UserResponseBean>> 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) {
@@ -118,7 +119,7 @@ public interface UserApi {
@RequestMapping(value = "/reset-password/initiate",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<String>> initiatePasswordReset(
ResponseEntity<Response<Void>> initiatePasswordReset(HttpServletRequest request,
@Parameter(description = "Initiate password reset request object", required = true) @Valid @RequestBody InitiatePasswordResetReq initiatePasswordResetReq);
@Operation(summary = "Api to reset password",
@@ -131,7 +132,7 @@ public interface UserApi {
@RequestMapping(value = "/reset-password",
produces = {"application/json"},
method = RequestMethod.POST)
ResponseEntity<Response<Boolean>> resetPassword(
ResponseEntity<Response<Boolean>> resetPassword(HttpServletRequest request,
@Parameter(description = "Reset password request object", required = true) @Valid @RequestBody ResetPasswordReq resetPasswordReq);
@Operation(summary = "Api to change user password",
responses = {

View File

@@ -7,6 +7,7 @@ import java.util.Map;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.model.request.UserActionRequest;
import net.gepafin.tendermanagement.model.response.VatCheckResponseBean;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import org.slf4j.Logger;
@@ -112,15 +113,15 @@ public class CompanyApiController implements CompanyApi{
}
@Override
public ResponseEntity<Response<Map<String,Object>>> checkVatNumber(HttpServletRequest request, String vatNumber) {
public ResponseEntity<Response<VatCheckResponseBean>> checkVatNumber(HttpServletRequest request, String vatNumber) {
log.info("check VatNumber with: {}", vatNumber);
/** This code is responsible for creating user action logs for the "Check vat number" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.CHECK_COMPANY_VAT_NUMBER).build());
Map<String,Object> data = companyService.checkVatNumber(request, vatNumber);
VatCheckResponseBean vatCheckResponseBean = companyService.checkVatNumber(request, vatNumber);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(data, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG)));
.body(new Response<>(vatCheckResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CHECK_VATNUMBER_SUCCESS_MSG)));
}
@Override

View File

@@ -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);

View File

@@ -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<Response<ApplicationWidgetResponseBean>> 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)));
}
}

View File

@@ -0,0 +1,74 @@
package net.gepafin.tendermanagement.web.rest.api.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.enums.NotificationEnum;
import net.gepafin.tendermanagement.model.request.NotificationReq;
import net.gepafin.tendermanagement.model.response.NotificationResponse;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.NotificationService;
import net.gepafin.tendermanagement.web.rest.api.NotificationApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("${openapi.gepafin.base-path:/v1/notification}")
public class NotificationApiController implements NotificationApi {
@Autowired
private NotificationService notificationService;
public ResponseEntity<Response<NotificationResponse>> sendNotification(HttpServletRequest request, NotificationReq notificationReq, Long userId, Long companyId) {
NotificationResponse notificationData = notificationService.sendNotification(userId, notificationReq, companyId);
return ResponseEntity.status(HttpStatus.OK).body(new Response<>(notificationData, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_SENT_SUCCESSFULLY)));
}
@Override
public ResponseEntity<Response<NotificationResponse>> getNotificationById(HttpServletRequest request, Long id) {
NotificationResponse notificationResponse = notificationService.getNotificationById(request, id);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(notificationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY)));
}
@Override
public ResponseEntity<Response<List<NotificationResponse>>> getNotificationByUserId(HttpServletRequest request, Long userId, Long companyId, List<NotificationEnum> statuses) {
List<NotificationResponse> notificationResponses = notificationService.getNotificationByUserId(request, userId, companyId, statuses);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<List<NotificationResponse>>(notificationResponses, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY)));
}
@Override
public ResponseEntity<Response<NotificationResponse>> updateNotificationStatus(HttpServletRequest request, Long id, NotificationEnum notificationEnums) {
NotificationResponse notificationResponse = notificationService.updateNotificationStatus(request, id, notificationEnums);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(notificationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_UPDATED_SUCCESSFULLY)));
}
@Override
public ResponseEntity<Response<Void>> deleteNotification(HttpServletRequest request, Long id) {
notificationService.deleteNotification(request, id);
return ResponseEntity.status(HttpStatus.OK).body(new Response<>(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_DELETED_SUCCESSFULLY)));
}
@Override
public ResponseEntity<Response<List<NotificationResponse>>> getNotificationsByUserIdAndCompanyId(HttpServletRequest request,Long userId, Long companyId, List<NotificationEnum> statuses) {
List<NotificationResponse> notificationResponses = notificationService.getNotificationsByCompanyIdAndUserId(userId, companyId, statuses);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(notificationResponses, Status.SUCCESS, Translator.toLocale(GepafinConstant.NOTIFICATION_FETCHED_SUCCESSFULLY)));
}
}

View File

@@ -125,20 +125,35 @@ public class UserApiController implements UserApi {
@Override
public ResponseEntity<Response<Boolean>> 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<Response<String>> initiatePasswordReset(InitiatePasswordResetReq request) {
public ResponseEntity<Response<Void>> 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<Response<Boolean>> resetPassword(ResetPasswordReq request) {
public ResponseEntity<Response<Boolean>> 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());