From 76c5875dfc58f086808f7d24676a161490d886eb Mon Sep 17 00:00:00 2001 From: DacunzoMa Date: Mon, 6 Jul 2026 10:06:03 +0200 Subject: [PATCH] PN-20529 feat: add call to sendCourtesyShortMessage in external channels client --- .../WorkflowManagerExceptionCodes.java | 1 + .../PnExternalChannelsClient.java | 7 +++ .../PnExternalChannelsClientImpl.java | 33 +++++++++++++ .../PnExternalChannelsClientImplTest.java | 47 +++++++++++++++++++ 4 files changed, 88 insertions(+) diff --git a/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java b/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java index db22980..3d93bce 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java @@ -19,5 +19,6 @@ public class WorkflowManagerExceptionCodes extends PnExceptionsCodes { public static final String ERROR_CODE_WORKFLOWMANAGER_ROUTER_EVENT_TYPE_NOT_SUPPORTED = "PN_WORKFLOWMANAGER_ROUTER_EVENT_TYPE_NOT_SUPPORTED"; public static final String ERROR_CODE_WORKFLOWMANAGER_GENERIC_WORKFLOW_ERROR = "PN_WORKFLOWMANAGER_GENERICWORKFLOWERROR"; public static final String ERROR_CODE_WORKFLOWMANAGER_SEND_ON_CHANNEL_ERROR = "PN_WORKFLOWMANAGER_SENDONCHANNELERROR"; + public static final String ERROR_CODE_WORKFLOWMANAGER_SENDSMSNOTIFICATIONFAILED = "PN_WORKFLOWMANAGER_SENDSMSNOTIFICATIONFAILED"; } diff --git a/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClient.java b/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClient.java index 4d9d1d2..54ef523 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClient.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClient.java @@ -12,6 +12,7 @@ public interface PnExternalChannelsClient { String LEGAL_NOTIFICATION_REQUEST = "LEGAL NOTIFICATION_REQUEST"; + String COURTESY_NOTIFICATION_REQUEST = "COURTESY NOTIFICATION_REQUEST"; void sendNotificationPEC( String requestId, String mailBody, @@ -20,4 +21,10 @@ void sendNotificationPEC( LegalDigitalAddressInt digitalAddress, List fileKeys ); + + void sendNotificationSMS( + String requestIdx, + String textMessage, + String senderDigitalAddress + ); } diff --git a/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImpl.java b/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImpl.java index 2f91608..f6c830f 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImpl.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImpl.java @@ -1,12 +1,15 @@ package it.pagopa.pn.workflowmanager.middleware.externalclient.pnclient.externalchannel; import it.pagopa.pn.commons.exceptions.PnInternalException; +import it.pagopa.pn.commons.utils.LogUtils; import it.pagopa.pn.workflowmanager.action.utils.FileUtils; import it.pagopa.pn.workflowmanager.config.PnWorkflowManagerConfigs; import it.pagopa.pn.workflowmanager.dto.address.LegalDigitalAddressInt; import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.NotificationInt; import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.NotificationRecipientInt; +import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.api.DigitalCourtesyMessagesApi; import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.api.DigitalLegalMessagesApi; +import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.model.DigitalCourtesySmsRequest; import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.model.DigitalNotificationRequest; import lombok.CustomLog; import lombok.RequiredArgsConstructor; @@ -16,6 +19,7 @@ import java.util.List; import static it.pagopa.pn.workflowmanager.exceptions.WorkflowManagerExceptionCodes.ERROR_CODE_WORKFLOWMANAGER_SENDPECNOTIFICATIONFAILED; +import static it.pagopa.pn.workflowmanager.exceptions.WorkflowManagerExceptionCodes.ERROR_CODE_WORKFLOWMANAGER_SENDSMSNOTIFICATIONFAILED; @Component @CustomLog @@ -24,6 +28,7 @@ public class PnExternalChannelsClientImpl implements PnExternalChannelsClient { private static final String EVENT_TYPE_INFORMAL = "INFORMAL"; private final PnWorkflowManagerConfigs cfg; private final DigitalLegalMessagesApi digitalLegalMessagesApi; + private final DigitalCourtesyMessagesApi digitalCourtesyMessagesApi; @Override public void sendNotificationPEC( @@ -59,4 +64,32 @@ public void sendNotificationPEC( throw new PnInternalException("error sending PEC notification", ERROR_CODE_WORKFLOWMANAGER_SENDPECNOTIFICATIONFAILED, e); } } + + @Override + public void sendNotificationSMS( + String requestIdx, + String textMessage, + String senderDigitalAddress + ) { + try { + log.logInvokingAsyncExternalService(CLIENT_NAME, COURTESY_NOTIFICATION_REQUEST + "[SMS]", requestIdx); + log.debug("[enter] sendNotificationSMS requestId={} senderDigitalAddress={}", requestIdx, LogUtils.maskNumber(senderDigitalAddress)); + + DigitalCourtesySmsRequest digitalNotificationRequest = new DigitalCourtesySmsRequest(); + digitalNotificationRequest.setChannel(DigitalCourtesySmsRequest.ChannelEnum.SMS); + digitalNotificationRequest.setRequestId(requestIdx); + digitalNotificationRequest.setCorrelationId(requestIdx); + digitalNotificationRequest.setEventType(EVENT_TYPE_INFORMAL); + digitalNotificationRequest.setQos(DigitalCourtesySmsRequest.QosEnum.BATCH); + digitalNotificationRequest.setReceiverDigitalAddress(senderDigitalAddress); + digitalNotificationRequest.setClientRequestTimeStamp(Instant.now()); + digitalNotificationRequest.setMessageText(textMessage); + + digitalCourtesyMessagesApi.sendCourtesyShortMessage(requestIdx, cfg.getCxId(), digitalNotificationRequest); + log.debug("[exit] sendNotificationSMS requestId={} senderDigitalAddress={}", requestIdx, LogUtils.maskNumber(senderDigitalAddress)); + } catch (Exception e) { + log.error("error sending SMS notification for requestIdx={}", requestIdx); + throw new PnInternalException("error sending SMS notification", ERROR_CODE_WORKFLOWMANAGER_SENDSMSNOTIFICATIONFAILED, e); + } + } } diff --git a/src/test/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImplTest.java b/src/test/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImplTest.java index 8b86e83..af891b9 100644 --- a/src/test/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImplTest.java +++ b/src/test/java/it/pagopa/pn/workflowmanager/middleware/externalclient/pnclient/externalchannel/PnExternalChannelsClientImplTest.java @@ -7,7 +7,9 @@ import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.NotificationInt; import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.NotificationMessageInt; import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.NotificationRecipientInt; +import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.api.DigitalCourtesyMessagesApi; import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.api.DigitalLegalMessagesApi; +import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.model.DigitalCourtesySmsRequest; import it.pagopa.pn.workflowmanager.generated.openapi.msclient.externalchannels.model.DigitalNotificationRequest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,6 +31,9 @@ class PnExternalChannelsClientImplTest { @Mock private DigitalLegalMessagesApi digitalLegalMessagesApi; + @Mock + private DigitalCourtesyMessagesApi digitalCourtesyMessagesApi; + @InjectMocks private PnExternalChannelsClientImpl client; @@ -167,4 +172,46 @@ void wrapsAndRethrowsWhenFileKeysIsNull() { () -> client.sendNotificationPEC("request-id", "body", notification, recipient, digitalAddress, null) ); } + + @Test + void sendsSmsNotificationWithExpectedPayload() { + String requestIdx = "request-idx"; + String cxId = "cx-id"; + String textMessage = "Hello SMS"; + String senderDigitalAddress = "+39123456789"; + + when(cfg.getCxId()).thenReturn(cxId); + + client.sendNotificationSMS(requestIdx, textMessage, senderDigitalAddress); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(DigitalCourtesySmsRequest.class); + verify(digitalCourtesyMessagesApi).sendCourtesyShortMessage(eq(requestIdx), eq(cxId), requestCaptor.capture()); + + DigitalCourtesySmsRequest sent = requestCaptor.getValue(); + assertEquals(DigitalCourtesySmsRequest.ChannelEnum.SMS, sent.getChannel()); + assertEquals(requestIdx, sent.getRequestId()); + assertEquals(requestIdx, sent.getCorrelationId()); + assertEquals("INFORMAL", sent.getEventType()); + assertEquals(DigitalCourtesySmsRequest.QosEnum.BATCH, sent.getQos()); + assertEquals(senderDigitalAddress, sent.getReceiverDigitalAddress()); + assertEquals(textMessage, sent.getMessageText()); + assertNotNull(sent.getClientRequestTimeStamp()); + } + + @Test + void wrapsAndRethrowsWhenSmsApiFails() { + String requestIdx = "request-idx"; + RuntimeException apiException = new RuntimeException("boom"); + + when(cfg.getCxId()).thenReturn("cx-id"); + doThrow(apiException).when(digitalCourtesyMessagesApi) + .sendCourtesyShortMessage(anyString(), anyString(), any(DigitalCourtesySmsRequest.class)); + + PnInternalException thrown = assertThrows( + PnInternalException.class, + () -> client.sendNotificationSMS(requestIdx, "text", "+39123456789") + ); + + assertSame(apiException, thrown.getCause()); + } } \ No newline at end of file