From b842bcee73e08bfd3265d206d669881fa98afcdd Mon Sep 17 00:00:00 2001 From: harish Date: Thu, 10 Oct 2024 18:03:02 +0530 Subject: [PATCH] Beneficiario must be abfle to dowload Call Documents --- .../constants/GepafinConstant.java | 2 + .../gepafin/tendermanagement/dao/CallDao.java | 45 +++++++++++++++++++ .../repositories/DocumentRepository.java | 1 + .../tendermanagement/service/CallService.java | 2 +- .../service/impl/CallServiceImpl.java | 5 +++ .../web/rest/api/CallApi.java | 15 +++++++ .../web/rest/api/impl/CallApiController.java | 20 +++++++++ src/main/resources/message_en.properties | 3 ++ src/main/resources/message_it.properties | 3 ++ 9 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index afbfbea3..d72853c7 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -201,5 +201,7 @@ public class GepafinConstant { public static final String DELEGATION_DELETE_SUCCESS = "delegation.delete.success"; public static final String USER_NOT_AUTHORIZED_TO_CREATE_APPLICATION = "user.not.authorized.create.application"; public static final String APPLICATION_SUBMITTED_CANNOT_CHANGE = "application.submitted.cannot.change"; + public static final String CALL_DOCUMENTS_FETCH_SUCCESS_MSG = "call.documents.fetch.success"; + public static final String CALL_DOCUMENTS_NOT_FOUND_MSG = "call.documents.not.found"; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java index c6345d59..0827b62a 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -1,5 +1,9 @@ package net.gepafin.tendermanagement.dao; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; @@ -8,13 +12,21 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.service.*; import net.gepafin.tendermanagement.util.DateTimeUtil; import net.gepafin.tendermanagement.util.Utils; +import org.h2.util.IOUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @@ -85,6 +97,10 @@ public class CallDao { private FlowDao flowDao; @Autowired private FormDao formDao; + @Value("${aws.s3.url.folder}") + private String s3Folder; + @Autowired + private AmazonS3Service amazonS3Service; public CallResponse createCallStep1(CreateCallRequestStep1 createCallRequest, Long userId) { UserEntity userEntity = userService.validateUser(userId); @@ -101,6 +117,35 @@ public class CallDao { return createCallResponseBean; } + public byte[] downloadCallDocumentsAsZip(Long callId) { + List documents = documentRepository.findBySourceIdAndSourceAndTypeAndIsDeletedFalse(callId, DocumentSourceTypeEnum.CALL.getValue(),DocumentTypeEnum.DOCUMENT.getValue()); + 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) { + try (InputStream fileInputStream = amazonS3Service.getFile(s3Folder, document.getFileName())) { + ZipEntry zipEntry = new ZipEntry(document.getFileName()); + zos.putNextEntry(zipEntry); + 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); + } + } + + public CallEntity convertToCallEntity(CreateCallRequestStep1 createCallRequest) { CallEntity callEntity = new CallEntity(); diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 339efd13..1543def3 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -20,6 +20,7 @@ public interface DocumentRepository extends JpaRepository Optional findByIdAndSourceIdAndIsDeletedFalse(Long id, Long sourceId); List findBySource(String source); + List findBySourceIdAndSourceAndTypeAndIsDeletedFalse(Long sourceId, String source, String type); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java index aa6ea872..9a62d89d 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/CallService.java +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -32,5 +32,5 @@ public interface CallService { CallEntity validateCall(Long callId); CallEntity validatePublishedCall(Long callId); - + byte[] downloadCallDocumentsAsZip(Long callId); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java index a6a6a901..f6ca0b66 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -92,4 +92,9 @@ public class CallServiceImpl implements CallService { public CallEntity validatePublishedCall(Long callId) { return callDao.validatePublishedCall(callId); } + @Override + @Transactional(readOnly = true) + public byte[] downloadCallDocumentsAsZip(Long callId) { + return callDao.downloadCallDocumentsAsZip(callId); + } } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java index cc7f985a..3e2861ff 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -134,4 +134,19 @@ public interface CallApi { public ResponseEntity> updateCallStatus(HttpServletRequest request, @Parameter(description = "The call id", required = true) @PathVariable("callId") Long callId, @Parameter(description = "status", required = true)@RequestParam(value = "status", required = true) CallStatusEnum status); + + @Operation(summary = "Api to download call documents as 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 = "/{callId}/documents/zip") + ResponseEntity downloadCallDocumentsAsZip(HttpServletRequest httpServletRequest, + @Parameter(description = "The call ID", required = true) @PathVariable("callId") Long callId); + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java index e4680428..926dccab 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -4,7 +4,9 @@ import java.util.List; import net.gepafin.tendermanagement.enums.CallStatusEnum; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; @@ -84,4 +86,22 @@ public class CallApiController implements CallApi { CallResponse updateCall = callService.updateCallStatus(request, callId, status); return ResponseEntity.ok(new Response<>(updateCall, Status.SUCCESS, Translator.toLocale(GepafinConstant.UPDATE_CALL_STATUS_SUCCESS_MSG))); } + @Override + public ResponseEntity downloadCallDocumentsAsZip(HttpServletRequest request, Long callId) { + byte[] zipFile = callService.downloadCallDocumentsAsZip(callId); + + 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.CALL_DOCUMENTS_NOT_FOUND_MSG); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(notFoundMessage.getBytes()); + } + + return new ResponseEntity<>(zipFile, headers, HttpStatus.OK); + } + + } \ No newline at end of file diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index 0d68c6d7..8ae7bcfa 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -226,5 +226,8 @@ user.company.relation.not.found=User with the specified company relation not fou delegation.delete.success=Delegation deleted successfully. user.not.authorized.create.application=User must be a legal representative or have delegation. application.submitted.cannot.change=The submitted application cannot be changed. +# Call Document Messages +call.documents.fetch.success=Documents fetched successfully. +call.documents.not.found=No documents found for the specified call. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 3e665e82..9b998124 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -222,5 +222,8 @@ delegation.delete.success=Delega eliminata con successo. user.not.authorized.create.application=L'utente deve essere un rappresentante legale o avere una delega. application.submitted.cannot.change=La domanda inviata non puņ essere modificata. +# Call Document Messages +call.documents.fetch.success=Documenti recuperati con successo. +call.documents.not.found=Nessun documento trovato per la chiamata specificata.