This is an automated email from the ASF dual-hosted git repository.
ptuomola pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 8146a73 FINERACT-1273: Triggered emails
8146a73 is described below
commit 8146a7399c2ed936f7d353f0f4777bb4e5006d76
Author: Adonay <[email protected]>
AuthorDate: Thu May 20 16:41:32 2021 -0500
FINERACT-1273: Triggered emails
Basically send an email when a client does an action: for now when a loan
is approved, rejected and when a repayment is done. More triggers should be
added in the future
---
.../campaigns/email/domain/EmailCampaign.java | 12 +-
.../email/domain/EmailCampaignRepository.java | 9 +-
.../campaigns/email/domain/EmailCampaignType.java | 10 +-
.../EmailCampaignDomainService.java} | 7 +-
.../service/EmailCampaignDomainServiceImpl.java | 151 +++++++++++++++++++++
...ailCampaignWritePlatformCommandHandlerImpl.java | 80 +++++++----
.../service/EmailCampaignWritePlatformService.java | 5 +
.../service/EmailMessageJobEmailServiceImpl.java | 64 ++++-----
.../AddressCommandFromApiJsonDeserializer.java | 7 +-
.../core_db/V367__reports_for_email_campaigns.sql | 26 ++++
...sql => V370__message_gateway_hook_template.sql} | 0
.../integrationtests/client/ReportsTest.java | 2 +-
12 files changed, 287 insertions(+), 86 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java
index 272f219..72ac226 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaign.java
@@ -75,11 +75,11 @@ public class EmailCampaign extends
AbstractPersistableCustom {
@Column(name = "email_message", nullable = false)
private String emailMessage;
- @Column(name = "email_attachment_file_format", nullable = false)
+ @Column(name = "email_attachment_file_format")
private String emailAttachmentFileFormat;
@ManyToOne
- @JoinColumn(name = "stretchy_report_id", nullable = false)
+ @JoinColumn(name = "stretchy_report_id")
private Report stretchyReport;
@Column(name = "stretchy_report_param_map", nullable = true)
@@ -109,18 +109,18 @@ public class EmailCampaign extends
AbstractPersistableCustom {
@JoinColumn(name = "approvedon_userid", nullable = true)
private AppUser approvedBy;
- @Column(name = "recurrence", nullable = false)
+ @Column(name = "recurrence")
private String recurrence;
- @Column(name = "next_trigger_date", nullable = false)
+ @Column(name = "next_trigger_date")
@Temporal(TemporalType.TIMESTAMP)
private Date nextTriggerDate;
- @Column(name = "last_trigger_date", nullable = false)
+ @Column(name = "last_trigger_date")
@Temporal(TemporalType.TIMESTAMP)
private Date lastTriggerDate;
- @Column(name = "recurrence_start_date", nullable = false)
+ @Column(name = "recurrence_start_date")
@Temporal(TemporalType.TIMESTAMP)
private Date recurrenceStartDate;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
index 291698b..8a0eec2 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
@@ -18,7 +18,14 @@
*/
package org.apache.fineract.infrastructure.campaigns.email.domain;
+import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
-public interface EmailCampaignRepository extends JpaRepository<EmailCampaign,
Long>, JpaSpecificationExecutor<EmailCampaign> {}
+public interface EmailCampaignRepository extends JpaRepository<EmailCampaign,
Long>, JpaSpecificationExecutor<EmailCampaign> {
+
+ @Query("SELECT campaign FROM EmailCampaign campaign WHERE
campaign.paramValue LIKE :reportPattern AND campaign.campaignType=:type AND
campaign.status=300")
+ List<EmailCampaign> findActiveEmailCampaigns(@Param("reportPattern")
String reportPattern, @Param("type") Integer type);
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignType.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignType.java
index 95c36ce..79059ea 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignType.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignType.java
@@ -20,7 +20,8 @@ package
org.apache.fineract.infrastructure.campaigns.email.domain;
public enum EmailCampaignType {
- DIRECT(1, "emailCampaignStatusType.direct"), SCHEDULE(2,
"emailCampaignStatusType.schedule");
+ DIRECT(1, "emailCampaignStatusType.direct"), SCHEDULE(2,
"emailCampaignStatusType.schedule"), TRIGGERED(3,
+ "emailCampaignStatusType.triggered");
private final Integer value;
private final String code;
@@ -47,6 +48,9 @@ public enum EmailCampaignType {
case 2:
type = SCHEDULE;
break;
+ case 3:
+ type = TRIGGERED;
+ break;
}
return type;
}
@@ -58,4 +62,8 @@ public enum EmailCampaignType {
public boolean isSchedule() {
return this.value.equals(EmailCampaignType.SCHEDULE.getValue());
}
+
+ public boolean isTriggered() {
+ return this.value.equals(EmailCampaignType.TRIGGERED.getValue());
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainService.java
similarity index 70%
copy from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
copy to
fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainService.java
index 291698b..c02d697 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/domain/EmailCampaignRepository.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainService.java
@@ -16,9 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.campaigns.email.domain;
+package org.apache.fineract.infrastructure.campaigns.email.service;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-
-public interface EmailCampaignRepository extends JpaRepository<EmailCampaign,
Long>, JpaSpecificationExecutor<EmailCampaign> {}
+public interface EmailCampaignDomainService {}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainServiceImpl.java
new file mode 100644
index 0000000..31342a9
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignDomainServiceImpl.java
@@ -0,0 +1,151 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.infrastructure.campaigns.email.service;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.apache.fineract.infrastructure.campaigns.email.domain.EmailCampaign;
+import
org.apache.fineract.infrastructure.campaigns.email.domain.EmailCampaignRepository;
+import
org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignTriggerType;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import org.apache.fineract.portfolio.common.service.BusinessEventListener;
+import
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EmailCampaignDomainServiceImpl implements
EmailCampaignDomainService {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(EmailCampaignDomainServiceImpl.class);
+ private final BusinessEventNotifierService businessEventNotifierService;
+ private final EmailCampaignWritePlatformService
emailCampaignWritePlatformService;
+ private final EmailCampaignRepository emailCampaignRepository;
+
+ @Autowired
+ public EmailCampaignDomainServiceImpl(BusinessEventNotifierService
businessEventNotifierService,
+ EmailCampaignWritePlatformService
emailCampaignWritePlatformService, EmailCampaignRepository
emailCampaignRepository) {
+ this.businessEventNotifierService = businessEventNotifierService;
+ this.emailCampaignWritePlatformService =
emailCampaignWritePlatformService;
+ this.emailCampaignRepository = emailCampaignRepository;
+ }
+
+ @PostConstruct
+ public void addListeners() {
+
this.businessEventNotifierService.addBusinessEventPostListeners(BusinessEventNotificationConstants.BusinessEvents.LOAN_APPROVED,
+ new EmailCampaignDomainServiceImpl.SendEmailOnLoanApproved());
+
this.businessEventNotifierService.addBusinessEventPostListeners(BusinessEventNotificationConstants.BusinessEvents.LOAN_REJECTED,
+ new EmailCampaignDomainServiceImpl.SendEmailOnLoanRejected());
+ this.businessEventNotifierService.addBusinessEventPostListeners(
+
BusinessEventNotificationConstants.BusinessEvents.LOAN_MAKE_REPAYMENT,
+ new EmailCampaignDomainServiceImpl.SendEmailOnLoanRepayment());
+ }
+
+ private class SendEmailOnLoanRepayment extends EmailBusinessEventAdapter {
+
+ @Override
+ public void
businessEventWasExecuted(Map<BusinessEventNotificationConstants.BusinessEntity,
Object> businessEventEntity) {
+ Object entity =
businessEventEntity.get(BusinessEventNotificationConstants.BusinessEntity.LOAN_TRANSACTION);
+ if (entity instanceof LoanTransaction) {
+ LoanTransaction loanTransaction = (LoanTransaction) entity;
+ try {
+ notifyLoanOwner(loanTransaction, "Loan Repayment");
+ } catch (IOException e) {
+ LOG.error("Exception when trying to send triggered email:
{}", e.getMessage());
+ }
+ }
+ }
+ }
+
+ private class SendEmailOnLoanRejected extends EmailBusinessEventAdapter {
+
+ @Override
+ public void
businessEventWasExecuted(Map<BusinessEventNotificationConstants.BusinessEntity,
Object> businessEventEntity) {
+ Object entity =
businessEventEntity.get(BusinessEventNotificationConstants.BusinessEntity.LOAN);
+ if (entity instanceof Loan) {
+ Loan loan = (Loan) entity;
+ try {
+ notifyLoanOwner(loan, "Loan Rejected");
+ } catch (IOException e) {
+ LOG.error("Exception when trying to send triggered email:
{}", e.getMessage());
+ }
+ }
+ }
+ }
+
+ private class SendEmailOnLoanApproved extends EmailBusinessEventAdapter {
+
+ @Override
+ public void
businessEventWasExecuted(Map<BusinessEventNotificationConstants.BusinessEntity,
Object> businessEventEntity) {
+ Object entity =
businessEventEntity.get(BusinessEventNotificationConstants.BusinessEntity.LOAN);
+ if (entity instanceof Loan) {
+ Loan loan = (Loan) entity;
+ try {
+ notifyLoanOwner(loan, "Loan Approved");
+ } catch (IOException e) {
+ LOG.error("Exception when trying to send triggered email:
{}", e.getMessage());
+ }
+ }
+ }
+ }
+
+ private void notifyLoanOwner(LoanTransaction loanTransaction, String
paramValue) throws IOException {
+ List<EmailCampaign> campaigns =
this.retrieveEmailCampaigns(paramValue);
+ for (EmailCampaign emailCampaign : campaigns) {
+ HashMap<String, String> campaignParams = new
ObjectMapper().readValue(emailCampaign.getParamValue(),
+ new TypeReference<HashMap<String, String>>() {});
+ campaignParams.put("loanId",
loanTransaction.getLoan().getId().toString());
+ campaignParams.put("loanTransactionId",
loanTransaction.getId().toString());
+
this.emailCampaignWritePlatformService.insertDirectCampaignIntoEmailOutboundTable(loanTransaction.getLoan(),
emailCampaign,
+ campaignParams);
+ }
+ }
+
+ private void notifyLoanOwner(Loan loan, String paramValue) throws
IOException {
+ List<EmailCampaign> campaigns =
this.retrieveEmailCampaigns(paramValue);
+ for (EmailCampaign emailCampaign : campaigns) {
+ HashMap<String, String> campaignParams = new
ObjectMapper().readValue(emailCampaign.getParamValue(),
+ new TypeReference<HashMap<String, String>>() {});
+ campaignParams.put("loanId", loan.getId().toString());
+
this.emailCampaignWritePlatformService.insertDirectCampaignIntoEmailOutboundTable(loan,
emailCampaign, campaignParams);
+ }
+ }
+
+ private abstract static class EmailBusinessEventAdapter implements
BusinessEventListener {
+
+ @Override
+ public void
businessEventToBeExecuted(Map<BusinessEventNotificationConstants.BusinessEntity,
Object> businessEventEntity) {
+ // Nothing to do
+ }
+ }
+
+ private List<EmailCampaign> retrieveEmailCampaigns(String paramValue) {
+ List<EmailCampaign> emailCampaigns =
emailCampaignRepository.findActiveEmailCampaigns("%" + paramValue + "%",
+ SmsCampaignTriggerType.TRIGGERED.getValue());
+ return emailCampaigns;
+ }
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java
index 5ba082d..543c23b 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformCommandHandlerImpl.java
@@ -158,20 +158,24 @@ public class EmailCampaignWritePlatformCommandHandlerImpl
implements EmailCampai
final Long reportId =
command.longValueOfParameterNamed(EmailCampaignValidator.stretchyReportId);
- final Report report =
this.reportRepository.findById(reportId).orElseThrow(() -> new
ReportNotFoundException(reportId));
-
- // find all report parameters and store them as json string
- final Set<ReportParameterUsage> reportParameterUsages =
report.getReportParameterUsages();
- final Map<String, String> stretchyReportParams = new HashMap<>();
-
- if (reportParameterUsages != null && !reportParameterUsages.isEmpty())
{
- for (final ReportParameterUsage reportParameterUsage :
reportParameterUsages) {
-
stretchyReportParams.put(reportParameterUsage.getReportParameterName(), "");
+ Report report = null;
+ Map<String, String> stretchyReportParams = null;
+ if (reportId != null) {
+ report = this.reportRepository.findById(reportId).orElseThrow(()
-> new ReportNotFoundException(reportId));
+ final Set<ReportParameterUsage> reportParameterUsages =
report.getReportParameterUsages();
+ stretchyReportParams = new HashMap<>();
+
+ if (reportParameterUsages != null &&
!reportParameterUsages.isEmpty()) {
+ for (final ReportParameterUsage reportParameterUsage :
reportParameterUsages) {
+
stretchyReportParams.put(reportParameterUsage.getReportParameterName(), "");
+ }
}
}
EmailCampaign emailCampaign = EmailCampaign.instance(currentUser,
businessRule, report, command);
- emailCampaign.setStretchyReportParamMap(new
Gson().toJson(stretchyReportParams));
+ if (stretchyReportParams != null) {
+ emailCampaign.setStretchyReportParamMap(new
Gson().toJson(stretchyReportParams));
+ }
this.emailCampaignRepository.save(emailCampaign);
@@ -241,6 +245,32 @@ public class EmailCampaignWritePlatformCommandHandlerImpl
implements EmailCampai
}
+ @Override
+ public void insertDirectCampaignIntoEmailOutboundTable(final Loan loan,
final EmailCampaign emailCampaign,
+ HashMap<String, String> campaignParams) {
+ try {
+ List<HashMap<String, Object>> runReportObject =
this.getRunReportByServiceImpl(campaignParams.get("reportName"),
+ campaignParams);
+
+ if (runReportObject != null) {
+ for (HashMap<String, Object> entry : runReportObject) {
+ String message =
this.compileEmailTemplate(emailCampaign.getEmailMessage(),
emailCampaign.getCampaignName(), entry);
+ Client client = loan.getClient();
+ String emailAddress = client.emailAddress();
+
+ if (emailAddress != null && isValidEmail(emailAddress)) {
+ EmailMessage emailMessage =
EmailMessage.pendingEmail(null, client, null, emailCampaign,
+ emailCampaign.getEmailSubject(), message,
emailAddress, emailCampaign.getCampaignName());
+ this.emailMessageRepository.save(emailMessage);
+ }
+ }
+ }
+ } catch (final IOException e) {
+ // TODO throw something here
+ }
+
+ }
+
private void insertDirectCampaignIntoEmailOutboundTable(final String
emailParams, final String emailSubject,
final String messageTemplate, final String campaignName, final
Long campaignId) {
try {
@@ -589,8 +619,11 @@ public class EmailCampaignWritePlatformCommandHandlerImpl
implements EmailCampai
final EmailCampaign emailCampaign =
this.emailCampaignRepository.findById(emailMessage.getEmailCampaign().getId())
.orElse(null); //
- final ScheduledEmailAttachmentFileFormat
emailAttachmentFileFormat = ScheduledEmailAttachmentFileFormat
-
.instance(emailCampaign.getEmailAttachmentFileFormat());
+ ScheduledEmailAttachmentFileFormat
emailAttachmentFileFormat = null;
+ if (emailCampaign.getEmailAttachmentFileFormat() != null) {
+ emailAttachmentFileFormat =
ScheduledEmailAttachmentFileFormat
+
.instance(emailCampaign.getEmailAttachmentFileFormat());
+ }
final List<File> attachmentList = new ArrayList<>();
@@ -690,29 +723,16 @@ public class EmailCampaignWritePlatformCommandHandlerImpl
implements EmailCampai
final EmailMessageWithAttachmentData
emailMessageWithAttachmentData = EmailMessageWithAttachmentData.createNew(
emailMessage.getEmailAddress(),
emailMessage.getMessage(), emailMessage.getEmailSubject(), attachmentList);
-
- if (!attachmentList.isEmpty() && attachmentList.size() >
0) { // only
-
// send
-
// email
-
// message
-
// if
-
// there
-
// is
-
// an
-
// attachment
-
// to
-
// it
+ try {
this.emailMessageJobEmailService.sendEmailWithAttachment(emailMessageWithAttachmentData);
emailMessage.setStatusType(EmailMessageStatusType.SENT.getValue());
this.emailMessageRepository.save(emailMessage);
- } else {
- emailMessage.updateErrorMessage(errorLog.toString());
-
+ } catch (Exception e) {
+ emailMessage.updateErrorMessage(e.getMessage());
emailMessage.setStatusType(EmailMessageStatusType.FAILED.getValue());
-
this.emailMessageRepository.save(emailMessage);
}
}
@@ -734,7 +754,9 @@ public class EmailCampaignWritePlatformCommandHandlerImpl
implements EmailCampai
*/
private File generateAttachments(final EmailCampaign emailCampaign, final
ScheduledEmailAttachmentFileFormat emailAttachmentFileFormat,
final Map<String, String> reportParams, final String reportName,
final StringBuilder errorLog) {
-
+ if (reportName == null) {
+ return null;
+ }
try {
final ByteArrayOutputStream byteArrayOutputStream =
this.readReportingService.generatePentahoReportAsOutputStream(reportName,
emailAttachmentFileFormat.getValue(), reportParams, null,
emailCampaign.getApprovedBy(), errorLog);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformService.java
index 9819131..46601de 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailCampaignWritePlatformService.java
@@ -18,11 +18,14 @@
*/
package org.apache.fineract.infrastructure.campaigns.email.service;
+import java.util.HashMap;
import
org.apache.fineract.infrastructure.campaigns.email.data.PreviewCampaignMessage;
+import org.apache.fineract.infrastructure.campaigns.email.domain.EmailCampaign;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.api.JsonQuery;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
public interface EmailCampaignWritePlatformService {
@@ -44,4 +47,6 @@ public interface EmailCampaignWritePlatformService {
void sendEmailMessage() throws JobExecutionException;
+ void insertDirectCampaignIntoEmailOutboundTable(Loan loan, EmailCampaign
emailCampaign, HashMap<String, String> campaignParams);
+
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailMessageJobEmailServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailMessageJobEmailServiceImpl.java
index 5194644..c9abac4 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailMessageJobEmailServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/email/service/EmailMessageJobEmailServiceImpl.java
@@ -23,10 +23,9 @@ import java.util.List;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
-import org.apache.fineract.infrastructure.campaigns.email.EmailApiConstants;
import
org.apache.fineract.infrastructure.campaigns.email.data.EmailMessageWithAttachmentData;
-import
org.apache.fineract.infrastructure.campaigns.email.domain.EmailConfiguration;
-import
org.apache.fineract.infrastructure.campaigns.email.domain.EmailConfigurationRepository;
+import
org.apache.fineract.infrastructure.configuration.data.SMTPCredentialsData;
+import
org.apache.fineract.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -38,30 +37,33 @@ import org.springframework.stereotype.Service;
public final class EmailMessageJobEmailServiceImpl implements
EmailMessageJobEmailService {
private static final Logger LOG =
LoggerFactory.getLogger(EmailMessageJobEmailServiceImpl.class);
- private EmailConfigurationRepository emailConfigurationRepository;
+ private final ExternalServicesPropertiesReadPlatformService
externalServicesReadPlatformService;
@Autowired
- private EmailMessageJobEmailServiceImpl(final EmailConfigurationRepository
emailConfigurationRepository) {
- this.emailConfigurationRepository = emailConfigurationRepository;
+ private
EmailMessageJobEmailServiceImpl(ExternalServicesPropertiesReadPlatformService
externalServicesReadPlatformService) {
+ this.externalServicesReadPlatformService =
externalServicesReadPlatformService;
}
@Override
public void sendEmailWithAttachment(EmailMessageWithAttachmentData
emailMessageWithAttachmentData) {
+ final SMTPCredentialsData smtpCredentialsData =
this.externalServicesReadPlatformService.getSMTPCredentials();
try {
JavaMailSenderImpl javaMailSenderImpl = new JavaMailSenderImpl();
- javaMailSenderImpl.setHost(this.getGmailSmtpServer());
- javaMailSenderImpl.setPort(this.getGmailSmtpPort());
- javaMailSenderImpl.setUsername(this.getGmailSmtpUsername());
- javaMailSenderImpl.setPassword(this.getGmailSmtpPassword());
-
javaMailSenderImpl.setJavaMailProperties(this.getJavaMailProperties());
+ javaMailSenderImpl.setHost(smtpCredentialsData.getHost());
+
javaMailSenderImpl.setPort(Integer.parseInt(smtpCredentialsData.getPort()));
+ javaMailSenderImpl.setUsername(smtpCredentialsData.getUsername());
+ javaMailSenderImpl.setPassword(smtpCredentialsData.getPassword());
+ javaMailSenderImpl
+
.setJavaMailProperties(this.getJavaMailProperties(smtpCredentialsData,
javaMailSenderImpl.getJavaMailProperties()));
MimeMessage mimeMessage = javaMailSenderImpl.createMimeMessage();
// use the true flag to indicate you need a multipart message
MimeMessageHelper mimeMessageHelper = new
MimeMessageHelper(mimeMessage, true);
+ mimeMessageHelper.setFrom(smtpCredentialsData.getFromEmail());
mimeMessageHelper.setTo(emailMessageWithAttachmentData.getTo());
-
mimeMessageHelper.setText(emailMessageWithAttachmentData.getText());
+
mimeMessageHelper.setText(emailMessageWithAttachmentData.getText(), true);
mimeMessageHelper.setSubject(emailMessageWithAttachmentData.getSubject());
final List<File> attachments =
emailMessageWithAttachmentData.getAttachments();
if (attachments != null && attachments.size() > 0) {
@@ -80,32 +82,18 @@ public final class EmailMessageJobEmailServiceImpl
implements EmailMessageJobEma
}
- private String getGmailSmtpServer() {
- final EmailConfiguration gmailSmtpServer =
this.emailConfigurationRepository.findByName(EmailApiConstants.SMTP_SERVER);
- return (gmailSmtpServer != null) ? gmailSmtpServer.getValue() : null;
- }
-
- private Integer getGmailSmtpPort() {
- final EmailConfiguration gmailSmtpPort =
this.emailConfigurationRepository.findByName(EmailApiConstants.SMTP_PORT);
- return (gmailSmtpPort != null) ?
Integer.parseInt(gmailSmtpPort.getValue()) : null;
- }
-
- private String getGmailSmtpUsername() {
- final EmailConfiguration gmailSmtpUsername =
this.emailConfigurationRepository.findByName(EmailApiConstants.SMTP_USERNAME);
- return (gmailSmtpUsername != null) ? gmailSmtpUsername.getValue() :
null;
- }
-
- private String getGmailSmtpPassword() {
- final EmailConfiguration gmailSmtpPassword =
this.emailConfigurationRepository.findByName(EmailApiConstants.SMTP_PASSWORD);
- return (gmailSmtpPassword != null) ? gmailSmtpPassword.getValue() :
null;
- }
-
- private Properties getJavaMailProperties() {
- Properties properties = new Properties();
- properties.setProperty("mail.smtp.starttls.enable", "true");
- properties.setProperty("mail.smtp.auth", "true");
- properties.setProperty("mail.smtp.ssl.trust",
this.getGmailSmtpServer());
-
+ private Properties getJavaMailProperties(SMTPCredentialsData
smtpCredentialsData, Properties properties) {
+ properties.put("mail.smtp.starttls.enable", "true");
+ properties.put("mail.transport.protocol", "smtp");
+ properties.put("mail.smtp.auth", "true");
+ properties.put("mail.smtp.ssl.trust", smtpCredentialsData.getHost());
+ if (smtpCredentialsData.isUseTLS()) {
+ // Needs to disable startTLS if the port is 465 in order to send
the email successfully when using the
+ // smtp.gmail.com as the host
+ if (smtpCredentialsData.getPort().equals("465")) {
+ properties.put("mail.smtp.starttls.enable", "false");
+ }
+ }
return properties;
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java
index 9b8d37e..39eef97 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java
@@ -74,9 +74,7 @@ public class AddressCommandFromApiJsonDeserializer {
final List<FieldConfigurationData> configData =
configurationData.stream().filter(FieldConfigurationData::isEnabled)
.collect(Collectors.toList());
- final Set<String> supportedParameters = configData.stream()
- .map(FieldConfigurationData::getField)
- .collect(Collectors.toSet());
+ final Set<String> supportedParameters =
configData.stream().map(FieldConfigurationData::getField).collect(Collectors.toSet());
supportedParameters.add("locale");
supportedParameters.add("dateFormat");
@@ -85,8 +83,7 @@ public class AddressCommandFromApiJsonDeserializer {
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
supportedParameters);
configData.forEach(fieldConfiguration -> {
- final String field =
- fieldConfiguration.getField().equals("addressType") ?
"addressTypeId" : fieldConfiguration.getField();
+ final String field =
fieldConfiguration.getField().equals("addressType") ? "addressTypeId" :
fieldConfiguration.getField();
final String fieldValue =
this.fromApiJsonHelper.extractStringNamed(field, element);
if (fieldConfiguration.getField().equals("addressType") &&
fromNewClient) {
diff --git
a/fineract-provider/src/main/resources/sql/migrations/core_db/V367__reports_for_email_campaigns.sql
b/fineract-provider/src/main/resources/sql/migrations/core_db/V367__reports_for_email_campaigns.sql
new file mode 100644
index 0000000..86a97fc
--- /dev/null
+++
b/fineract-provider/src/main/resources/sql/migrations/core_db/V367__reports_for_email_campaigns.sql
@@ -0,0 +1,26 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`,
`report_sql`, `description`, `core_report`, `use_report`,
`self_service_user_report`) VALUES ('Loan Approved - Email', 'Email',
'Triggered', 'select ml.id as loanId, ifnull(mc.id,mc2.id) as id,
ifnull(mc.firstname,mc2.firstname) as firstname,
\nifnull(mc.middlename,ifnull(mc2.middlename,(\'\'))) as middlename,
ifnull(mc.lastname,mc2.lastname) as lastname,
\nifnull(mc.display_name,mc2.display_name) as dis [...]
+INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`,
`report_sql`, `description`, `core_report`, `use_report`,
`self_service_user_report`) VALUES ('Loan Rejected - Email', 'Email',
'Triggered', 'select ml.id as loanId, ifnull(mc.id,mc2.id) as id,
ifnull(mc.firstname,mc2.firstname) as firstname,
\nifnull(mc.middlename,ifnull(mc2.middlename,(\'\'))) as middlename,
ifnull(mc.lastname,mc2.lastname) as lastname,
\nifnull(mc.display_name,mc2.display_name) as dis [...]
+INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`,
`report_sql`, `description`, `core_report`, `use_report`,
`self_service_user_report`) VALUES ('Loan Repayment - Email', 'Email',
'Triggered', 'select ml.id as loanId, ifnull(mc.id,mc2.id) as id,
ifnull(mc.firstname,mc2.firstname) as firstname,
\nifnull(mc.middlename,ifnull(mc2.middlename,(\'\'))) as middlename,
ifnull(mc.lastname,mc2.lastname) as lastname,
\nifnull(mc.display_name,mc2.display_name) as di [...]
+
+ALTER TABLE `scheduled_email_campaign`
+CHANGE COLUMN `email_attachment_file_format` `email_attachment_file_format`
VARCHAR(10) NULL ,
+CHANGE COLUMN `stretchy_report_id` `stretchy_report_id` INT(11) NULL ;
diff --git
a/fineract-provider/src/main/resources/sql/migrations/core_db/V367__message_gateway_hook_template.sql
b/fineract-provider/src/main/resources/sql/migrations/core_db/V370__message_gateway_hook_template.sql
similarity index 100%
rename from
fineract-provider/src/main/resources/sql/migrations/core_db/V367__message_gateway_hook_template.sql
rename to
fineract-provider/src/main/resources/sql/migrations/core_db/V370__message_gateway_hook_template.sql
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ReportsTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ReportsTest.java
index f1eda5f..98378b1 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ReportsTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/ReportsTest.java
@@ -35,7 +35,7 @@ public class ReportsTest extends IntegrationTest {
@Test
void listReports() {
- assertThat(ok(fineract().reports.retrieveReportList())).hasSize(117);
+ assertThat(ok(fineract().reports.retrieveReportList())).hasSize(120);
}
@Test