Skip to content

Commit

Permalink
Merge pull request #86 from pagopa/PAGOPA-1998-lap-sviluppo-modificar…
Browse files Browse the repository at this point in the history
…e-lattuale-generazione-pdf

[PAGOPA-1998] PDF new path
  • Loading branch information
jacopocarlini authored Sep 5, 2024
2 parents cefc4c7 + 368e270 commit d82a774
Show file tree
Hide file tree
Showing 23 changed files with 4,327 additions and 4,459 deletions.
4,079 changes: 1,997 additions & 2,082 deletions openapi/openapi.json

Large diffs are not rendered by default.

1,077 changes: 507 additions & 570 deletions openapi/openapi_ec.json

Large diffs are not rendered by default.

1,438 changes: 699 additions & 739 deletions openapi/openapi_helpdesk.json

Large diffs are not rendered by default.

1,385 changes: 654 additions & 731 deletions openapi/openapi_io.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package it.gov.pagopa.bizeventsservice.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* This configuration is required ignore the 'accept' header in the request.
* If the client uses a different value of the response then SpringBoot goes wrong because the response type doesn't match.
* We can ignore the accept header from the client.
* <p>
* see more information in this GitHub <a href="https://github.com/swagger-api/swagger-ui/issues/5649">issue</a>
*/
@Configuration
public class ContentNegotiationConf implements WebMvcConfigurer {

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.ignoreAcceptHeader(true)
.defaultContentType(MediaType.ALL);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import it.gov.pagopa.bizeventsservice.model.filterandorder.Order;
import it.gov.pagopa.bizeventsservice.model.response.paidnotice.NoticeDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.paidnotice.NoticeListWrapResponse;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
Expand Down Expand Up @@ -93,5 +95,20 @@ ResponseEntity<Void> disablePaidNotice(
@RequestHeader(X_FISCAL_CODE) @NotBlank String fiscalCode,
@Parameter(description = "The id of the paid event.", required = true) @NotBlank @PathVariable("event-id") String eventId);

@Operation(summary = "Retrieve the PDF receipt given event id.", security = {
@SecurityRequirement(name = "ApiKey")}, operationId = "generatePDF")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Obtained the PDF receipt.",
headers = {@Header(name = HttpHeaders.CONTENT_DISPOSITION, description = "Content disposition with name of the file", schema = @Schema(type = "string"))},
content = {@Content(mediaType = MediaType.APPLICATION_PDF_VALUE, schema = @Schema(implementation = Resource.class)),}),
@ApiResponse(responseCode = "401", description = "Wrong or missing function key.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)),
@ApiResponse(responseCode = "404", description = "Not found the receipt.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "422", description = "Unprocessable receipt.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "429", description = "Too many requests.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))})
@GetMapping(value = "/{event-id}/pdf", produces = {MediaType.APPLICATION_PDF_VALUE, MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<Resource> generatePDF(
@RequestHeader(X_FISCAL_CODE) @NotBlank String fiscalCode,
@Parameter(description = "The id of the paid event.", required = true) @NotBlank @PathVariable("event-id") String eventId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,14 @@ ResponseEntity<Void> disableTransaction(
@RequestHeader("x-fiscal-code") @NotBlank String fiscalCode,
@Parameter(description = "The id of the transaction.", required = true) @NotBlank @PathVariable("transaction-id") String transactionId);

@Operation(summary = "Retrieve the PDF receipt given event id.", security = {
/**
* @deprecated
* @param fiscalCode
* @param eventId
* @return
*/
@Operation(summary = "Retrieve the PDF receipt given event id.", deprecated = true,
description = "This operation is deprecated. Use Paid Notice APIs instead", security = {
@SecurityRequirement(name = "ApiKey")}, operationId = "getPDFReceipt")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Obtained the PDF receipt.", content = @Content(mediaType = MediaType.APPLICATION_PDF_VALUE, schema = @Schema(type = "string", format = "binary"))),
Expand All @@ -118,6 +125,7 @@ ResponseEntity<Void> disableTransaction(
@ApiResponse(responseCode = "429", description = "Too many requests.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))})
@GetMapping(value = "/{event-id}/pdf")
@Deprecated(forRemoval = false)
ResponseEntity<byte[]> getPDFReceipt(
@RequestHeader("x-fiscal-code") @NotBlank String fiscalCode,
@Parameter(description = "The id of the event.", required = true) @NotBlank @PathVariable("event-id") String eventId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import it.gov.pagopa.bizeventsservice.model.response.paidnotice.NoticeDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.paidnotice.NoticeListWrapResponse;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionListResponse;
import it.gov.pagopa.bizeventsservice.service.IBizEventsService;
import it.gov.pagopa.bizeventsservice.service.ITransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -24,10 +26,12 @@
public class PaidNoticeController implements IPaidNoticeController {

private final ITransactionService transactionService;
private final IBizEventsService bizEventsService;

@Autowired
public PaidNoticeController(ITransactionService transactionService) {
public PaidNoticeController(ITransactionService transactionService, IBizEventsService bizEventsService) {
this.transactionService = transactionService;
this.bizEventsService = bizEventsService;
}

@Override
Expand Down Expand Up @@ -60,4 +64,12 @@ public ResponseEntity<Void> disablePaidNotice(String fiscalCode, String transact
transactionService.disableTransaction(fiscalCode, transactionId);
return new ResponseEntity<>(HttpStatus.OK);
}

@Override
public ResponseEntity<Resource> generatePDF(@NotBlank String fiscalCode, @NotBlank String eventId) {
// to check if is an OLD event present only on the PM --> the receipt is not available for events present exclusively on the PM
bizEventsService.getBizEvent(eventId);
return transactionService.getPDFReceiptResponse(fiscalCode, eventId);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package it.gov.pagopa.bizeventsservice.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import it.gov.pagopa.bizeventsservice.model.ProblemJson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
Expand Down Expand Up @@ -142,6 +145,17 @@ public ResponseEntity<ProblemJson> handleAppException(final AppException ex, fin
return new ResponseEntity<>(errorResponse, ex.getHttpStatus());
}

@ExceptionHandler({FeignException.class})
public ResponseEntity<ProblemJson> handleFeignException(final FeignException ex, final WebRequest request) throws JsonProcessingException {
log.error("FeignException raised:", ex);
ProblemJson body = new ObjectMapper().readValue(ex.contentUTF8(), ProblemJson.class);
var errorResponse = ProblemJson.builder()
.status(body.getStatus())
.title("A dependency returned an error: " + body.getTitle())
.detail(body.getDetail())
.build();
return new ResponseEntity<>(errorResponse, HttpStatus.valueOf(ex.status()));
}

/**
* Handle if a {@link Exception} is raised
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class ConvertViewsToTransactionDetailResponse {
private static final List<String> LIST_RECEIPT_DATE_FORMAT_IN = List.of("yyyy-MM-dd'T'HH:mm:ss");
private static final String RECEIPT_DATE_FORMAT_OUT = "yyyy-MM-dd'T'HH:mm:ssX";
private static String payeeCartName;

private ConvertViewsToTransactionDetailResponse() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import it.gov.pagopa.bizeventsservice.model.response.paidnotice.NoticeDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionDetailResponse;
import it.gov.pagopa.bizeventsservice.model.response.transaction.TransactionListResponse;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.ResponseEntity;

public interface ITransactionService {

Expand All @@ -24,5 +26,7 @@ public interface ITransactionService {

byte[] getPDFReceipt(String fiscalCode, String eventId);

ResponseEntity<Resource> getPDFReceiptResponse(String fiscalCode, String eventId);

void disableTransaction(String fiscalCode, String transactionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@
import it.gov.pagopa.bizeventsservice.repository.BizEventsViewUserRepository;
import it.gov.pagopa.bizeventsservice.service.ITransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class TransactionService implements ITransactionService {
Expand Down Expand Up @@ -68,7 +73,7 @@ public TransactionListResponse getTransactionList(String taxCode, Boolean isPaye
List<BizEventsViewUser> listOfViewUser = page.getContent().stream()
.sorted(Comparator.comparing(BizEventsViewUser::getIsDebtor, Comparator.reverseOrder()))
.filter(p -> set.add(p.getTransactionId()))
.collect(Collectors.toList())
.toList()
.stream()
.sorted(Comparator.comparing(BizEventsViewUser::getTransactionDate, Comparator.reverseOrder()))
.toList();
Expand Down Expand Up @@ -160,20 +165,37 @@ public byte[] getPDFReceipt(String fiscalCode, String eventId) {
return this.acquirePDFReceipt(fiscalCode, eventId);
}

@Override
public ResponseEntity<Resource> getPDFReceiptResponse(String fiscalCode, String eventId) {
var attachmentDetails = getAttachmentDetails(fiscalCode, eventId);
var name = attachmentDetails.getAttachments().get(0).getName();
var url = attachmentDetails.getAttachments().get(0).getUrl();
var receiptFile = getAttachmentFile(fiscalCode, eventId, url);

return ResponseEntity
.ok()
.contentLength(receiptFile.length)
.contentType(MediaType.APPLICATION_PDF)
.header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.inline().filename(Optional.ofNullable(name).orElse("Receipt.pdf")).build().toString())
.body(new ByteArrayResource(receiptFile));
}

private byte[] acquirePDFReceipt(String fiscalCode, String eventId) {
String url = "";
String url = getAttachmentDetails(fiscalCode, eventId).getAttachments().get(0).getUrl();
return this.getAttachmentFile(fiscalCode, eventId, url);
}

private AttachmentsDetailsResponse getAttachmentDetails(String fiscalCode, String eventId) {
try {
// call the receipt-pdf-service to retrieve the PDF receipt details
AttachmentsDetailsResponse response = receiptClient.getAttachments(fiscalCode, eventId);
url = response.getAttachments().get(0).getUrl();
return receiptClient.getAttachments(fiscalCode, eventId);
} catch (FeignException.NotFound e) {
generateReceiptClient.generateReceipt(eventId, "false", "{}");
url = receiptClient.getAttachments(fiscalCode, eventId).getAttachments().get(0).getUrl();
return receiptClient.getAttachments(fiscalCode, eventId);
}
return this.getAttachment(fiscalCode, eventId, url);
}

private byte[] getAttachment(String fiscalCode, String eventId, String url) {
private byte[] getAttachmentFile(String fiscalCode, String eventId, String url) {
try {
// call the receipt-pdf-service to retrieve the PDF receipt attachment
return receiptClient.getReceipt(fiscalCode, eventId, url);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package it.gov.pagopa.bizeventsservice.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class BaseControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private MockMvc mockMvc;

@Test
void shouldRespondOKtoHeartBeat() throws Exception {
mockMvc.perform(get("/info")).andExpect(status().isOk());
}
@Test
void shouldRespondOKtoHeartBeat() throws Exception {
mockMvc.perform(get("/info")).andExpect(status().isOk());
}
}
Loading

0 comments on commit d82a774

Please sign in to comment.