You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by na...@apache.org on 2016/08/12 03:39:54 UTC

[2/5] incubator-fineract git commit: commit for FINERACT-65 (Implement ability to schedule & e-mail reports)

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobTimelineData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobTimelineData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobTimelineData.java
new file mode 100644
index 0000000..0320097
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobTimelineData.java
@@ -0,0 +1,59 @@
+/**
+ * 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.reportmailingjob.data;
+
+import org.joda.time.LocalDate;
+
+/** 
+ * Immutable data object represent the timeline events of a report mailing job (creation)
+ **/
+@SuppressWarnings("unused")
+public class ReportMailingJobTimelineData {
+    private final LocalDate createdOnDate;
+    private final String createdByUsername;
+    private final String createdByFirstname;
+    private final String createdByLastname;
+    private final LocalDate updatedOnDate;
+    private final String updatedByUsername;
+    private final String updatedByFirstname;
+    private final String updatedByLastname;
+    
+    /**
+     * @param createdOnDate
+     * @param createdByUsername
+     * @param createdByFirstname
+     * @param createdByLastname
+     * @param updatedOnDate
+     * @param updatedByUsername
+     * @param updatedByFirstname
+     * @param updatedByLastname
+     */
+    public ReportMailingJobTimelineData(LocalDate createdOnDate, String createdByUsername, String createdByFirstname,
+            String createdByLastname, LocalDate updatedOnDate, String updatedByUsername, String updatedByFirstname,
+            String updatedByLastname) {
+        this.createdOnDate = createdOnDate;
+        this.createdByUsername = createdByUsername;
+        this.createdByFirstname = createdByFirstname;
+        this.createdByLastname = createdByLastname;
+        this.updatedOnDate = updatedOnDate;
+        this.updatedByUsername = updatedByUsername;
+        this.updatedByFirstname = updatedByFirstname;
+        this.updatedByLastname = updatedByLastname;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJob.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJob.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJob.java
new file mode 100644
index 0000000..c7f3bb7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJob.java
@@ -0,0 +1,558 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.UniqueConstraint;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableCustom;
+import org.apache.fineract.infrastructure.dataqueries.domain.Report;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailAttachmentFileFormat;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobPreviousRunStatus;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+@Entity
+@Table(name = "m_report_mailing_job", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unique_name") })
+public class ReportMailingJob extends AbstractAuditableCustom<AppUser, Long> {
+    private static final long serialVersionUID = -2197602941230009227L;
+    
+    @Column(name = "name", nullable = false)
+    private String name;
+    
+    @Column(name = "description", nullable = true)
+    private String description;
+    
+    @Column(name = "start_datetime", nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date startDateTime;
+    
+    @Column(name = "recurrence", nullable = true)
+    private String recurrence;
+    
+    @Column(name = "email_recipients", nullable = false)
+    private String emailRecipients;
+    
+    @Column(name = "email_subject", nullable = false)
+    private String emailSubject;
+    
+    @Column(name = "email_message", nullable = false)
+    private String emailMessage;
+    
+    @Column(name = "email_attachment_file_format", nullable = false)
+    private String emailAttachmentFileFormat;
+    
+    @ManyToOne
+    @JoinColumn(name = "stretchy_report_id", nullable = false)
+    private Report stretchyReport;
+    
+    @Column(name = "stretchy_report_param_map", nullable = true)
+    private String stretchyReportParamMap;
+    
+    @Column(name = "previous_run_datetime", nullable = true)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date previousRunDateTime;
+    
+    @Column(name = "next_run_datetime", nullable = true)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date nextRunDateTime;
+    
+    @Column(name = "previous_run_status", nullable = true)
+    private String previousRunStatus;
+    
+    @Column(name = "previous_run_error_log", nullable = true)
+    private String previousRunErrorLog;
+    
+    @Column(name = "previous_run_error_message", nullable = true)
+    private String previousRunErrorMessage;
+    
+    @Column(name = "number_of_runs", nullable = false)
+    private Integer numberOfRuns;
+    
+    @Column(name = "is_active", nullable = false)
+    private boolean isActive;
+    
+    @Column(name = "is_deleted", nullable = false)
+    private boolean isDeleted;
+    
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "run_as_userid", nullable = false)
+    private AppUser runAsUser;
+    
+    /** 
+     * ReportMailingJob protected constructor
+     **/
+    protected ReportMailingJob() { }
+    
+    /** 
+     * ReportMailingJob private constructor 
+     **/
+    private ReportMailingJob(final String name, final String description, final LocalDateTime startDateTime, 
+            final String recurrence, final String emailRecipients, final String emailSubject, 
+            final String emailMessage, final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat, 
+            final Report stretchyReport, final String stretchyReportParamMap, final LocalDateTime previousRunDateTime, final LocalDateTime nextRunDateTime, 
+            final ReportMailingJobPreviousRunStatus previousRunStatus, final String previousRunErrorLog, final String previousRunErrorMessage, 
+            final boolean isActive, final boolean isDeleted, final AppUser runAsUser) { 
+        this.name = name;
+        this.description = description;
+        this.startDateTime = null;
+        
+        if (startDateTime != null) {
+            this.startDateTime = startDateTime.toDate();
+        }
+        
+        this.recurrence = recurrence;
+        this.emailRecipients = emailRecipients;
+        this.emailSubject = emailSubject;
+        this.emailMessage = emailMessage;
+        this.emailAttachmentFileFormat = emailAttachmentFileFormat.getValue();
+        this.stretchyReport = stretchyReport;
+        this.stretchyReportParamMap = stretchyReportParamMap;
+        this.previousRunDateTime = null;
+        
+        if (previousRunDateTime != null) {
+            this.previousRunDateTime = previousRunDateTime.toDate();
+        }
+        
+        this.nextRunDateTime = null;
+        
+        if (nextRunDateTime != null) {
+            this.nextRunDateTime = nextRunDateTime.toDate();
+        }
+        
+        this.previousRunStatus = null;
+        
+        if (previousRunStatus != null) {
+            this.previousRunStatus = previousRunStatus.getValue();
+        }
+        
+        if (numberOfRuns == null) {
+            this.numberOfRuns = 0;
+        }
+        
+        this.previousRunErrorLog = previousRunErrorLog;
+        this.previousRunErrorMessage = previousRunErrorMessage;
+        this.isActive = isActive;
+        this.isDeleted = isDeleted;
+        this.runAsUser = runAsUser;
+    }
+    
+    /** 
+     * create a new instance of the ReportMailingJob for a new entry
+     * 
+     * @return ReportMailingJob object
+     **/
+    public static ReportMailingJob newInstance(final String name, final String description, final LocalDateTime startDateTime, final String recurrence, 
+            final String emailRecipients, final String emailSubject, final String emailMessage, 
+            final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat, final Report stretchyReport, final String stretchyReportParamMap, 
+            final boolean isActive, final AppUser runAsUser) {
+        return new ReportMailingJob(name, description, startDateTime, recurrence, emailRecipients, emailSubject, 
+                emailMessage, emailAttachmentFileFormat, stretchyReport, stretchyReportParamMap, null, null, null, null, null, isActive, false, runAsUser);
+    }
+    
+    /** 
+     * create a new instance of the ReportmailingJob for a new entry 
+     * 
+     * @return ReportMailingJob object
+     **/
+    public static ReportMailingJob newInstance(JsonCommand jsonCommand, final Report stretchyReport, 
+            final AppUser runAsUser) {
+        final String name = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.NAME_PARAM_NAME);
+        final String description = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.DESCRIPTION_PARAM_NAME);
+        final String recurrence = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.RECURRENCE_PARAM_NAME);
+        final boolean isActive = jsonCommand.booleanPrimitiveValueOfParameterNamed(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME);
+        final String emailRecipients = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME);
+        final String emailSubject = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME);
+        final String emailMessage = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME);
+        final String stretchyReportParamMap = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.STRETCHY_REPORT_PARAM_MAP_PARAM_NAME);
+        final Integer emailAttachmentFileFormatId = jsonCommand.integerValueOfParameterNamed(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME);
+        final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat.newInstance(emailAttachmentFileFormatId);
+        LocalDateTime startDateTime = new LocalDateTime();
+        
+        if (jsonCommand.hasParameter(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME)) {
+            final String startDateTimeString = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME);
+            
+            if (startDateTimeString != null) {
+                final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
+                startDateTime = LocalDateTime.parse(startDateTimeString, dateTimeFormatter); 
+            }
+        }
+        
+        return new ReportMailingJob(name, description, startDateTime, recurrence, emailRecipients, emailSubject, 
+                emailMessage, emailAttachmentFileFormat, stretchyReport, stretchyReportParamMap, null, startDateTime, null, null, null, isActive, false, runAsUser);
+    }
+    
+    /** 
+     * Update the ReportMailingJob entity 
+     * 
+     * @param jsonCommand JsonCommand object
+     * @return map of string to object
+     **/
+    public Map<String, Object> update(final JsonCommand jsonCommand) {
+        final Map<String, Object> actualChanges = new LinkedHashMap<>();
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.NAME_PARAM_NAME, this.name)) {
+            final String name = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.NAME_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.NAME_PARAM_NAME, name);
+            
+            this.name = name;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.DESCRIPTION_PARAM_NAME, this.description)) {
+            final String description = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.DESCRIPTION_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.DESCRIPTION_PARAM_NAME, description);
+            
+            this.description = description;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.RECURRENCE_PARAM_NAME, this.recurrence)) {
+            final String recurrence = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.RECURRENCE_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.RECURRENCE_PARAM_NAME, recurrence);
+            
+            this.recurrence = recurrence;
+        }
+        
+        if (jsonCommand.isChangeInBooleanParameterNamed(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME, this.isActive)) {
+            final boolean isActive = jsonCommand.booleanPrimitiveValueOfParameterNamed(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME, isActive);
+            
+            this.isActive = isActive;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME, this.emailRecipients)) {
+            final String emailRecipients = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME, emailRecipients);
+            
+            this.emailRecipients = emailRecipients;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME, this.emailSubject)) {
+            final String emailSubject = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME, emailSubject);
+            
+            this.emailSubject = emailSubject;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME, this.emailMessage)) {
+            final String emailMessage = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME, emailMessage);
+            
+            this.emailMessage = emailMessage;
+        }
+        
+        if (jsonCommand.isChangeInStringParameterNamed(ReportMailingJobConstants.STRETCHY_REPORT_PARAM_MAP_PARAM_NAME, this.stretchyReportParamMap)) {
+            final String stretchyReportParamMap = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.STRETCHY_REPORT_PARAM_MAP_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.STRETCHY_REPORT_PARAM_MAP_PARAM_NAME, stretchyReportParamMap);
+            
+            this.stretchyReportParamMap = stretchyReportParamMap;
+        }
+        
+        final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat.newInstance(this.emailAttachmentFileFormat);
+        
+        if (jsonCommand.isChangeInIntegerParameterNamed(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, emailAttachmentFileFormat.getId())) {
+            final Integer emailAttachmentFileFormatId = jsonCommand.integerValueOfParameterNamed(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, emailAttachmentFileFormatId);
+            
+            final ReportMailingJobEmailAttachmentFileFormat newEmailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat.newInstance(emailAttachmentFileFormatId);
+            this.emailAttachmentFileFormat = newEmailAttachmentFileFormat.getValue();
+        }
+        
+        final String newStartDateTimeString = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME);
+        
+        if (!StringUtils.isEmpty(newStartDateTimeString)) {
+            final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
+            final LocalDateTime newStartDateTime = LocalDateTime.parse(newStartDateTimeString, dateTimeFormatter);
+            final LocalDateTime oldStartDateTime = (this.startDateTime != null) ? new LocalDateTime(this.startDateTime) : null;
+            
+            if ((oldStartDateTime != null) && !newStartDateTime.equals(oldStartDateTime)) {
+                actualChanges.put(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME, newStartDateTimeString);
+                
+                this.startDateTime = newStartDateTime.toDate();
+            }
+        }
+        
+        Long currentStretchyReportId = null;
+        
+        if (this.stretchyReport != null) {
+            currentStretchyReportId = this.stretchyReport.getId();
+        }
+        
+        if (jsonCommand.isChangeInLongParameterNamed(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME, currentStretchyReportId)) {
+            final Long updatedStretchyReportId = jsonCommand.longValueOfParameterNamed(
+                    ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME);
+            actualChanges.put(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME, updatedStretchyReportId);
+        }
+        
+        return actualChanges;
+    }
+    
+    /** 
+     * update the stretchy report entity associated with the credit check 
+     * 
+     * @param stretchyReport -- Report entity
+     * @return None
+     **/
+    public void update(final Report stretchyReport) {
+        if (stretchyReport != null) {
+            this.stretchyReport = stretchyReport;
+        }
+    }
+    
+    /** 
+     * delete the report mailing job, set the isDeleted property to 1 and alter the name 
+     * 
+     * @return None
+     **/
+    public void delete() {
+        this.isDeleted = true;
+        this.isActive = false;
+        this.name = this.name + "_deleted_" + this.getId();
+    }
+    
+    /** 
+     * @return the value of the name property 
+     **/
+    public String getName() {
+        return this.name;
+    }
+    
+    /** 
+     * @return the value of the description property 
+     **/
+    public String getDescription() {
+        return this.description;
+    }
+    
+    /** 
+     * @return the value of the startDateTime property 
+     **/
+    public DateTime getStartDateTime() {
+        return (this.startDateTime != null) ? new DateTime(this.startDateTime) : null;
+    }
+    
+    /** 
+     * @return the value of the recurrence property 
+     **/
+    public String getRecurrence() {
+        return this.recurrence;
+    }
+    
+    /** 
+     * @return value of the isDeleted property 
+     **/
+    public boolean isDeleted() {
+        return this.isDeleted;
+    }
+    
+    /** 
+     * @return boolean true if isDeleted property equals 0, else false 
+     **/
+    public boolean isNotDeleted() {
+        return !this.isDeleted;
+    }
+    
+    /** 
+     * @return the value of the isActive property 
+     **/
+    public boolean isActive() {
+        return this.isActive;
+    }
+    
+    /** 
+     * @return boolean true if isActive property equals 0, else false 
+     **/
+    public boolean isNotActive() {
+        return !this.isActive;
+    }
+
+    /**
+     * @return the emailRecipients
+     */
+    public String getEmailRecipients() {
+        return emailRecipients;
+    }
+
+    /**
+     * @return the emailSubject
+     */
+    public String getEmailSubject() {
+        return emailSubject;
+    }
+
+    /**
+     * @return the emailMessage
+     */
+    public String getEmailMessage() {
+        return emailMessage;
+    }
+
+    /**
+     * @return the emailAttachmentFileFormat
+     */
+    public String getEmailAttachmentFileFormat() {
+        return emailAttachmentFileFormat;
+    }
+
+    /**
+     * @return the stretchyReport
+     */
+    public Report getStretchyReport() {
+        return stretchyReport;
+    }
+
+    /**
+     * @return the stretchyReportParamMap
+     */
+    public String getStretchyReportParamMap() {
+        return stretchyReportParamMap;
+    }
+
+    /**
+     * @return the previousRunDateTime
+     */
+    public DateTime getPreviousRunDateTime() {
+        return (this.previousRunDateTime != null) ? new DateTime(this.previousRunDateTime) : null;
+    }
+
+    /**
+     * @return the nextRunDateTime
+     */
+    public DateTime getNextRunDateTime() {
+        return (this.nextRunDateTime != null) ? new DateTime(this.nextRunDateTime) : null;
+    }
+
+    /**
+     * @return the previousRunStatus
+     */
+    public String getPreviousRunStatus() {
+        return previousRunStatus;
+    }
+
+    /**
+     * @return the previousRunErrorLog
+     */
+    public String getPreviousRunErrorLog() {
+        return previousRunErrorLog;
+    }
+
+    /**
+     * @return the previousRunErrorMessage
+     */
+    public String getPreviousRunErrorMessage() {
+        return previousRunErrorMessage;
+    }
+
+    /**
+     * @return the numberOfRuns
+     */
+    public Integer getNumberOfRuns() {
+        return numberOfRuns;
+    }
+
+    /**
+     * @return the runAsUser
+     */
+    public AppUser getRunAsUser() {
+        return runAsUser;
+    }
+    
+    /** 
+     * increase the numberOfRuns by 1 
+     * 
+     * @return None
+     **/
+    public void increaseNumberOfRunsByOne() {
+        this.numberOfRuns++;
+    }
+    
+    /** 
+     * update the previousRunStatus 
+     * 
+     * @param previousRunStatus -- the status of the previous job execution
+     * @return None
+     **/
+    public void updatePreviousRunStatus(final String previousRunStatus) {
+        if (!StringUtils.isEmpty(previousRunStatus)) {
+            this.previousRunStatus = previousRunStatus;
+        }
+    }
+    
+    /** 
+     * update the previousRunDateTime
+     * 
+     * @param previousRunDateTime -- previous run date
+     * @return None
+     **/
+    public void updatePreviousRunDateTime(final DateTime previousRunDateTime) {
+        if (previousRunDateTime != null) {
+            this.previousRunDateTime = previousRunDateTime.toDate();
+        }
+    }
+    
+    /** 
+     * update the nextRunDateTime
+     * 
+     * @param nextRunDateTime -- the next run DateTime
+     * @return None
+     **/
+    public void updateNextRunDateTime(final DateTime nextRunDateTime) {
+        if (nextRunDateTime != null) {
+            this.nextRunDateTime = nextRunDateTime.toDate();
+        }
+        
+        else {
+            this.nextRunDateTime = null;
+        }
+    }
+    
+    /** 
+     * deactivate the report mailing job by setting the isActive property to 0 
+     * 
+     * @return None
+     **/
+    public void deactivate() {
+        this.isActive = false;
+    }
+    
+    /** 
+     * update the previousRunErrorLog property
+     * 
+     * @param previousRunErrorLog -- the previous job run error log
+     * @return None
+     **/
+    public void updatePreviousRunErrorLog(final String previousRunErrorLog) {
+        this.previousRunErrorLog = previousRunErrorLog;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfiguration.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfiguration.java
new file mode 100644
index 0000000..17eb7b6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfiguration.java
@@ -0,0 +1,74 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.springframework.data.jpa.domain.AbstractPersistable;
+
+@Entity
+@Table(name = "m_report_mailing_job_configuration", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unique_name") })
+public class ReportMailingJobConfiguration extends AbstractPersistable<Integer> {
+    private static final long serialVersionUID = 3099279770861263184L;
+
+    @Column(name = "name", nullable = false)
+    private String name;
+    
+    @Column(name = "value", nullable = false)
+    private String value;
+    
+    /** 
+     * ReportMailingJobConfiguration protected constructor
+     **/
+    protected ReportMailingJobConfiguration() { }
+    
+    /** 
+     * ReportMailingJobConfiguration private constructor
+     **/
+    private ReportMailingJobConfiguration(final String name, final String value) {
+        this.name = name;
+        this.value = value;
+    }
+    
+    /** 
+     * creates an instance of the ReportMailingJobConfiguration class
+     * 
+     * @return ReportMailingJobConfiguration object
+     **/
+    public static ReportMailingJobConfiguration newInstance(final String name, final String value) {
+        return new ReportMailingJobConfiguration(name, value);
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfigurationRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfigurationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfigurationRepository.java
new file mode 100644
index 0000000..8e7168e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobConfigurationRepository.java
@@ -0,0 +1,31 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ReportMailingJobConfigurationRepository extends JpaRepository<ReportMailingJobConfiguration, Integer>, 
+        JpaSpecificationExecutor<ReportMailingJobConfiguration> {
+    
+    /** 
+     * find ReportMailingJobConfiguration by name 
+     **/
+    ReportMailingJobConfiguration findByName(final String name);
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepository.java
new file mode 100644
index 0000000..94268d8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepository.java
@@ -0,0 +1,33 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import java.util.Collection;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ReportMailingJobRepository extends JpaRepository<ReportMailingJob, Long>, JpaSpecificationExecutor<ReportMailingJob> {
+    /**
+     * Returns all instances of {@link ReportMailingJob} where isActive is true and isDeleted is false
+     * 
+     * @return instances of {@link ReportMailingJob}
+     */
+    public Collection<ReportMailingJob> findByIsActiveTrueAndIsDeletedFalse();
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepositoryWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepositoryWrapper.java
new file mode 100644
index 0000000..ad9e84e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRepositoryWrapper.java
@@ -0,0 +1,56 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import org.apache.fineract.infrastructure.reportmailingjob.exception.ReportMailingJobNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReportMailingJobRepositoryWrapper {
+    private final ReportMailingJobRepository reportMailingJobRepository;
+    
+    @Autowired
+    public ReportMailingJobRepositoryWrapper(final ReportMailingJobRepository reportMailingJobRepository) {
+        this.reportMailingJobRepository = reportMailingJobRepository;
+    }
+    
+    /** 
+     * find report mailing job by ID, throw a "entity not found" exception if the job does not exist
+     * 
+     * @param id -- the identifier of the report mailing job to be found
+     * @return ReportMailingJob object
+     **/
+    public ReportMailingJob findOneThrowExceptionIfNotFound(final Long id) {
+        final ReportMailingJob reportMailingJob = this.reportMailingJobRepository.findOne(id);
+        
+        if (reportMailingJob == null || reportMailingJob.isDeleted()) {
+            throw new ReportMailingJobNotFoundException(id);
+        }
+        
+        return reportMailingJob;
+    }
+    
+    /** 
+     * @return ReportMailingJobRepository Jpa Repository object
+     **/
+    public ReportMailingJobRepository getReportMailingJobRepository() {
+        return this.reportMailingJobRepository;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistory.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistory.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistory.java
new file mode 100644
index 0000000..4839ed6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistory.java
@@ -0,0 +1,139 @@
+/**
+ * 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.reportmailingjob.domain;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.joda.time.DateTime;
+import org.springframework.data.jpa.domain.AbstractPersistable;
+
+@Entity
+@Table(name = "m_report_mailing_job_run_history")
+public class ReportMailingJobRunHistory extends AbstractPersistable<Long> {
+    private static final long serialVersionUID = -3757370929988421076L;
+
+    @ManyToOne
+    @JoinColumn(name = "job_id", nullable = false)
+    private ReportMailingJob reportMailingJob;
+    
+    @Column(name = "start_datetime", nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date startDateTime;
+    
+    @Column(name = "end_datetime", nullable = false)
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date endDateTime;
+    
+    @Column(name = "status", nullable = false)
+    private String status;
+    
+    @Column(name = "error_message", nullable = false)
+    private String errorMessage;
+    
+    @Column(name = "error_log", nullable = false)
+    private String errorLog;
+    
+    /** 
+     * ReportMailingJobRunHistory protected constructor 
+     **/
+    protected ReportMailingJobRunHistory() { }
+
+    /** 
+     * ReportMailingJobRunHistory private constructor
+     **/
+    private ReportMailingJobRunHistory(final ReportMailingJob reportMailingJob, final DateTime startDateTime, final DateTime endDateTime, final String status,
+            final String errorMessage, final String errorLog) {
+        this.reportMailingJob = reportMailingJob;
+        this.startDateTime = null;
+        
+        if (startDateTime != null) {
+            this.startDateTime = startDateTime.toDate();
+        }
+        
+        this.endDateTime = null;
+        
+        if (endDateTime != null) {
+            this.endDateTime = endDateTime.toDate();
+        }
+        
+        this.status = status;
+        this.errorMessage = errorMessage;
+        this.errorLog = errorLog;
+    } 
+    
+    /** 
+     * Creates an instance of the ReportMailingJobRunHistory class
+     * 
+     * @return ReportMailingJobRunHistory object
+     **/
+    public static ReportMailingJobRunHistory newInstance(final ReportMailingJob reportMailingJob, final DateTime startDateTime, final DateTime endDateTime, 
+            final String status, final String errorMessage, final String errorLog) {
+        return new ReportMailingJobRunHistory(reportMailingJob, startDateTime, endDateTime, status, errorMessage, errorLog);
+    }
+
+    /**
+     * @return the reportMailingJobId
+     */
+    public ReportMailingJob getReportMailingJob() {
+        return this.reportMailingJob;
+    }
+
+    /**
+     * @return the startDateTime
+     */
+    public DateTime getStartDateTime() {
+        return (this.startDateTime != null) ? new DateTime(this.startDateTime) : null;
+    }
+
+    /**
+     * @return the endDateTime
+     */
+    public DateTime getEndDateTime() {
+        return (this.endDateTime != null) ? new DateTime(this.endDateTime) : null;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @return the errorMessage
+     */
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    /**
+     * @return the errorLog
+     */
+    public String getErrorLog() {
+        return errorLog;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistoryRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistoryRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistoryRepository.java
new file mode 100644
index 0000000..be6cdfa
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/domain/ReportMailingJobRunHistoryRepository.java
@@ -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.
+ */
+package org.apache.fineract.infrastructure.reportmailingjob.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface ReportMailingJobRunHistoryRepository extends JpaRepository<ReportMailingJobRunHistory, Long>, JpaSpecificationExecutor<ReportMailingJobRunHistory> {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobConfigurationNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobConfigurationNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobConfigurationNotFoundException.java
new file mode 100644
index 0000000..9d45449
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobConfigurationNotFoundException.java
@@ -0,0 +1,33 @@
+/**
+ * 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.reportmailingjob.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+/**
+ * A {@link RuntimeException} thrown when report mailing job configuration resources are not found.
+ **/
+@SuppressWarnings("serial")
+public class ReportMailingJobConfigurationNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+    public ReportMailingJobConfigurationNotFoundException(final String name) {
+        super("error.msg.report.mailing.job.configuration.name.invalid", "Report mailing job configuration with name " + name + 
+                " does not exist", name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobNotFoundException.java
new file mode 100644
index 0000000..b8e6626
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobNotFoundException.java
@@ -0,0 +1,33 @@
+/**
+ * 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.reportmailingjob.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+/**
+ * A {@link RuntimeException} thrown when report mailing job resources are not found.
+ **/
+@SuppressWarnings("serial")
+public class ReportMailingJobNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+    public ReportMailingJobNotFoundException(final Long reportMailingJobId) {
+        super("error.msg.report.mailing.job.id.invalid", "Report mailing job with identifier " + reportMailingJobId + 
+                " does not exist", reportMailingJobId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobRunHistoryNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobRunHistoryNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobRunHistoryNotFoundException.java
new file mode 100644
index 0000000..a69999b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/exception/ReportMailingJobRunHistoryNotFoundException.java
@@ -0,0 +1,32 @@
+/**
+ * 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.reportmailingjob.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+/**
+ * A {@link RuntimeException} thrown when report mailing job run history resources are not found.
+ **/
+@SuppressWarnings("serial")
+public class ReportMailingJobRunHistoryNotFoundException extends AbstractPlatformResourceNotFoundException {
+    public ReportMailingJobRunHistoryNotFoundException(final Long reportMailingJobId) {
+        super("error.msg.report.mailing.job.run.history.invalid", "Report mailing job run history with job identifier "
+                + reportMailingJobId + " does not exist", reportMailingJobId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/CreateReportMailingJobCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/CreateReportMailingJobCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/CreateReportMailingJobCommandHandler.java
new file mode 100644
index 0000000..501caed
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/CreateReportMailingJobCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * 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.reportmailingjob.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, action = "CREATE")
+public class CreateReportMailingJobCommandHandler implements NewCommandSourceHandler {
+    private final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService;
+    
+    @Autowired
+    public CreateReportMailingJobCommandHandler(final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService) {
+        this.reportMailingJobWritePlatformService = reportMailingJobWritePlatformService;
+    }
+
+    @Override
+    @Transactional
+    public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
+        return this.reportMailingJobWritePlatformService.createReportMailingJob(jsonCommand);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/DeleteReportMailingJobCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/DeleteReportMailingJobCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/DeleteReportMailingJobCommandHandler.java
new file mode 100644
index 0000000..51d57d7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/DeleteReportMailingJobCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * 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.reportmailingjob.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, action = "DELETE")
+public class DeleteReportMailingJobCommandHandler implements NewCommandSourceHandler {
+    private final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService;
+    
+    @Autowired
+    public DeleteReportMailingJobCommandHandler(final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService) {
+        this.reportMailingJobWritePlatformService = reportMailingJobWritePlatformService;
+    }
+
+    @Override
+    @Transactional
+    public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
+        return this.reportMailingJobWritePlatformService.deleteReportMailingJob(jsonCommand.entityId());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/UpdateReportMailingJobCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/UpdateReportMailingJobCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/UpdateReportMailingJobCommandHandler.java
new file mode 100644
index 0000000..7622ca6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/handler/UpdateReportMailingJobCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * 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.reportmailingjob.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@CommandType(entity = ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, action = "UPDATE")
+public class UpdateReportMailingJobCommandHandler implements NewCommandSourceHandler {
+    private final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService;
+    
+    @Autowired
+    public UpdateReportMailingJobCommandHandler(final ReportMailingJobWritePlatformService reportMailingJobWritePlatformService) {
+        this.reportMailingJobWritePlatformService = reportMailingJobWritePlatformService;
+    }
+
+    @Override
+    @Transactional
+    public CommandProcessingResult processCommand(JsonCommand jsonCommand) {
+        return this.reportMailingJobWritePlatformService.updateReportMailingJob(jsonCommand.entityId(), jsonCommand);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformService.java
new file mode 100644
index 0000000..4812ae0
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformService.java
@@ -0,0 +1,39 @@
+/**
+ * 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.reportmailingjob.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobConfigurationData;
+
+public interface ReportMailingJobConfigurationReadPlatformService {
+    /** 
+     * Retrieve all report mailing job configurations
+     * 
+     * @return ReportMailingJobConfigurationData object
+     **/
+    Collection<ReportMailingJobConfigurationData> retrieveAllReportMailingJobConfigurations();
+    
+    /** 
+     * Retrieve report mailing job configuration by name
+     * 
+     * @return ReportMailingJobConfigurationData object
+     **/
+    ReportMailingJobConfigurationData retrieveReportMailingJobConfiguration(final String name);
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformServiceImpl.java
new file mode 100644
index 0000000..fd8dfac
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobConfigurationReadPlatformServiceImpl.java
@@ -0,0 +1,84 @@
+/**
+ * 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.reportmailingjob.service;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobConfigurationData;
+import org.apache.fineract.infrastructure.reportmailingjob.exception.ReportMailingJobConfigurationNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReportMailingJobConfigurationReadPlatformServiceImpl implements ReportMailingJobConfigurationReadPlatformService {
+    private final JdbcTemplate jdbcTemplate;
+    
+    /** 
+     * ReportMailingJobConfigurationReadPlatformServiceImpl constructor
+     **/
+    @Autowired
+    public ReportMailingJobConfigurationReadPlatformServiceImpl(final RoutingDataSource dataSource) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+    }
+    
+    @Override
+    public Collection<ReportMailingJobConfigurationData> retrieveAllReportMailingJobConfigurations() {
+        final ReportMailingJobConfigurationMapper mapper = new ReportMailingJobConfigurationMapper();
+        final String sql = "select " + mapper.ReportMailingJobConfigurationSchema();
+        
+        return this.jdbcTemplate.query(sql, mapper, new Object[] {});
+    }
+
+    @Override
+    public ReportMailingJobConfigurationData retrieveReportMailingJobConfiguration(String name) {
+        try {
+            final ReportMailingJobConfigurationMapper mapper = new ReportMailingJobConfigurationMapper();
+            final String sql = "select " + mapper.ReportMailingJobConfigurationSchema() + " where rmjc.name = ?";
+            
+            return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { name });
+        }
+        
+        catch (final EmptyResultDataAccessException ex) {
+            throw new ReportMailingJobConfigurationNotFoundException(name);
+        }
+    }
+    
+    private static final class ReportMailingJobConfigurationMapper implements RowMapper<ReportMailingJobConfigurationData> {
+        public String ReportMailingJobConfigurationSchema() {
+            return "rmjc.id, rmjc.name, rmjc.value "
+                    + "from m_report_mailing_job_configuration rmjc";
+        }
+        
+        @Override
+        public ReportMailingJobConfigurationData mapRow(ResultSet rs, int rowNum) throws SQLException {
+            final Integer id = JdbcSupport.getInteger(rs, "id");
+            final String name = rs.getString("name");
+            final String value = rs.getString("value");
+            
+            return ReportMailingJobConfigurationData.newInstance(id, name, value);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailService.java
new file mode 100644
index 0000000..5df05a3
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailService.java
@@ -0,0 +1,30 @@
+/**
+ * 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.reportmailingjob.service;
+
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailData;
+
+public interface ReportMailingJobEmailService {
+    /**
+     * Handles request to send an email with attachment
+     * 
+     * @param reportMailingJobEmailData {@link ReportMailingJobEmailData} object
+     */
+    void sendEmailWithAttachment(final ReportMailingJobEmailData reportMailingJobEmailData);
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailServiceImpl.java
new file mode 100644
index 0000000..58bb09a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobEmailServiceImpl.java
@@ -0,0 +1,162 @@
+/**
+ * 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.reportmailingjob.service;
+
+import java.util.Collection;
+import java.util.Properties;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobConfigurationData;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ReportMailingJobEmailServiceImpl implements ReportMailingJobEmailService {
+    private final ReportMailingJobConfigurationReadPlatformService reportMailingJobConfigurationReadPlatformService;
+    private Collection<ReportMailingJobConfigurationData> reportMailingJobConfigurationDataCollection;
+    
+    /** 
+     * ReportMailingJobEmailServiceImpl constructor
+     **/
+    @Autowired
+    public ReportMailingJobEmailServiceImpl(final ReportMailingJobConfigurationReadPlatformService reportMailingJobConfigurationReadPlatformService) {
+        this.reportMailingJobConfigurationReadPlatformService = reportMailingJobConfigurationReadPlatformService;
+        
+    }
+
+    @Override
+    public void sendEmailWithAttachment(ReportMailingJobEmailData reportMailingJobEmailData) {
+        try {
+            // get all ReportMailingJobConfiguration objects from the database
+            this.reportMailingJobConfigurationDataCollection = this.reportMailingJobConfigurationReadPlatformService.
+                    retrieveAllReportMailingJobConfigurations();
+            
+            JavaMailSenderImpl javaMailSenderImpl = new JavaMailSenderImpl();
+            javaMailSenderImpl.setHost(this.getGmailSmtpServer());
+            javaMailSenderImpl.setPort(this.getGmailSmtpPort());
+            javaMailSenderImpl.setUsername(this.getGmailSmtpUsername());
+            javaMailSenderImpl.setPassword(this.getGmailSmtpPassword());
+            javaMailSenderImpl.setJavaMailProperties(this.getJavaMailProperties());
+            
+            MimeMessage mimeMessage = javaMailSenderImpl.createMimeMessage();
+            
+            // use the true flag to indicate you need a multipart message
+            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
+            
+            mimeMessageHelper.setTo(reportMailingJobEmailData.getTo());
+            mimeMessageHelper.setText(reportMailingJobEmailData.getText());
+            mimeMessageHelper.setSubject(reportMailingJobEmailData.getSubject());
+            
+            if (reportMailingJobEmailData.getAttachment() != null) {
+                mimeMessageHelper.addAttachment(reportMailingJobEmailData.getAttachment().getName(), reportMailingJobEmailData.getAttachment());
+            }
+            
+            javaMailSenderImpl.send(mimeMessage);
+        } 
+        
+        catch (MessagingException e) {
+            // handle the exception
+            e.printStackTrace();
+        }
+    }
+    
+    /** 
+     * @return Properties object containing JavaMail properties 
+     **/
+    private Properties getJavaMailProperties() {
+        Properties properties = new Properties();
+        
+        properties.setProperty("mail.smtp.auth", "true");
+        properties.setProperty("mail.smtp.starttls.enable", "true");
+        properties.setProperty("mail.smtp.ssl.trust", this.getGmailSmtpServer());
+        
+        return properties;
+    }
+    
+    /** 
+     * get a report mailing job configuration object by name from collection of objects 
+     * 
+     * @param name -- the value of the name property
+     * @return ReportMailingJobConfigurationData object
+     **/
+    private ReportMailingJobConfigurationData getReportMailingJobConfigurationData(final String name) {
+        ReportMailingJobConfigurationData reportMailingJobConfigurationData = null;
+        
+        if (this.reportMailingJobConfigurationDataCollection != null && !this.reportMailingJobConfigurationDataCollection.isEmpty()) {
+            for (ReportMailingJobConfigurationData reportMailingJobConfigurationDataObject : this.reportMailingJobConfigurationDataCollection) {
+                String configurationName = reportMailingJobConfigurationDataObject.getName();
+                
+                if (!StringUtils.isEmpty(configurationName) && configurationName.equals(name)) {
+                    reportMailingJobConfigurationData = reportMailingJobConfigurationDataObject;
+                    break;
+                }
+            }
+        }
+        
+        return reportMailingJobConfigurationData;
+    }
+    
+    /** 
+     * @return Gmail smtp server name 
+     **/
+    private String getGmailSmtpServer() {
+        final ReportMailingJobConfigurationData reportMailingJobConfigurationData = this.getReportMailingJobConfigurationData
+                (ReportMailingJobConstants.GMAIL_SMTP_SERVER);
+        
+        return (reportMailingJobConfigurationData != null) ? reportMailingJobConfigurationData.getValue() : null;
+    }
+    
+    /** 
+     * @return Gmail smtp server port number 
+     **/
+    private Integer getGmailSmtpPort() {
+        final ReportMailingJobConfigurationData reportMailingJobConfigurationData = this.getReportMailingJobConfigurationData
+                (ReportMailingJobConstants.GMAIL_SMTP_PORT);
+        final String portNumber = (reportMailingJobConfigurationData != null) ? reportMailingJobConfigurationData.getValue() : null;
+        
+        return (portNumber != null) ? Integer.parseInt(portNumber) : null;
+    }
+    
+    /** 
+     * @return Gmail smtp username 
+     **/
+    private String getGmailSmtpUsername() {
+        final ReportMailingJobConfigurationData reportMailingJobConfigurationData = this.getReportMailingJobConfigurationData
+                (ReportMailingJobConstants.GMAIL_SMTP_USERNAME);
+        
+        return (reportMailingJobConfigurationData != null) ? reportMailingJobConfigurationData.getValue() : null;
+    }
+    
+    /** 
+     * @return Gmail smtp password 
+     **/
+    private String getGmailSmtpPassword() {
+        final ReportMailingJobConfigurationData reportMailingJobConfigurationData = this.getReportMailingJobConfigurationData
+                (ReportMailingJobConstants.GMAIL_SMTP_PASSWORD);
+        
+        return (reportMailingJobConfigurationData != null) ? reportMailingJobConfigurationData.getValue() : null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobReadPlatformService.java
new file mode 100644
index 0000000..3ac274d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/service/ReportMailingJobReadPlatformService.java
@@ -0,0 +1,47 @@
+/**
+ * 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.reportmailingjob.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobData;
+
+public interface ReportMailingJobReadPlatformService {
+    /** 
+     * Retrieve all report mailing jobs that have the isDeleted property set to 0  
+     **/
+    Page<ReportMailingJobData> retrieveAllReportMailingJobs(SearchParameters searchParameters);
+    
+    /** 
+     * Retrieve a report mailing job that has the isDeleted property set to 0 
+     **/
+    ReportMailingJobData retrieveReportMailingJob(Long reportMailingJobId);
+    
+    /** 
+     * Retrieve the report mailing job enumeration/dropdown options 
+     **/
+    ReportMailingJobData retrieveReportMailingJobEnumOptions();
+
+    /** 
+     * Retrieve all active report mailing jobs that have their isDeleted property set to 0 
+     **/
+    Collection<ReportMailingJobData> retrieveAllActiveReportMailingJobs();
+}