commit for FINERACT-65 (Implement ability to schedule & e-mail reports)

This commit is contained in:
Emmanuel Nnaa
2016-08-08 14:18:11 +02:00
parent 5647ffb966
commit b30976bbfd
43 changed files with 4765 additions and 5 deletions
+444
View File
@@ -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>
@@ -2736,4 +2736,27 @@ public class CommandWrapperBuilder {
return this;
}
}
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;
}
}
@@ -443,4 +443,33 @@ public final class SearchParameters {
return this.isSelfUser;
}
}
/**
* 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);
}
}
@@ -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;
}
}
@@ -484,5 +484,4 @@ public class ReadReportingServiceImpl implements ReadReportingService {
return new ReportParameterData(id, null, null, parameterName);
}
}
}
}
@@ -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;
@@ -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";
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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());
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
@@ -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();
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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> {
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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());
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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);
}
}
}
@@ -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);
}
@@ -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;
}
}
@@ -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();
}
@@ -0,0 +1,203 @@
/**
* 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.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobData;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailAttachmentFileFormat;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobStretchyReportParamDateOption;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobTimelineData;
import org.apache.fineract.infrastructure.reportmailingjob.exception.ReportMailingJobNotFoundException;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
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 ReportMailingJobReadPlatformServiceImpl implements ReportMailingJobReadPlatformService {
private final JdbcTemplate jdbcTemplate;
@Autowired
public ReportMailingJobReadPlatformServiceImpl(final RoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Page<ReportMailingJobData> retrieveAllReportMailingJobs(final SearchParameters searchParameters) {
final StringBuilder sqlStringBuilder = new StringBuilder(200);
final List<Object> queryParameters = new ArrayList<>();
final ReportMailingJobMapper mapper = new ReportMailingJobMapper();
final PaginationHelper<ReportMailingJobData> paginationHelper = new PaginationHelper<>();
sqlStringBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlStringBuilder.append(mapper.ReportMailingJobSchema());
sqlStringBuilder.append(" where rmj.is_deleted = 0");
if (searchParameters.isOrderByRequested()) {
sqlStringBuilder.append(" order by ").append(searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlStringBuilder.append(" ").append(searchParameters.getSortOrder());
}
} else {
sqlStringBuilder.append(" order by rmj.name ");
}
if (searchParameters.isLimited()) {
sqlStringBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
sqlStringBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
return paginationHelper.fetchPage(this.jdbcTemplate, "SELECT FOUND_ROWS()", sqlStringBuilder.toString(),
queryParameters.toArray(), mapper);
}
@Override
public Collection<ReportMailingJobData> retrieveAllActiveReportMailingJobs() {
final ReportMailingJobMapper mapper = new ReportMailingJobMapper();
final String sql = "select " + mapper.ReportMailingJobSchema() + " where rmj.is_deleted = 0 and is_active = 1"
+ " order by rmj.name";
return this.jdbcTemplate.query(sql, mapper, new Object[] {});
}
@Override
public ReportMailingJobData retrieveReportMailingJob(final Long reportMailingJobId) {
try {
final ReportMailingJobMapper mapper = new ReportMailingJobMapper();
final String sql = "select " + mapper.ReportMailingJobSchema() + " where rmj.id = ? and rmj.is_deleted = 0";
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { reportMailingJobId });
}
catch (final EmptyResultDataAccessException ex) {
throw new ReportMailingJobNotFoundException(reportMailingJobId);
}
}
@Override
public ReportMailingJobData retrieveReportMailingJobEnumOptions() {
final List<EnumOptionData> emailAttachmentFileFormatOptions = ReportMailingJobEmailAttachmentFileFormat.validOptions();
final List<EnumOptionData> stretchyReportParamDateOptions = ReportMailingJobStretchyReportParamDateOption.validOptions();
return ReportMailingJobData.newInstance(emailAttachmentFileFormatOptions, stretchyReportParamDateOptions);
}
private static final class ReportMailingJobMapper implements RowMapper<ReportMailingJobData> {
public String ReportMailingJobSchema() {
return "rmj.id, rmj.name, rmj.description, rmj.start_datetime as startDateTime, rmj.recurrence, rmj.created_date as createdOnDate, "
+ "cbu.username as createdByUsername, cbu.firstname as createdByFirstname, cbu.lastname as createdByLastname, "
+ "rmj.lastmodified_date as updatedOnDate, "
+ "mbu.username as updatedByUsername, mbu.firstname as updatedByFirstname, mbu.lastname as updatedByLastname, "
+ "rmj.email_recipients as emailRecipients, "
+ "rmj.email_subject as emailSubject, rmj.email_message as emailMessage, "
+ "rmj.email_attachment_file_format as emailAttachmentFileFormat, "
+ "rmj.stretchy_report_param_map as stretchyReportParamMap, rmj.previous_run_datetime as previousRunDateTime, "
+ "rmj.next_run_datetime as nextRunDateTime, rmj.previous_run_status as previousRunStatus, "
+ "rmj.previous_run_error_log as previousRunErrorLog, rmj.previous_run_error_message as previousRunErrorMessage, "
+ "rmj.number_of_runs as numberOfRuns, rmj.is_active as isActive, rmj.run_as_userid as runAsUserId, "
+ "sr.id as reportId, sr.report_name as reportName, sr.report_type as reportType, sr.report_subtype as reportSubType, "
+ "sr.report_category as reportCategory, sr.report_sql as reportSql, sr.description as reportDescription, "
+ "sr.core_report as coreReport, sr.use_report as useReport "
+ "from m_report_mailing_job rmj "
+ "inner join m_appuser cbu "
+ "on cbu.id = rmj.createdby_id "
+ "left join m_appuser mbu "
+ "on mbu.id = rmj.lastmodifiedby_id "
+ "left join stretchy_report sr "
+ "on rmj.stretchy_report_id = sr.id";
}
@Override
public ReportMailingJobData mapRow(ResultSet rs, int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String name = rs.getString("name");
final String description = rs.getString("description");
final DateTime startDateTime = JdbcSupport.getDateTime(rs, "startDateTime");
final String recurrence = rs.getString("recurrence");
final LocalDate createdOnDate = JdbcSupport.getLocalDate(rs, "createdOnDate");
final LocalDate updatedOnDate = JdbcSupport.getLocalDate(rs, "updatedOnDate");
final String emailRecipients = rs.getString("emailRecipients");
final String emailSubject = rs.getString("emailSubject");
final String emailMessage = rs.getString("emailMessage");
final String emailAttachmentFileFormatString = rs.getString("emailAttachmentFileFormat");
EnumOptionData emailAttachmentFileFormat = null;
if (emailAttachmentFileFormatString != null) {
ReportMailingJobEmailAttachmentFileFormat format = ReportMailingJobEmailAttachmentFileFormat.newInstance(emailAttachmentFileFormatString);
emailAttachmentFileFormat = format.toEnumOptionData();
}
final String stretchyReportParamMap = rs.getString("stretchyReportParamMap");
final DateTime previousRunDateTime = JdbcSupport.getDateTime(rs, "previousRunDateTime");
final DateTime nextRunDateTime = JdbcSupport.getDateTime(rs, "nextRunDateTime");
final String previousRunStatus = rs.getString("previousRunStatus");
final String previousRunErrorLog = rs.getString("previousRunErrorLog");
final String previousRunErrorMessage = rs.getString("previousRunErrorMessage");
final Integer numberOfRuns = JdbcSupport.getInteger(rs, "numberOfRuns");
final boolean isActive = rs.getBoolean("isActive");
final String createdByUsername = rs.getString("createdByUsername");
final String createdByFirstname = rs.getString("createdByFirstname");
final String createdByLastname = rs.getString("createdByLastname");
final String updatedByUsername = rs.getString("updatedByUsername");
final String updatedByFirstname = rs.getString("updatedByFirstname");
final String updatedByLastname = rs.getString("updatedByLastname");
final ReportMailingJobTimelineData timeline = new ReportMailingJobTimelineData(createdOnDate, createdByUsername,
createdByFirstname, createdByLastname, updatedOnDate, updatedByUsername, updatedByFirstname, updatedByLastname);
final Long runAsUserId = JdbcSupport.getLong(rs, "runAsUserId");
final Long reportId = JdbcSupport.getLong(rs, "reportId");
final String reportName = rs.getString("reportName");
final String reportType = rs.getString("reportType");
final String reportSubType = rs.getString("reportSubType");
final String reportCategory = rs.getString("reportCategory");
final String reportSql = rs.getString("reportSql");
final String reportDescription = rs.getString("reportDescription");
final boolean coreReport = rs.getBoolean("coreReport");
final boolean useReport = rs.getBoolean("useReport");
final ReportData stretchyReport = new ReportData(reportId, reportName, reportType, reportSubType, reportCategory,
reportDescription, reportSql, coreReport, useReport, null);
return ReportMailingJobData.newInstance(id, name, description, startDateTime, recurrence, timeline, emailRecipients,
emailSubject, emailMessage, emailAttachmentFileFormat, stretchyReport, stretchyReportParamMap, previousRunDateTime,
nextRunDateTime, previousRunStatus, previousRunErrorLog, previousRunErrorMessage, numberOfRuns, isActive,
runAsUserId);
}
}
}
@@ -0,0 +1,34 @@
/**
* 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.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobRunHistoryData;
public interface ReportMailingJobRunHistoryReadPlatformService {
/**
* Retrieve all report mailing run history with similar job id to the one passed
*
* @param reportMailingJobId ReportMailingJob identifier
* @param searchParameters {@link SearchParameters} object
* @return collection of {@link ReportMailingJobRunHistoryData} objects
**/
Page<ReportMailingJobRunHistoryData> retrieveRunHistoryByJobId(Long reportMailingJobId, SearchParameters searchParameters);
}
@@ -0,0 +1,106 @@
/**
* 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.ArrayList;
import java.util.List;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobRunHistoryData;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class ReportMailingJobRunHistoryReadPlatformServiceImpl implements ReportMailingJobRunHistoryReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final ReportMailingJobRunHistoryMapper reportMailingJobRunHistoryMapper;
private final PaginationHelper<ReportMailingJobRunHistoryData> paginationHelper = new PaginationHelper<>();
@Autowired
public ReportMailingJobRunHistoryReadPlatformServiceImpl(final RoutingDataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.reportMailingJobRunHistoryMapper = new ReportMailingJobRunHistoryMapper();
}
@Override
public Page<ReportMailingJobRunHistoryData> retrieveRunHistoryByJobId(final Long reportMailingJobId,
final SearchParameters searchParameters) {
final StringBuilder sqlStringBuilder = new StringBuilder(200);
final List<Object> queryParameters = new ArrayList<>();
sqlStringBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlStringBuilder.append(this.reportMailingJobRunHistoryMapper.ReportMailingJobRunHistorySchema());
if (reportMailingJobId != null) {
sqlStringBuilder.append(" where rmjrh.job_id = ? ");
queryParameters.add(reportMailingJobId);
}
if (searchParameters.isOrderByRequested()) {
sqlStringBuilder.append(" order by ").append(searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlStringBuilder.append(" ").append(searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
sqlStringBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
sqlStringBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
return this.paginationHelper.fetchPage(this.jdbcTemplate, "SELECT FOUND_ROWS()", sqlStringBuilder.toString(),
queryParameters.toArray(), this.reportMailingJobRunHistoryMapper);
}
private static final class ReportMailingJobRunHistoryMapper implements RowMapper<ReportMailingJobRunHistoryData> {
public String ReportMailingJobRunHistorySchema() {
return "rmjrh.id, rmjrh.job_id as reportMailingJobId, rmjrh.start_datetime as startDateTime, "
+ "rmjrh.end_datetime as endDateTime, rmjrh.status, rmjrh.error_message as errorMessage, "
+ "rmjrh.error_log as errorLog "
+ "from m_report_mailing_job_run_history rmjrh";
}
@Override
public ReportMailingJobRunHistoryData mapRow(ResultSet rs, int rowNum) throws SQLException {
final Long id = JdbcSupport.getLong(rs, "id");
final Long reportMailingJobId = JdbcSupport.getLong(rs, "reportMailingJobId");
final DateTime startDateTime = JdbcSupport.getDateTime(rs, "startDateTime");
final DateTime endDateTime = JdbcSupport.getDateTime(rs, "endDateTime");
final String status = rs.getString("status");
final String errorMessage = rs.getString("errorMessage");
final String errorLog = rs.getString("errorLog");
return ReportMailingJobRunHistoryData.newInstance(id, reportMailingJobId, startDateTime, endDateTime, status,
errorMessage, errorLog);
}
}
}
@@ -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.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
public interface ReportMailingJobWritePlatformService {
CommandProcessingResult createReportMailingJob(JsonCommand jsonCommand);
CommandProcessingResult updateReportMailingJob(Long reportMailingJobId, JsonCommand jsonCommand);
CommandProcessingResult deleteReportMailingJob(Long reportMailingJobId);
void executeReportMailingJobs() throws JobExecutionException;
}
@@ -0,0 +1,495 @@
/**
* 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.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.dataqueries.domain.Report;
import org.apache.fineract.infrastructure.dataqueries.domain.ReportRepositoryWrapper;
import org.apache.fineract.infrastructure.dataqueries.service.ReadReportingService;
import org.apache.fineract.infrastructure.documentmanagement.contentrepository.FileSystemContentRepository;
import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailAttachmentFileFormat;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailData;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobPreviousRunStatus;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobStretchyReportParamDateOption;
import org.apache.fineract.infrastructure.reportmailingjob.domain.ReportMailingJob;
import org.apache.fineract.infrastructure.reportmailingjob.domain.ReportMailingJobRepository;
import org.apache.fineract.infrastructure.reportmailingjob.domain.ReportMailingJobRepositoryWrapper;
import org.apache.fineract.infrastructure.reportmailingjob.domain.ReportMailingJobRunHistory;
import org.apache.fineract.infrastructure.reportmailingjob.domain.ReportMailingJobRunHistoryRepository;
import org.apache.fineract.infrastructure.reportmailingjob.util.ReportMailingJobDateUtil;
import org.apache.fineract.infrastructure.reportmailingjob.validation.ReportMailingJobValidator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
import org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sun.jersey.core.util.MultivaluedMapImpl;
@Service
public class ReportMailingJobWritePlatformServiceImpl implements ReportMailingJobWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(ReportMailingJobWritePlatformServiceImpl.class);
private final ReportRepositoryWrapper reportRepositoryWrapper;
private final ReportMailingJobValidator reportMailingJobValidator;
private final ReportMailingJobRepositoryWrapper reportMailingJobRepositoryWrapper;
private final ReportMailingJobRepository reportMailingJobRepository;
private final PlatformSecurityContext platformSecurityContext;
private final ReportMailingJobEmailService reportMailingJobEmailService;
private final ReadReportingService readReportingService;
private final ReportingProcessServiceProvider reportingProcessServiceProvider;
private final ReportMailingJobRunHistoryRepository reportMailingJobRunHistoryRepository;
private final static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Autowired
public ReportMailingJobWritePlatformServiceImpl(final ReportRepositoryWrapper reportRepositoryWrapper,
final ReportMailingJobValidator reportMailingJobValidator,
final ReportMailingJobRepositoryWrapper reportMailingJobRepositoryWrapper,
final ReportMailingJobRepository reportMailingJobRepository,
final PlatformSecurityContext platformSecurityContext,
final ReportMailingJobEmailService reportMailingJobEmailService,
final ReadReportingService readReportingService,
final ReportMailingJobRunHistoryRepository reportMailingJobRunHistoryRepository,
final ReportingProcessServiceProvider reportingProcessServiceProvider) {
this.reportRepositoryWrapper = reportRepositoryWrapper;
this.reportMailingJobValidator = reportMailingJobValidator;
this.reportMailingJobRepositoryWrapper = reportMailingJobRepositoryWrapper;
this.reportMailingJobRepository = reportMailingJobRepositoryWrapper.getReportMailingJobRepository();
this.platformSecurityContext = platformSecurityContext;
this.reportMailingJobEmailService = reportMailingJobEmailService;
this.readReportingService = readReportingService;
this.reportMailingJobRunHistoryRepository = reportMailingJobRunHistoryRepository;
this.reportingProcessServiceProvider = reportingProcessServiceProvider;
}
@Override
@Transactional
public CommandProcessingResult createReportMailingJob(JsonCommand jsonCommand) {
try {
// validate the create request
this.reportMailingJobValidator.validateCreateRequest(jsonCommand);
final AppUser appUser = this.platformSecurityContext.authenticatedUser();
// get the stretchy Report object
final Report stretchyReport = this.reportRepositoryWrapper.findOneThrowExceptionIfNotFound(jsonCommand.longValueOfParameterNamed(
ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME));
// create an instance of ReportMailingJob class from the JsonCommand object
final ReportMailingJob reportMailingJob = ReportMailingJob.newInstance(jsonCommand, stretchyReport, appUser);
// save entity
this.reportMailingJobRepository.save(reportMailingJob);
return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId()).
withEntityId(reportMailingJob.getId()).build();
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(jsonCommand, dve);
return CommandProcessingResult.empty();
}
}
@Override
@Transactional
public CommandProcessingResult updateReportMailingJob(Long reportMailingJobId, JsonCommand jsonCommand) {
try {
// validate the update request
this.reportMailingJobValidator.validateUpdateRequest(jsonCommand);
// retrieve the ReportMailingJob object from the database
final ReportMailingJob reportMailingJob = this.reportMailingJobRepositoryWrapper.findOneThrowExceptionIfNotFound(reportMailingJobId);
final Map<String, Object> changes = reportMailingJob.update(jsonCommand);
// get the recurrence rule string
final String recurrence = reportMailingJob.getRecurrence();
// get the next run DateTime from the ReportMailingJob entity
DateTime nextRunDateTime = reportMailingJob.getNextRunDateTime();
// check if the stretchy report id was updated
if (changes.containsKey(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME)) {
final Long stretchyReportId = (Long) changes.get(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME);
final Report stretchyReport = this.reportRepositoryWrapper.findOneThrowExceptionIfNotFound(stretchyReportId);
// update the stretchy report
reportMailingJob.update(stretchyReport);
}
// check if the recurrence was updated
if (changes.containsKey(ReportMailingJobConstants.RECURRENCE_PARAM_NAME)) {
// go ahead if the recurrence is not null
if (StringUtils.isNotBlank(recurrence)) {
// set the start DateTime to the current tenant date time
DateTime startDateTime = DateUtils.getLocalDateTimeOfTenant().toDateTime();
// check if the start DateTime was updated
if (changes.containsKey(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME)) {
// get the updated start DateTime
startDateTime = reportMailingJob.getStartDateTime();
}
startDateTime = reportMailingJob.getStartDateTime();
// get the next recurring DateTime
final DateTime nextRecurringDateTime = this.createNextRecurringDateTime(recurrence, startDateTime);
// update the next run time property
reportMailingJob.updateNextRunDateTime(nextRecurringDateTime);
// check if the next run DateTime is not empty and the recurrence is empty
} else if (StringUtils.isBlank(recurrence) && (nextRunDateTime != null)) {
// the next run DateTime should be set to null
reportMailingJob.updateNextRunDateTime(null);
}
}
if (changes.containsKey(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME)) {
final DateTime startDateTime = reportMailingJob.getStartDateTime();
// initially set the next recurring date time to the new start date time
DateTime nextRecurringDateTime = startDateTime;
// ensure that the recurrence pattern string is not empty
if (StringUtils.isNotBlank(recurrence)) {
// get the next recurring DateTime
nextRecurringDateTime = this.createNextRecurringDateTime(recurrence, startDateTime);
}
// update the next run time property
reportMailingJob.updateNextRunDateTime(nextRecurringDateTime);
}
if (!changes.isEmpty()) {
// save and flush immediately so any data integrity exception can be handled in the "catch" block
this.reportMailingJobRepository.saveAndFlush(reportMailingJob);
}
return new CommandProcessingResultBuilder().
withCommandId(jsonCommand.commandId()).
withEntityId(reportMailingJob.getId()).
with(changes).
build();
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(jsonCommand, dve);
return CommandProcessingResult.empty();
}
}
@Override
@Transactional
public CommandProcessingResult deleteReportMailingJob(Long reportMailingJobId) {
// retrieve the ReportMailingJob object from the database
final ReportMailingJob reportMailingJob = this.reportMailingJobRepositoryWrapper.findOneThrowExceptionIfNotFound(reportMailingJobId);
// delete the report mailing job by setting the isDeleted property to 1 and altering the name
reportMailingJob.delete();
// save the report mailing job entity
this.reportMailingJobRepository.save(reportMailingJob);
return new CommandProcessingResultBuilder().withEntityId(reportMailingJobId).build();
}
@Override
@CronTarget(jobName = JobName.EXECUTE_REPORT_MAILING_JOBS)
public void executeReportMailingJobs() throws JobExecutionException {
final Collection<ReportMailingJob> reportMailingJobCollection = this.reportMailingJobRepository.findByIsActiveTrueAndIsDeletedFalse();
for (ReportMailingJob reportMailingJob : reportMailingJobCollection) {
// get the tenant's date as a DateTime object
final DateTime localDateTimeOftenant = DateUtils.getLocalDateTimeOfTenant().toDateTime();
final DateTime nextRunDateTime = reportMailingJob.getNextRunDateTime();
if (nextRunDateTime != null && nextRunDateTime.isBefore(localDateTimeOftenant)) {
// get the emailAttachmentFileFormat enum object
final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat = ReportMailingJobEmailAttachmentFileFormat.
newInstance(reportMailingJob.getEmailAttachmentFileFormat());
if (emailAttachmentFileFormat != null && emailAttachmentFileFormat.isValid()) {
final Report stretchyReport = reportMailingJob.getStretchyReport();
final String reportName = (stretchyReport != null) ? stretchyReport.getReportName() : null;
final StringBuilder errorLog = new StringBuilder();
final Map<String, String> validateStretchyReportParamMap = this.reportMailingJobValidator.
validateStretchyReportParamMap(reportMailingJob.getStretchyReportParamMap());
MultivaluedMap<String, String> reportParams = new MultivaluedMapImpl();
if (validateStretchyReportParamMap != null) {
Iterator<Map.Entry<String, String>> validateStretchyReportParamMapEntries = validateStretchyReportParamMap.entrySet().iterator();
while (validateStretchyReportParamMapEntries.hasNext()) {
Map.Entry<String, String> validateStretchyReportParamMapEntry = validateStretchyReportParamMapEntries.next();
String key = validateStretchyReportParamMapEntry.getKey();
String value = validateStretchyReportParamMapEntry.getValue();
if (StringUtils.containsIgnoreCase(key, "date")) {
ReportMailingJobStretchyReportParamDateOption reportMailingJobStretchyReportParamDateOption =
ReportMailingJobStretchyReportParamDateOption.newInstance(value);
if (reportMailingJobStretchyReportParamDateOption.isValid()) {
value = ReportMailingJobDateUtil.getDateAsString(reportMailingJobStretchyReportParamDateOption);
}
}
reportParams.add(key, value);
}
}
// generate the report output stream, method in turn call another that sends the file to the email recipients
this.generateReportOutputStream(reportMailingJob, emailAttachmentFileFormat, reportParams, reportName, errorLog);
// update the previous run time, next run time, status, error log properties
this.updateReportMailingJobAfterJobExecution(reportMailingJob, errorLog, localDateTimeOftenant);
}
}
}
}
/**
* update the report mailing job entity after job execution
*
* @param reportMailingJob -- the report mailing job entity
* @param errorLog -- StringBuilder object containing the error log if any
* @param jobStartDateTime -- the start DateTime of the job
* @return None
**/
private void updateReportMailingJobAfterJobExecution(final ReportMailingJob reportMailingJob, final StringBuilder errorLog,
final DateTime jobStartDateTime) {
final String recurrence = reportMailingJob.getRecurrence();
final DateTime nextRunDateTime = reportMailingJob.getNextRunDateTime();
ReportMailingJobPreviousRunStatus reportMailingJobPreviousRunStatus = ReportMailingJobPreviousRunStatus.SUCCESS;
reportMailingJob.updatePreviousRunErrorLog(null);
if (errorLog != null && errorLog.length() > 0) {
reportMailingJobPreviousRunStatus = ReportMailingJobPreviousRunStatus.ERROR;
reportMailingJob.updatePreviousRunErrorLog(errorLog.toString());
}
reportMailingJob.increaseNumberOfRunsByOne();
reportMailingJob.updatePreviousRunStatus(reportMailingJobPreviousRunStatus.getValue());
reportMailingJob.updatePreviousRunDateTime(reportMailingJob.getNextRunDateTime());
// check if the job has a recurrence pattern, if not deactivate the job. The job will only run once
if (StringUtils.isEmpty(recurrence)) {
// deactivate job
reportMailingJob.deactivate();
// job will only run once, no next run time
reportMailingJob.updateNextRunDateTime(null);
} else if (nextRunDateTime != null) {
final DateTime nextRecurringDateTime = this.createNextRecurringDateTime(recurrence, nextRunDateTime);
// finally update the next run date time property
reportMailingJob.updateNextRunDateTime(nextRecurringDateTime);
}
// save the ReportMailingJob entity
this.reportMailingJobRepository.save(reportMailingJob);
// create a new report mailing job run history entity
this.createReportMailingJobRunHistroryAfterJobExecution(reportMailingJob, errorLog, jobStartDateTime,
reportMailingJobPreviousRunStatus.getValue());
}
/**
* create the next recurring DateTime from recurrence pattern, start DateTime and current DateTime
*
* @param recurrencePattern
* @param startDateTime
* @return DateTime object
*/
private DateTime createNextRecurringDateTime(final String recurrencePattern, final DateTime startDateTime) {
DateTime nextRecurringDateTime = null;
// the recurrence pattern/rule cannot be empty
if (StringUtils.isNotBlank(recurrencePattern) && startDateTime != null) {
final LocalDate nextDayLocalDate = startDateTime.plus(1).toLocalDate();
final LocalDate nextRecurringLocalDate = CalendarUtils.getNextRecurringDate(recurrencePattern, startDateTime.toLocalDate(),
nextDayLocalDate);
final String nextDateTimeString = nextRecurringLocalDate + " " + startDateTime.getHourOfDay() + ":" + startDateTime.getMinuteOfHour()
+ ":" + startDateTime.getSecondOfMinute();
final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(DATETIME_FORMAT);
nextRecurringDateTime = DateTime.parse(nextDateTimeString, dateTimeFormatter);
}
return nextRecurringDateTime;
}
/**
* create a new report mailing job run history entity after job execution
*
* @param reportMailingJob -- the report mailing job entity
* @param errorLog -- StringBuilder object containing the error log if any
* @param jobStartDateTime -- the start DateTime of the job
* @param jobRunStatus -- the status of the job (success/error)
* @return None
**/
private void createReportMailingJobRunHistroryAfterJobExecution(final ReportMailingJob reportMailingJob, final StringBuilder errorLog,
final DateTime jobStartDateTime, final String jobRunStatus) {
final DateTime jobEndDateTime = DateUtils.getLocalDateTimeOfTenant().toDateTime();
final String errorLogToString = (errorLog != null) ? errorLog.toString() : null;
final ReportMailingJobRunHistory reportMailingJobRunHistory = ReportMailingJobRunHistory.newInstance(reportMailingJob, jobStartDateTime,
jobEndDateTime, jobRunStatus, null, errorLogToString);
this.reportMailingJobRunHistoryRepository.save(reportMailingJobRunHistory);
}
/**
* Handle any SQL data integrity issue
*
* @param jsonCommand -- JsonCommand object
* @param dve -- data integrity exception object
* @return None
**/
private void handleDataIntegrityIssues(final JsonCommand jsonCommand, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains(ReportMailingJobConstants.NAME_PARAM_NAME)) {
final String name = jsonCommand.stringValueOfParameterNamed(ReportMailingJobConstants.NAME_PARAM_NAME);
throw new PlatformDataIntegrityException("error.msg.report.mailing.job.duplicate.name", "Report mailing job with name `" + name + "` already exists",
ReportMailingJobConstants.NAME_PARAM_NAME, name);
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.charge.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage());
}
/**
* generate the report output stream
*
* @param reportMailingJob
* @param emailAttachmentFileFormat
* @param reportParams
* @param reportName
* @param errorLog
* @return the error log StringBuilder object
*/
private StringBuilder generateReportOutputStream(final ReportMailingJob reportMailingJob, final ReportMailingJobEmailAttachmentFileFormat emailAttachmentFileFormat,
final MultivaluedMap<String, String> reportParams, final String reportName, final StringBuilder errorLog) {
try {
final String reportType = this.readReportingService.getReportType(reportName);
final ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType);
if (reportingProcessService != null) {
final Response processReport = reportingProcessService.processRequest(reportName, reportParams);
final Object reponseObject = (processReport != null) ? processReport.getEntity() : null;
if (reponseObject != null && reponseObject.getClass().equals(ByteArrayOutputStream.class)) {
final ByteArrayOutputStream byteArrayOutputStream = ByteArrayOutputStream.class.cast(reponseObject);
final String fileLocation = FileSystemContentRepository.FINERACT_BASE_DIR + File.separator + "";
final String fileNameWithoutExtension = fileLocation + File.separator + reportName;
// check if file directory exists, if not create directory
if (!new File(fileLocation).isDirectory()) {
new File(fileLocation).mkdirs();
}
if ((byteArrayOutputStream == null) || byteArrayOutputStream.size() == 0) {
errorLog.append("Report processing failed, empty output stream created");
} else if ((errorLog != null && errorLog.length() == 0) && (byteArrayOutputStream.size() > 0)) {
final String fileName = fileNameWithoutExtension + "." + emailAttachmentFileFormat.getValue();
// send the file to email recipients
this.sendReportFileToEmailRecipients(reportMailingJob, fileName, byteArrayOutputStream, errorLog);
}
} else {
errorLog.append("Response object entity is not equal to ByteArrayOutputStream ---------- ");
}
} else {
errorLog.append("ReportingProcessService object is null ---------- ");
}
} catch (Exception e) {
errorLog.append("The ReportMailingJobWritePlatformServiceImpl.generateReportOutputStream method threw an Exception: "
+ e + " ---------- ");
}
return errorLog;
}
/**
* send report file to email recipients
*
* @param reportMailingJob
* @param fileName
* @param byteArrayOutputStream
* @param errorLog
*/
private void sendReportFileToEmailRecipients(final ReportMailingJob reportMailingJob, final String fileName,
final ByteArrayOutputStream byteArrayOutputStream, final StringBuilder errorLog) {
final Set<String> emailRecipients = this.reportMailingJobValidator.validateEmailRecipients(reportMailingJob.getEmailRecipients());
try {
final File file = new File(fileName);
final FileOutputStream outputStream = new FileOutputStream(file);
byteArrayOutputStream.writeTo(outputStream);
for (String emailRecipient : emailRecipients) {
final ReportMailingJobEmailData reportMailingJobEmailData = new ReportMailingJobEmailData(emailRecipient,
reportMailingJob.getEmailMessage(), reportMailingJob.getEmailSubject(), file);
this.reportMailingJobEmailService.sendEmailWithAttachment(reportMailingJobEmailData);
}
outputStream.close();
} catch (IOException e) {
errorLog.append("The ReportMailingJobWritePlatformServiceImpl.sendReportFileToEmailRecipients method threw an IOException "
+ "exception: " + e + " ---------- ");
}
}
}
@@ -0,0 +1,114 @@
/**
* 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.util;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobStretchyReportParamDateOption;
public class ReportMailingJobDateUtil {
public static final String MYSQL_DATE_FORMAT = "yyyy-MM-dd";
/**
* get the current date as string using the mysql date format yyyy-MM-dd
**/
public static String getTodayDateAsString() {
// get a calendar instance, which defaults to "now"
Calendar calendar = Calendar.getInstance();
// get a date to represent "today"
Date today = calendar.getTime();
// get a SimpleDateFormat instance, passing the mysql date format as parameter
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(MYSQL_DATE_FORMAT);
// return date as string
return simpleDateFormat.format(today);
}
/**
* get the yesterday's date as string using the mysql date format yyyy-MM-dd
**/
public static String getYesterdayDateAsString() {
// get a calendar instance, which defaults to "now"
Calendar calendar = Calendar.getInstance();
// add one day to the date/calendar
calendar.add(Calendar.DAY_OF_YEAR, -1);
// now get "yesterday"
Date yesterday = calendar.getTime();
// get a SimpleDateFormat instance, passing the mysql date format as parameter
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(MYSQL_DATE_FORMAT);
// return date as string
return simpleDateFormat.format(yesterday);
}
/**
* get the tomorrow's date as string using the mysql date format yyyy-MM-dd
**/
public static String getTomorrowDateAsString() {
// get a calendar instance, which defaults to "now"
Calendar calendar = Calendar.getInstance();
// add one day to the date/calendar
calendar.add(Calendar.DAY_OF_YEAR, 1);
// now get "tomorrow"
Date tomorrow = calendar.getTime();
// get a SimpleDateFormat instance, passing the mysql date format as parameter
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(MYSQL_DATE_FORMAT);
// return date as string
return simpleDateFormat.format(tomorrow);
}
/**
* get date as string based on the value of the {@link ReportMailingJobStretchyReportParamDateOption} object
*
* @param reportMailingJobStretchyReportParamDateOption {@link ReportMailingJobStretchyReportParamDateOption} Enum
**/
public static String getDateAsString(final ReportMailingJobStretchyReportParamDateOption reportMailingJobStretchyReportParamDateOption) {
String dateAsString = null;
switch (reportMailingJobStretchyReportParamDateOption) {
case TODAY:
dateAsString = getTodayDateAsString();
break;
case YESTERDAY:
dateAsString = getYesterdayDateAsString();
break;
case TOMORROW:
dateAsString = getTomorrowDateAsString();
break;
default:
break;
}
return dateAsString;
}
}
@@ -0,0 +1,319 @@
/**
* 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.validation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.reportmailingjob.ReportMailingJobConstants;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobEmailAttachmentFileFormat;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public class ReportMailingJobValidator {
private final FromJsonHelper fromJsonHelper;
private static final String EMAIL_REGEX = "^[\\w!#$%&’*+/=?`{|}~^-]+(?:\\.[\\w!#$%&’*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$";
private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
@Autowired
public ReportMailingJobValidator(final FromJsonHelper fromJsonHelper) {
this.fromJsonHelper = fromJsonHelper;
}
/**
* validate the request to create a new report mailing job
*
* @param jsonCommand -- the JSON command object (instance of the JsonCommand class)
* @return None
**/
public void validateCreateRequest(final JsonCommand jsonCommand) {
final String jsonString = jsonCommand.json();
final JsonElement jsonElement = jsonCommand.parsedJson();
if (StringUtils.isBlank(jsonString)) {
throw new InvalidJsonException();
}
final Type typeToken = new TypeToken<Map<String, Object>>() {}.getType();
this.fromJsonHelper.checkForUnsupportedParameters(typeToken, jsonString,
ReportMailingJobConstants.CREATE_REQUEST_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors).
resource(StringUtils.lowerCase(ReportMailingJobConstants.REPORT_MAILING_JOB_RESOURCE_NAME));
final String name = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.NAME_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.NAME_PARAM_NAME).value(name).notBlank().notExceedingLengthOf(100);
final String startDateTime = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME).value(startDateTime).notBlank();
final Integer stretchyReportId = this.fromJsonHelper.extractIntegerWithLocaleNamed(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME).value(stretchyReportId).notNull().
integerGreaterThanZero();
final String emailRecipients = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME).value(emailRecipients).notBlank();
final String emailSubject = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME).value(emailSubject).notBlank().notExceedingLengthOf(100);
final String emailMessage = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME).value(emailMessage).notBlank();
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME, jsonElement)) {
final Boolean isActive = this.fromJsonHelper.extractBooleanNamed(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME).value(isActive).notNull();
}
final Integer emailAttachmentFileFormatId = this.fromJsonHelper.extractIntegerSansLocaleNamed(
ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME).
value(emailAttachmentFileFormatId).notNull();
if (emailAttachmentFileFormatId != null) {
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME).value(emailAttachmentFileFormatId).
isOneOfTheseValues(ReportMailingJobEmailAttachmentFileFormat.validIds());
}
final String dateFormat = jsonCommand.dateFormat();
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.DATE_FORMAT_PARAM_NAME).value(dateFormat).notBlank();
if (StringUtils.isNotEmpty(dateFormat)) {
try {
final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(dateFormat).withLocale(jsonCommand.extractLocale());
// try to parse the date time string
LocalDateTime.parse(startDateTime, dateTimeFormatter);
}
catch(IllegalArgumentException ex) {
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.DATE_FORMAT_PARAM_NAME).value(dateFormat).failWithCode("invalid.date.format");
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
/**
* validate the request to update a report mailing job
*
* @param jsonCommand -- the JSON command object (instance of the JsonCommand class)
* @return None
**/
public void validateUpdateRequest(final JsonCommand jsonCommand) {
final String jsonString = jsonCommand.json();
final JsonElement jsonElement = jsonCommand.parsedJson();
if (StringUtils.isBlank(jsonString)) {
throw new InvalidJsonException();
}
final Type typeToken = new TypeToken<Map<String, Object>>() {}.getType();
this.fromJsonHelper.checkForUnsupportedParameters(typeToken, jsonString,
ReportMailingJobConstants.UPDATE_REQUEST_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors).
resource(StringUtils.lowerCase(ReportMailingJobConstants.REPORT_MAILING_JOB_RESOURCE_NAME));
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.NAME_PARAM_NAME, jsonElement)) {
final String name = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.NAME_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.NAME_PARAM_NAME).value(name).notBlank().notExceedingLengthOf(100);
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME, jsonElement)) {
final Integer stretchyReportId = this.fromJsonHelper.extractIntegerWithLocaleNamed(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.STRETCHY_REPORT_ID_PARAM_NAME).value(stretchyReportId).notNull().
integerGreaterThanZero();
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME, jsonElement)) {
final String emailRecipients = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_RECIPIENTS_PARAM_NAME).value(emailRecipients).notBlank();
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME, jsonElement)) {
final String emailSubject = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_SUBJECT_PARAM_NAME).value(emailSubject).notBlank().notExceedingLengthOf(100);
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME, jsonElement)) {
final String emailMessage = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_MESSAGE_PARAM_NAME).value(emailMessage).notBlank();
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME, jsonElement)) {
final Boolean isActive = this.fromJsonHelper.extractBooleanNamed(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.IS_ACTIVE_PARAM_NAME).value(isActive).notNull();
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, jsonElement)) {
final Integer emailAttachmentFileFormatId = this.fromJsonHelper.extractIntegerSansLocaleNamed(
ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME, jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME).
value(emailAttachmentFileFormatId).notNull();
if (emailAttachmentFileFormatId != null) {
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.EMAIL_ATTACHMENT_FILE_FORMAT_ID_PARAM_NAME).value(emailAttachmentFileFormatId).
isOneOfTheseValues(ReportMailingJobEmailAttachmentFileFormat.validIds());
}
}
if (this.fromJsonHelper.parameterExists(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME, jsonElement)) {
final String dateFormat = jsonCommand.dateFormat();
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.DATE_FORMAT_PARAM_NAME).value(dateFormat).notBlank();
final String startDateTime = this.fromJsonHelper.extractStringNamed(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME,
jsonElement);
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.START_DATE_TIME_PARAM_NAME).value(startDateTime).notBlank();
if (StringUtils.isNotEmpty(dateFormat)) {
try {
final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(dateFormat).withLocale(jsonCommand.extractLocale());
// try to parse the date time string
LocalDateTime.parse(startDateTime, dateTimeFormatter);
}
catch(IllegalArgumentException ex) {
dataValidatorBuilder.reset().parameter(ReportMailingJobConstants.DATE_FORMAT_PARAM_NAME).value(dateFormat).failWithCode("invalid.date.format");
}
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
/**
* check if string is a valid email address
*
* @param email -- string to be validated
* @return true if string is a valid email address
**/
public boolean isValidEmail(String email) {
// this is the easiest check
if (email == null) {
return false;
}
// this is another easy check
if (email.endsWith(".")) {
return false;
}
// Check the whole email address structure
Matcher emailMatcher = EMAIL_PATTERN.matcher(email);
// check if the Matcher matches the email pattern
if (!emailMatcher.matches()) {
return false;
}
return true;
}
/**
* Validate the email recipients string
*
* @param emailRecipients -- the email recipients string to be validated
* @return a hashset containing valid email addresses
**/
public Set<String> validateEmailRecipients(String emailRecipients) {
Set<String> emailRecipientsSet = new HashSet<>();
if (emailRecipients != null) {
String[] split = emailRecipients.split(",");
for (String emailAddress : split) {
emailAddress = emailAddress.trim();
if (this.isValidEmail(emailAddress)) {
emailRecipientsSet.add(emailAddress);
}
}
}
return emailRecipientsSet;
}
/**
* validate the stretchy report param json string
*
* @param stretchyReportParamMap -- json string to be validated
* @return if string is valid or empty, a HashMap object, else null
**/
public HashMap<String,String> validateStretchyReportParamMap(String stretchyReportParamMap) {
HashMap<String,String> stretchyReportParamHashMap = new HashMap<>();
if (!StringUtils.isEmpty(stretchyReportParamMap)) {
try {
stretchyReportParamHashMap = new ObjectMapper().readValue(stretchyReportParamMap, new TypeReference<HashMap<String,String>>(){});
}
catch(Exception e) {
stretchyReportParamHashMap = null;
}
}
return stretchyReportParamHashMap;
}
/**
* throw a PlatformApiDataValidationException exception if there are validation errors
*
* @param dataValidationErrors -- list of ApiParameterError objects
* @return None
**/
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
}
@@ -0,0 +1,61 @@
create table if not exists m_report_mailing_job (
id bigint primary key auto_increment,
name varchar(100) not null,
description text null,
start_datetime datetime not null,
recurrence varchar(100) null,
created_date date not null,
createdby_id bigint not null,
lastmodified_date date null,
lastmodifiedby_id bigint null,
email_recipients text not null,
email_subject varchar(100) not null,
email_message text not null,
email_attachment_file_format varchar(10) not null,
stretchy_report_id int not null,
stretchy_report_param_map text null,
previous_run_datetime datetime null,
next_run_datetime datetime null,
previous_run_status varchar(10) null,
previous_run_error_log text null,
previous_run_error_message text null,
number_of_runs int not null default 0,
is_active tinyint(1) not null default 0,
is_deleted tinyint(1) not null default 0,
run_as_userid bigint not null,
foreign key (createdby_id) references m_appuser(id),
foreign key (lastmodifiedby_id) references m_appuser(id),
foreign key (stretchy_report_id) references stretchy_report(id),
foreign key (run_as_userid) references m_appuser(id),
constraint unique_name unique (name)
);
create table if not exists m_report_mailing_job_run_history (
id bigint primary key auto_increment,
job_id bigint not null,
start_datetime datetime not null,
end_datetime datetime not null,
status varchar(10) not null,
error_message text null,
error_log text null,
foreign key (job_id) references m_report_mailing_job (id)
);
create table if not exists m_report_mailing_job_configuration (
id int primary key auto_increment,
name varchar(50) not null,
`value` varchar(200) not null,
constraint unique_name unique (name)
);
insert into m_permission (`grouping`, code, entity_name, action_name, can_maker_checker)
values ('jobs', 'CREATE_REPORTMAILINGJOB', 'REPORTMAILINGJOB', 'CREATE', 0),
('jobs', 'UPDATE_REPORTMAILINGJOB', 'REPORTMAILINGJOB', 'UPDATE', 0),
('jobs', 'DELETE_REPORTMAILINGJOB', 'REPORTMAILINGJOB', 'DELETE', 0),
('jobs', 'READ_REPORTMAILINGJOB', 'REPORTMAILINGJOB', 'READ', 0);
insert into m_report_mailing_job_configuration (name, `value`)
values ('GMAIL_SMTP_SERVER', 'smtp.gmail.com'), ('GMAIL_SMTP_PORT', 587), ('GMAIL_SMTP_USERNAME', ''), ('GMAIL_SMTP_PASSWORD', '');
insert into job (name, display_name, cron_expression, create_time)
values ('Execute Report Mailing Jobs', 'Execute Report Mailing Jobs', '0 0/15 * * * ?', NOW());