diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 3a160d09..dd9f2779 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -290,5 +290,6 @@ public class GepafinConstant { public static final String REMINDER_EMAIL_SENT_SUCCESS_MSG = "reminder.email.sent.success.msg"; public static final String ENCRYPT_INIT_VECTOR = "IG8*(*@&)*#biVVD"; public static final String ENCRYPT_KEY = "U2VjdXJlRW5jcnlwdEtleQ=="; + public static final String APPLICATION_DOCUMENTS_NOT_FOUND_MSG = "application.documents.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 716c1d11..d03002bd 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -4,12 +4,7 @@ import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; -import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum; -import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; -import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; -import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; -import net.gepafin.tendermanagement.enums.RoleStatusEnum; -import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; +import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.request.ApplicationFormFieldRequestBean; import net.gepafin.tendermanagement.model.request.ApplicationRequest; import net.gepafin.tendermanagement.model.request.ApplicationRequestBean; @@ -31,6 +26,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationExceptio import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.h2.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -42,10 +38,15 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.persistence.criteria.Predicate; import jakarta.servlet.http.HttpServletRequest; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.text.MessageFormat; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; @Component public class ApplicationDao { @@ -57,7 +58,8 @@ public class ApplicationDao { @Autowired private ApplicationRepository applicationRepository; - + @Autowired + private DocumentRepository documentRepository; @Autowired private ApplicationFormRepository applicationFormRepository; @@ -90,9 +92,13 @@ public class ApplicationDao { @Autowired private CompanyService companyService; + @Autowired + private S3PathConfig s3PathConfig; @Autowired private SystemEmailTemplatesService systemEmailTemplatesService; + @Autowired + private AssignedApplicationsRepository assignedApplicationsRepository; @Value("${default_System_Receiver_Email}") private String defaultSystemReceiverEmail; @@ -972,5 +978,59 @@ public class ApplicationDao { applicationEntity = saveApplicationEntity(applicationEntity); return getApplicationResponse(applicationEntity); } + public byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request,Long applicationId) { + AssignedApplicationsEntity assignedApplications = assignedApplicationsRepository.findByApplicationIdAndIsDeletedFalse(applicationId).orElse(null); + + List applicationForms = applicationFormRepository.findByApplicationId(applicationId); + if(assignedApplications!=null){ + validator.validatePreInstructor(request,assignedApplications.getUserId());} + Set documentIds = new HashSet<>(); + applicationForms.forEach(applicationForm -> { + FormEntity formEntity = applicationForm.getForm(); + if (formEntity != null) { + List contentResponseBeans = formDao.convertFormEntityToFormResponseBean(formEntity).getContent(); + contentResponseBeans.stream() + .filter(content -> "fileupload".equals(content.getName())) + .forEach(content -> { + Optional formField = applicationFormFieldRepository + .findByFieldIdAndApplicationFormIdAndApplicationFormApplicationId( + content.getId(), applicationForm.getId(), applicationId); + formField.ifPresent(field -> { + if (field.getFieldValue() != null) { + Arrays.stream(field.getFieldValue().split(",")) + .map(String::trim) + .map(Long::valueOf) + .forEach(documentIds::add); + } + }); + }); + } + }); + List documents = documentRepository.findAllById(documentIds); + if (documents.isEmpty()) { + throw new ResourceNotFoundException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND)); + } + try (ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream(); + ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) { + + for (DocumentEntity document : documents) { + String s3Folder = s3PathConfig.generateDocumentPath(DocumentSourceTypeEnum.APPLICATION, applicationId, 0L); + try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, document.getFilePath())) { + String fileName = Utils.extractFileName(document.getFilePath()); + zos.putNextEntry(new ZipEntry(fileName)); + IOUtils.copy(fileInputStream, zos); + zos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException("Error downloading or adding document to ZIP: " + document.getFileName(), e); + } + } + + zos.finish(); + return zipOutputStream.toByteArray(); + + } catch (IOException e) { + throw new RuntimeException("Error while creating ZIP file", e); + } + } } diff --git a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java index 9ef06c48..3ab94ae2 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/ApplicationService.java @@ -41,5 +41,5 @@ public interface ApplicationService { public void deleteSignedDocument(HttpServletRequest request, Long applicationId); public ApplicationResponse validateApplication(HttpServletRequest request, Long applicationId); - + byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java index 886b91c1..0fec17a7 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/ApplicationServiceImpl.java @@ -116,6 +116,10 @@ public class ApplicationServiceImpl implements ApplicationService { public ApplicationResponse validateApplication(HttpServletRequest request, Long applicationId) { return applicationDao.validateApplication(request, applicationId); } - + @Override + @Transactional(readOnly = true) + public byte[] downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId) { + return applicationDao.downloadApplicationDocumentsAsZip(request,applicationId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java index 700bf353..d37c004e 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/ApplicationApi.java @@ -200,6 +200,18 @@ public interface ApplicationApi { ResponseEntity> validateApplication(HttpServletRequest request, @Parameter(description = "The application id", required = true) @PathVariable("applicationId") Long applicationId); - + @Operation(summary = "Api to download all the File inserted by beneficiary in a ZIP file", + 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 = "/{applicationId}/documents/zip") + ResponseEntity downloadApplicationDocumentsAsZip(HttpServletRequest httpServletRequest, + @Parameter(required = true) @PathVariable("applicationId") Long applicationId); } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java index 27ea0bb7..958d8096 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/ApplicationApiController.java @@ -148,5 +148,21 @@ public class ApplicationApiController implements ApplicationApi { return ResponseEntity.status(HttpStatus.OK) .body(new Response<>(applicationResponse, Status.SUCCESS, Translator.toLocale(GepafinConstant.APPLICATION_STATUS_UPDATED_SUCCESSFULLY))); } + @Override + public ResponseEntity downloadApplicationDocumentsAsZip(HttpServletRequest request, Long applicationId) { + byte[] zipFile = applicationService.downloadApplicationDocumentsAsZip(request, applicationId); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", "documents.zip"); + + if (zipFile == null || zipFile.length == 0) { + String notFoundMessage = Translator.toLocale(GepafinConstant.APPLICATION_DOCUMENTS_NOT_FOUND_MSG); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(notFoundMessage.getBytes()); + } + + return new ResponseEntity<>(zipFile, headers, HttpStatus.OK); + } } diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 220d4654..938ee15b 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -306,3 +306,4 @@ comment.not.associate.with.amendment = Comment Not Associated with Amendment Req amendment.found.success = Amendment Request Found Successfully. invalid.amendment.for.comment = Invalid Amendment Request for the Given Comment. DD_MM_YYYY_HH_MM = dd_MM_yyyy HH:mm +application.documents.not.found=No documents found for the application. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index ea702497..6e7c8353 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -301,3 +301,4 @@ DD_MM_YYYY_HH_MM = dd_MM_yyyy HH:mm create.application.data.amendment.msg =Emendamento alla domanda inviato con successo beneficiary.email.not.found.msg=L'indirizzo email per il beneficiario non è stato trovato. Si prega di assicurarsi che il beneficiario abbia un indirizzo email valido. reminder.email.sent.success.msg=Email di promemoria inviata con successo! +application.documents.not.found=Nessun documento trovato per la domanda.