fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject [3/5] incubator-fineract git commit: commit for FINERACT-65 (Implement ability to schedule & e-mail reports)
Date Fri, 12 Aug 2016 03:39:55 GMT
commit for FINERACT-65 (Implement ability to schedule & e-mail reports)


Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/b30976bb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/b30976bb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/b30976bb

Branch: refs/heads/develop
Commit: b30976bbfd0663deddcdb510e49f5bda06a46462
Parents: 5647ffb
Author: Emmanuel Nnaa <emmanuelnnaa@musoni.eu>
Authored: Tue Aug 2 12:29:15 2016 +0200
Committer: Emmanuel Nnaa <emmanuelnnaa@musoni.eu>
Committed: Mon Aug 8 14:18:11 2016 +0200

----------------------------------------------------------------------
 api-docs/apiLive.htm                            | 444 +++++++++++++++
 .../commands/service/CommandWrapperBuilder.java |  25 +-
 .../core/service/SearchParameters.java          |  31 +-
 .../domain/ReportRepositoryWrapper.java         |  54 ++
 .../service/ReadReportingServiceImpl.java       |   3 +-
 .../infrastructure/jobs/service/JobName.java    |   3 +-
 .../ReportMailingJobConstants.java              |  88 +++
 .../api/ReportMailingJobApiResource.java        | 162 ++++++
 .../ReportMailingJobRunHistoryApiResource.java  |  80 +++
 .../data/ReportMailingJobConfigurationData.java |  67 +++
 .../data/ReportMailingJobData.java              | 272 +++++++++
 ...portMailingJobEmailAttachmentFileFormat.java | 176 ++++++
 .../data/ReportMailingJobEmailData.java         |  66 +++
 .../data/ReportMailingJobPreviousRunStatus.java |  90 +++
 .../data/ReportMailingJobRunHistoryData.java    | 107 ++++
 ...MailingJobStretchyReportParamDateOption.java | 166 ++++++
 .../data/ReportMailingJobTimelineData.java      |  59 ++
 .../domain/ReportMailingJob.java                | 558 +++++++++++++++++++
 .../domain/ReportMailingJobConfiguration.java   |  74 +++
 ...ReportMailingJobConfigurationRepository.java |  31 ++
 .../domain/ReportMailingJobRepository.java      |  33 ++
 .../ReportMailingJobRepositoryWrapper.java      |  56 ++
 .../domain/ReportMailingJobRunHistory.java      | 139 +++++
 .../ReportMailingJobRunHistoryRepository.java   |  26 +
 ...ailingJobConfigurationNotFoundException.java |  33 ++
 .../ReportMailingJobNotFoundException.java      |  33 ++
 ...rtMailingJobRunHistoryNotFoundException.java |  32 ++
 .../CreateReportMailingJobCommandHandler.java   |  46 ++
 .../DeleteReportMailingJobCommandHandler.java   |  46 ++
 .../UpdateReportMailingJobCommandHandler.java   |  46 ++
 ...lingJobConfigurationReadPlatformService.java |  39 ++
 ...JobConfigurationReadPlatformServiceImpl.java |  84 +++
 .../service/ReportMailingJobEmailService.java   |  30 +
 .../ReportMailingJobEmailServiceImpl.java       | 162 ++++++
 .../ReportMailingJobReadPlatformService.java    |  47 ++
 ...ReportMailingJobReadPlatformServiceImpl.java | 203 +++++++
 ...MailingJobRunHistoryReadPlatformService.java |  34 ++
 ...ingJobRunHistoryReadPlatformServiceImpl.java | 106 ++++
 .../ReportMailingJobWritePlatformService.java   |  30 +
 ...eportMailingJobWritePlatformServiceImpl.java | 495 ++++++++++++++++
 .../util/ReportMailingJobDateUtil.java          | 114 ++++
 .../validation/ReportMailingJobValidator.java   | 319 +++++++++++
 .../core_db/V312__report_mailing_job_module.sql |  61 ++
 43 files changed, 4765 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/api-docs/apiLive.htm
----------------------------------------------------------------------
diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 7fe3fc9..c002f6e 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3040,6 +3040,30 @@
 								<td></td>
 								<td></td>
 							</tr>
+							<tr>
+								<td><a href="#report_mailing_jobs">Report Mailing Job</a></td>
+								<td>reportmailingjob</td>
+								<td><a href="#report_mailing_jobs_create">Create a Report Mailing Job</a></td>
+								<td><a href="#report_mailing_jobs_list">List Reports Mailing Jobs</a></td>
+								<td></td>
+								<td></td>
+							</tr>
+							<tr>
+								<td></td>
+								<td>reportmailingjob/{id}</td>
+								<td></td>
+								<td><a href="#report_mailing_jobs_retrieve">Retrieve a Report Mailing Job</a></td>
+								<td><a href="#report_mailing_jobs_update">Update a Report Mailing Job</a></td>
+								<td><a href="#report_mailing_jobs_delete">Delete a Report Mailing Job</a></td>
+							</tr>
+                            <tr>
+								<td></td>
+								<td>reportmailingjobrunhistory/{jobId}</td>
+								<td></td>
+								<td><a href="#report_mailing_job_history_list">Retrieve Reports Mailing Job History</a></td>
+								<td></td>
+								<td></td>
+							</tr>
 						</table>
 					</div>
 				</div>
@@ -33710,6 +33734,426 @@ GET https://DomainName/api/v1/runreports/{reportName}
 					</code>
 				</div>
 			</div>
+			
+			<!-- start of report mailing jobs api docs -->
+			<a id="report_mailing_jobs" name="report_mailing_jobs" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h3>Report Mailing Jobs</h3>
+					<p>This resource allows you to create a scheduled job that runs a report and sents it by email to specified email addresses.</p>
+					<p>The scheduled job can be configured to run once or on a regular basis (once a day, twice a week, etc).</p>
+					<table class=matrixHeading>
+						<tr class="matrixHeadingBG">
+							<td><div class="fineractHeading2">Field Descriptions</div></td>
+						</tr>
+						<tr class=alt>
+							<td>name</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>The name of the report mailing job. It must be unique.</td>
+						</tr>
+						<tr class=alt>
+							<td>description</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Optional: Description of the report mailing job.</td>
+						</tr>
+						<tr class=alt>
+							<td>startDateTime</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Date and time to start the report mailing job.</td>
+						</tr>
+						<tr class=alt>
+							<td>stretchyReportId</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>The identifier of the stretchy report to be sent.</td>
+						</tr>
+						<tr class=alt>
+							<td>emailRecipients</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Comma separated report recipient email addresses.</td>
+						</tr>
+						<tr class=alt>
+							<td>emailSubject</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>The subject of the email to be sent.</td>
+						</tr>
+						<tr class=alt>
+							<td>emailMessage</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>The body of the email to be sent.</td>
+						</tr>
+						<tr class=alt>
+							<td>emailAttachmentFileFormatId</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>The Enum constant id of the email attachment file format.</td>
+						</tr>
+						<tr class=alt>
+							<td>recurrence</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Rule or repeating pattern for recurring events. See - <a target="_blank" href="http://www.kanzaki.com/docs/ical/rrule.html">http://www.kanzaki.com/docs/ical/rrule.html</a></td>
+						</tr>
+						<tr class=alt>
+							<td>isActive</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Indicates whether or not the scheduler should be created as active.</td>
+						</tr>
+						<tr class=alt>
+							<td>stretchyReportParamMap</td>
+						</tr>
+						<tr>
+							<td class=fielddesc>Optional: A map of the stretchy report parameter names to values.</td>
+						</tr>
+					</table>
+				</div>
+			</div>
+			
+			<a id="report_mailing_jobs_template" name="report_mailing_jobs_template" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>Retrieve Report Mailing Job Details Template</h4>
+					<p>This is a convenience resource. It can be useful when
+						building maintenance user interface screens for report mailing job
+						applications. The template data returned consists of any or all
+						of:
+					<ul>
+						<li class=normalli>Field Defaults</li>
+						<li class=normalli>Allowed Value Lists</li>
+					</ul>
+					</p>
+					<p>Example Request:</p>
+					<div class=apiClick>reportmailingjobs/template</div>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+GET https://DomainName/api/v1/reportmailingjobs/template
+					</code>
+					<code class="method-response">
+{
+    "isActive": false,
+    "emailAttachmentFileFormatOptions": [
+        {
+          "id": 1,
+          "code": "ReportMailingJobEmailAttachmentFileFormat.xls",
+          "value": "xls"
+        },
+        {
+          "id": 2,
+          "code": "ReportMailingJobEmailAttachmentFileFormat.pdf",
+          "value": "pdf"
+        },
+        {
+          "id": 3,
+          "code": "ReportMailingJobEmailAttachmentFileFormat.csv",
+          "value": "csv"
+        }
+    ],
+    "stretchyReportParamDateOptions": [
+        {
+          "id": 1,
+          "code": "reportMailingJobStretchyReportParamDateOption.today",
+          "value": "today"
+        },
+        {
+          "id": 2,
+          "code": "reportMailingJobStretchyReportParamDateOption.yesterday",
+          "value": "yesterday"
+        },
+        {
+          "id": 3,
+          "code": "reportMailingJobStretchyReportParamDateOption.tomorrow",
+          "value": "tomorrow"
+        }
+    ]
+}
+					</code>
+				</div>
+			</div>
+            
+            <a id="report_mailing_jobs_retrieve" name="report_mailing_jobs_retrieve" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>Retrieve a Report Mailing Job</h4>
+					<p>Example Requests:</p>
+					<div class=apiClick>reportmailingjobs/1</div>
+					<br>
+					<br>
+					<div class=apiClick>reportmailingjobs/1?template=true</div>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+GET https://DomainName/api/v1/reportmailingjobs/{id}
+					</code>
+					<code class="method-response">
+{
+    "id": 1,
+    "name": "Client Numbers Report",
+    "description": "Client Numbers Report",
+    "startDateTime": 1469627093000,
+    "recurrence": "",
+    "timeline": {
+        "createdOnDate": [
+            2016,
+            7,
+            27
+        ],
+        "createdByUsername": "musoni",
+        "createdByFirstname": "firstname",
+        "createdByLastname": "lastname"
+    },
+    "emailRecipients": "info@musonisystem.com",
+    "emailSubject": "Client Numbers Report",
+    "emailMessage": "Client Numbers Report",
+    "emailAttachmentFileFormat": {
+        "id": 1,
+        "code": "ReportMailingJobEmailAttachmentFileFormat.xls",
+        "value": "xls"
+    },
+    "stretchyReport": {
+        "id": 120,
+        "reportName": "Client Numbers Report",
+        "reportType": "Pentaho",
+        "reportCategory": "Client",
+        "description": "",
+        "coreReport": false,
+        "useReport": true
+    },
+    "stretchyReportParamMap": "{\"startDate\":\"2016-07-01\",\"endDate\":\"2016-08-02\",\"selectOffice\":\"1\",\"environementUrl\":\"environementUrl\"}",
+    "nextRunDateTime": 1469627093000,
+    "numberOfRuns": 0,
+    "isActive": true,
+    "runAsUserId": 1
+}
+					</code>
+				</div>
+			</div>
+            
+            <a id="report_mailing_jobs_list" name="report_mailing_jobs_list" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>List Report Mailing Jobs</h4>
+					<p>Example Requests:</p>
+					<div class=apiClick>reportmailingjobs</div>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+GET https://DomainName/api/v1/reportmailingjobs
+					</code>
+					<code class="method-response">
+[
+    {
+        "id": 1,
+        "name": "Client Numbers Report",
+        "description": "Client Numbers Report",
+        "startDateTime": 1469627093000,
+        "recurrence": "",
+        "timeline": {
+            "createdOnDate": [
+                2016,
+                7,
+                27
+            ],
+            "createdByUsername": "musoni",
+            "createdByFirstname": "firstname",
+            "createdByLastname": "lastname"
+        },
+        "emailRecipients": "info@musonisystem.com",
+        "emailSubject": "Client Numbers Report",
+        "emailMessage": "Client Numbers Report",
+        "emailAttachmentFileFormat": {
+            "id": 1,
+            "code": "ReportMailingJobEmailAttachmentFileFormat.xls",
+            "value": "xls"
+        },
+        "stretchyReport": {
+            "id": 120,
+            "reportName": "Client Numbers Report",
+            "reportType": "Pentaho",
+            "reportCategory": "Client",
+            "description": "",
+            "coreReport": false,
+            "useReport": true
+        },
+        "stretchyReportParamMap": "{\"startDate\":\"2016-07-01\",\"endDate\":\"2016-08-02\",\"selectOffice\":\"1\",\"environementUrl\":\"environementUrl\"}",
+        "nextRunDateTime": 1469627093000,
+        "numberOfRuns": 0,
+        "isActive": true,
+        "runAsUserId": 1
+    }
+]
+					</code>
+				</div>
+			</div>
+            
+            <a id="report_mailing_job_history_list" name="report_mailing_job_history_list" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>List Report Mailing Job History</h4>
+                    <p>The <i>list</i> capability of report mailing job history can support <b>pagination</b> and <b>sorting</b>.</p>
+					<h5>Optional Arguments</h5>
+					<dl class="argument-list">
+						<dt>offset</dt>
+						<dd>
+							Integer <span>optional</span>, defaults to 0
+						</dd>
+						<dd>Indicates the result from which pagination starts</dd>
+
+						<dt>limit</dt>
+						<dd>
+							Integer <span>optional</span>, defaults to 200
+						</dd>
+						<dd>Restricts the size of results returned. To override the default and return all entries you must explicitly pass a non-positive integer value for limit e.g. limit=0, or limit=-1</dd>
+
+						<dt>orderBy</dt>
+						<dd>
+							String <span>optional</span>, one of <span>startDateTime, endDateTime, status</span>
+						</dd>
+						<dd>Orders results by the indicated field.</dd>
+
+						<dt>sortBy</dt>
+						<dd>
+							String <span>optional</span>, one of <span>ASC, DESC</span>
+						</dd>
+						<dd>Indicates what way to order results if <i>orderBy</i> is used.</dd>
+					</dl>
+					<p>Example Requests:</p>
+					<div class=apiClick>reportmailingjobrunhistory/1</div>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+GET https://DomainName/api/v1/reportmailingjobrunhistory/{reportMailingJobId}
+					</code>
+					<code class="method-response">
+[
+    {
+        "id": 1,
+        "reportMailingJobId": 1,
+        "startDateTime": 1469627093000",
+        "endDateTime": 1469627093050,
+        "status": "success",
+        "errorMessage": "",
+        "errorLog": ""
+    }
+]
+					</code>
+				</div>
+			</div>
+			
+			<a id="report_mailing_jobs_create" name="report_mailing_jobs_create" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>Create a Report Mailing Job</h4>
+					<table class=matrixHeading>
+						<tr class="matrixHeadingBG">
+							<td><div class="fineractHeading2">Mandatory Fields</div></td>
+						</tr>
+						<tr class=alt>
+							<td>name, startDateTime, stretchyReportId, emailRecipients, emailSubject, emailMessage, emailAttachmentFileFormatId, recurrence, isActive</td>
+						</tr>
+					</table>
+						<br />
+					<table class=matrixHeading>
+						<tr class="matrixHeadingBG">
+							<td><div class="fineractHeading2">Optional Fields</div></td>
+						</tr>
+						<tr class=alt>
+							<td>description, stretchyReportParamMap</td>
+						</tr>
+					</table>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+POST https://DomainName/api/v1/reportmailingjobs
+					</code>
+					<code class="method-request">
+POST reportmailingjobs
+Content-Type: application/json Request Body:
+{
+    "locale": "en_GB",
+    "dateFormat": "dd-MM-yyyy HH:mm:ss",
+    "name": "Client Numbers Report",
+    "description": "Client Numbers Report",
+    "startDateTime": "02-08-2016 11:34:18",
+    "stretchyReportId": "120",
+    "emailRecipients": "info@musonisystem.com",
+    "emailSubject": "Client Numbers Report",
+    "emailMessage": "Client Numbers Report",
+    "emailAttachmentFileFormatId": "1",
+    "recurrence": "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR",
+    "isActive": true,
+    "stretchyReportParamMap": "{\"startDate\":\"2016-07-01\",\"endDate\":\"2016-08-02\",\"selectOffice\":\"1\",\"environementUrl\":\"environementUrl\"}"
+}
+					</code>
+					<code class="method-response">
+{
+    "resourceId": 1
+}
+					</code>
+				</div>
+			</div>
+			
+			<a id="report_mailing_jobs_update" name="report_mailing_jobs_update" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>Update a Report Mailing Job</h4>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+PUT https://DomainName/api/v1/reportmailingjobs/{id}
+						</code>
+					<code class="method-request">
+PUT reportmailingjobs/1
+Content-Type: application/json
+Request Body:
+{
+    "locale": "en_GB",
+    "dateFormat": "dd-MM-yyyy HH:mm:ss",
+    "startDateTime": "10-08-2016 23:30:00"
+}
+				
+					</code>
+					<code class="method-response">
+{
+    "resourceId": 1,
+    "changes": {
+        "startDateTime": "10-08-2016 23:30:00"
+    }
+}
+					</code>
+				</div>
+			</div>
+			
+			<a id="report_mailing_jobs_delete" name="report_mailing_jobs_delete" class="old-syle-anchor">&nbsp;</a>
+			<div class="method-section">
+				<div class="method-description">
+					<h4>Delete a Report Mailing Job</h4>
+				</div>
+				<div class="method-example">
+					<code class="method-declaration">
+DELETE https://DomainName/api/v1/reportmailingjobs/{id}
+						</code>
+					<code class="method-request">
+DELETE reportmailingjobs/1
+Content-Type: application/json
+Request Body:
+{
+}
+					</code>
+					<code class="method-response">
+{
+    "resourceId": 1
+}
+					</code>
+				</div>
+			</div>
 
 			<!-- start of authentication api docs -->
 			<a id="authenticationbasic" name="authenticationbasic" class="old-syle-anchor">&nbsp;</a>

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 3b26e1d..0fdb0ec 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2736,4 +2736,27 @@ public class CommandWrapperBuilder {
         return this;
 	}
 
-}
\ No newline at end of file
+	public CommandWrapperBuilder createReportMailingJob(final String entityName) {
+        this.actionName = "CREATE";
+        this.entityName = entityName;
+        this.entityId = null;
+        this.href = "/reportmailingjobs";
+        return this;
+    }
+    
+    public CommandWrapperBuilder updateReportMailingJob(final String entityName, final Long entityId) {
+        this.actionName = "UPDATE";
+        this.entityName = entityName;
+        this.entityId = entityId;
+        this.href = "/reportmailingjobs/" + entityId;
+        return this;
+    }
+    
+    public CommandWrapperBuilder deleteReportMailingJob(final String entityName, final Long entityId) {
+        this.actionName = "DELETE";
+        this.entityName = entityName;
+        this.entityId = entityId;
+        this.href = "/reportmailingjobs/" + entityId;
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java
index 97c98ba..c1da252 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java
@@ -443,4 +443,33 @@ public final class SearchParameters {
         return this.isSelfUser;
     }
 
-}
\ No newline at end of file
+    /** 
+     * creates an instance of the SearchParameters from a request for the report mailing job run history
+     * 
+     * @return SearchParameters object
+     **/
+    public static SearchParameters fromReportMailingJobRunHistory(final Integer offset, 
+            final Integer limit, final String orderBy, final String sortOrder) {
+        final Integer maxLimitAllowed = getCheckedLimit(limit);
+        
+        return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy,
+                sortOrder, null, null, null, null, null, false);
+    }
+    
+    /**
+     * creates an instance of the {@link SearchParameters} from a request for the report mailing job
+     * 
+     * @param offset
+     * @param limit
+     * @param orderBy
+     * @param sortOrder
+     * @return {@link SearchParameters} object
+     */
+    public static SearchParameters fromReportMailingJob(final Integer offset, 
+            final Integer limit, final String orderBy, final String sortOrder) {
+        final Integer maxLimitAllowed = getCheckedLimit(limit);
+        
+        return new SearchParameters(null, null, null, null, null, null, null, offset, maxLimitAllowed, orderBy,
+                sortOrder, null, null, null, null, null, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/domain/ReportRepositoryWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/domain/ReportRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/domain/ReportRepositoryWrapper.java
new file mode 100644
index 0000000..6421053
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/domain/ReportRepositoryWrapper.java
@@ -0,0 +1,54 @@
+/**
+ * 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.dataqueries.domain;
+
+import org.apache.fineract.infrastructure.dataqueries.exception.ReportNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/** 
+ *  A wrapper class for the ReportRepository that provides a method that returns a Report entity if it exists, 
+ *  else throws "ReportNotFoundException" exception if the Report does not exist
+ **/
+@Service
+public class ReportRepositoryWrapper {
+    private final ReportRepository reportRepository;
+    
+    @Autowired
+    public ReportRepositoryWrapper(final ReportRepository reportRepository) {
+        this.reportRepository = reportRepository;
+    }
+    
+    /**
+     * Retrieves an entity by its id
+     * 
+     * @param id must not be null
+     * @throws ReportNotFoundException if entity not found
+     * @return {@link Report} object
+     */
+    public Report findOneThrowExceptionIfNotFound(final Long id) {
+        final Report report = this.reportRepository.findOne(id);
+        
+        if (report == null) {
+            throw new ReportNotFoundException(id);
+        }
+        
+        return report;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java
index 69c8056..a6e97ae 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadReportingServiceImpl.java
@@ -484,5 +484,4 @@ public class ReadReportingServiceImpl implements ReadReportingService {
             return new ReportParameterData(id, null, null, parameterName);
         }
     }
-
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
index 0580a4c..d893c3b 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java
@@ -41,7 +41,8 @@ public enum JobName {
     GENERATE_LOANLOSS_PROVISIONING("Generate Loan Loss Provisioning"), //
     POST_DIVIDENTS_FOR_SHARES("Post Dividends For Shares"), //
     UPDATE_SAVINGS_DORMANT_ACCOUNTS("Update Savings Dormant Accounts"), //
-    ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add Accrual Transactions For Loans With Income Posted As Transactions");
+    ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_LOANS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add Accrual Transactions For Loans With Income Posted As Transactions"),
+    EXECUTE_REPORT_MAILING_JOBS("Execute Report Mailing Jobs");
 
     private 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/ReportMailingJobConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/ReportMailingJobConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/ReportMailingJobConstants.java
new file mode 100644
index 0000000..ab5f110
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/ReportMailingJobConstants.java
@@ -0,0 +1,88 @@
+/**
+ * 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;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ReportMailingJobConstants {
+
+    // define the API resource entity name
+    public static final String REPORT_MAILING_JOB_ENTITY_NAME = "REPORTMAILINGJOB";
+    
+    // define the API resource name for the report mailing job resource
+    public static final String REPORT_MAILING_JOB_RESOURCE_NAME = "reportmailingjobs";
+    
+    // define the API resource name for the report mailing job history resource
+    public static final String REPORT_MAILING_JOB_RUN_HISTORY_RESOURCE_NAME = "reportmailingjobrunhistory";
+    
+    // general API resource request parameter constants
+    public static final String LOCALE_PARAM_NAME = "locale";
+    public static final String DATE_FORMAT_PARAM_NAME = "dateFormat";
+    
+    // parameter constants for create/update entity API request
+    public static final String NAME_PARAM_NAME = "name";
+    public static final String DESCRIPTION_PARAM_NAME = "description";
+    public static final String START_DATE_TIME_PARAM_NAME = "startDateTime";
+    public static final String RECURRENCE_PARAM_NAME = "recurrence";
+    public static final String EMAIL_RECIPIENTS_PARAM_NAME = "emailRecipients";
+    public static final String EMAIL_SUBJECT_PARAM_NAME = "emailSubject";
+    public static final String EMAIL_MESSAGE_PARAM_NAME = "emailMessage";
+    public static final String EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME = "emailAttachmentFileFormatId";
+    public static final String STRETCHY_REPORT_ID_PARAM_NAME = "stretchyReportId";
+    public static final String STRETCHY_REPORT_PARAM_MAP_PARAM_NAME = "stretchyReportParamMap";
+    public static final String IS_ACTIVE_PARAM_NAME = "isActive";
+    
+    // other parameter constants
+    public static final String ID_PARAM_NAME = "id";
+    public static final String EMAIL_ATTACHMENT_FILE_FORMAT_PARAM_NAME = "emailAttachmentFileFormat";
+    public static final String PREVIOUS_RUN_DATE_TIME_PARAM_NAME = "previousRunDateTime";
+    public static final String NEXT_RUN_DATE_TIME_PARAM_NAME = "nextRunDateTime";
+    public static final String PREVIOUS_RUN_STATUS = "previousRunStatus";
+    public static final String PREVIOUS_RUN_ERROR_LOG = "previousRunErrorLog";
+    public static final String PREVIOUS_RUN_ERROR_MESSAGE = "previousRunErrorMessage";
+    public static final String NUMBER_OF_RUNS = "numberOfRuns";
+    public static final String STRETCHY_REPORT_PARAM_NAME = "stretchyReport";
+    
+    // list of permitted parameters for the create report mailing job request
+    public static final Set<String> CREATE_REQUEST_PARAMETERS = new HashSet<>(Arrays.asList(LOCALE_PARAM_NAME, DATE_FORMAT_PARAM_NAME, 
+            NAME_PARAM_NAME, DESCRIPTION_PARAM_NAME, RECURRENCE_PARAM_NAME, EMAIL_RECIPIENTS_PARAM_NAME, EMAIL_SUBJECT_PARAM_NAME, 
+            EMAIL_MESSAGE_PARAM_NAME, EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, STRETCHY_REPORT_ID_PARAM_NAME, 
+            STRETCHY_REPORT_PARAM_MAP_PARAM_NAME, IS_ACTIVE_PARAM_NAME, START_DATE_TIME_PARAM_NAME));
+    
+    // list of permitted parameters for the update report mailing job request
+    public static final Set<String> UPDATE_REQUEST_PARAMETERS = new HashSet<>(Arrays.asList(LOCALE_PARAM_NAME, DATE_FORMAT_PARAM_NAME, 
+            NAME_PARAM_NAME, DESCRIPTION_PARAM_NAME, RECURRENCE_PARAM_NAME, EMAIL_RECIPIENTS_PARAM_NAME, EMAIL_SUBJECT_PARAM_NAME, 
+            EMAIL_MESSAGE_PARAM_NAME, EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, STRETCHY_REPORT_ID_PARAM_NAME, 
+            STRETCHY_REPORT_PARAM_MAP_PARAM_NAME, IS_ACTIVE_PARAM_NAME, START_DATE_TIME_PARAM_NAME));
+    
+    // list of parameters that represent the properties of a report mailing job
+    public static final Set<String> REPORT_MAILING_JOB_DATA_PARAMETERS = new HashSet<>(Arrays.asList(ID_PARAM_NAME, NAME_PARAM_NAME, 
+            DESCRIPTION_PARAM_NAME, RECURRENCE_PARAM_NAME, EMAIL_RECIPIENTS_PARAM_NAME, EMAIL_SUBJECT_PARAM_NAME, EMAIL_MESSAGE_PARAM_NAME, 
+            EMAIL_ATTACHMENT_FILE_FORMAT_PARAM_NAME, STRETCHY_REPORT_PARAM_NAME, STRETCHY_REPORT_PARAM_MAP_PARAM_NAME, IS_ACTIVE_PARAM_NAME, 
+            START_DATE_TIME_PARAM_NAME, PREVIOUS_RUN_DATE_TIME_PARAM_NAME, NEXT_RUN_DATE_TIME_PARAM_NAME, PREVIOUS_RUN_STATUS, 
+            PREVIOUS_RUN_ERROR_LOG, PREVIOUS_RUN_ERROR_MESSAGE, NUMBER_OF_RUNS));
+    
+    // report mailing job configuration names
+    public static final String GMAIL_SMTP_SERVER = "GMAIL_SMTP_SERVER";
+    public static final String GMAIL_SMTP_PORT = "GMAIL_SMTP_PORT";
+    public static final String GMAIL_SMTP_USERNAME = "GMAIL_SMTP_USERNAME";
+    public static final String GMAIL_SMTP_PASSWORD = "GMAIL_SMTP_PASSWORD";
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobApiResource.java
new file mode 100644
index 0000000..da6da6d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobApiResource.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.api;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.fineract.commands.domain.CommandWrapper;
+import org.apache.fineract.commands.service.CommandWrapperBuilder;
+import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobData;
+import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobReadPlatformService;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RESOURCE_NAME)
+@Component
+@Scope("singleton")
+public class ReportMailingJobApiResource {
+
+    private final PlatformSecurityContext platformSecurityContext;
+    private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+    private final ApiRequestParameterHelper apiRequestParameterHelper;
+    private final DefaultToApiJsonSerializer<ReportMailingJobData> reportMailingToApiJsonSerializer;
+    private final ReportMailingJobReadPlatformService reportMailingJobReadPlatformService;
+    
+    @Autowired
+    public ReportMailingJobApiResource(final PlatformSecurityContext platformSecurityContext, 
+            final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, 
+            final ApiRequestParameterHelper apiRequestParameterHelper, 
+            final DefaultToApiJsonSerializer<ReportMailingJobData> reportMailingToApiJsonSerializer, 
+            final ReportMailingJobReadPlatformService reportMailingJobReadPlatformService) {
+        this.platformSecurityContext = platformSecurityContext;
+        this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+        this.apiRequestParameterHelper = apiRequestParameterHelper;
+        this.reportMailingToApiJsonSerializer = reportMailingToApiJsonSerializer;
+        this.reportMailingJobReadPlatformService = reportMailingJobReadPlatformService;
+    }
+    
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String createReportMailingJob(final String apiRequestBodyAsJson) {
+        final CommandWrapper commandWrapper = new CommandWrapperBuilder().
+                createReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME).
+                withJson(apiRequestBodyAsJson).build();
+        
+        final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
+        
+        return this.reportMailingToApiJsonSerializer.serialize(commandProcessingResult);
+    }
+    
+    @PUT
+    @Path("{entityId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String updateReportMailingJob(@PathParam("entityId") final Long entityId, final String apiRequestBodyAsJson) {
+        final CommandWrapper commandWrapper = new CommandWrapperBuilder().
+                updateReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, entityId).
+                withJson(apiRequestBodyAsJson).build();
+        
+        final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
+        
+        return this.reportMailingToApiJsonSerializer.serialize(commandProcessingResult);
+    }
+    
+    @DELETE
+    @Path("{entityId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String deleteReportMailingJob(@PathParam("entityId") final Long entityId, final String apiRequestBodyAsJson) {
+        final CommandWrapper commandWrapper = new CommandWrapperBuilder().
+                deleteReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, entityId).
+                withJson(apiRequestBodyAsJson).build();
+        
+        final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper);
+        
+        return this.reportMailingToApiJsonSerializer.serialize(commandProcessingResult);
+    }
+    
+    @GET
+    @Path("{entityId}")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveReportMailingJob(@PathParam("entityId") final Long entityId, @Context final UriInfo uriInfo) {
+        this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
+        
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        ReportMailingJobData reportMailingJobData = this.reportMailingJobReadPlatformService.retrieveReportMailingJob(entityId);
+        
+        if (settings.isTemplate()) {
+            final ReportMailingJobData ReportMailingJobDataOptions = this.reportMailingJobReadPlatformService.retrieveReportMailingJobEnumOptions();
+            reportMailingJobData = ReportMailingJobData.newInstance(reportMailingJobData, ReportMailingJobDataOptions);
+        }
+        
+        return this.reportMailingToApiJsonSerializer.serialize(settings, reportMailingJobData, ReportMailingJobConstants.REPORT_MAILING_JOB_DATA_PARAMETERS);
+    }
+    
+    @GET
+    @Path("template")
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveReportMailingJobTemplate(@Context final UriInfo uriInfo) {
+        this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
+        
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        final ReportMailingJobData ReportMailingJobDataOptions = this.reportMailingJobReadPlatformService.retrieveReportMailingJobEnumOptions();
+        
+        return this.reportMailingToApiJsonSerializer.serialize(settings, ReportMailingJobDataOptions, ReportMailingJobConstants.REPORT_MAILING_JOB_DATA_PARAMETERS);
+    }
+    
+    @GET
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveAllReportMailingJobs(@Context final UriInfo uriInfo, 
+            @QueryParam("offset") final Integer offset,
+            @QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
+            @QueryParam("sortOrder") final String sortOrder) {
+        this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
+        
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        final SearchParameters searchParameters = SearchParameters.fromReportMailingJob(offset, limit, orderBy, sortOrder);
+        final Page<ReportMailingJobData> reportMailingJobData = this.reportMailingJobReadPlatformService.retrieveAllReportMailingJobs(searchParameters);
+        
+        return this.reportMailingToApiJsonSerializer.serialize(settings, reportMailingJobData, ReportMailingJobConstants.REPORT_MAILING_JOB_DATA_PARAMETERS);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobRunHistoryApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobRunHistoryApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobRunHistoryApiResource.java
new file mode 100644
index 0000000..a7802ee
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/api/ReportMailingJobRunHistoryApiResource.java
@@ -0,0 +1,80 @@
+/**
+ * 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.api;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
+import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobRunHistoryData;
+import org.apache.fineract.infrastructure.reportmailingjob.service.ReportMailingJobRunHistoryReadPlatformService;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RUN_HISTORY_RESOURCE_NAME)
+@Component
+@Scope("singleton")
+public class ReportMailingJobRunHistoryApiResource {
+    
+    private final PlatformSecurityContext platformSecurityContext;
+    private final ApiRequestParameterHelper apiRequestParameterHelper;
+    private final DefaultToApiJsonSerializer<ReportMailingJobRunHistoryData> reportMailingToApiJsonSerializer;
+    private final ReportMailingJobRunHistoryReadPlatformService reportMailingJobRunHistoryReadPlatformService;
+    
+    @Autowired
+    public ReportMailingJobRunHistoryApiResource(final PlatformSecurityContext platformSecurityContext, 
+            final ApiRequestParameterHelper apiRequestParameterHelper, 
+            final DefaultToApiJsonSerializer<ReportMailingJobRunHistoryData> reportMailingToApiJsonSerializer, 
+            final ReportMailingJobRunHistoryReadPlatformService reportMailingJobRunHistoryReadPlatformService) {
+        this.platformSecurityContext = platformSecurityContext;
+        this.apiRequestParameterHelper = apiRequestParameterHelper;
+        this.reportMailingToApiJsonSerializer = reportMailingToApiJsonSerializer;
+        this.reportMailingJobRunHistoryReadPlatformService = reportMailingJobRunHistoryReadPlatformService;
+    }
+    
+    @GET
+    @Consumes({ MediaType.APPLICATION_JSON })
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String retrieveAllByReportMailingJobId(@Context final UriInfo uriInfo, 
+            @QueryParam("reportMailingJobId") final Long reportMailingJobId, @QueryParam("offset") final Integer offset,
+            @QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
+            @QueryParam("sortOrder") final String sortOrder) {
+        this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
+        final SearchParameters searchParameters = SearchParameters.fromReportMailingJobRunHistory(offset, limit, orderBy, sortOrder);
+        
+        final Page<ReportMailingJobRunHistoryData> reportMailingJobRunHistoryData = this.reportMailingJobRunHistoryReadPlatformService.
+                retrieveRunHistoryByJobId(reportMailingJobId, searchParameters);
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
+        
+        return this.reportMailingToApiJsonSerializer.serialize(settings, reportMailingJobRunHistoryData);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobConfigurationData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobConfigurationData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobConfigurationData.java
new file mode 100644
index 0000000..48d075a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobConfigurationData.java
@@ -0,0 +1,67 @@
+/**
+ * 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;
+
+/** 
+ * Immutable data object representing report mailing job configuration data. 
+ **/
+public class ReportMailingJobConfigurationData {
+    private final int id;
+    private final String name;
+    private final String value;
+    
+    /** 
+     * ReportMailingJobConfigurationData private constructor 
+     **/
+    private ReportMailingJobConfigurationData(final int id, final String name, final String value) {
+        this.id = id;
+        this.name = name;
+        this.value = value;
+    }
+    
+    /** 
+     * creates an instance of the ReportMailingJobConfigurationData class
+     * 
+     * @return ReportMailingJobConfigurationData object
+     **/
+    public static ReportMailingJobConfigurationData newInstance(final int id, final String name, final String value) {
+        return new ReportMailingJobConfigurationData(id, name, value);
+    }
+
+    /**
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * @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/data/ReportMailingJobData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobData.java
new file mode 100644
index 0000000..aa5172f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobData.java
@@ -0,0 +1,272 @@
+/**
+ * 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 java.util.List;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
+import org.joda.time.DateTime;
+
+/** 
+ * Immutable data object representing report mailing job data. 
+ **/
+public class ReportMailingJobData {
+    private final Long id;
+    private final String name;
+    private final String description;
+    private final DateTime startDateTime;
+    private final String recurrence;
+    private final ReportMailingJobTimelineData timeline;
+    private final String emailRecipients;
+    private final String emailSubject;
+    private final String emailMessage;
+    private final EnumOptionData emailAttachmentFileFormat;
+    private final ReportData stretchyReport;
+    private final String stretchyReportParamMap;
+    private final DateTime previousRunDateTime;
+    private final DateTime nextRunDateTime;
+    private final String previousRunStatus;
+    private final String previousRunErrorLog;
+    private final String previousRunErrorMessage;
+    private final Integer numberOfRuns;
+    private final boolean isActive;
+    private final List<EnumOptionData> emailAttachmentFileFormatOptions;
+    private final List<EnumOptionData> stretchyReportParamDateOptions;
+    private final Long runAsUserId;
+    
+    private ReportMailingJobData(final Long id, final String name, final String description, final DateTime startDateTime, 
+            final String recurrence, final ReportMailingJobTimelineData timeline, final String emailRecipients, final String emailSubject, 
+            final String emailMessage, final EnumOptionData emailAttachmentFileFormat, final ReportData stretchyReport, final String stretchyReportParamMap, 
+            final DateTime previousRunDateTime, final DateTime nextRunDateTime, final String previousRunStatus, final String previousRunErrorLog, 
+            final String previousRunErrorMessage, final Integer numberOfRuns, final boolean isActive, final List<EnumOptionData> emailAttachmentFileFormatOptions, 
+            final List<EnumOptionData> stretchyReportParamDateOptions, final Long runAsUserId) {
+        this.id = id;
+        this.name = name;
+        this.description = description;
+        this.startDateTime = startDateTime;
+        this.recurrence = recurrence;
+        this.timeline = timeline;
+        this.emailRecipients = emailRecipients;
+        this.emailMessage = emailMessage;
+        this.emailSubject = emailSubject;
+        this.emailAttachmentFileFormat = emailAttachmentFileFormat;
+        this.stretchyReport = stretchyReport;
+        this.stretchyReportParamMap = stretchyReportParamMap;
+        this.previousRunDateTime = previousRunDateTime;
+        this.nextRunDateTime = nextRunDateTime;
+        this.previousRunStatus = previousRunStatus;
+        this.previousRunErrorLog = previousRunErrorLog;
+        this.previousRunErrorMessage = previousRunErrorMessage;
+        this.isActive = isActive;
+        this.numberOfRuns = numberOfRuns;
+        this.emailAttachmentFileFormatOptions = emailAttachmentFileFormatOptions;
+        this.stretchyReportParamDateOptions = stretchyReportParamDateOptions;
+        this.runAsUserId = runAsUserId;
+    }
+    
+    /** 
+     * @return an instance of the ReportMailingJobData class 
+     **/
+    public static ReportMailingJobData newInstance(final Long id, final String name, final String description, final DateTime startDateTime, 
+            final String recurrence, final ReportMailingJobTimelineData timeline, final String emailRecipients, final String emailSubject, 
+            final String emailMessage, final EnumOptionData emailAttachmentFileFormat, final ReportData stretchyReport, final String stretchyReportParamMap, 
+            final DateTime previousRunDateTime, final DateTime nextRunDateTime, final String previousRunStatus, final String previousRunErrorLog, 
+            final String previousRunErrorMessage, final Integer numberOfRuns, final boolean isActive, final Long runAsUserId) {
+        return new ReportMailingJobData(id, name, description, startDateTime, recurrence, timeline, emailRecipients, emailSubject, 
+                emailMessage, emailAttachmentFileFormat, stretchyReport, stretchyReportParamMap, previousRunDateTime, nextRunDateTime, 
+                previousRunStatus, previousRunErrorLog, previousRunErrorMessage, numberOfRuns, isActive, null, null, runAsUserId);
+    }
+    
+    /** 
+     * @return an instance of the ReportMailingJobData class 
+     **/
+    public static ReportMailingJobData newInstance(final List<EnumOptionData> emailAttachmentFileFormatOptions, 
+            final List<EnumOptionData> stretchyReportParamDateOptions) {
+        return new ReportMailingJobData(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
+                null, false, emailAttachmentFileFormatOptions, stretchyReportParamDateOptions, null);
+    }
+    
+    /** 
+     * @return an instance of the ReportMailingJobData class 
+     **/
+    public static ReportMailingJobData newInstance(final ReportMailingJobData dataWithoutEnumOptions, final ReportMailingJobData dataWithEnumOptions) {
+        return new ReportMailingJobData(dataWithoutEnumOptions.id, dataWithoutEnumOptions.name, dataWithoutEnumOptions.description, dataWithoutEnumOptions.startDateTime, 
+                dataWithoutEnumOptions.recurrence, dataWithoutEnumOptions.timeline, dataWithoutEnumOptions.emailRecipients, dataWithoutEnumOptions.emailSubject, 
+                dataWithoutEnumOptions.emailMessage, dataWithoutEnumOptions.emailAttachmentFileFormat, dataWithoutEnumOptions.stretchyReport, 
+                dataWithoutEnumOptions.stretchyReportParamMap, dataWithoutEnumOptions.previousRunDateTime, dataWithoutEnumOptions.nextRunDateTime, 
+                dataWithoutEnumOptions.previousRunStatus, dataWithoutEnumOptions.previousRunErrorLog, dataWithoutEnumOptions.previousRunErrorMessage, 
+                dataWithoutEnumOptions.numberOfRuns, dataWithoutEnumOptions.isActive, dataWithEnumOptions.emailAttachmentFileFormatOptions, 
+                dataWithEnumOptions.stretchyReportParamDateOptions, dataWithoutEnumOptions.runAsUserId);
+    }
+
+    /**
+     * @return the id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the description
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the startDateTime
+     */
+    public DateTime getStartDateTime() {
+        return startDateTime;
+    }
+
+    /**
+     * @return the recurrence
+     */
+    public String getRecurrence() {
+        return recurrence;
+    }
+
+    /**
+     * @return the timeline
+     */
+    public ReportMailingJobTimelineData getTimeline() {
+        return timeline;
+    }
+
+    /**
+     * @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 EnumOptionData getEmailAttachmentFileFormat() {
+        return emailAttachmentFileFormat;
+    }
+
+    /**
+     * @return the stretchyReport
+     */
+    public ReportData getStretchyReport() {
+        return stretchyReport;
+    }
+
+    /**
+     * @return the stretchyReportParamMap
+     */
+    public String getStretchyReportParamMap() {
+        return stretchyReportParamMap;
+    }
+
+    /**
+     * @return the previousRunDateTime
+     */
+    public DateTime getPreviousRunDateTime() {
+        return previousRunDateTime;
+    }
+
+    /**
+     * @return the nextRunDateTime
+     */
+    public DateTime getNextRunDateTime() {
+        return nextRunDateTime;
+    }
+
+    /**
+     * @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 isActive
+     */
+    public boolean isActive() {
+        return isActive;
+    }
+
+    /**
+     * @return the emailAttachmentFileFormatOptions
+     */
+    public List<EnumOptionData> getEmailAttachmentFileFormatOptions() {
+        return emailAttachmentFileFormatOptions;
+    }
+    
+    /** 
+     * @return the stretchyReportParamDateOptions
+     **/
+    public List<EnumOptionData> getStretchyReportParamDateOptions() {
+        return this.stretchyReportParamDateOptions;
+    }
+
+    /**
+     * @return the numberOfRuns
+     */
+    public Integer getNumberOfRuns() {
+        return numberOfRuns;
+    }
+
+    /**
+     * @return the runAsUserId
+     */
+    public Long getRunAsUserId() {
+        return runAsUserId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailAttachmentFileFormat.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailAttachmentFileFormat.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailAttachmentFileFormat.java
new file mode 100644
index 0000000..c3e15ca
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailAttachmentFileFormat.java
@@ -0,0 +1,176 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+public enum ReportMailingJobEmailAttachmentFileFormat {
+    INVALID(0, "ReportMailingJobEmailAttachmentFileFormat.INVALID", "Invalid"),
+    XLS(1, "ReportMailingJobEmailAttachmentFileFormat.XLS", "XLS"),
+    PDF(2, "ReportMailingJobEmailAttachmentFileFormat.PDF", "PDF"),
+    CSV(3, "ReportMailingJobEmailAttachmentFileFormat.CSV", "CSV");
+    
+    private String code;
+    private String value;
+    private Integer id;
+    
+    private ReportMailingJobEmailAttachmentFileFormat(final Integer id, final String code, final String value) {
+        this.value = value;
+        this.code = code;
+        this.id = id;
+    }
+    
+    /**
+     * Creates a new {@link ReportMailingJobEmailAttachmentFileFormat} object
+     * 
+     * @param value the value of the enum constant
+     * @return {@link ReportMailingJobEmailAttachmentFileFormat} object
+     */
+    public static ReportMailingJobEmailAttachmentFileFormat newInstance(final String value) {
+        ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = INVALID;
+        
+        if (StringUtils.equalsIgnoreCase(value, XLS.value)) {
+            emailAttachmentFileFormat = XLS;
+        } else if (StringUtils.equalsIgnoreCase(value, PDF.value)) {
+            emailAttachmentFileFormat = PDF;
+        } else if (StringUtils.equalsIgnoreCase(value, CSV.value)) {
+            emailAttachmentFileFormat = CSV;
+        }
+        
+        return emailAttachmentFileFormat;
+    }
+    
+    /**
+     * Creates a new {@link ReportMailingJobEmailAttachmentFileFormat} object
+     * 
+     * @param id the id of the enum constant
+     * @return {@link ReportMailingJobEmailAttachmentFileFormat} object
+     */
+    public static ReportMailingJobEmailAttachmentFileFormat newInstance(final Integer id) {
+        ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = INVALID;
+        
+        if (id == XLS.id) {
+            emailAttachmentFileFormat = XLS;
+        } else if (id == PDF.id) {
+            emailAttachmentFileFormat = PDF;
+        } else if (id == CSV.id) {
+            emailAttachmentFileFormat = CSV;
+        }
+        
+        return emailAttachmentFileFormat;
+    }
+    
+    /**
+     * @return the code
+     */
+    public String getCode() {
+        return code;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * @return the id
+     */
+    public Integer getId() {
+        return id;
+    }
+    
+    /** 
+     * @return true if the enum is equals to "INVALID"
+     */
+    public boolean isInvalid() {
+        return this.equals(INVALID);
+    }
+    
+    /**
+     * @return true if the enum is not equals to "INVALID"
+     */
+    public boolean isValid() {
+        return !this.isInvalid();
+    }
+    
+    /** 
+     * @return list of valid ReportMailingJobEmailAttachmentFileFormat values
+     **/
+    public static Object[] validValues() {
+        List<Object> validValues = new ArrayList<>();
+        
+        for (ReportMailingJobEmailAttachmentFileFormat constant : ReportMailingJobEmailAttachmentFileFormat.values()) {
+            if (constant.isValid()) {
+                validValues.add(constant.value);
+            }
+        }
+        
+        return validValues.toArray();
+    }
+    
+    /** 
+     * @return list of valid ReportMailingJobEmailAttachmentFileFormat values
+     **/
+    public static Object[] validIds() {
+        List<Object> validValues = new ArrayList<>();
+        
+        for (ReportMailingJobEmailAttachmentFileFormat constant : ReportMailingJobEmailAttachmentFileFormat.values()) {
+            if (constant.isValid()) {
+                validValues.add(constant.id);
+            }
+        }
+        
+        return validValues.toArray();
+    }
+    
+    /**
+     * get a {@link EnumOptionData} representation of the {@link ReportMailingJobEmailAttachmentFileFormat} object
+     * 
+     * @return {@link EnumOptionData} object
+     */
+    public EnumOptionData toEnumOptionData() {
+        // get the long value of the enum id
+        final Long id = (this.id != null) ? this.id.longValue() : null;
+        
+        return new EnumOptionData(id, code, value);
+    }
+    
+    /**
+     * get the {@link EnumOptionData} representation of all valid {@link ReportMailingJobEmailAttachmentFileFormat} objects
+     * 
+     * @return List of {@link EnumOptionData} objects
+     */
+    public static List<EnumOptionData> validOptions() {
+        List<EnumOptionData> options = new ArrayList<>();
+        
+        for (ReportMailingJobEmailAttachmentFileFormat constant : ReportMailingJobEmailAttachmentFileFormat.values()) {
+            if (constant.isValid()) {
+                options.add(constant.toEnumOptionData());
+            }
+        }
+        
+        return options;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailData.java
new file mode 100644
index 0000000..dda7e2d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobEmailData.java
@@ -0,0 +1,66 @@
+/**
+ * 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 java.io.File;
+
+/** 
+ * Immutable data object representing report mailing job email data. 
+ **/
+public class ReportMailingJobEmailData {
+    private final String to;
+    private final String text;
+    private final String subject;
+    private final File attachment;
+    
+    public ReportMailingJobEmailData(final String to, final String text, final String subject, final File attachment) {
+        this.to = to;
+        this.text = text;
+        this.subject = subject;
+        this.attachment = attachment;
+    }
+
+    /**
+     * @return the to
+     */
+    public String getTo() {
+        return to;
+    }
+
+    /**
+     * @return the text
+     */
+    public String getText() {
+        return text;
+    }
+
+    /**
+     * @return the subject
+     */
+    public String getSubject() {
+        return subject;
+    }
+
+    /**
+     * @return the attachment
+     */
+    public File getAttachment() {
+        return attachment;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobPreviousRunStatus.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobPreviousRunStatus.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobPreviousRunStatus.java
new file mode 100644
index 0000000..3f49cd9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobPreviousRunStatus.java
@@ -0,0 +1,90 @@
+/**
+ * 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.apache.commons.lang.StringUtils;
+
+public enum ReportMailingJobPreviousRunStatus {
+    INVALID(-1, "ReportMailingJobPreviousRunStatus.INVALID", "Invalid"),
+    SUCCESS(1, "ReportMailingJobPreviousRunStatus.SUCCESS", "Success"),
+    ERROR(0, "ReportMailingJobPreviousRunStatus.ERROR", "Error");
+    
+    private final String code;
+    private final String value;
+    private final Integer id;
+    
+    private ReportMailingJobPreviousRunStatus(final Integer id, final String code, final String value) {
+        this.value = value;
+        this.code = code;
+        this.id = id;
+    }
+    
+    /**
+     * Creates a {@link ReportMailingJobPreviousRunStatus} object
+     * 
+     * @param value the value of the enum constant
+     * @return {@link ReportMailingJobPreviousRunStatus} object
+     */
+    public static ReportMailingJobPreviousRunStatus newInstance(final String value) {
+        ReportMailingJobPreviousRunStatus previousRunStatus = INVALID;
+        
+        if (StringUtils.equalsIgnoreCase(value, SUCCESS.value)) {
+            previousRunStatus = SUCCESS;
+        } else if (StringUtils.equalsIgnoreCase(value, ERROR.value)) {
+            previousRunStatus = ERROR;
+        }
+        
+        return previousRunStatus;
+    }
+
+    /**
+     * @return the code
+     */
+    public String getCode() {
+        return code;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+    
+    /**
+     * @return the id
+     */
+    public Integer getId() {
+        return id;
+    }
+    
+    /** 
+     * @return true/false 
+     **/
+    public boolean isSuccess() {
+        return this.value.equals(SUCCESS.getValue());
+    }
+    
+    /** 
+     * @return boolean true/false 
+     **/
+    public boolean isError() {
+        return this.value.equals(ERROR.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b30976bb/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobRunHistoryData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobRunHistoryData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobRunHistoryData.java
new file mode 100644
index 0000000..0642f7b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobRunHistoryData.java
@@ -0,0 +1,107 @@
+/**
+ * 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.DateTime;
+
+/** 
+ * Immutable data object representing report mailing job run history data. 
+ **/
+public class ReportMailingJobRunHistoryData {
+    private final Long id;
+    private final Long reportMailingJobId;
+    private final DateTime startDateTime;
+    private final DateTime endDateTime;
+    private final String status;
+    private final String errorMessage;
+    private final String errorLog;
+    
+    /** 
+     * ReportMailingJobRunHistoryData private constructor 
+     **/
+    private ReportMailingJobRunHistoryData(Long id, Long reportMailingJobId, DateTime startDateTime,
+            DateTime endDateTime, String status, String errorMessage, String errorLog) {
+        this.id = id;
+        this.reportMailingJobId = reportMailingJobId;
+        this.startDateTime = startDateTime;
+        this.endDateTime = endDateTime;
+        this.status = status;
+        this.errorMessage = errorMessage;
+        this.errorLog = errorLog;
+    }
+    
+    /** 
+     * creates an instance of the ReportMailingJobRunHistoryData class
+     * 
+     * @return ReportMailingJobRunHistoryData object
+     **/
+    public static ReportMailingJobRunHistoryData newInstance(Long id, Long reportMailingJobId, DateTime startDateTime,
+            DateTime endDateTime, String status, String errorMessage, String errorLog) {
+        return new ReportMailingJobRunHistoryData(id, reportMailingJobId, startDateTime, endDateTime, status, errorMessage, errorLog);
+    }
+
+    /**
+     * @return the id
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * @return the reportMailingJobId
+     */
+    public Long getReportMailingJobId() {
+        return reportMailingJobId;
+    }
+
+    /**
+     * @return the startDateTime
+     */
+    public DateTime getStartDateTime() {
+        return startDateTime;
+    }
+
+    /**
+     * @return the endDateTime
+     */
+    public DateTime getEndDateTime() {
+        return endDateTime;
+    }
+
+    /**
+     * @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/data/ReportMailingJobStretchyReportParamDateOption.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobStretchyReportParamDateOption.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobStretchyReportParamDateOption.java
new file mode 100644
index 0000000..01cf808
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/reportmailingjob/data/ReportMailingJobStretchyReportParamDateOption.java
@@ -0,0 +1,166 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+public enum ReportMailingJobStretchyReportParamDateOption {
+    INVALID(0, "ReportMailingJobStretchyReportParamDateOption.INVALID", "Invalid"),
+    TODAY(1, "ReportMailingJobStretchyReportParamDateOption.TODAY", "Today"),
+    YESTERDAY(2, "ReportMailingJobStretchyReportParamDateOption.YESTERDAY", "Yesterday"),
+    TOMORROW(3, "ReportMailingJobStretchyReportParamDateOption.TOMORROW", "Tomorrow");
+    
+    private String code;
+    private String value;
+    private Integer id;
+    
+    /**
+     * @param id
+     * @param code
+     * @param value
+     */
+    private ReportMailingJobStretchyReportParamDateOption(final Integer id, final String code, final String value) {
+        this.value = value;
+        this.code = code;
+        this.id = id;
+    }
+    
+    /**
+     * Creates a new {@link ReportMailingJobStretchyReportParamDateOption} object
+     * 
+     * @param value value of the enum constant
+     * @return {@link ReportMailingJobStretchyReportParamDateOption} object
+     */
+    public static ReportMailingJobStretchyReportParamDateOption newInstance(final String value) {
+        ReportMailingJobStretchyReportParamDateOption reportMailingJobStretchyReportParamDateOption = INVALID;
+        
+        if (StringUtils.equalsIgnoreCase(value, TODAY.value)) {
+            reportMailingJobStretchyReportParamDateOption = TODAY;
+        } else if (StringUtils.equalsIgnoreCase(value, YESTERDAY.value)) {
+            reportMailingJobStretchyReportParamDateOption = YESTERDAY;
+        } else if (StringUtils.equalsIgnoreCase(value, TOMORROW.value)) {
+            reportMailingJobStretchyReportParamDateOption = TOMORROW;
+        }
+        
+        return reportMailingJobStretchyReportParamDateOption;
+    }
+    
+    /**
+     * Creates a new {@link ReportMailingJobStretchyReportParamDateOption} object
+     * 
+     * @param id id of the enum constant
+     * @return {@link ReportMailingJobStretchyReportParamDateOption} object
+     */
+    public static ReportMailingJobStretchyReportParamDateOption newInstance(final Integer id) {
+        ReportMailingJobStretchyReportParamDateOption reportMailingJobStretchyReportParamDateOption = INVALID;
+        
+        if (id == TODAY.id) {
+            reportMailingJobStretchyReportParamDateOption = TODAY;
+        } else if (id == YESTERDAY.id) {
+            reportMailingJobStretchyReportParamDateOption = YESTERDAY;
+        } else if (id == TOMORROW.id) {
+            reportMailingJobStretchyReportParamDateOption = TOMORROW;
+        }
+        
+        return reportMailingJobStretchyReportParamDateOption;
+    }
+    
+    /**
+     * @return the code
+     */
+    public String getCode() {
+        return code;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * @return the id
+     */
+    public Integer getId() {
+        return id;
+    }
+    
+    /** 
+     * @return true if the enum is equals to "INVALID"
+     */
+    public boolean isInvalid() {
+        return this.equals(INVALID);
+    }
+    
+    /**
+     * @return true if the enum is not equals to "INVALID"
+     */
+    public boolean isValid() {
+        return !this.isInvalid();
+    }
+    
+    /** 
+     * @return list of valid ReportMailingJobStretchyReportParamDateOption values
+     **/
+    public static Object[] validValues() {
+        List<Object> validValues = new ArrayList<>();
+        
+        for (ReportMailingJobStretchyReportParamDateOption constant :  ReportMailingJobStretchyReportParamDateOption.values()) {
+            if (constant.isValid()) {
+                validValues.add(constant.value);
+            }
+        }
+        
+        return validValues.toArray();
+    }
+    
+    /**
+     * get a {@link EnumOptionData} representation of the {@link ReportMailingJobStretchyReportParamDateOption} object
+     * 
+     * @return {@link EnumOptionData} object
+     */
+    public EnumOptionData toEnumOptionData() {
+        // get the long value of the enum id
+        final Long id = (this.id != null) ? this.id.longValue() : null;
+        
+        return new EnumOptionData(id, code, value);
+    }
+    
+    /**
+     * get the {@link EnumOptionData} representation of all valid {@link ReportMailingJobStretchyReportParamDateOption} objects
+     * 
+     * @return List of {@link EnumOptionData} objects
+     */
+    public static List<EnumOptionData> validOptions() {
+        List<EnumOptionData> options = new ArrayList<>();
+        
+        for (ReportMailingJobStretchyReportParamDateOption constant : ReportMailingJobStretchyReportParamDateOption.values()) {
+            if (constant.isValid()) {
+                options.add(constant.toEnumOptionData());
+            }
+        }
+        
+        return options;
+    }
+}


Mime
View raw message