diff --git a/src/main/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumer.java b/src/main/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumer.java index ed8300a..bf10e91 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumer.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumer.java @@ -83,7 +83,7 @@ && isValidSenderId(campaign.getSenderId()) && StringUtils.hasText(campaign.getDescriptionScope()) && Objects.nonNull(campaign.getStartDate()) && Objects.nonNull(campaign.getEndDate()) - && Objects.nonNull(campaign.getClosed()) + && Objects.nonNull(campaign.getStatus()) && StringUtils.hasText(campaign.getServiceId()) && hasValidWorkflow(campaign.getWorkflow()); } diff --git a/src/main/java/it/pagopa/pn/workflowmanager/exceptions/PnCampaignInvalidStatus.java b/src/main/java/it/pagopa/pn/workflowmanager/exceptions/PnCampaignInvalidStatus.java new file mode 100644 index 0000000..3774b93 --- /dev/null +++ b/src/main/java/it/pagopa/pn/workflowmanager/exceptions/PnCampaignInvalidStatus.java @@ -0,0 +1,12 @@ +package it.pagopa.pn.workflowmanager.exceptions; + +import it.pagopa.pn.commons.exceptions.PnInternalException; +import it.pagopa.pn.workflowmanager.models.internal.campaign.CampaignStatus; + +import static it.pagopa.pn.workflowmanager.exceptions.WorkflowManagerExceptionCodes.ERROR_CODE_WORKFLOWMANAGER_INVALID_CAMPAIGN_STATUS; + +public class PnCampaignInvalidStatus extends PnInternalException { + public PnCampaignInvalidStatus(String campaignId, CampaignStatus status) { + super(String.format("Campaign %s has %s status", campaignId, status), ERROR_CODE_WORKFLOWMANAGER_INVALID_CAMPAIGN_STATUS); + } +} 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 ca86f3a..7143043 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/exceptions/WorkflowManagerExceptionCodes.java @@ -17,6 +17,8 @@ public class WorkflowManagerExceptionCodes extends PnExceptionsCodes { public static final String ERROR_CODE_WORKFLOWMANAGER_CONFIGURATION_NOT_FOUND = "PN_WORKFLOWMANAGER_CONFIGURATIONNOTFOUND"; public static final String ERROR_CODE_WORKFLOWMANAGER_ACTION_CONFLICT = "PN_WORKFLOWMANAGER_ERROR_CODE_ACTION_CONFLICT"; 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_INVALID_CAMPAIGN_STATUS = "PN_WORKFLOWMANAGER_ERROR_CODE_INVALID_CAMPAIGN_STATUS"; 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_UNKNOWN_EVENT_CODE = "PN_WORKFLOWMANAGER_UNKNOWNEVENTCODE"; diff --git a/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/Campaign.java b/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/Campaign.java index 314df00..b22096c 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/Campaign.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/Campaign.java @@ -19,7 +19,7 @@ public class Campaign { private String descriptionScope; private OffsetDateTime startDate; private OffsetDateTime endDate; - private Boolean closed; + private CampaignStatus status; private String senderContact; private String serviceId; private Boolean sensitiveContent; diff --git a/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/CampaignStatus.java b/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/CampaignStatus.java new file mode 100644 index 0000000..3222f29 --- /dev/null +++ b/src/main/java/it/pagopa/pn/workflowmanager/models/internal/campaign/CampaignStatus.java @@ -0,0 +1,8 @@ +package it.pagopa.pn.workflowmanager.models.internal.campaign; + +public enum CampaignStatus { + DRAFT, + IN_PROGRESS, + CANCELED, + CONCLUDED +} diff --git a/src/main/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImpl.java b/src/main/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImpl.java index 3eee79e..2c9e823 100644 --- a/src/main/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImpl.java +++ b/src/main/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImpl.java @@ -1,7 +1,9 @@ package it.pagopa.pn.workflowmanager.service.impl; import it.pagopa.pn.workflowmanager.config.CampaignsParameterConsumer; +import it.pagopa.pn.workflowmanager.exceptions.PnCampaignInvalidStatus; import it.pagopa.pn.workflowmanager.models.internal.campaign.Campaign; +import it.pagopa.pn.workflowmanager.models.internal.campaign.CampaignStatus; import it.pagopa.pn.workflowmanager.service.CampaignService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -15,6 +17,10 @@ public class CampaignServiceImpl implements CampaignService { @Override public Campaign getCampaignByCampaignIdAndSenderId(String campaignId, String senderId) { - return campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(campaignId, senderId); + Campaign campaign = campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(campaignId, senderId); + if (!CampaignStatus.IN_PROGRESS.equals(campaign.getStatus())) { + throw new PnCampaignInvalidStatus(campaignId, campaign.getStatus()); + } + return campaign; } } diff --git a/src/test/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumerTest.java b/src/test/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumerTest.java index 063594e..c6b498e 100644 --- a/src/test/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumerTest.java +++ b/src/test/java/it/pagopa/pn/workflowmanager/config/CampaignsParameterConsumerTest.java @@ -4,10 +4,7 @@ import it.pagopa.pn.commons.exceptions.PnInternalException; import it.pagopa.pn.workflowmanager.dto.ext.delivery.notification.RecipientTypeInt; import it.pagopa.pn.workflowmanager.exceptions.PnCampaignNotFoundException; -import it.pagopa.pn.workflowmanager.models.internal.campaign.Campaign; -import it.pagopa.pn.workflowmanager.models.internal.campaign.ChannelType; -import it.pagopa.pn.workflowmanager.models.internal.campaign.DesiredFeedbackType; -import it.pagopa.pn.workflowmanager.models.internal.campaign.WorkFlowEntity; +import it.pagopa.pn.workflowmanager.models.internal.campaign.*; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -48,7 +45,7 @@ void initialize_unexpectedInternalExceptionIsPropagated() { @Test void getCampaignByCampaignIdAndSenderId_success() { - Campaign campaign = validCampaign("c1", SENDER_A); + Campaign campaign = validCampaign("c1", SENDER_A, CampaignStatus.IN_PROGRESS); Mockito.when(parameterConsumer.getParameterValue(Mockito.anyString(), Mockito.eq(Campaign[].class))) .thenReturn(Optional.of(new Campaign[]{campaign})); @@ -64,7 +61,7 @@ void getCampaignByCampaignIdAndSenderId_success() { @Test void getCampaignByCampaignIdAndSenderId_notFoundByCampaignId() { Campaign[] campaigns = new Campaign[]{ - validCampaign("c1", SENDER_A) + validCampaign("c1", SENDER_A, CampaignStatus.IN_PROGRESS) }; Mockito.when(parameterConsumer.getParameterValue(Mockito.anyString(), Mockito.eq(Campaign[].class))) @@ -78,7 +75,7 @@ void getCampaignByCampaignIdAndSenderId_notFoundByCampaignId() { @Test void getCampaignByCampaignIdAndSenderId_notFoundBySenderId() { Campaign[] campaigns = new Campaign[]{ - validCampaign("c1", SENDER_B) + validCampaign("c1", SENDER_B, CampaignStatus.IN_PROGRESS) }; Mockito.when(parameterConsumer.getParameterValue(Mockito.anyString(), Mockito.eq(Campaign[].class))) @@ -102,9 +99,9 @@ void getCampaignByCampaignIdAndSenderId_parameterNotFound() { @Test void getCampaignByCampaignIdAndSenderId_multipleCampaigns() { Campaign[] campaigns = new Campaign[]{ - validCampaign("c1", SENDER_A), - validCampaign("c2", SENDER_A), - validCampaign("c3", SENDER_A) + validCampaign("c1", SENDER_A, CampaignStatus.IN_PROGRESS), + validCampaign("c2", SENDER_A, CampaignStatus.IN_PROGRESS), + validCampaign("c3", SENDER_A, CampaignStatus.IN_PROGRESS) }; Mockito.when(parameterConsumer.getParameterValue(Mockito.anyString(), Mockito.eq(Campaign[].class))) @@ -117,14 +114,24 @@ void getCampaignByCampaignIdAndSenderId_multipleCampaigns() { Assertions.assertEquals("c2", result.getCampaignId()); } + @Test + void initialize_invalidCampaignStatus() { + Mockito.when(parameterConsumer.getParameterValue(Mockito.anyString(), Mockito.eq(Campaign[].class))) + .thenReturn(Optional.of(new Campaign[]{validCampaign("c1", SENDER_A, null)})); + + campaignsParameterConsumer.initialize(); + + Assertions.assertThrows(PnCampaignNotFoundException.class, + () -> campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId("c1", SENDER_A)); + } - private Campaign validCampaign(String campaignId, String senderId) { + private Campaign validCampaign(String campaignId, String senderId, CampaignStatus status) { return Campaign.builder() .campaignId(campaignId) .senderId(senderId) .title("Campaign " + campaignId) .descriptionScope("Description " + campaignId) - .closed(false) + .status(status) .startDate(OffsetDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC)) .endDate(OffsetDateTime.of(2025, 1, 31, 0, 0, 0, 0, ZoneOffset.UTC)) .serviceId("service-" + campaignId) diff --git a/src/test/java/it/pagopa/pn/workflowmanager/exception/PnWorkflowManagerExceptionCodesTest.java b/src/test/java/it/pagopa/pn/workflowmanager/exception/PnWorkflowManagerExceptionCodesTest.java index 266a7d2..f7ab446 100644 --- a/src/test/java/it/pagopa/pn/workflowmanager/exception/PnWorkflowManagerExceptionCodesTest.java +++ b/src/test/java/it/pagopa/pn/workflowmanager/exception/PnWorkflowManagerExceptionCodesTest.java @@ -11,7 +11,8 @@ void checkAll() { Assertions.assertAll( () -> Assertions.assertEquals("PN_TIMELINESERVICE_TIMELINEELEMENTNOTPRESENT", WorkflowManagerExceptionCodes.ERROR_CODE_TIMELINESERVICE_TIMELINE_ELEMENT_NOT_PRESENT), () -> Assertions.assertEquals("PN_DELIVERYPUSH_ACTIONTYPENOTSUPPORTED", WorkflowManagerExceptionCodes.ERROR_CODE_DELIVERYPUSH_ACTIONTYPENOTSUPPORTED), - () -> Assertions.assertEquals("PN_DELIVERY_CAMPAIGN_NOT_FOUND", WorkflowManagerExceptionCodes.ERROR_CODE_DELIVERY_CAMPAIGN_NOT_FOUND) + () -> Assertions.assertEquals("PN_DELIVERY_CAMPAIGN_NOT_FOUND", WorkflowManagerExceptionCodes.ERROR_CODE_DELIVERY_CAMPAIGN_NOT_FOUND), + () -> Assertions.assertEquals("PN_WORKFLOWMANAGER_ERROR_CODE_INVALID_CAMPAIGN_STATUS", WorkflowManagerExceptionCodes.ERROR_CODE_WORKFLOWMANAGER_INVALID_CAMPAIGN_STATUS) ); } diff --git a/src/test/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImplTest.java b/src/test/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImplTest.java index 340eaaf..7fc20c7 100644 --- a/src/test/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImplTest.java +++ b/src/test/java/it/pagopa/pn/workflowmanager/service/impl/CampaignServiceImplTest.java @@ -1,7 +1,10 @@ package it.pagopa.pn.workflowmanager.service.impl; +import it.pagopa.pn.commons.exceptions.PnInternalException; import it.pagopa.pn.workflowmanager.config.CampaignsParameterConsumer; import it.pagopa.pn.workflowmanager.models.internal.campaign.Campaign; +import it.pagopa.pn.workflowmanager.models.internal.campaign.CampaignStatus; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -66,20 +69,6 @@ void getCampaignByCampaignIdAndSenderId_shouldCallConsumerWithCorrectParameters( verify(campaignsParameterConsumer, times(1)).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); } - @Test - void getCampaignByCampaignIdAndSenderId_shouldReturnNull_whenCampaignDoesNotExist() { - // Arrange - when(campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID)) - .thenReturn(null); - - // Act - Campaign result = service.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); - - // Assert - assertNull(result); - verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); - } - @Test void getCampaignByCampaignIdAndSenderId_shouldHandleDifferentCampaignIds() { // Arrange @@ -137,7 +126,7 @@ void getCampaignByCampaignIdAndSenderId_shouldReturnCampaignWithAllFields() { assertEquals(TEST_SERVICE_ID, result.getServiceId()); assertNotNull(result.getStartDate()); assertNotNull(result.getEndDate()); - assertNotNull(result.getClosed()); + assertNotNull(result.getStatus()); assertNotNull(result.getSensitiveContent()); assertNotNull(result.getStopOnViewed()); verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); @@ -158,50 +147,6 @@ void getCampaignByCampaignIdAndSenderId_shouldThrowException_whenConsumerThrowsE verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); } - @Test - void getCampaignByCampaignIdAndSenderId_shouldHandleNullCampaignId() { - // Arrange - when(campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(null, TEST_SENDER_ID)) - .thenReturn(null); - - // Act - Campaign result = service.getCampaignByCampaignIdAndSenderId(null, TEST_SENDER_ID); - - // Assert - assertNull(result); - verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(null, TEST_SENDER_ID); - } - - @Test - void getCampaignByCampaignIdAndSenderId_shouldHandleNullSenderId() { - // Arrange - when(campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, null)) - .thenReturn(null); - - // Act - Campaign result = service.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, null); - - // Assert - assertNull(result); - verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, null); - } - - @Test - void getCampaignByCampaignIdAndSenderId_shouldHandleEmptyStrings() { - // Arrange - String emptyCampaignId = ""; - String emptySenderId = ""; - when(campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(emptyCampaignId, emptySenderId)) - .thenReturn(null); - - // Act - Campaign result = service.getCampaignByCampaignIdAndSenderId(emptyCampaignId, emptySenderId); - - // Assert - assertNull(result); - verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(emptyCampaignId, emptySenderId); - } - @Test void getCampaignByCampaignIdAndSenderId_shouldReturnSameCampaignObjectFromConsumer() { // Arrange @@ -232,6 +177,21 @@ void getCampaignByCampaignIdAndSenderId_shouldDelegateDirectlyToConsumer() { verifyNoMoreInteractions(campaignsParameterConsumer); } + @Test + void getCampaignByCampaignIdAndSenderId_shouldThrowException_whenCampaignStatusIsNotInProgress() { + + Campaign campaign = createMockCampaign(); + campaign.setStatus(CampaignStatus.DRAFT); + when(campaignsParameterConsumer.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID)) + .thenReturn(campaign); + + PnInternalException thrownException = assertThrows(PnInternalException.class, + () -> service.getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID)); + Assertions.assertNotNull(thrownException.getProblem().getDetail()); + assertTrue(thrownException.getProblem().getDetail().contains("Campaign CAMPAIGN-001 has DRAFT status")); + verify(campaignsParameterConsumer).getCampaignByCampaignIdAndSenderId(TEST_CAMPAIGN_ID, TEST_SENDER_ID); + } + private Campaign createMockCampaign() { return Campaign.builder() .campaignId(TEST_CAMPAIGN_ID) @@ -239,6 +199,7 @@ private Campaign createMockCampaign() { .title(TEST_TITLE) .descriptionScope(TEST_DESCRIPTION) .serviceId(TEST_SERVICE_ID) + .status(CampaignStatus.IN_PROGRESS) .build(); } @@ -251,7 +212,7 @@ private Campaign createCompletelyPopulatedCampaign() { .serviceId(TEST_SERVICE_ID) .startDate(OffsetDateTime.now()) .endDate(OffsetDateTime.now().plusDays(30)) - .closed(false) + .status(CampaignStatus.IN_PROGRESS) .senderContact("contact@example.com") .sensitiveContent(false) .stopOnViewed(true)