Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
976d986
draft
aomegax Dec 15, 2025
4aef895
receiptToReviewed
aomegax Dec 15, 2025
b0403d8
added all helpdesk http fn
aomegax Dec 16, 2025
621c90f
fix helm
aomegax Dec 16, 2025
d142f5c
imported unit tests
aomegax Dec 16, 2025
ce857fc
fix unit tests
aomegax Dec 16, 2025
f50ace3
fix unit tests
aomegax Dec 16, 2025
e3aece8
optimized ReceiptCosmosClient
aomegax Dec 16, 2025
111f101
RecoverFailedReceipt
aomegax Dec 18, 2025
44d5209
RecoverFailedReceiptMassive
aomegax Dec 18, 2025
836dfde
Schedule
aomegax Dec 19, 2025
0bb271a
added unit tests for ReceiptCosmosServiceImpl
aomegax Dec 19, 2025
fbcbfde
removed code not used
aomegax Dec 19, 2025
cb31975
added unit tests
aomegax Dec 19, 2025
4c509a6
code cleaning
aomegax Dec 19, 2025
1a255ae
fix tests
aomegax Dec 21, 2025
5d4658e
fix integration tests
aomegax Jan 5, 2026
8120ac0
clean codes
aomegax Jan 5, 2026
1561d37
clean codes
aomegax Jan 5, 2026
c164bfa
clean codes
aomegax Jan 5, 2026
7c31a53
improvements
aomegax Jan 12, 2026
cc6a334
[PAGOPA-3343] added recover failed cart function
gioelemella Jan 12, 2026
99390c2
[PAGOPA-3343] added massive and scheduled recover failed cart functio…
gioelemella Jan 13, 2026
173ef01
[PAGOPA-3343] refactor to reduce duplicated code
gioelemella Jan 13, 2026
5541060
[PAGOPA-3343] improve code and minor fix
gioelemella Jan 13, 2026
90a5336
[PAGOPA-3343] removed unused code
gioelemella Jan 13, 2026
5528223
[PAGOPA-3343] refactor recover failed receipt function to reduce dupl…
gioelemella Jan 13, 2026
8103626
[PAGOPA-3343] refactor recover not notified receipt function to reduc…
gioelemella Jan 13, 2026
3469e01
[PAGOPA-3343] added recover not notified cart function
gioelemella Jan 13, 2026
02a23eb
[PAGOPA-3343] minor refactor
gioelemella Jan 13, 2026
60cb5ae
[PAGOPA-3343] added unit tests on clients
gioelemella Jan 14, 2026
5305518
[PAGOPA-3343] refactor to reduce code coupling
gioelemella Jan 14, 2026
9857f54
[PAGOPA-3343] added and updated unit tests
gioelemella Jan 14, 2026
cee5280
log level
jacopocarlini Jan 15, 2026
e61184f
test: fix junit
jacopocarlini Jan 21, 2026
88472d9
Merge branch 'main' into PAGOPA-3421-migrare-da-ai-a-elk
jacopocarlini Jan 22, 2026
960ef25
rollback
jacopocarlini Jan 22, 2026
14a3f63
service name
jacopocarlini Jan 22, 2026
2a21886
helpdesk alert
jacopocarlini Jan 22, 2026
bb10f9a
Merge branch 'main' into PAGOPA-3421-migrare-da-ai-a-elk
jacopocarlini Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions helm/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ microservice-chart: &microservice-chart
ENV: "dev"
TZ: "Europe/Rome"
WEBSITE_SITE_NAME: "pagopareceiptpdfdatastore" # required to show cloud role name in application insights
SERVICE_NAME: "pagopa-receipt-pdf-datastore"
ASPNETCORE_URLS: "http://*:8080"
FUNCTIONS_WORKER_RUNTIME: "java"
RECEIPT_QUEUE_TOPIC: "pagopa-d-weu-receipts-queue-receipt-waiting-4-gen"
Expand Down Expand Up @@ -199,6 +200,7 @@ pagopa-receipt-pdf-datastore-helpdesk:
envConfig:
!!merge <<: *envConfig
WEBSITE_SITE_NAME: 'pagopareceiptpdfdatastorehelpdesk'
SERVICE_NAME: "pagopa-receipt-pdf-datastore-helpdesk"
AzureWebJobs.BizEventToReceiptProcessor.Disabled: "true"
AzureWebJobs.CartReceiptToReviewed.Disabled: "false"
AzureWebJobs.ReceiptToReviewed.Disabled: "false"
Expand Down
2 changes: 2 additions & 0 deletions helm/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ microservice-chart: &microservice-chart
ENV: "prod"
TZ: "Europe/Rome"
WEBSITE_SITE_NAME: "pagopareceiptpdfdatastore" # required to show cloud role name in application insights
SERVICE_NAME: "pagopa-receipt-pdf-datastore"
ASPNETCORE_URLS: "http://*:8080"
FUNCTIONS_WORKER_RUNTIME: "java"
RECEIPT_QUEUE_TOPIC: "pagopa-p-weu-receipts-queue-receipt-waiting-4-gen"
Expand Down Expand Up @@ -214,6 +215,7 @@ pagopa-receipt-pdf-datastore-helpdesk:
envConfig:
!!merge <<: *envConfig
WEBSITE_SITE_NAME: 'pagopareceiptpdfdatastorehelpdesk'
SERVICE_NAME: "pagopa-receipt-pdf-datastore-helpdesk"
COSMOS_BIZ_EVENT_READ_REGION: "North Europe"
COSMOS_RECEIPT_READ_REGION: "North Europe"
AzureWebJobs.BizEventToReceiptProcessor.Disabled: "true"
Expand Down
2 changes: 2 additions & 0 deletions helm/values-uat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ microservice-chart: &microservice-chart
ENV: "uat"
TZ: "Europe/Rome"
WEBSITE_SITE_NAME: "pagopareceiptpdfdatastore" # required to show cloud role name in application insights
SERVICE_NAME: "pagopa-receipt-pdf-datastore"
ASPNETCORE_URLS: "http://*:8080"
FUNCTIONS_WORKER_RUNTIME: "java"
RECEIPT_QUEUE_TOPIC: "pagopa-u-weu-receipts-queue-receipt-waiting-4-gen"
Expand Down Expand Up @@ -199,6 +200,7 @@ pagopa-receipt-pdf-datastore-helpdesk:
envConfig:
!!merge <<: *envConfig
WEBSITE_SITE_NAME: 'pagopareceiptpdfdatastorehelpdesk'
SERVICE_NAME: "pagopa-receipt-pdf-datastore-helpdesk"
AzureWebJobs.BizEventToReceiptProcessor.Disabled: "true"
AzureWebJobs.CartReceiptToReviewed.Disabled: "false"
AzureWebJobs.ReceiptToReviewed.Disabled: "false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public synchronized AppInfo getInfo() {
name = properties.getProperty("name", null);
}
} catch (Exception e) {
logger.error("Impossible to retrieve information from pom.properties file.", e);
logger.warn("Impossible to retrieve information from pom.properties file.", e);
}
return AppInfo.builder().version(version).environment("azure-fn").name(name).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ public HttpResponseMessage run(
receiptError = cartReceiptCosmosService.getCartReceiptError(cartId);
} catch (NoSuchElementException | CartNotFoundException e) {
responseMsg = String.format("No cartReceiptError has been found with cartId %s", cartId);
logger.error("[{}] {}", context.getFunctionName(), responseMsg, e);
logger.warn("[{}] {}", context.getFunctionName(), responseMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, responseMsg);
}

if (!ReceiptErrorStatusType.TO_REVIEW.equals(receiptError.getStatus())) {
responseMsg = String.format("Found cartReceiptError with invalid status %s for cartId %s", receiptError.getStatus(), cartId);
logger.warn("[{}] {}", context.getFunctionName(), responseMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, responseMsg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ public HttpResponseMessage run(
receiptError = receiptCosmosService.getReceiptError(eventId);
} catch (NoSuchElementException | ReceiptNotFoundException e) {
responseMsg = String.format("No receiptError has been found with bizEventId %s", eventId);
logger.error("[{}] {}", context.getFunctionName(), responseMsg, e);
logger.warn("[{}] {}", context.getFunctionName(), responseMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, responseMsg);
}

if (!ReceiptErrorStatusType.TO_REVIEW.equals(receiptError.getStatus())) {
responseMsg = String.format("Found receiptError with invalid status %s for bizEventId %s", receiptError.getStatus(), eventId);
logger.warn("[{}] {}", context.getFunctionName(), responseMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, responseMsg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public HttpResponseMessage run(
existingCart = this.cartReceiptCosmosService.getCart(cartId);
} catch (CartNotFoundException e) {
String errMsg = "Cart receipt not found with the provided cart id";
logger.error(errMsg, e);
logger.warn(errMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, errMsg);
}

Expand All @@ -118,18 +118,18 @@ public HttpResponseMessage run(
"statuses (WAITING_FOR_BIZ_EVENT, INSERTED, NOT_QUEUE_SENT, FAILED).",
existingCart.getStatus()
);
logger.error(errMsg);
logger.warn(errMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, errMsg);
}

CartForReceipt cart;
try {
cart = this.helpdeskService.recoverFailedCart(existingCart);
} catch (BizEventUnprocessableEntityException e) {
logger.error(e.getMessage(), e);
logger.warn(e.getMessage(), e);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (BizEventBadRequestException e) {
logger.error(e.getMessage(), e);
logger.warn(e.getMessage(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
} catch (PDVTokenizerException | JsonProcessingException e) {
logger.error(e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ public HttpResponseMessage run(
try {
status = validateCartStatusParam(statusParam);
} catch (InvalidParameterException e) {
logger.warn("[{}]", context.getFunctionName(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
}

if (status == null || status.isNotAFailedDatastoreStatus()) {
String message = String.format("The provided status %s is not among the processable" +
"statuses (WAITING_FOR_BIZ_EVENT, INSERTED, NOT_QUEUE_SENT, FAILED).", status);
logger.warn("[{}] {}", context.getFunctionName(), message);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, message);
}

Expand All @@ -101,6 +103,7 @@ public HttpResponseMessage run(
documentdb.setValue(recoverResult.getFailedCartList());

String msg = String.format("Recovered %s receipts but %s encountered an error.", successCounter, errorCounter);
logger.error("[{}] {}", context.getFunctionName(), msg);
return request
.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ProblemJson.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public HttpResponseMessage run(
existingReceipt = this.receiptCosmosService.getReceipt(eventId);
} catch (ReceiptNotFoundException e) {
String errMsg = "Receipt not found with the provided event id";
logger.error(errMsg, e);
logger.warn(errMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, errMsg);
}

Expand All @@ -114,18 +114,18 @@ public HttpResponseMessage run(
"statuses (INSERTED, NOT_QUEUE_SENT, FAILED).",
existingReceipt.getStatus()
);
logger.error(errMsg);
logger.warn(errMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, errMsg);
}

Receipt receipt;
try {
receipt = this.helpdeskService.recoverFailedReceipt(existingReceipt);
} catch (BizEventUnprocessableEntityException e) {
logger.error(e.getMessage(), e);
logger.warn(e.getMessage(), e);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, e.getMessage());
} catch (BizEventBadRequestException | BizEventNotFoundException e) {
logger.error(e.getMessage(), e);
logger.warn(e.getMessage(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,14 @@ public HttpResponseMessage run(
try {
status = validateReceiptStatusParam(statusParam);
} catch (InvalidParameterException e) {
logger.warn("[{}]", context.getFunctionName(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
}

if (status == null || status.isNotAFailedDatastoreStatus()) {
String message = String.format("The provided status %s is not among the processable" +
"statuses (INSERTED, NOT_QUEUE_SENT, FAILED).", status);
logger.warn("[{}] {}", context.getFunctionName(), message);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, message);
}

Expand All @@ -100,6 +102,7 @@ public HttpResponseMessage run(
documentdb.setValue(recoverResult.getFailedReceiptList());

String msg = String.format("Recovered %s receipts but %s encountered an error.", successCounter, errorCounter);
logger.error("[{}] {}", context.getFunctionName(), msg);
return request
.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ProblemJson.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ public HttpResponseMessage run(
cart = this.cartReceiptCosmosService.getCart(cartId);
} catch (CartNotFoundException e) {
String errMsg = String.format("Unable to retrieve the cart receipt with id %s", cartId);
logger.error("[{}] {}", context.getFunctionName(), errMsg, e);
logger.warn("[{}] {}", context.getFunctionName(), errMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, errMsg);
}

if (cart.getStatus() == null || cart.getStatus().isNotANotificationFailedStatus()) {
String errMsg = String.format("The requested cart receipt with id %s is not in the expected status",
cart.getEventId());
logger.error(errMsg);
logger.warn(errMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, errMsg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,14 @@ public HttpResponseMessage run(
try {
status = validateCartStatusParam(statusParam);
} catch (InvalidParameterException e) {
logger.warn("[{}]", context.getFunctionName(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
}

if (status == null || status.isNotANotificationFailedStatus()) {
String message = String.format("The provided status %s is not among the processable" +
"statuses (GENERATED, IO_ERROR_TO_NOTIFY).", status);
logger.warn("[{}] {}", context.getFunctionName(), message);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ public HttpResponseMessage run(
receipt = this.receiptCosmosService.getReceipt(eventId);
} catch (ReceiptNotFoundException e) {
String errMsg = String.format("Unable to retrieve the receipt with eventId %s", eventId);
logger.error("[{}] {}", context.getFunctionName(), errMsg, e);
logger.warn("[{}] {}", context.getFunctionName(), errMsg, e);
return buildErrorResponse(request, HttpStatus.NOT_FOUND, errMsg);
}

if (receipt.getStatus() == null || receipt.getStatus().isNotANotificationFailedStatus()) {
String errMsg = String.format("The requested receipt with eventId %s is not in the expected status",
receipt.getEventId());
logger.error(errMsg);
logger.warn(errMsg);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, errMsg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,14 @@ public HttpResponseMessage run(
try {
status = validateReceiptStatusParam(statusParam);
} catch (InvalidParameterException e) {
logger.warn("[{}]", context.getFunctionName(), e);
return buildErrorResponse(request, HttpStatus.BAD_REQUEST, e.getMessage());
}

if (status == null || status.isNotANotificationFailedStatus()) {
String message = String.format("The provided status %s is not among the processable" +
"statuses (GENERATED, IO_ERROR_TO_NOTIFY).", status);
logger.warn("[{}] {}", context.getFunctionName(), message);
return buildErrorResponse(request, HttpStatus.UNPROCESSABLE_ENTITY, message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private List<CartForReceipt> recover(CartStatusType status) {
int errorCounter = recoverResult.getErrorCounter();

if (errorCounter > 0) {
logger.error("Recovered {} cart receipts but {} encountered an error.", successCounter, errorCounter);
logger.warn("Recovered {} cart receipts but {} encountered an error.", successCounter, errorCounter);
return recoverResult.getFailedCartList();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private List<Receipt> recover(ReceiptStatusType status) {
int errorCounter = recoverResult.getErrorCounter();

if (errorCounter > 0) {
logger.error("Recovered {} cart receipts but {} encountered an error.", successCounter, errorCounter);
logger.warn("Recovered {} cart receipts but {} encountered an error.", successCounter, errorCounter);
return recoverResult.getFailedReceiptList();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void handleSendMessageToQueue(List<BizEvent> bizEventList, Receipt receip
statusCode = sendMessageResult.getStatusCode();
} catch (Exception e) {
statusCode = ReasonErrorCode.ERROR_QUEUE.getCode();
logger.error("Sending BizEvent with id {} to queue failed", bizEventList.get(0).getId(), e);
logger.warn("Sending BizEvent with id {} to queue failed", bizEventList.get(0).getId(), e);
}

if (statusCode != HttpStatus.CREATED.value()) {
Expand All @@ -114,7 +114,7 @@ public void handleSendCartMessageToQueue(List<BizEvent> bizEventList, CartForRec
statusCode = sendMessageResult.getStatusCode();
} catch (Exception e) {
statusCode = ReasonErrorCode.ERROR_QUEUE.getCode();
logger.error("Failed to enqueue cart with id {}", cartForReceipt.getEventId(), e);
logger.warn("Failed to enqueue cart with id {}", cartForReceipt.getEventId(), e);
}

if (statusCode != HttpStatus.CREATED.value()) {
Expand Down Expand Up @@ -164,7 +164,7 @@ public void handleSaveReceipt(Receipt receipt) {
statusCode = response.getStatusCode();
} catch (Exception e) {
statusCode = ReasonErrorCode.ERROR_COSMOS.getCode();
logger.error("Save receipt with eventId {} on cosmos failed", receipt.getEventId(), e);
logger.warn("Save receipt with eventId {} on cosmos failed", receipt.getEventId(), e);
}

if (statusCode != HttpStatus.CREATED.value()) {
Expand Down Expand Up @@ -323,7 +323,7 @@ public CartForReceipt saveCartForReceipt(CartForReceipt cartForReceipt, BizEvent
cartForReceipt = buildCartForReceipt(bizEvent);

if (!isCartStatusValid(cartForReceipt)) {
logger.error("Cart build after fetch failed");
logger.warn("Cart build after fetch failed");
return cartForReceipt;
}
statusCode = trySaveCart(cartForReceipt);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public HelpdeskServiceImpl(
@Override
public Receipt recoverFailedReceipt(Receipt existingReceipt)
throws BizEventUnprocessableEntityException, BizEventBadRequestException, BizEventNotFoundException {
// retrieve biz-event with the specified cartId

BizEvent bizEvent = this.bizEventCosmosClient.getBizEventDocument(existingReceipt.getEventId());
validateBizEvent(bizEvent, 1);

Expand Down Expand Up @@ -149,7 +151,7 @@ public MassiveRecoverResult massiveRecoverFailedReceipt(ReceiptStatusType status
errorCounter++;
}
} catch (Exception e) {
logger.error("Recover for receipt {} failed", receipt.getEventId(), e);
logger.warn("Recover for receipt {} failed", receipt.getEventId(), e);
errorCounter++;
}
}
Expand Down Expand Up @@ -186,7 +188,7 @@ public MassiveCartRecoverResult massiveRecoverFailedCart(CartStatusType status)
errorCounter++;
}
} catch (Exception e) {
logger.error("Recover for cart {} failed", cart.getEventId(), e);
logger.warn("Recover for cart {} failed", cart.getEventId(), e);
errorCounter++;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<then>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="co.elastic.logging.logback.EcsEncoder">
<serviceName>${name}</serviceName>
<serviceName>${SERVICE_NAME}</serviceName>
<serviceVersion>${version}</serviceVersion>
<serviceEnvironment>${ENV}</serviceEnvironment>
</encoder>
Expand Down
Loading