package net.gepafin.tendermanagement.dao; import lombok.extern.slf4j.Slf4j; import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.VersionHistoryRequest; import net.gepafin.tendermanagement.repositories.ApplicationEvaluationRepository; import net.gepafin.tendermanagement.repositories.ApplicationRepository; import net.gepafin.tendermanagement.util.LoggingUtil; import net.gepafin.tendermanagement.util.Utils; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.ApplicationEntity; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.entities.DocumentEntity; import net.gepafin.tendermanagement.model.response.DocumentResponseBean; import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response; import net.gepafin.tendermanagement.repositories.ApplicationAmendmentRequestRepository; import net.gepafin.tendermanagement.repositories.DocumentRepository; import net.gepafin.tendermanagement.service.AmazonS3Service; import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService; import net.gepafin.tendermanagement.service.ApplicationService; import net.gepafin.tendermanagement.service.CallService; import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Value; import java.util.ArrayList; import java.util.List; @Slf4j @Component public class DocumentDao { @Autowired private AmazonS3Service amazonS3Service; @Autowired private DocumentRepository documentRepository; @Autowired private CallDao callDao; @Autowired private CallService callService; @Autowired private S3PathConfig s3ConfigBean; @Autowired private ApplicationRepository applicationRepository; @Autowired ApplicationService applicationService; @Autowired ApplicationAmendmentRequestService applicationAmendmentRequestService; @Autowired ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; @Autowired private ApplicationEvaluationRepository applicationEvaluationRepository; @Value("${aws.s3.bucket.name}") private String bucketName; @Autowired private LoggingUtil loggingUtil; @Autowired private HttpServletRequest request; // @Value("${aws.s3.url.folder}") // private String s3Folder; public List uploadFiles(Long userId,List files, Long sourceId, DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { List documentEntities = new ArrayList<>(); Long source = resolveSourceId(sourceId, sourceType); for (MultipartFile file : files) { UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = uploadFileOnAmazonS3(file, sourceType, sourceId); if (uploadFileOnAmazonS3Response != null) { DocumentEntity documentEntity = new DocumentEntity(); documentEntity.setFileName(uploadFileOnAmazonS3Response.getFileName()); documentEntity.setSource(sourceType.getValue()); documentEntity.setSourceId(source); documentEntity.setType(fileType.getValue()); documentEntity.setFilePath(uploadFileOnAmazonS3Response.getFilePath()); documentEntity.setIsDeleted(false); documentEntity.setUploadedBy(userId); documentEntities.add(documentEntity); } } documentRepository.saveAll(documentEntities); /** This code is responsible for adding a version history log for the "Upload call or application document based on source type" operation. **/ documentEntities.forEach(entity -> loggingUtil.addVersionHistory( VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(entity).build())); return documentEntities.stream().map(callDao::convertToDocumentResponseBean).collect(Collectors.toList()); } public UserActionContextEnum getUserActionContextEnum(DocumentSourceTypeEnum sourceType, DocumentTypeEnum fileType) { UserActionContextEnum userActionContext = null; if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.CALL)) { userActionContext = UserActionContextEnum.UPLOAD_CALL_DOCUMENT; } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.CALL)) { userActionContext = UserActionContextEnum.UPLOAD_CALL_IMAGES; } else if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.APPLICATION)) { userActionContext = UserActionContextEnum.UPLOAD_APPLICATION_DOCUMENT; } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.APPLICATION)) { userActionContext = UserActionContextEnum.UPLOAD_APPLICATION_IMAGES; }else if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.AMENDMENT)) { userActionContext = UserActionContextEnum.UPLOAD_AMENDMENT_DOCUMENT; } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.AMENDMENT)) { userActionContext = UserActionContextEnum.UPLOAD_AMENDMENT_IMAGES; }else if (fileType.equals(DocumentTypeEnum.DOCUMENT) && sourceType.equals(DocumentSourceTypeEnum.EVALUATION)) { userActionContext = UserActionContextEnum.UPLOAD_EVALUATION_DOCUMENT; } else if (fileType.equals(DocumentTypeEnum.IMAGES) && sourceType.equals(DocumentSourceTypeEnum.EVALUATION)) { userActionContext = UserActionContextEnum.UPLOAD_EVALUATION_IMAGES; } return userActionContext; } public UserActionContextEnum getUserActionContextForUpdatingDocOrImage(DocumentTypeEnum documentTypeEnum) { UserActionContextEnum userActionContext; if (DocumentTypeEnum.DOCUMENT.equals(documentTypeEnum)) { userActionContext = UserActionContextEnum.UPDATE_DOCUMENT; } else{ userActionContext = UserActionContextEnum.UPDATE_IMAGES; } return userActionContext; } private UploadFileOnAmazonS3Response uploadFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long sourceId) { Long applicationId = 0L; Long amendmentId = 0L; Long evaluationId = 0L; Long callId = sourceId; if (type == DocumentSourceTypeEnum.APPLICATION) { applicationId = sourceId; callId = applicationRepository.findCallIdById(applicationId); } else if (type == DocumentSourceTypeEnum.AMENDMENT) { amendmentId = sourceId; ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); }else if (type == DocumentSourceTypeEnum.EVALUATION) { evaluationId = sourceId; ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); } try { String s3Path = generateS3Path(type, callId, applicationId, amendmentId); log.info("Generated S3 path {}", s3Path); return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); } catch (Exception e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); } } public String generateS3Path(DocumentSourceTypeEnum typeOfDocument, Long callId, Long applicationId, Long amendmentId) { try { return s3ConfigBean.generateDocumentPath(typeOfDocument, callId, applicationId, amendmentId); } catch (IllegalArgumentException e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); } } private Long resolveSourceId(Long sourceId, DocumentSourceTypeEnum sourceType) { if (sourceType == DocumentSourceTypeEnum.CALL) { CallEntity callEntity = callService.validateCall(sourceId); // callDao.validateUpdate(callEntity); return callEntity.getId(); } // else if (sourceType == SourceTypeEnum.APPLICATION) { // ApplicationEntity applicationEntity = applicationService.validateApplication(sourceId); // return applicationEntity.getId(); // Assuming ApplicationEntity has getId() // } // return sourceId; } public void deleteFile(Long documentId) { DocumentEntity documentEntity = documentRepository.findById(documentId).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND))); if(Boolean.TRUE.equals(documentEntity.getIsDeleted())){ return; } Long callId = null; Long applicationId = null; Long amendmentId = null; Long evaluationId = null; if (DocumentSourceTypeEnum.CALL.getValue().equalsIgnoreCase(documentEntity.getSource())) { callId = documentEntity.getSourceId(); } else if (DocumentSourceTypeEnum.APPLICATION.getValue().equalsIgnoreCase(documentEntity.getSource())) { applicationId = documentEntity.getSourceId(); ApplicationEntity applicationEntity = applicationService.validateApplication(applicationId); callId = applicationEntity.getCall().getId(); } else if(DocumentSourceTypeEnum.AMENDMENT.getValue().equalsIgnoreCase(documentEntity.getSource())){ amendmentId = documentEntity.getSourceId(); ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); } else if(DocumentSourceTypeEnum.EVALUATION.getValue().equalsIgnoreCase(documentEntity.getSource())){ evaluationId = documentEntity.getSourceId(); ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); } deleteFileFromS3(documentEntity, callId, applicationId,amendmentId); } public DocumentEntity validateDocument(Long id) { return documentRepository.findByIdAndNotDeleted(id).orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND))); } public DocumentResponseBean updateDocument(Long documentId, MultipartFile file, DocumentTypeEnum documentTypeEnum) { DocumentEntity documentEntity = validateDocument(documentId); //cloned entity for old data DocumentEntity oldDocumentData = Utils.getClonedEntityForData(documentEntity); String type = documentEntity.getSource(); UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = updateFileOnAmazonS3(file, DocumentSourceTypeEnum.valueOf(type), documentEntity.getSourceId()); if (uploadFileOnAmazonS3Response != null) { documentEntity.setFileName(uploadFileOnAmazonS3Response.getFileName()); documentEntity.setFilePath(uploadFileOnAmazonS3Response.getFilePath()); documentEntity.setType(documentTypeEnum.getValue()); documentEntity.setSource(documentEntity.getSource()); documentEntity.setSourceId(documentEntity.getSourceId()); documentRepository.save(documentEntity); /** This code is responsible for adding a version history log for the "updating doc or image" operation. **/ loggingUtil.addVersionHistory( VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldDocumentData).newData(documentEntity).build()); } return callDao.convertToDocumentResponseBean(documentEntity); } private UploadFileOnAmazonS3Response updateFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long id) { try { Long callId=null; Long applicationId=null; Long amendmentId=null; Long evaluationId=null; if (type.equals(DocumentSourceTypeEnum.APPLICATION)) { callId = applicationRepository.findCallIdById(id); applicationId = id; } else if(type.equals(DocumentSourceTypeEnum.AMENDMENT)){ amendmentId = id; ApplicationEntity applicationEntity = applicationAmendmentRequestRepository.findApplicationByAmendmentId(amendmentId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); }else if(type.equals(DocumentSourceTypeEnum.EVALUATION)){ evaluationId = id; ApplicationEntity applicationEntity = applicationEvaluationRepository.findApplicationByEvaluationId(evaluationId); applicationId = applicationEntity.getId(); callId = applicationEntity.getCall().getId(); } else { callId = id; applicationId = 0L; } String s3Path = generateS3Path(type, callId, applicationId,amendmentId); log.info("Generated S3 path {}", s3Path); return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); } catch (Exception e) { throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); } } public DocumentResponseBean getDocument(Long documentId) { DocumentEntity documentEntity = validateDocument(documentId); return callDao.convertToDocumentResponseBean(documentEntity); } public void deleteFileFromS3(DocumentEntity documentEntity, Long callId, Long applicationId,Long amendmentId) { try { DocumentEntity oldDocumentEntity = Utils.getClonedEntityForData(documentEntity); String oldS3Path = documentEntity.getFilePath(); String newS3Path = s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.valueOf("DELETED_" + documentEntity.getSource().toUpperCase()), callId, applicationId,amendmentId); UploadFileOnAmazonS3Response response = amazonS3Service.moveFile(documentEntity.getFileName(), oldS3Path, newS3Path); documentEntity.setFileName(response.getFileName()); documentEntity.setFilePath(response.getFilePath()); documentEntity.setIsDeleted(true); documentRepository.save(documentEntity); /** This code is responsible for adding a version history log for the "Soft delete document" operation. **/ loggingUtil.addVersionHistory( VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldDocumentEntity).newData(documentEntity).build()); log.info("File for document ID {} successfully moved to deleted folder.", documentEntity.getId()); } catch (Exception e) { log.error("Error moving file for document ID {} to deleted folder: {}", documentEntity.getId(), e.getMessage()); throw new CustomValidationException(Status.VALIDATION_ERROR, "Error occurred while moving file to deleted folder."); } } }