@@ -1,9 +1,9 @@
package uk.gov.pay.connector.resources;

import com.google.common.base.Splitter;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.persist.Transactional;
@@ -16,6 +16,7 @@
import uk.gov.pay.connector.exception.CredentialsException;
import uk.gov.pay.connector.model.GatewayAccountRequest;
import uk.gov.pay.connector.model.domain.CardTypeEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationEntity;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;
import uk.gov.pay.connector.model.domain.GatewayAccountResourceDTO;
import uk.gov.pay.connector.model.domain.UuidAbstractEntity;
@@ -30,8 +31,8 @@
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@@ -41,7 +42,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@@ -129,7 +129,7 @@ private Response getGatewayAccounts(
try{
accountIds = COMMA_SEPARATOR.splitToList(accountIdsArg)
.stream()
.map(accountIdStr -> Long.parseLong(accountIdStr))
.map(Long::parseLong)
.collect(Collectors.toList());
} catch (NumberFormatException e) {
return badRequestResponse(format("Could not parse accountIds %s as Longs.", accountIdsArg));
@@ -230,6 +230,7 @@ public Response createNewGatewayAccount(JsonNode node, @Context UriInfo uriInfo)

logger.info("Creating new gateway account using the {} provider pointing to {}", provider, accountType);
GatewayAccountEntity entity = new GatewayAccountEntity(provider, newHashMap(), type);

logger.info("Setting the new account to accept all card types by default", provider, accountType);
entity.setCardTypes(cardTypeDao.findAllNon3ds());
if (node.has(SERVICE_NAME_FIELD_NAME)) {
@@ -10,6 +10,7 @@
import uk.gov.pay.connector.app.ConnectorConfiguration;
import uk.gov.pay.connector.model.domain.ChargeEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;
import uk.gov.pay.connector.service.notify.NotifyClientFactory;
import uk.gov.pay.connector.service.notify.NotifyClientFactoryProvider;
@@ -54,7 +55,11 @@ public UserNotificationService(NotifyClientFactoryProvider notifyClientFactoryPr
}

public Future<Optional<String>> notifyPaymentSuccessEmail(ChargeEntity chargeEntity) {
if (emailNotifyGloballyEnabled && chargeEntity.getGatewayAccount().hasEmailNotificationsEnabled()) {
Boolean isConfirmationEmailEnabled = chargeEntity.getGatewayAccount().
getEmailNotifications()
.get(EmailNotificationType.CONFIRMATION)
.isEnabled();
if (emailNotifyGloballyEnabled && isConfirmationEmailEnabled) {
String emailAddress = chargeEntity.getEmail();
Stopwatch responseTimeStopwatch = Stopwatch.createStarted();
return executorService.submit(() -> {
@@ -106,7 +111,7 @@ private void readEmailConfig(ConnectorConfiguration configuration) {
private HashMap<String, String> buildEmailPersonalisationFromCharge(ChargeEntity charge) {
GatewayAccountEntity gatewayAccount = charge.getGatewayAccount();
EmailNotificationEntity emailNotification = gatewayAccount
.getEmailNotification();
.getEmailNotifications().get(EmailNotificationType.CONFIRMATION);

String customParagraph = emailNotification != null ? emailNotification.getTemplateBody() : "";
HashMap<String, String> map = new HashMap<>();
@@ -1444,13 +1444,34 @@

<changeSet id="add type column to email notifications table" author="">
<addColumn tableName="email_notifications">
<column name="type" type="boolean" />
<column name="type" type="VARCHAR(36)" >
<constraints nullable="true" unique="false"/>
</column>
</addColumn>
</changeSet>

<changeSet id="backfill existing notifications with CONFIRMATION value" author="">
<sql>
UPDATE email_notifications SET type = 'CONFIRMATION';
</sql>
</changeSet>

<changeSet id="add email_collection_mode column to gateway accounts table" author="">
<addColumn tableName="gateway_accounts">
<column name="email_collection_mode" type="VARCHAR(36)" />
<column name="email_collection_mode" type="VARCHAR(36)">
<constraints nullable="true" unique="false"/>
</column>
</addColumn>
</changeSet>

<changeSet id="add default value to email_collection_mode in gateway accounts table" author="">
<addDefaultValue tableName="gateway_accounts" columnName="email_collection_mode" defaultValue="MANDATORY"/>
</changeSet>

<changeSet id="backfill existing gateway accounts with MANDATORY default value" author="">
<sql>
UPDATE gateway_accounts SET email_collection_mode = 'MANDATORY';
</sql>
</changeSet>

</databaseChangeLog>
@@ -1,10 +1,13 @@
package uk.gov.pay.connector.it.dao;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.RandomUtils;
import uk.gov.pay.commons.model.SupportedLanguage;
import uk.gov.pay.connector.model.ServicePaymentReference;
import uk.gov.pay.connector.model.domain.CardTypeEntity.Type;
import uk.gov.pay.connector.model.domain.ChargeStatus;
import uk.gov.pay.connector.model.domain.EmailCollectionMode;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;
import uk.gov.pay.connector.model.domain.RefundStatus;
import uk.gov.pay.connector.util.DatabaseTestHelper;
@@ -285,6 +288,12 @@ public class TestAccount {
private String serviceName = "service_name";
private String description = "a description";
private String analyticsId = "an analytics id";
private EmailCollectionMode emailCollectionMode = EmailCollectionMode.OPTIONAL;
private Map<EmailNotificationType, TestEmailNotification> emailNotifications =
ImmutableMap.of(
EmailNotificationType.CONFIRMATION, new TestEmailNotification().withEnabled(true),
EmailNotificationType.REFUND, new TestEmailNotification().withEnabled(false)
);
private GatewayAccountEntity.Type type = TEST;
private List<TestCardType> cardTypes = new ArrayList<>();

@@ -313,6 +322,14 @@ public String getAnalyticsId() {
return analyticsId;
}

public EmailCollectionMode getEmailCollectionMode() {
return emailCollectionMode;
}

public Map<EmailNotificationType, TestEmailNotification> getEmailNotifications() {
return emailNotifications;
}

public TestAccount withAccountId(long accountId) {
this.accountId = accountId;
return this;
@@ -355,6 +372,8 @@ public TestAccount insert() {
for (TestCardType cardType : cardTypes) {
databaseTestHelper.addAcceptedCardType(this.getAccountId(), cardType.getId());
}
emailNotifications.forEach((type, notification) -> databaseTestHelper.addEmailNotification(this.getAccountId(), notification.getTemplate(), notification.isEnabled(), type));

return this;
}
}
@@ -435,17 +454,17 @@ public TestCharge withDescription(String description) {
this.description = description;
return this;
}

public TestCharge withLanguage(SupportedLanguage language) {
this.language = language;
return this;
}

public TestCharge withDelayedCapture(boolean delayedCapture) {
this.delayedCapture = delayedCapture;
return this;
}

public TestCharge insert() {
if (testAccount == null)
throw new IllegalStateException("Test Account must be provided.");
@@ -498,11 +517,11 @@ public ZonedDateTime getCreatedDate() {
public String getDescription() {
return description;
}

public SupportedLanguage getLanguage() {
return language;
}

public boolean isDelayedCapture() {
return delayedCapture;
}
@@ -623,12 +642,26 @@ public class TestEmailNotification {

TestAccount testAccount;
String template = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
boolean enabled = true;

public String getTemplate() {
return template;
}

public boolean isEnabled() {
return enabled;
}

public TestEmailNotification withTestAccount(TestAccount testAccount) {
this.testAccount = testAccount;
return this;
}

public TestEmailNotification withEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}

public TestEmailNotification insert() {
if (testAccount == null)
throw new IllegalStateException("Test Account must be provided.");
@@ -4,9 +4,9 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import uk.gov.pay.connector.dao.ChargeDao;
import uk.gov.pay.connector.dao.EmailNotificationsDao;
import uk.gov.pay.connector.model.domain.EmailNotificationEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationType;

import java.util.Optional;

@@ -19,15 +19,13 @@ public class EmailNotificationsDaoITest extends DaoITestBase {
@Rule
public ExpectedException expectedException = ExpectedException.none();
private EmailNotificationsDao emailNotificationsDao;
private ChargeDao chargeDao;

private DatabaseFixtures.TestAccount defaultTestAccount;
private DatabaseFixtures.TestEmailNotification defaultEmailNotification;

@Before
public void setUp() throws Exception {
public void setUp() {
emailNotificationsDao = env.getInstance(EmailNotificationsDao.class);
chargeDao = env.getInstance(ChargeDao.class);

this.defaultTestAccount = DatabaseFixtures
.withDatabaseTestHelper(databaseTestHelper)
@@ -45,7 +43,7 @@ public void setUp() throws Exception {
public void findByAccountId_shouldFindEmailNotification() {

String template = "lorem ipsum";
databaseTestHelper.addEmailNotification(defaultEmailNotification.getTestAccount().getAccountId(), template, true);
databaseTestHelper.addEmailNotification(defaultEmailNotification.getTestAccount().getAccountId(), template, true, EmailNotificationType.CONFIRMATION);

Optional<EmailNotificationEntity> emailNotificationOptional = emailNotificationsDao.findByAccountId(defaultEmailNotification.getTestAccount().getAccountId());

@@ -6,6 +6,8 @@
import org.junit.Test;
import uk.gov.pay.connector.dao.GatewayAccountDao;
import uk.gov.pay.connector.model.domain.CardTypeEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;
import uk.gov.pay.connector.model.domain.GatewayAccountResourceDTO;
import uk.gov.pay.connector.model.domain.NotificationCredentials;
@@ -38,13 +40,13 @@ public class GatewayAccountDaoITest extends DaoITestBase {
private DatabaseFixtures databaseFixtures;

@Before
public void setUp() throws Exception {
public void setUp() {
gatewayAccountDao = env.getInstance(GatewayAccountDao.class);
databaseFixtures = DatabaseFixtures.withDatabaseTestHelper(databaseTestHelper);
}

@Test
public void persist_shouldCreateAnAccount() throws Exception {
public void persist_shouldCreateAnAccount() {
DatabaseFixtures.TestCardType mastercardCreditCardTypeRecord = createMastercardCreditCardTypeRecord();
DatabaseFixtures.TestCardType visaDebitCardTypeRecord = createVisaDebitCardTypeRecord();
createAccountRecord(mastercardCreditCardTypeRecord, visaDebitCardTypeRecord);
@@ -63,12 +65,13 @@ public void persist_shouldCreateAnAccount() throws Exception {
gatewayAccountDao.persist(account);

assertThat(account.getId(), is(notNullValue()));
assertThat(account.getEmailNotification(), is(notNullValue()));
assertThat(account.getEmailNotifications().isEmpty(), is(false));
assertThat(account.getDescription(), is(nullValue()));
assertThat(account.getAnalyticsId(), is(nullValue()));
assertThat(account.getEmailNotification().getAccountEntity().getId(), is(account.getId()));
assertThat(account.getEmailNotification().isEnabled(), is(true));
assertThat(account.getNotificationCredentials(), is(nullValue()));
EmailNotificationEntity confirmationEmail = account.getEmailNotifications().get(EmailNotificationType.CONFIRMATION);
assertThat(confirmationEmail.getAccountEntity().getId(), is(account.getId()));
assertThat(confirmationEmail.isEnabled(), is(true));

databaseTestHelper.getAccountCredentials(account.getId());

@@ -3,9 +3,11 @@
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import uk.gov.pay.connector.it.dao.DatabaseFixtures;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.resources.EmailNotificationResource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.jayway.restassured.http.ContentType.JSON;
@@ -26,7 +28,7 @@ public void updateEmailNotification_shouldUpdateSuccessfullyIfEmailNotificationA
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getEmailNotificationByAccountId(Long.valueOf(accountId));
Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.valueOf(accountId));
assertThat(emailNotification.get("template_body"), is(templateBody));
assertThat(emailNotification.get("enabled"), is(true));
}
@@ -44,7 +46,7 @@ public void updateEmailNotification_shouldUpdateSuccessfullyIfEmailNotificationD
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getEmailNotificationByAccountId(Long.valueOf(testAccount.getAccountId()));
Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.valueOf(testAccount.getAccountId()));
assertThat(emailNotification.get("template_body"), is(templateBody));
assertThat(emailNotification.get("enabled"), is(true));
}
@@ -61,7 +63,7 @@ public void updateEmailNotification_shouldTurnOnEmailNotificationsSuccessfullyIf
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getEmailNotificationByAccountId(Long.valueOf(testAccount.getAccountId()));
Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.valueOf(testAccount.getAccountId()));
assertThat(emailNotification.get("enabled"), is(true));
}

@@ -101,40 +103,126 @@ public void disableEmailNotification_shouldUpdateSuccessfully() {
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getEmailNotificationByAccountId(Long.parseLong(accountId));
Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.parseLong(accountId));
assertThat(emailNotification.get("enabled"), is(false));
}

// PP-4111 Old endpoint
@Test
public void enableEmailNotification_shouldUpdateSuccessfully() {
public void patchEnableNotification_shouldUpdateSuccessfully() {
String accountId = createAGatewayAccountFor("smartpay");
app.getDatabaseTestHelper().updateEmailNotification(Long.parseLong(accountId), "lorem ipsum", false);

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_ENABLED, true))
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_ENABLED, false))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification")
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getEmailNotificationByAccountId(Long.parseLong(accountId));
assertThat(emailNotification.get("enabled"), is(true));
Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.parseLong(accountId));
assertThat(emailNotification.get("enabled"), is(false));
}

@Test
public void patchEmailBody_shouldUpdateSuccessfully() {
String accountId = createAGatewayAccountFor("smartpay");
String newTemplateBody = "not anymore";

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_TEMPLATE_BODY, newTemplateBody))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification")
.then()
.statusCode(200);

Map<String, Object> emailNotification = app.getDatabaseTestHelper().getConfirmationEmailNotificationByAccountId(Long.parseLong(accountId));
assertThat(emailNotification.get("template_body"), is(newTemplateBody));
}

@Test
public void patchEnableNotification_shouldUpdateSuccessfullyRefundNotifications() {
String accountId = createAGatewayAccountFor("smartpay");

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_ENABLED, false))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification/refund")
.then()
.statusCode(200);

List<Map<String, Object>> emailNotifications = app.getDatabaseTestHelper().getEmailNotificationsByAccountId(Long.parseLong(accountId));
Map<String, Object> confirmationEmail = emailNotifications.get(0);
assertThat(confirmationEmail.get("enabled"), is(true));
Map<String, Object> refundEmail = emailNotifications.get(1);
assertThat(refundEmail.get("enabled"), is(false));
}

@Test
public void patchEnableNotification_shouldUpdateSuccessfullyConfirmationNotifications() {
String accountId = createAGatewayAccountFor("smartpay");

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_ENABLED, false))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification/confirmation")
.then()
.statusCode(200);

List<Map<String, Object>> emailNotifications = app.getDatabaseTestHelper().getEmailNotificationsByAccountId(Long.parseLong(accountId));
Map<String, Object> confirmationEmail = emailNotifications.get(0);
assertThat(confirmationEmail.get("enabled"), is(false));
Map<String, Object> refundEmail = emailNotifications.get(1);
assertThat(refundEmail.get("enabled"), is(true));
}

@Test
public void patchTemplateBodyNotification_shouldUpdateSuccessfullyRefundNotifications() {
String accountId = createAGatewayAccountFor("smartpay");
String newTemplateBody = "new value";

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_TEMPLATE_BODY, newTemplateBody))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification/refund")
.then()
.statusCode(200);

List<Map<String, Object>> emailNotifications = app.getDatabaseTestHelper().getEmailNotificationsByAccountId(Long.parseLong(accountId));
Map<String, Object> confirmationEmail = emailNotifications.get(0);
assertThat(confirmationEmail.get("template_body"), is("lorem ipsum"));
Map<String, Object> refundEmail = emailNotifications.get(1);
assertThat(refundEmail.get("template_body"), is(newTemplateBody));
}

@Test
public void patchTemplateBodyNotification_shouldUpdateSuccessfullyConfirmationNotifications() {
String accountId = createAGatewayAccountFor("smartpay");
String newTemplateBody = "new value";

givenSetup().accept(JSON)
.body(getPatchRequestBody("replace", EmailNotificationResource.EMAIL_NOTIFICATION_TEMPLATE_BODY, false))
.patch(ACCOUNTS_API_URL + accountId + "/email-notification/confirmation")
.then()
.statusCode(200);

List<Map<String, Object>> emailNotifications = app.getDatabaseTestHelper().getEmailNotificationsByAccountId(Long.parseLong(accountId));
Map<String, Object> confirmationEmail = emailNotifications.get(0);
assertThat(confirmationEmail.get("template_body"), is(newTemplateBody));
Map<String, Object> refundEmail = emailNotifications.get(1);
assertThat(refundEmail.get("template_body"), is("lorem ipsum"));
}

@Test
public void getEmailNotificationSuccessfully() {
String templateBody = "lorem ipsum";
String accountId = createAGatewayAccountFor("worldpay");
app.getDatabaseTestHelper().updateEmailNotification(Long.parseLong(accountId), templateBody, true);
app.getDatabaseTestHelper().updateEmailNotification(Long.parseLong(accountId), templateBody, true, EmailNotificationType.CONFIRMATION);

givenSetup().accept(JSON)
givenSetup()
.accept(JSON)
.get(ACCOUNTS_API_URL + accountId + "/email-notification")
.then()
.statusCode(200)
.body("template_body", is(templateBody))
.body("enabled", is(true));
}

private String getPatchRequestBody(String operation, String path, boolean value) {
private String getPatchRequestBody(String operation, String path, Object value) {
return toJson(ImmutableMap.of("op",operation, "path", path, "value", value));
}
}
@@ -25,7 +25,7 @@ public class GatewayAccountResourceITest extends GatewayAccountResourceTestBase
private DatabaseFixtures.TestAccount defaultTestAccount;

@Test
public void getAccountShouldReturn404IfAccountIdIsUnknown() throws Exception {
public void getAccountShouldReturn404IfAccountIdIsUnknown() {
String unknownAccountId = "92348739";
givenSetup()
.get(ACCOUNTS_API_URL + unknownAccountId)
@@ -34,7 +34,7 @@ public void getAccountShouldReturn404IfAccountIdIsUnknown() throws Exception {
}

@Test
public void getAccountShouldNotReturnCredentials() throws Exception {
public void getAccountShouldNotReturnCredentials() {
String gatewayAccountId = createAGatewayAccountFor("worldpay");
givenSetup()
.get(ACCOUNTS_API_URL + gatewayAccountId)
@@ -44,7 +44,7 @@ public void getAccountShouldNotReturnCredentials() throws Exception {
}

@Test
public void getAccountShouldNotReturnCardTypes() throws Exception {
public void getAccountShouldNotReturnCardTypes() {
String gatewayAccountId = createAGatewayAccountFor("worldpay");
givenSetup()
.get(ACCOUNTS_API_URL + gatewayAccountId)
@@ -54,7 +54,7 @@ public void getAccountShouldNotReturnCardTypes() throws Exception {
}

@Test
public void getAccountShouldReturnDescriptionAndAnalyticsId() throws Exception {
public void getAccountShouldReturnDescriptionAndAnalyticsId() {
String gatewayAccountId = createAGatewayAccountFor("worldpay", "desc", "id");
givenSetup()
.get(ACCOUNTS_API_URL + gatewayAccountId)
@@ -65,7 +65,7 @@ public void getAccountShouldReturnDescriptionAndAnalyticsId() throws Exception {
}

@Test
public void getAccountShouldReturnAnalyticsId() throws Exception {
public void getAccountShouldReturnAnalyticsId() {
String gatewayAccountId = createAGatewayAccountFor("worldpay", null, "id");
givenSetup()
.get(ACCOUNTS_API_URL + gatewayAccountId)
@@ -76,7 +76,7 @@ public void getAccountShouldReturnAnalyticsId() throws Exception {
}

@Test
public void getAccountShouldReturnDescription() throws Exception {
public void getAccountShouldReturnDescription() {
String gatewayAccountId = createAGatewayAccountFor("worldpay", "desc", null);
givenSetup()
.get(ACCOUNTS_API_URL + gatewayAccountId)
@@ -102,6 +102,11 @@ public void shouldReturnAccountInformationForGetAccountById() {
.body("type", is(TEST.toString()))
.body("description", is("a description"))
.body("analytics_id", is("an analytics id"))
.body("email_collection_mode", is("MANDATORY"))
.body("email_notifications.CONFIRMATION.template_body", is("Lorem ipsum dolor sit amet, consectetur adipiscing elit."))
.body("email_notifications.CONFIRMATION.enabled", is(true))
.body("email_notifications.REFUND.template_body", is("Lorem ipsum dolor sit amet, consectetur adipiscing elit."))
.body("email_notifications.REFUND.enabled", is(false))
.body("service_name", is("service_name"));
}

@@ -177,7 +182,7 @@ public void shouldReturnEmptyCollectionOfAccountsWhenNoneFound() {
}

@Test
public void createGatewayAccountWithoutPaymentProviderDefaultsToSandbox() throws Exception {
public void createGatewayAccountWithoutPaymentProviderDefaultsToSandbox() {
String payload = toJson(ImmutableMap.of("name", "test account"));
ValidatableResponse response = givenSetup()
.body(payload)
@@ -254,7 +259,7 @@ public void createAccountShouldFailIfPaymentProviderIsNotRecognised() throws Exc
}

@Test
public void getAccountShouldReturn404IfAccountIdIsNotNumeric() throws Exception {
public void getAccountShouldReturn404IfAccountIdIsNotNumeric() {
String unknownAccountId = "92348739wsx673hdg";

givenSetup()
@@ -267,22 +272,22 @@ public void getAccountShouldReturn404IfAccountIdIsNotNumeric() throws Exception
}

@Test
public void createAGatewayAccountForSandbox() throws Exception {
public void createAGatewayAccountForSandbox() {
createAGatewayAccountFor("sandbox");
}

@Test
public void createAGatewayAccountForWorldpay() throws Exception {
public void createAGatewayAccountForWorldpay() {
createAGatewayAccountFor("worldpay");
}

@Test
public void createAGatewayAccountForSmartpay() throws Exception {
public void createAGatewayAccountForSmartpay() {
createAGatewayAccountFor("smartpay");
}

@Test
public void createAGatewayAccountForEpdq() throws Exception {
public void createAGatewayAccountForEpdq() {
createAGatewayAccountFor("epdq");
}

@@ -41,10 +41,6 @@ protected RequestSpecification givenSetup() {
.contentType(JSON);
}

RequestSpecification givenAdminSetup() {
return given().port(app.getAdminPort()).contentType(JSON);
}

//TODO remove this after complete migration
String createAGatewayAccountFor(String testProvider) {
return createAGatewayAccountFor(testProvider, null, null);
@@ -143,7 +143,7 @@ public static GatewayAccountEntity defaultGatewayAccountEntity() {
accountEntity.setServiceName("MyService");
EmailNotificationEntity emailNotificationEntity = new EmailNotificationEntity(accountEntity);
emailNotificationEntity.setTemplateBody("template body");
accountEntity.setEmailNotification(emailNotificationEntity);
accountEntity.addNotification(EmailNotificationType.CONFIRMATION, emailNotificationEntity);
return accountEntity;
}
}
@@ -34,7 +34,7 @@
public class ApiValidatorsTest {

@Test
public void shouldValidateEmailLength_WhenPatchingAnEmail() throws Exception {
public void shouldValidateEmailLength_WhenPatchingAnEmail() {

PatchRequestBuilder.PatchRequest request = PatchRequestBuilder.aPatchRequestBuilder(
ImmutableMap.of(
@@ -48,7 +48,7 @@ public void shouldValidateEmailLength_WhenPatchingAnEmail() throws Exception {
}

@Test
public void shouldInvalidateEmailLength_WhenPatchingAnEmail() throws Exception {
public void shouldInvalidateEmailLength_WhenPatchingAnEmail() {

PatchRequestBuilder.PatchRequest request = PatchRequestBuilder.aPatchRequestBuilder(
ImmutableMap.of(
@@ -16,6 +16,7 @@
import uk.gov.pay.connector.model.domain.ChargeEntity;
import uk.gov.pay.connector.model.domain.ChargeEntityFixture;
import uk.gov.pay.connector.model.domain.EmailNotificationEntity;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;
import uk.gov.pay.connector.service.notify.NotifyClientFactory;
import uk.gov.pay.connector.service.notify.NotifyClientFactoryProvider;
@@ -36,7 +37,15 @@
import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class UserNotificationServiceTest {
@@ -111,7 +120,7 @@ public void shouldSendEmailIfEmailNotifyIsEnabled() throws Exception {
}

@Test
public void testEmailSendingThrowsExceptionForMissingTemplate() throws Exception {
public void testEmailSendingThrowsExceptionForMissingTemplate() {
try {
reset(mockNotifyConfiguration);
when(mockNotifyConfiguration.isEmailNotifyEnabled()).thenReturn(true);
@@ -138,15 +147,18 @@ public void testEmailSendWhenEmailsNotifyDisabled() throws Exception {
}

@Test
public void whenEmailNotificationsAreDisabledForService_emailShouldNotBeSent() throws Exception {
public void whenConfirmationEmailNotificationsAreDisabledForService_emailShouldNotBeSent() throws Exception {
when(mockNotifyConfiguration.isEmailNotifyEnabled()).thenReturn(true);
when(mockNotifyClientFactoryProvider.clientFactory()).thenReturn(mockNotifyClientFactory);
when(mockNotifyClientFactory.getInstance()).thenReturn(mockNotifyClient);
when(mockNotifyClient.sendEmail(any(), any(), any(), any())).thenReturn(mockNotificationCreatedResponse);
when(mockNotificationCreatedResponse.getNotificationId()).thenReturn(randomUUID());

ChargeEntity chargeEntity = ChargeEntityFixture.aValidChargeEntity().build();
chargeEntity.getGatewayAccount().getEmailNotification().setEnabled(false);
chargeEntity.getGatewayAccount()
.getEmailNotifications()
.get(EmailNotificationType.CONFIRMATION)
.setEnabled(false);

userNotificationService = new UserNotificationService(mockNotifyClientFactoryProvider, mockConfig, mockEnvironment);
userNotificationService.notifyPaymentSuccessEmail(chargeEntity);
@@ -196,7 +208,7 @@ public void shouldRecordNotifyResponseTimesAndFailureWhenSendEmailFails() throws
}

@Test
public void shouldSendBlankCustomParagraphIfNotSet() throws Exception {
public void shouldSendBlankCustomParagraphIfNotSetInConfirmationEmail() throws Exception {
when(mockConfig.getNotifyConfiguration().isEmailNotifyEnabled()).thenReturn(true);
when(mockNotifyClientFactoryProvider.clientFactory()).thenReturn(mockNotifyClientFactory);
when(mockNotifyClientFactory.getInstance()).thenReturn(mockNotifyClient);
@@ -211,7 +223,7 @@ public void shouldSendBlankCustomParagraphIfNotSet() throws Exception {
GatewayAccountEntity accountEntity = charge.getGatewayAccount();
EmailNotificationEntity emailNotificationEntity = new EmailNotificationEntity(accountEntity);
emailNotificationEntity.setTemplateBody(null);
accountEntity.setEmailNotification(emailNotificationEntity);
accountEntity.addNotification(EmailNotificationType.CONFIRMATION, emailNotificationEntity);

userNotificationService = new UserNotificationService(mockNotifyClientFactoryProvider, mockConfig, mockEnvironment);
Future<Optional<String>> idF = userNotificationService.notifyPaymentSuccessEmail(charge);
@@ -9,6 +9,7 @@
import uk.gov.pay.connector.model.ServicePaymentReference;
import uk.gov.pay.connector.model.domain.AuthCardDetails;
import uk.gov.pay.connector.model.domain.ChargeStatus;
import uk.gov.pay.connector.model.domain.EmailNotificationType;
import uk.gov.pay.connector.model.domain.GatewayAccountEntity;

import java.sql.SQLException;
@@ -326,15 +327,24 @@ public Map<String, Object> getChargeCardDetails(long chargeId) {
return ret;
}

public Map<String, Object> getEmailNotificationByAccountId(Long accountId) {
public Map<String, Object> getConfirmationEmailNotificationByAccountId(Long accountId) {

return jdbi.withHandle(h ->
h.createQuery("SELECT template_body, enabled from email_notifications WHERE account_id = :account_id ORDER BY id DESC")
h.createQuery("SELECT template_body, enabled from email_notifications WHERE account_id = :account_id AND type = 'CONFIRMATION' ORDER BY id DESC")
.bind("account_id", accountId)
.first()
);
}

public List<Map<String, Object>> getEmailNotificationsByAccountId(Long accountId) {

return jdbi.withHandle(h ->
h.createQuery("SELECT template_body, enabled from email_notifications WHERE account_id = :account_id ORDER BY id DESC")
.bind("account_id", accountId)
.list()
);
}

public String getChargeTokenByExternalChargeId(String externalChargeId) {

String chargeId = jdbi.withHandle(h ->
@@ -399,24 +409,26 @@ public void addToken(Long chargeId, String tokenId) {
);
}

public void addEmailNotification(Long accountId, String templateBody, boolean enabled) {
public void addEmailNotification(Long accountId, String templateBody, boolean enabled, EmailNotificationType type) {
jdbi.withHandle(handle ->
handle
.createStatement("INSERT INTO email_notifications(account_id, template_body, enabled) VALUES (:account_id, :templateBody, :enabled)")
.createStatement("INSERT INTO email_notifications(account_id, template_body, enabled, type) VALUES (:account_id, :templateBody, :enabled, :type)")
.bind("account_id", accountId)
.bind("templateBody", templateBody)
.bind("enabled", enabled)
.bind("type", type)
.execute()
);
}

public void updateEmailNotification(Long accountId, String templateBody, boolean enabled) {
public void updateEmailNotification(Long accountId, String templateBody, boolean enabled, EmailNotificationType type) {
jdbi.withHandle(handle ->
handle
.createStatement("UPDATE email_notifications SET template_body= :templateBody, enabled= :enabled WHERE account_id=:account_id")
.createStatement("UPDATE email_notifications SET template_body= :templateBody, enabled= :enabled WHERE account_id=:account_id AND type = :type")
.bind("account_id", accountId)
.bind("enabled", enabled)
.bind("templateBody", templateBody)
.bind("type", type.toString())
.execute()
);
}