diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml
index f57de18..aef08a3 100644
--- a/helm/values-dev.yaml
+++ b/helm/values-dev.yaml
@@ -89,6 +89,7 @@ microservice-chart:
COSMOS_BIZ_EVENT_DB_NAME: "db"
COSMOS_RECEIPT_CONTAINER_NAME: "receipts"
COSMOS_RECEIPT_ERROR_CONTAINER_NAME: "receipts-message-errors"
+ COSMOS_RECEIPT_MESSAGE_CONTAINER_NAME: "receipts-io-messages"
COSMOS_BIZ_EVENT_CONTAINER_NAME: "biz-events"
PDF_ENGINE_ENDPOINT: "https://api.dev.platform.pagopa.it/shared/pdf-engine/v1/generate-pdf"
BLOB_STORAGE_ACCOUNT_ENDPOINT: "https://pagopadweureceiptsfnsa.blob.core.windows.net/"
diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml
index 9abb4a4..6c36bae 100644
--- a/helm/values-prod.yaml
+++ b/helm/values-prod.yaml
@@ -89,6 +89,7 @@ microservice-chart:
COSMOS_BIZ_EVENT_DB_NAME: "db"
COSMOS_RECEIPT_CONTAINER_NAME: "receipts"
COSMOS_RECEIPT_ERROR_CONTAINER_NAME: "receipts-message-errors"
+ COSMOS_RECEIPT_MESSAGE_CONTAINER_NAME: "receipts-io-messages"
COSMOS_BIZ_EVENT_CONTAINER_NAME: "biz-events"
PDF_ENGINE_ENDPOINT: "https://api.platform.pagopa.it/shared/pdf-engine/v1/generate-pdf"
BLOB_STORAGE_ACCOUNT_ENDPOINT: "https://pagopapweureceiptsfnsa.blob.core.windows.net"
diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml
index 715c9c6..bca76a5 100644
--- a/helm/values-uat.yaml
+++ b/helm/values-uat.yaml
@@ -89,6 +89,7 @@ microservice-chart:
COSMOS_BIZ_EVENT_DB_NAME: "db"
COSMOS_RECEIPT_CONTAINER_NAME: "receipts"
COSMOS_RECEIPT_ERROR_CONTAINER_NAME: "receipts-message-errors"
+ COSMOS_RECEIPT_MESSAGE_CONTAINER_NAME: "receipts-io-messages"
COSMOS_BIZ_EVENT_CONTAINER_NAME: "biz-events"
PDF_ENGINE_ENDPOINT: "https://api.uat.platform.pagopa.it/shared/pdf-engine/v1/generate-pdf"
BLOB_STORAGE_ACCOUNT_ENDPOINT: "https://pagopauweureceiptsfnsa.blob.core.windows.net"
diff --git a/integration-test/src/features/receipt_pdf_helpdesk.feature b/integration-test/src/features/receipt_pdf_helpdesk.feature
index 51b64e4..0744c48 100644
--- a/integration-test/src/features/receipt_pdf_helpdesk.feature
+++ b/integration-test/src/features/receipt_pdf_helpdesk.feature
@@ -25,6 +25,13 @@ Feature: All about payment events to recover managed by Azure functions receipt-
When getReceiptPdf API is called with filename "int-test-helpdesk-receipt.pdf"
Then the api response has a 200 Http status
+ Scenario: getReceiptMessage API return receipt-error stored on datastore
+ Given a receipt-io-message with bizEventId "receipt-helpdesk-int-test-id-3" and messageId "receipt-helpdesk-int-test-message-id-3" stored into receipt-io-message datastore
+ When getReceiptMessage API is called with messageId "receipt-helpdesk-int-test-id-3"
+ Then the api response has a 200 Http status
+ And the receipt-message has messageId "receipt-helpdesk-int-test-message-id-3"
+ And the receipt-message has eventId "receipt-helpdesk-int-test-id-3"
+
Scenario: receiptToReviewed API retrieve a receipt error and updates its status to REVIEWED
Given a receipt-error with bizEventId "receipt-helpdesk-int-test-id-5" and status "TO_REVIEW" stored into receipt-error datastore
When receiptToReviewed API is called with bizEventId "receipt-helpdesk-int-test-id-5"
diff --git a/integration-test/src/script/teardown_script.js b/integration-test/src/script/teardown_script.js
index 2605205..d7e33a6 100644
--- a/integration-test/src/script/teardown_script.js
+++ b/integration-test/src/script/teardown_script.js
@@ -7,10 +7,12 @@ const cosmos_db_conn_string = process.env.RECEIPTS_COSMOS_CONN_STRING || "";
const databaseId = process.env.RECEIPT_COSMOS_DB_NAME;
const receiptContainerId = process.env.RECEIPT_COSMOS_DB_CONTAINER_NAME;
const receiptErrorContainerId = process.env.RECEIPT_ERROR_COSMOS_DB_CONTAINER_NAME;
+const receiptMessageContainerId = process.env.RECEIPT_MESSAGE_COSMOS_DB_CONTAINER_NAME;
const client = new CosmosClient(cosmos_db_conn_string);
const receiptContainer = client.database(databaseId).container(receiptContainerId);
const receiptErrorContainer = client.database(databaseId).container(receiptErrorContainerId);
+const receiptMessageContainer = client.database(databaseId).container(receiptMessageContainerId);
//COSMOS BIZEVENT
const biz_cosmos_db_conn_string = process.env.BIZEVENTS_COSMOS_CONN_STRING;
@@ -82,6 +84,24 @@ const deleteDocumentFromAllDatabases = async () => {
}
}
+ //Delete Receipt message from CosmosDB
+ try {
+ let response = await receiptMessageContainer.items.query({
+ query: "SELECT * from c WHERE c.eventId = @eventId",
+ parameters: [{ name: "@eventId", value: el.eventId }]
+ }).fetchAll();
+
+ let resourcesMessage = response.resources;
+
+ for (let message of resourcesMessage) {
+ await receiptMessageContainer.item(message.id, message.id).delete();
+ }
+ } catch (error) {
+ if (error.code !== 404) {
+ console.error(`Error deleting receipt message ${el.eventId}`);
+ }
+ }
+
//Delete BizEvent from CosmosDB
try {
await bizContainer.item(el.eventId, el.eventId).delete();
diff --git a/integration-test/src/step_definitions/common.js b/integration-test/src/step_definitions/common.js
index 15dddef..f068f58 100644
--- a/integration-test/src/step_definitions/common.js
+++ b/integration-test/src/step_definitions/common.js
@@ -175,11 +175,19 @@ function createReceiptError(id, status) {
}
}
+function createReceiptMessage(eventId, messageId) {
+ return {
+ "messageId": messageId,
+ "eventId": eventId
+ }
+}
+
module.exports = {
TOKENIZED_FISCAL_CODE,
createEvent,
sleep,
createReceipt,
createReceiptError,
+ createReceiptMessage,
getRandomInt
}
\ No newline at end of file
diff --git a/integration-test/src/step_definitions/receipt_pdf_helpdesk_step.js b/integration-test/src/step_definitions/receipt_pdf_helpdesk_step.js
index 5ea84c1..277d943 100644
--- a/integration-test/src/step_definitions/receipt_pdf_helpdesk_step.js
+++ b/integration-test/src/step_definitions/receipt_pdf_helpdesk_step.js
@@ -11,12 +11,15 @@ const {
deleteDocumentFromReceiptErrorDatastore,
getDocumentFromReceiptsErrorDatastoreByBizEventId,
getDocumentFromReceiptsDatastoreByEventId,
- deleteMultipleDocumentFromReceiptErrorDatastoreByEventId
+ deleteMultipleDocumentFromReceiptErrorDatastoreByEventId,
+ deleteDocumentFromReceiptMessageDatastore,
+ createDocumentInReceiptIoMessageDatastore
} = require("./receipts_datastore_client");
const {
getReceipt,
getReceiptByOrganizationFiscalCodeAndIUV,
getReceiptError,
+ getReceiptMessage,
getReceiptPdf,
postReceiptToReviewed,
postRecoverFailedReceipt,
@@ -32,9 +35,11 @@ setDefaultTimeout(360 * 1000);
// initialize variables
let eventId = null;
+let messageId = null;
let responseAPI = null;
let receipt = null;
let receiptError = null;
+let receiptMessage = null;
let receiptPdfFileName = null;
let listOfReceipts = [];
@@ -243,6 +248,28 @@ Then("wait {int} ms", async function (milliSec) {
sleep(milliSec)
});
+Given('a receipt-io-message with bizEventId {string} and status {string} stored into receipt-error datastore', async function (eventId, messageId) {
+ messageId = messageId;
+ // prior cancellation to avoid dirty cases
+ await deleteDocumentFromReceiptMessageDatastore(messageId);
+
+ let receiptsMessageStoreResponse = await createDocumentInReceiptIoMessageDatastore(eventId, messageId);
+ assert.strictEqual(receiptsMessageStoreResponse.statusCode, 201);
+});
+
+When("getReceiptMessage API is called with messageId {string}", async function (id) {
+ responseAPI = await getReceiptMessage(id);
+ receiptMessage = responseAPI.data;
+});
+
+Then("the receipt-message has eventId {string}", async function (id) {
+ assert.strictEqual(receiptMessage.eventId, id);
+});
+
+Then("the receipt-message has messageId {string}", async function (id) {
+ assert.strictEqual(receiptMessage.messageId, id);
+});
+
diff --git a/integration-test/src/step_definitions/receipts_datastore_client.js b/integration-test/src/step_definitions/receipts_datastore_client.js
index 74a15f8..b5ad050 100644
--- a/integration-test/src/step_definitions/receipts_datastore_client.js
+++ b/integration-test/src/step_definitions/receipts_datastore_client.js
@@ -1,14 +1,16 @@
const { CosmosClient } = require("@azure/cosmos");
-const { createReceipt, createReceiptError } = require("./common");
+const { createReceipt, createReceiptError, createReceiptMessage } = require("./common");
const cosmos_db_conn_string = process.env.RECEIPTS_COSMOS_CONN_STRING || "";
const databaseId = process.env.RECEIPT_COSMOS_DB_NAME;
const receiptContainerId = process.env.RECEIPT_COSMOS_DB_CONTAINER_NAME;
const receiptErrorContainerId = process.env.RECEIPT_ERROR_COSMOS_DB_CONTAINER_NAME;
+const receiptMessageContainerId = process.env.RECEIPT_MESSAGE_COSMOS_DB_CONTAINER_NAME;
const client = new CosmosClient(cosmos_db_conn_string);
const receiptContainer = client.database(databaseId).container(receiptContainerId);
const receiptErrorContainer = client.database(databaseId).container(receiptErrorContainerId);
+const receiptMessageContainer = client.database(databaseId).container(receiptMessageContainerId);
//RECEIPT
async function createDocumentInReceiptsDatastore(id, status) {
@@ -57,6 +59,16 @@ async function createDocumentInReceiptErrorDatastore(id, status) {
}
}
+//RECEIPT-MESSAGE
+async function createDocumentInReceiptIoMessageDatastore(eventId, messageId) {
+ let message = createReceiptMessage(eventId, messageId);
+ try {
+ return await receiptMessageContainer.items.create(receipt);
+ } catch (err) {
+ console.log(err);
+ }
+}
+
async function getDocumentFromReceiptsErrorDatastoreByBizEventId(id) {
return await receiptErrorContainer.items
.query({
@@ -84,6 +96,16 @@ async function deleteDocumentFromReceiptErrorDatastore(id) {
}
}
+async function deleteDocumentFromReceiptMessageDatastore(id) {
+ try {
+ return await receiptMessageContainer.item(id, id).delete();
+ } catch (error) {
+ if (error.code !== 404) {
+ console.log(error)
+ }
+ }
+}
+
async function updateReceiptToFailed(id) {
const operations =
@@ -131,6 +153,21 @@ async function deleteAllTestReceiptsError() {
}
}
+async function deleteAllTestReceiptsMessage() {
+ let response = await receiptErrorContainer.items.query({
+ query: 'SELECT * from c WHERE c.messageId LIKE @messageId',
+ parameters: [{ name: "@messageId", value: "%receipt-helpdesk-int-test-message%" }]
+ }).fetchNext();
+
+ let receiptErrorList = response.resources;
+ if (receiptErrorList.length > 0) {
+ receiptErrorList.forEach((receiptMessage) => {
+ console.log("\n Deleting receiptMessage with id " + receiptMessage.messageId);
+ deleteDocumentFromReceiptMessageDatastore(receiptMessage.id);
+ })
+ }
+}
+
module.exports = {
createDocumentInReceiptsDatastore,
getDocumentFromReceiptsDatastoreByEventId,
@@ -138,8 +175,11 @@ module.exports = {
deleteDocumentFromReceiptsDatastore,
updateReceiptToFailed,
deleteAllTestReceipts,
+ deleteAllTestReceiptsMessage,
+ createDocumentInReceiptIoMessageDatastore,
deleteDocumentFromReceiptErrorDatastore,
+ deleteDocumentFromReceiptMessageDatastore,
deleteMultipleDocumentFromReceiptErrorDatastoreByEventId,
createDocumentInReceiptErrorDatastore,
getDocumentFromReceiptsErrorDatastoreByBizEventId,
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessage.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessage.java
new file mode 100644
index 0000000..294ba3b
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessage.java
@@ -0,0 +1,87 @@
+package it.gov.pagopa.receipt.pdf.helpdesk;
+
+import com.microsoft.azure.functions.*;
+import com.microsoft.azure.functions.annotation.AuthorizationLevel;
+import com.microsoft.azure.functions.annotation.BindingName;
+import com.microsoft.azure.functions.annotation.FunctionName;
+import com.microsoft.azure.functions.annotation.HttpTrigger;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
+import it.gov.pagopa.receipt.pdf.helpdesk.model.ProblemJson;
+import it.gov.pagopa.receipt.pdf.helpdesk.service.ReceiptCosmosService;
+import it.gov.pagopa.receipt.pdf.helpdesk.service.impl.ReceiptCosmosServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+/**
+ * Azure Functions with HTTP Trigger.
+ */
+public class GetReceiptMessage {
+
+ private final Logger logger = LoggerFactory.getLogger(GetReceiptMessage.class);
+
+ private final ReceiptCosmosService receiptCosmosService;
+
+ public GetReceiptMessage() {
+ this.receiptCosmosService = new ReceiptCosmosServiceImpl();
+ }
+
+ GetReceiptMessage(ReceiptCosmosService receiptCosmosService) {
+ this.receiptCosmosService = receiptCosmosService;
+ }
+
+ /**
+ * This function will be invoked when a Http Trigger occurs.
+ *
+ * It retrieves the receipt-message with the specified messageId
+ *
+ *
+ * @return response with {@link HttpStatus#OK} and the receipt notification message if found
+ */
+ @FunctionName("GetReceiptMessage")
+ public HttpResponseMessage run(
+ @HttpTrigger(name = "GetReceiptMessageTrigger",
+ methods = {HttpMethod.GET},
+ route = "/receipts/io-message/{message-id}",
+ authLevel = AuthorizationLevel.ANONYMOUS)
+ HttpRequestMessage> request,
+ @BindingName("message-id") String messageId,
+ final ExecutionContext context) {
+ logger.info("[{}] function called at {}", context.getFunctionName(), LocalDateTime.now());
+
+ if (messageId == null || messageId.isBlank()) {
+ return request
+ .createResponseBuilder(HttpStatus.BAD_REQUEST)
+ .body(ProblemJson.builder()
+ .title(HttpStatus.BAD_REQUEST.name())
+ .detail("Please pass a valid messageId")
+ .status(HttpStatus.BAD_REQUEST.value())
+ .build())
+ .build();
+ }
+
+ try {
+ IOMessage receipt = this.receiptCosmosService.getReceiptMessage(messageId);
+ return request
+ .createResponseBuilder(HttpStatus.OK)
+ .body(receipt)
+ .build();
+ } catch (IoMessageNotFoundException e) {
+ String responseMsg = String.format("Unable to retrieve the receipt message with messageId %s", messageId);
+ logger.error("[{}] {}", context.getFunctionName(), responseMsg, e);
+ return request
+ .createResponseBuilder(HttpStatus.NOT_FOUND)
+ .body(ProblemJson.builder()
+ .title(HttpStatus.NOT_FOUND.name())
+ .detail(responseMsg)
+ .status(HttpStatus.NOT_FOUND.value())
+ .build())
+ .build();
+ }
+ }
+}
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/ReceiptCosmosClient.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/ReceiptCosmosClient.java
index 7d12f55..da07eec 100644
--- a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/ReceiptCosmosClient.java
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/ReceiptCosmosClient.java
@@ -2,9 +2,11 @@
import com.azure.cosmos.models.CosmosItemResponse;
import com.azure.cosmos.models.FeedResponse;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.ReceiptError;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
public interface ReceiptCosmosClient {
@@ -53,4 +55,6 @@ public interface ReceiptCosmosClient {
* @return receipt documents
*/
Iterable> getIOErrorToNotifyReceiptDocuments(String continuationToken, Integer pageSize);
+
+ IOMessage getIoMessage(String messageId) throws IoMessageNotFoundException;
}
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImpl.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImpl.java
index 527ba7d..69a0bf6 100644
--- a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImpl.java
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImpl.java
@@ -9,10 +9,12 @@
import com.azure.cosmos.models.FeedResponse;
import com.azure.cosmos.util.CosmosPagedIterable;
import it.gov.pagopa.receipt.pdf.helpdesk.client.ReceiptCosmosClient;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.ReceiptError;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptErrorStatusType;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
import java.time.OffsetDateTime;
@@ -28,6 +30,8 @@ public class ReceiptCosmosClientImpl implements ReceiptCosmosClient {
private final String databaseId = System.getenv().getOrDefault("COSMOS_RECEIPT_DB_NAME", "db");
private final String containerId = System.getenv().getOrDefault("COSMOS_RECEIPT_CONTAINER_NAME", "receipt");
+ private final String containerMessageId = System.getenv().getOrDefault("COSMOS_RECEIPT_MESSAGE_CONTAINER_NAME", "receipts-io-messages");
+
private final String containerReceiptErrorId = System.getenv().getOrDefault("COSMOS_RECEIPT_ERROR_CONTAINER_NAME", "receipts-message-errors");
private final String millisDiff = System.getenv("MAX_DATE_DIFF_MILLIS");
@@ -233,4 +237,29 @@ public Iterable> getIOErrorToNotifyReceiptDocuments(String
.queryItems(query, new CosmosQueryRequestOptions(), Receipt.class)
.iterableByPage(continuationToken,pageSize);
}
+
+ /**
+ * Retrieve receipt document from CosmosDB database
+ *
+ * @param messageId IO Message id
+ * @return io message document
+ * @throws IoMessageNotFoundException in case no receipt has been found with the given messageId
+ */
+ @Override
+ public IOMessage getIoMessage(String messageId) throws IoMessageNotFoundException {
+ CosmosDatabase cosmosDatabase = this.cosmosClient.getDatabase(databaseId);
+ CosmosContainer cosmosContainer = cosmosDatabase.getContainer(containerMessageId);
+
+ //Build query
+ String query = String.format("SELECT * FROM c WHERE c.messageId = '%s'", messageId);
+
+ //Query the container
+ CosmosPagedIterable queryResponse = cosmosContainer
+ .queryItems(query, new CosmosQueryRequestOptions(), IOMessage.class);
+
+ if (queryResponse.iterator().hasNext()) {
+ return queryResponse.iterator().next();
+ }
+ throw new IoMessageNotFoundException("Document not found in the defined container");
+ }
}
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/entity/receipt/IOMessage.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/entity/receipt/IOMessage.java
new file mode 100644
index 0000000..a0f775e
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/entity/receipt/IOMessage.java
@@ -0,0 +1,14 @@
+package it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt;
+
+import lombok.*;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class IOMessage {
+
+ String messageId;
+ String eventId;
+}
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/exception/IoMessageNotFoundException.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/exception/IoMessageNotFoundException.java
new file mode 100644
index 0000000..8c3ede9
--- /dev/null
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/exception/IoMessageNotFoundException.java
@@ -0,0 +1,26 @@
+package it.gov.pagopa.receipt.pdf.helpdesk.exception;
+
+/** Thrown in case no receipt message to IO is found in the CosmosDB container */
+public class IoMessageNotFoundException extends Exception{
+
+ /**
+ * Constructs new exception with provided message and cause
+ *
+ * @param message Detail message
+ */
+ public IoMessageNotFoundException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs new exception with provided message and cause
+ *
+ * @param message Detail message
+ * @param cause Exception thrown
+ */
+ public IoMessageNotFoundException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
+
+
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/ReceiptCosmosService.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/ReceiptCosmosService.java
index 3d37a86..2fd4840 100644
--- a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/ReceiptCosmosService.java
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/ReceiptCosmosService.java
@@ -2,8 +2,10 @@
import com.azure.cosmos.models.FeedResponse;
import it.gov.pagopa.receipt.pdf.helpdesk.client.ReceiptCosmosClient;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
/**
@@ -47,4 +49,11 @@ Iterable> getFailedReceiptByStatus(
Integer pageSize,
ReceiptStatusType statusType
);
+
+ /**
+ *
+ * @param messageId
+ * @return
+ */
+ IOMessage getReceiptMessage(String messageId) throws IoMessageNotFoundException;
}
diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImpl.java b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImpl.java
index 7778b9c..016b588 100644
--- a/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImpl.java
+++ b/src/main/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImpl.java
@@ -3,8 +3,10 @@
import com.azure.cosmos.models.FeedResponse;
import it.gov.pagopa.receipt.pdf.helpdesk.client.ReceiptCosmosClient;
import it.gov.pagopa.receipt.pdf.helpdesk.client.impl.ReceiptCosmosClientImpl;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.service.ReceiptCosmosService;
@@ -83,4 +85,21 @@ public Iterable> getFailedReceiptByStatus(
String errMsg = String.format("Unexpected status for retrieving failed receipt: %s", statusType);
throw new IllegalStateException(errMsg);
}
+
+ @Override
+ public IOMessage getReceiptMessage(String messageId) throws IoMessageNotFoundException {
+ IOMessage message;
+ try {
+ message = this.receiptCosmosClient.getIoMessage(messageId);
+ } catch (IoMessageNotFoundException e) {
+ String errorMsg = String.format("Receipt Message to IO not found with the message id %s", messageId);
+ throw new IoMessageNotFoundException(errorMsg, e);
+ }
+
+ if (message == null) {
+ String errorMsg = String.format("Receipt retrieved with the message id %s is null", messageId);
+ throw new IoMessageNotFoundException(errorMsg);
+ }
+ return message;
+ }
}
\ No newline at end of file
diff --git a/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessageTest.java b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessageTest.java
new file mode 100644
index 0000000..e564c54
--- /dev/null
+++ b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/GetReceiptMessageTest.java
@@ -0,0 +1,125 @@
+package it.gov.pagopa.receipt.pdf.helpdesk;
+
+import com.microsoft.azure.functions.ExecutionContext;
+import com.microsoft.azure.functions.HttpRequestMessage;
+import com.microsoft.azure.functions.HttpResponseMessage;
+import com.microsoft.azure.functions.HttpStatus;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.ReasonError;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
+import it.gov.pagopa.receipt.pdf.helpdesk.model.ProblemJson;
+import it.gov.pagopa.receipt.pdf.helpdesk.service.ReceiptCosmosService;
+import it.gov.pagopa.receipt.pdf.helpdesk.util.HttpResponseMessageMock;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+class GetReceiptMessageTest {
+
+ private static final String MESSAGE_ID = "messageId";
+
+ private static final String EVENT_ID = "eventId";
+
+ @Mock
+ private ExecutionContext executionContextMock;
+
+ @Mock
+ private ReceiptCosmosService receiptCosmosServiceMock;
+
+ @Mock
+ private HttpRequestMessage> requestMock;
+
+ private GetReceiptMessage sut;
+
+ private AutoCloseable closeable;
+
+ @BeforeEach
+ public void openMocks() {
+ closeable = MockitoAnnotations.openMocks(this);
+ sut = spy(new GetReceiptMessage(receiptCosmosServiceMock));
+ }
+
+ @AfterEach
+ public void releaseMocks() throws Exception {
+ closeable.close();
+ }
+
+ @Test
+ void getReceiptReceiptSuccess() throws IoMessageNotFoundException {
+ IOMessage receipt = buildMessage();
+ when(receiptCosmosServiceMock.getReceiptMessage(MESSAGE_ID)).thenReturn(receipt);
+
+ doAnswer((Answer) invocation -> {
+ HttpStatus status = (HttpStatus) invocation.getArguments()[0];
+ return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status);
+ }).when(requestMock).createResponseBuilder(any(HttpStatus.class));
+
+ // test execution
+ HttpResponseMessage response = sut.run(requestMock, MESSAGE_ID, executionContextMock);
+
+ // test assertion
+ assertNotNull(response);
+ assertEquals(HttpStatus.OK, response.getStatus());
+ assertNotNull(response.getBody());
+ assertEquals(receipt, response.getBody());
+ }
+
+ @Test
+ void getReceiptForMissingEventId() {
+ doAnswer((Answer) invocation -> {
+ HttpStatus status = (HttpStatus) invocation.getArguments()[0];
+ return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status);
+ }).when(requestMock).createResponseBuilder(any(HttpStatus.class));
+
+ // test execution
+ HttpResponseMessage response = sut.run(requestMock, "", executionContextMock);
+
+ // test assertion
+ assertNotNull(response);
+ assertEquals(HttpStatus.BAD_REQUEST, response.getStatus());
+
+ ProblemJson problemJson = (ProblemJson) response.getBody();
+ assertNotNull(problemJson);
+ assertEquals(HttpStatus.BAD_REQUEST.value(), problemJson.getStatus());
+ assertEquals(HttpStatus.BAD_REQUEST.name(), problemJson.getTitle());
+ assertNotNull(problemJson.getDetail());
+ }
+
+ @Test
+ void getReceiptReceiptNotFound() throws IoMessageNotFoundException {
+ when(receiptCosmosServiceMock.getReceiptMessage(MESSAGE_ID)).thenThrow(IoMessageNotFoundException.class);
+
+ doAnswer((Answer) invocation -> {
+ HttpStatus status = (HttpStatus) invocation.getArguments()[0];
+ return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status);
+ }).when(requestMock).createResponseBuilder(any(HttpStatus.class));
+
+ // test execution
+ HttpResponseMessage response = sut.run(requestMock, MESSAGE_ID, executionContextMock);
+
+ // test assertion
+ assertNotNull(response);
+ assertEquals(HttpStatus.NOT_FOUND, response.getStatus());
+ assertNotNull(response.getBody());
+ }
+
+ private IOMessage buildMessage() {
+ return IOMessage.builder()
+ .messageId(MESSAGE_ID)
+ .eventId(EVENT_ID)
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImplTest.java b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImplTest.java
index 803d046..7b637ef 100644
--- a/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImplTest.java
+++ b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/client/impl/ReceiptCosmosClientImplTest.java
@@ -4,7 +4,9 @@
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.util.CosmosPagedIterable;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -188,4 +190,57 @@ void getIOErrorToNotifyReceiptDocumentsSuccess() {
assertDoesNotThrow(() -> client.getIOErrorToNotifyReceiptDocuments(null, 100));
}
+
+ @Test
+ void getIoMessageReceiptDocumentSuccess() {
+ CosmosDatabase mockDatabase = mock(CosmosDatabase.class);
+ CosmosContainer mockContainer = mock(CosmosContainer.class);
+
+ CosmosPagedIterable mockIterable = mock(CosmosPagedIterable.class);
+
+ Iterator mockIterator = mock(Iterator.class);
+ IOMessage ioMessage = new IOMessage();
+ ioMessage.setEventId(RECEIPT_ID);
+ ioMessage.setMessageId("MESSAGE_ID");
+
+ when(mockIterator.hasNext()).thenReturn(true);
+ when(mockIterator.next()).thenReturn(ioMessage);
+
+ when(mockIterable.iterator()).thenReturn(mockIterator);
+
+ when(mockContainer.queryItems(anyString(), any(), eq(IOMessage.class))).thenReturn(
+ mockIterable
+ );
+ when(mockDatabase.getContainer(any())).thenReturn(mockContainer);
+ when(mockClient.getDatabase(any())).thenReturn(mockDatabase);
+
+ IOMessage response = assertDoesNotThrow(() -> client.getIoMessage("MESSAGE_ID"));
+
+ assertEquals("MESSAGE_ID", response.getMessageId());
+ assertEquals(RECEIPT_ID, response.getEventId());
+
+ }
+
+ @Test
+ void getIoMessageReceiptDocumentFail() {
+ CosmosDatabase mockDatabase = mock(CosmosDatabase.class);
+ CosmosContainer mockContainer = mock(CosmosContainer.class);
+
+ CosmosPagedIterable mockIterable = mock(CosmosPagedIterable.class);
+
+ Iterator mockIterator = mock(Iterator.class);
+
+ when(mockIterator.hasNext()).thenReturn(false);
+
+ when(mockIterable.iterator()).thenReturn(mockIterator);
+
+ when(mockContainer.queryItems(anyString(), any(), eq(IOMessage.class))).thenReturn(
+ mockIterable
+ );
+ when(mockDatabase.getContainer(any())).thenReturn(mockContainer);
+ when(mockClient.getDatabase(any())).thenReturn(mockDatabase);
+
+ assertThrows(IoMessageNotFoundException.class, () -> client.getIoMessage("an invalid receipt id"));
+ }
+
}
\ No newline at end of file
diff --git a/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImplTest.java b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImplTest.java
index 7a266c9..2dcbcec 100644
--- a/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImplTest.java
+++ b/src/test/java/it/gov/pagopa/receipt/pdf/helpdesk/service/impl/ReceiptCosmosServiceImplTest.java
@@ -2,8 +2,10 @@
import com.azure.cosmos.models.FeedResponse;
import it.gov.pagopa.receipt.pdf.helpdesk.client.ReceiptCosmosClient;
+import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.IOMessage;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.Receipt;
import it.gov.pagopa.receipt.pdf.helpdesk.entity.receipt.enumeration.ReceiptStatusType;
+import it.gov.pagopa.receipt.pdf.helpdesk.exception.IoMessageNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.exception.ReceiptNotFoundException;
import it.gov.pagopa.receipt.pdf.helpdesk.service.ReceiptCosmosService;
import org.junit.jupiter.api.BeforeEach;
@@ -173,4 +175,28 @@ void getFailedReceiptByStatusFailUnexpectedStatus() {
verify(receiptCosmosClientMock, never()).getFailedReceiptDocuments(anyString(), anyInt());
verify(receiptCosmosClientMock, never()).getInsertedReceiptDocuments(anyString(), anyInt());
}
+
+ @Test
+ void getReceiptMessageSuccess() throws IoMessageNotFoundException {
+ when(receiptCosmosClientMock.getIoMessage(anyString())).thenReturn(new IOMessage());
+
+ IOMessage message = assertDoesNotThrow(() -> sut.getReceiptMessage(anyString()));
+
+ assertNotNull(message);
+ }
+
+ @Test
+ void getReceiptMessageFailClientThrowsReceiptNotFound() throws IoMessageNotFoundException {
+ when(receiptCosmosClientMock.getIoMessage(anyString())).thenThrow(IoMessageNotFoundException.class);
+
+ assertThrows(IoMessageNotFoundException.class, () -> sut.getReceiptMessage(anyString()));
+ }
+
+ @Test
+ void getReceiptMessageFailClientReturnNull() throws IoMessageNotFoundException {
+ when(receiptCosmosClientMock.getIoMessage(anyString())).thenReturn(null);
+
+ assertThrows(IoMessageNotFoundException.class, () -> sut.getReceiptMessage(anyString()));
+ }
+
}
\ No newline at end of file