RM-581 (A user will receive notification of rejected records)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@46138 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tuna Aksoy
2013-02-01 14:36:56 +00:00
parent d08b441438
commit fb2a90ff29
7 changed files with 441 additions and 256 deletions

View File

@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0" <view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:alf="http://www.alfresco.org" xmlns:alf="http://www.alfresco.org"
xmlns:d="http://www.alfresco.org/model/dictionary/1.0" xmlns:d="http://www.alfresco.org/model/dictionary/1.0"
xmlns:act="http://www.alfresco.org/model/action/1.0" xmlns:act="http://www.alfresco.org/model/action/1.0"
xmlns:wf="http://www.alfresco.org/model/workflow/1.0" xmlns:wf="http://www.alfresco.org/model/workflow/1.0"
xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:app="http://www.alfresco.org/model/application/1.0"
xmlns:usr="http://www.alfresco.org/model/user/1.0" xmlns:usr="http://www.alfresco.org/model/user/1.0"
xmlns:ver="http://www.alfresco.org/model/versionstore/1.0" xmlns:ver="http://www.alfresco.org/model/versionstore/1.0"
xmlns:cm="http://www.alfresco.org/model/content/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0"
xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:mix="http://www.jcp.org/jcr/mix/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:sys="http://www.alfresco.org/model/system/1.0" xmlns:sys="http://www.alfresco.org/model/system/1.0"
xmlns:rule="http://www.alfresco.org/model/rule/1.0" xmlns:rule="http://www.alfresco.org/model/rule/1.0"
xmlns:fm="http://www.alfresco.org/model/forum/1.0" xmlns:fm="http://www.alfresco.org/model/forum/1.0"
xmlns:bpm="http://www.alfresco.org/model/bpm/1.0" xmlns:bpm="http://www.alfresco.org/model/bpm/1.0"
xmlns:rma="http://www.alfresco.org/model/recordsmanagement/1.0" xmlns:rma="http://www.alfresco.org/model/recordsmanagement/1.0"
xmlns:custom="custom.model" xmlns:custom="custom.model"
xmlns="" > xmlns="" >
<cm:folder view:childName="cm:records_management"> <cm:folder view:childName="cm:records_management">
<view:properties> <view:properties>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-identifier>SpacesStore</sys:store-identifier> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:node-uuid>rm_config_folder</sys:node-uuid> <sys:node-uuid>rm_config_folder</sys:node-uuid>
@@ -30,15 +30,15 @@
<cm:title>Records Management</cm:title> <cm:title>Records Management</cm:title>
<cm:description>Configuration information for the Records Management application.</cm:description> <cm:description>Configuration information for the Records Management application.</cm:description>
</view:properties> </view:properties>
<view:associations> <view:associations>
<cm:contains> <cm:contains>
<cm:content view:childName="cm:rm_event_config.json"> <cm:content view:childName="cm:rm_event_config.json">
<view:aspects> <view:aspects>
<cm:titled></cm:titled> <cm:titled></cm:titled>
</view:aspects> </view:aspects>
<view:properties> <view:properties>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-identifier>SpacesStore</sys:store-identifier> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:node-uuid>rm_event_config</sys:node-uuid> <sys:node-uuid>rm_event_config</sys:node-uuid>
@@ -49,11 +49,11 @@
</view:properties> </view:properties>
</cm:content> </cm:content>
<cm:dictionaryModel view:childName="cm:recordsCustomModel.xml"> <cm:dictionaryModel view:childName="cm:recordsCustomModel.xml">
<view:aspects> <view:aspects>
<cm:titled></cm:titled> <cm:titled></cm:titled>
</view:aspects> </view:aspects>
<view:properties> <view:properties>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-identifier>SpacesStore</sys:store-identifier> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:node-uuid>records_management_custom_model</sys:node-uuid> <sys:node-uuid>records_management_custom_model</sys:node-uuid>
@@ -61,118 +61,133 @@
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/recordsCustomModel.xml|mimetype=text/plain|encoding=UTF-8</cm:content> <cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/recordsCustomModel.xml|mimetype=text/plain|encoding=UTF-8</cm:content>
<cm:title>recordsCustomModel.xml</cm:title> <cm:title>recordsCustomModel.xml</cm:title>
<cm:name>recordsCustomModel.xml</cm:name> <cm:name>recordsCustomModel.xml</cm:name>
<cm:modelName>{http://www.alfresco.org/model/rmcustom/1.0}rmcustom</cm:modelName> <cm:modelName>{http://www.alfresco.org/model/rmcustom/1.0}rmcustom</cm:modelName>
<cm:modelDescription>Records Management Custom Model</cm:modelDescription> <cm:modelDescription>Records Management Custom Model</cm:modelDescription>
<cm:modelAuthor>Alfresco</cm:modelAuthor> <cm:modelAuthor>Alfresco</cm:modelAuthor>
<cm:modelVersion>1.0</cm:modelVersion> <cm:modelVersion>1.0</cm:modelVersion>
<cm:modelActive>true</cm:modelActive> <cm:modelActive>true</cm:modelActive>
</view:properties>
</view:properties> </cm:dictionaryModel>
</cm:dictionaryModel>
<cm:folder view:childName="cm:records_management_scripts">
<cm:folder view:childName="cm:records_management_scripts"> <view:properties>
<view:properties> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:store-identifier>SpacesStore</sys:store-identifier> <sys:node-uuid>rm_scripts</sys:node-uuid>
<sys:node-uuid>rm_scripts</sys:node-uuid> <cm:name>Records Management Scripts</cm:name>
<cm:name>Records Management Scripts</cm:name> <cm:title>Records Management Scripts</cm:title>
<cm:title>Records Management Scripts</cm:title> <cm:description>Scripts intended for execution in response to RM events.</cm:description>
<cm:description>Scripts intended for execution in response to RM events.</cm:description> </view:properties>
</view:properties> <view:associations>
<view:associations> <cm:contains>
<cm:contains> <!-- TODO Will likely remove this script. Here for test purposes.
<!-- TODO Will likely remove this script. Here for test purposes. Or perhaps replace it with a product-ready script -->
Or perhaps replace it with a product-ready script --> <cm:content view:childName="cm:rma_isClosed.js">
<cm:content view:childName="cm:rma_isClosed.js"> <view:aspects>
<view:aspects> <cm:titled></cm:titled>
<cm:titled></cm:titled> </view:aspects>
</view:aspects> <view:properties>
<view:properties> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:store-identifier>SpacesStore</sys:store-identifier> <cm:description>Records management sample script.</cm:description>
<cm:description>Records management sample script.</cm:description> <cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/rma_isClosed.js|mimetype=text/javascript|encoding=UTF-8</cm:content>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/rma_isClosed.js|mimetype=text/javascript|encoding=UTF-8</cm:content> <cm:title>rma_isClosed.js</cm:title>
<cm:title>rma_isClosed.js</cm:title> <cm:name>rma_isClosed.js</cm:name>
<cm:name>rma_isClosed.js</cm:name> </view:properties>
</view:properties> </cm:content>
</cm:content>
<cm:content view:childName="cm:onCreate_supersedes.js">
<cm:content view:childName="cm:onCreate_supersedes.js"> <view:aspects>
<view:aspects> <cm:titled></cm:titled>
<cm:titled></cm:titled> </view:aspects>
</view:aspects> <view:properties>
<view:properties> <sys:store-protocol>workspace</sys:store-protocol>
<sys:store-protocol>workspace</sys:store-protocol> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:store-identifier>SpacesStore</sys:store-identifier> <cm:description>Records management sample script.</cm:description>
<cm:description>Records management sample script.</cm:description> <cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/onCreate_supersedes.js|mimetype=text/javascript|encoding=UTF-8</cm:content>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/onCreate_supersedes.js|mimetype=text/javascript|encoding=UTF-8</cm:content> <cm:title>onCreate_supersedes.js</cm:title>
<cm:title>onCreate_supersedes.js</cm:title> <cm:name>onCreate_supersedes.js</cm:name>
<cm:name>onCreate_supersedes.js</cm:name> </view:properties>
</view:properties> </cm:content>
</cm:content> </cm:contains>
</cm:contains> </view:associations>
</view:associations> </cm:folder>
</cm:folder>
<cm:folder view:childName="cm:records_management_email_templates">
<view:properties>
<cm:folder view:childName="cm:records_management_email_templates"> <sys:store-protocol>workspace</sys:store-protocol>
<view:properties> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:store-protocol>workspace</sys:store-protocol> <sys:node-uuid>records_management_email_templates</sys:node-uuid>
<sys:store-identifier>SpacesStore</sys:store-identifier> <cm:name>Records Management Email Templates</cm:name>
<sys:node-uuid>records_management_email_templates</sys:node-uuid> <cm:title>Records Management Email Templates</cm:title>
<cm:name>Records Management Email Templates</cm:name> <cm:description>Email templates for records management.</cm:description>
<cm:title>Records Management Email Templates</cm:title> </view:properties>
<cm:description>Email templates for records management.</cm:description>
</view:properties> <view:associations>
<cm:contains>
<view:associations> <cm:content
<cm:contains> view:childName="cm:notify-records-due-for-review-email.ftl">
<cm:content <view:aspects>
view:childName="cm:notify-records-due-for-review-email.ftl"> <cm:titled></cm:titled>
<view:aspects> <cm:author></cm:author>
<cm:titled></cm:titled> <app:inlineeditable></app:inlineeditable>
<cm:author></cm:author> <cm:versionable></cm:versionable>
<app:inlineeditable></app:inlineeditable> </view:aspects>
<cm:versionable></cm:versionable> <view:properties>
</view:aspects> <app:editInline>
<view:properties> true
<app:editInline> </app:editInline>
true <cm:description>Email template for notify records due for review job.</cm:description>
</app:editInline> <cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/notify-records-due-for-review-email.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
<cm:description>Email template for notify records due for review job.</cm:description> <cm:title>notify-records-due-for-review-email.ftl</cm:title>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/notify-records-due-for-review-email.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content> <cm:author></cm:author>
<cm:title>notify-records-due-for-review-email.ftl</cm:title> <cm:name>notify-records-due-for-review-email.ftl</cm:name>
<cm:author></cm:author> <cm:lastPatchUpdate>org_alfresco_module_rm_notificationTemplatePatch</cm:lastPatchUpdate>
<cm:name>notify-records-due-for-review-email.ftl</cm:name> </view:properties>
<cm:lastPatchUpdate>org_alfresco_module_rm_notificationTemplatePatch</cm:lastPatchUpdate> <view:associations></view:associations>
</view:properties> </cm:content>
<view:associations></view:associations> <cm:content view:childName="cm:record-superseded-email.ftl">
</cm:content> <view:aspects>
<cm:content view:childName="cm:record-superseded-email.ftl"> <cm:titled></cm:titled>
<view:aspects> <cm:author></cm:author>
<cm:titled></cm:titled> <app:inlineeditable></app:inlineeditable>
<cm:author></cm:author> <cm:versionable></cm:versionable>
<app:inlineeditable></app:inlineeditable> </view:aspects>
<cm:versionable></cm:versionable> <view:properties>
</view:aspects> <sys:store-protocol>workspace</sys:store-protocol>
<view:properties> <sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:store-protocol>workspace</sys:store-protocol> <sys:node-uuid>record_superseded_template</sys:node-uuid>
<sys:store-identifier>SpacesStore</sys:store-identifier> <cm:description>Record superseded email template.</cm:description>
<sys:node-uuid>record_superseded_template</sys:node-uuid> <cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/record-superseded-email.ftl|mimetype=text/plain|encoding=UTF-8</cm:content>
<cm:description>Record superseded email template.</cm:description> <cm:title>record-superseded-email.ftl</cm:title>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/record-superseded-email.ftl|mimetype=text/plain|encoding=UTF-8</cm:content> <cm:name>record-superseded-email.ftl</cm:name>
<cm:title>record-superseded-email.ftl</cm:title> <cm:lastPatchUpdate>org_alfresco_module_rm_notificationTemplatePatch</cm:lastPatchUpdate>
<cm:name>record-superseded-email.ftl</cm:name> </view:properties>
<cm:lastPatchUpdate>org_alfresco_module_rm_notificationTemplatePatch</cm:lastPatchUpdate> </cm:content>
<cm:content view:childName="cm:record-rejected-email.ftl">
</view:properties> <view:aspects>
</cm:content> <cm:titled></cm:titled>
</cm:contains> <cm:author></cm:author>
</view:associations> <app:inlineeditable></app:inlineeditable>
</cm:folder> <cm:versionable></cm:versionable>
</view:aspects>
<view:properties>
<sys:store-protocol>workspace</sys:store-protocol>
<sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:node-uuid>record_rejected_template</sys:node-uuid>
<cm:description>Record rejected email template.</cm:description>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/content/record-rejected-email.ftl|mimetype=text/plain|encoding=UTF-8</cm:content>
<cm:title>record-rejected-email.ftl</cm:title>
<cm:name>record-rejected-email.ftl</cm:name>
<cm:lastPatchUpdate>org_alfresco_module_rm_notificationTemplatePatch</cm:lastPatchUpdate>
</view:properties>
</cm:content>
</cm:contains>
</view:associations>
</cm:folder>
</cm:contains> </cm:contains>
</view:associations> </view:associations>
</cm:folder> </cm:folder>
</view:view> </view:view>

View File

@@ -0,0 +1,120 @@
<html>
<head>
<style type="text/css"><!--
body
{
font-family: Arial, sans-serif;
font-size: 14px;
color: #4c4c4c;
}
a, a:visited
{
color: #0072cf;
}
--></style>
</head>
<body bgcolor="#dddddd">
<table width="100%" cellpadding="20" cellspacing="0" border="0" bgcolor="#dddddd">
<tr>
<td width="100%" align="center">
<table width="70%" cellpadding="0" cellspacing="0" bgcolor="white" style="background-color: white; border: 1px solid #aaaaaa;">
<tr>
<td width="100%">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding: 10px 30px 0px;">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<img src="${shareUrl}/res/components/images/task-64.png" alt="" width="64" height="64" border="0" style="padding-right: 20px;" />
</td>
<td>
<div style="font-size: 22px; padding-bottom: 4px;">
Record has been rejected
</div>
<div style="font-size: 13px;">
${args.rejectDate?datetime?string.full}
</div>
</td>
</tr>
</table>
<div style="font-size: 14px; margin: 12px 0px 24px 0px; padding-top: 10px; border-top: 1px solid #aaaaaa;">
<p>Hello ${args.userName},</p>
<p>${args.rejectedPerson} has rejected the following record with this reason:</p>
<p>${args.rejectReason}</p>
<table cellpadding="0" callspacing="0" border="0" bgcolor="#eeeeee" style="padding:10px; border: 1px solid #aaaaaa;">
<tr>
<td>
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td valign="top">
<img src="${shareUrl}/res/rm/components/documentlibrary/images/record-64.png" alt="" width="64" height="64" border="0" style="padding-right: 10px;" />
</td>
<td>
<table cellpadding="2" cellspacing="0" border="0">
<tr>
<td><b>${args.record.properties["rma:identifier"]!} ${args.record.name}</b></td>
</tr>
<tr>
<td>Click on this link to view the record:</td>
</tr>
<tr>
<td>
<a href="${shareUrl}/page/site/${args.site}/document-details?nodeRef=${args.record.storeType}://${args.record.storeId}/${args.record.id}">
${shareUrl}/page/site/${args.site}/document-details?nodeRef=${args.record.storeType}://${args.record.storeId}/${args.record.id}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr><td><div style="border-top: 1px solid #aaaaaa; margin:12px;"></div></td></tr>
</table>
<p>Sincerely,<br />
Alfresco ${productName!""}</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<div style="border-top: 1px solid #aaaaaa;">&nbsp;</div>
</td>
</tr>
<tr>
<td style="padding: 0px 30px; font-size: 13px;">
To find out more about Alfresco ${productName!""} visit <a href="http://www.alfresco.com">http://www.alfresco.com</a>
</td>
</tr>
<tr>
<td>
<div style="border-bottom: 1px solid #aaaaaa;">&nbsp;</div>
</td>
</tr>
<tr>
<td style="padding: 10px 30px;">
<img src="${shareUrl}/themes/default/images/app-logo.png" alt="" width="117" height="48" border="0" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -1,2 +1,3 @@
notification.dueforreview.subject=Records Due For Review Notification notification.dueforreview.subject=Records Due For Review Notification
notification.superseded.subject=Record Superseded Notification notification.superseded.subject=Record Superseded Notification
notification.rejected.subject=Record Rejected Notification

View File

@@ -1101,7 +1101,7 @@
<property name="policyComponent" ref="policyComponent" /> <property name="policyComponent" ref="policyComponent" />
<property name="dispositionService" ref="DispositionService" /> <property name="dispositionService" ref="DispositionService" />
<property name="filePlanService" ref="FilePlanService" /> <property name="filePlanService" ref="FilePlanService" />
<property name="notificationService" ref="NotificationService"/> <property name="notificationHelper" ref="recordsManagementNotificationHelper"/>
</bean> </bean>
<bean id="RecordService" class="org.springframework.aop.framework.ProxyFactoryBean"> <bean id="RecordService" class="org.springframework.aop.framework.ProxyFactoryBean">

View File

@@ -19,6 +19,7 @@
package org.alfresco.module.org_alfresco_module_rm.notification; package org.alfresco.module.org_alfresco_module_rm.notification;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -26,6 +27,7 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role; import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.repo.notification.EMailNotificationProvider; import org.alfresco.repo.notification.EMailNotificationProvider;
@@ -46,6 +48,7 @@ import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil; import org.springframework.extensions.surf.util.I18NUtil;
@@ -53,17 +56,18 @@ import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* Helper bean containing methods useful when sending records * Helper bean containing methods useful when sending records
* management notifications via the {@link NotificationService} * management notifications via the {@link NotificationService}
* *
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public class RecordsManagementNotificationHelper public class RecordsManagementNotificationHelper implements RecordsManagementModel
{ {
private static Log logger = LogFactory.getLog(RecordsManagementNotificationHelper.class); private static Log logger = LogFactory.getLog(RecordsManagementNotificationHelper.class);
/** I18n */ /** I18n */
private static final String MSG_SUBJECT_RECORDS_DUE_FOR_REVIEW = "notification.dueforreview.subject"; private static final String MSG_SUBJECT_RECORDS_DUE_FOR_REVIEW = "notification.dueforreview.subject";
private static final String MSG_SUBJECT_RECORD_SUPERCEDED = "notification.superseded.subject"; private static final String MSG_SUBJECT_RECORD_SUPERCEDED = "notification.superseded.subject";
private static final String MSG_SUBJECT_RECORD_REJECTED = "notification.rejected.subject";
/** Defaults */ /** Defaults */
private static final String DEFAULT_SITE = "rm"; private static final String DEFAULT_SITE = "rm";
@@ -77,14 +81,15 @@ public class RecordsManagementNotificationHelper
private AuthorityService authorityService; private AuthorityService authorityService;
private TenantAdminService tenantAdminService; private TenantAdminService tenantAdminService;
private NodeService nodeService; private NodeService nodeService;
/** Notification role */ /** Notification role */
private String notificationRole; private String notificationRole;
/** EMail notification templates */ /** EMail notification templates */
private NodeRef supersededTemplate = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "record_superseded_template"); private NodeRef supersededTemplate = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "record_superseded_template");
private NodeRef dueForReviewTemplate; private NodeRef dueForReviewTemplate;
private NodeRef rejectedTemplate = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "record_rejected_template");
/** /**
* @param notificationService notification service * @param notificationService notification service
*/ */
@@ -92,7 +97,7 @@ public class RecordsManagementNotificationHelper
{ {
this.notificationService = notificationService; this.notificationService = notificationService;
} }
/** /**
* @param recordsManagementService rm service * @param recordsManagementService rm service
*/ */
@@ -100,7 +105,7 @@ public class RecordsManagementNotificationHelper
{ {
this.recordsManagementService = recordsManagementService; this.recordsManagementService = recordsManagementService;
} }
/** /**
* @param filePlanRoleService file plan role service * @param filePlanRoleService file plan role service
*/ */
@@ -108,7 +113,7 @@ public class RecordsManagementNotificationHelper
{ {
this.filePlanRoleService = filePlanRoleService; this.filePlanRoleService = filePlanRoleService;
} }
/** /**
* @param notificationRole rm notification role * @param notificationRole rm notification role
*/ */
@@ -116,7 +121,7 @@ public class RecordsManagementNotificationHelper
{ {
this.notificationRole = notificationRole; this.notificationRole = notificationRole;
} }
/** /**
* @param searchService search service * @param searchService search service
*/ */
@@ -124,7 +129,7 @@ public class RecordsManagementNotificationHelper
{ {
this.searchService = searchService; this.searchService = searchService;
} }
/** /**
* @param namespaceService namespace service * @param namespaceService namespace service
*/ */
@@ -132,7 +137,7 @@ public class RecordsManagementNotificationHelper
{ {
this.namespaceService = namespaceService; this.namespaceService = namespaceService;
} }
/** /**
* @param siteService site service * @param siteService site service
*/ */
@@ -140,7 +145,7 @@ public class RecordsManagementNotificationHelper
{ {
this.siteService = siteService; this.siteService = siteService;
} }
/** /**
* @param authorityService authority service * @param authorityService authority service
*/ */
@@ -148,7 +153,7 @@ public class RecordsManagementNotificationHelper
{ {
this.authorityService = authorityService; this.authorityService = authorityService;
} }
/** /**
* @param nodeService node service * @param nodeService node service
*/ */
@@ -156,7 +161,7 @@ public class RecordsManagementNotificationHelper
{ {
this.nodeService = nodeService; this.nodeService = nodeService;
} }
/** /**
* @param tenantAdminService tenant admin service * @param tenantAdminService tenant admin service
*/ */
@@ -164,7 +169,7 @@ public class RecordsManagementNotificationHelper
{ {
this.tenantAdminService = tenantAdminService; this.tenantAdminService = tenantAdminService;
} }
/** /**
* @return superseded email template * @return superseded email template
*/ */
@@ -172,7 +177,15 @@ public class RecordsManagementNotificationHelper
{ {
return supersededTemplate; return supersededTemplate;
} }
/**
* @return rejected email template
*/
public NodeRef getRejectedTemplate()
{
return rejectedTemplate;
}
/** /**
* @return due for review email template * @return due for review email template
*/ */
@@ -180,11 +193,11 @@ public class RecordsManagementNotificationHelper
{ {
if (dueForReviewTemplate == null) if (dueForReviewTemplate == null)
{ {
List<NodeRef> nodeRefs = List<NodeRef> nodeRefs =
searchService.selectNodes( searchService.selectNodes(
getRootNode(), getRootNode(),
"app:company_home/app:dictionary/cm:records_management/cm:records_management_email_templates/cm:notify-records-due-for-review-email.ftl", null, "app:company_home/app:dictionary/cm:records_management/cm:records_management_email_templates/cm:notify-records-due-for-review-email.ftl", null,
namespaceService, namespaceService,
false); false);
if (nodeRefs.size() == 1) if (nodeRefs.size() == 1)
{ {
@@ -193,10 +206,10 @@ public class RecordsManagementNotificationHelper
} }
return dueForReviewTemplate; return dueForReviewTemplate;
} }
/** /**
* Helper method to get root node in a tenant safe way. * Helper method to get root node in a tenant safe way.
* *
* @return NodeRef root node of spaces store * @return NodeRef root node of spaces store
*/ */
private NodeRef getRootNode() private NodeRef getRootNode()
@@ -205,15 +218,15 @@ public class RecordsManagementNotificationHelper
return TenantUtil.runAsSystemTenant(new TenantRunAsWork<NodeRef>() return TenantUtil.runAsSystemTenant(new TenantRunAsWork<NodeRef>()
{ {
public NodeRef doWork() throws Exception public NodeRef doWork() throws Exception
{ {
return nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); return nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
} }
}, tenantDomain); }, tenantDomain);
} }
/** /**
* Sends records due for review email notification. * Sends records due for review email notification.
* *
* @param records records due for review * @param records records due for review
*/ */
public void recordsDueForReviewEmailNotification(final List<NodeRef> records) public void recordsDueForReviewEmailNotification(final List<NodeRef> records)
@@ -222,23 +235,23 @@ public class RecordsManagementNotificationHelper
if (records.isEmpty() == false) if (records.isEmpty() == false)
{ {
NodeRef root = getRMRoot(records.get(0)); NodeRef root = getRMRoot(records.get(0));
String groupName = getGroupName(root); String groupName = getGroupName(root);
if (doesGroupContainUsers(groupName) == true) if (doesGroupContainUsers(groupName) == true)
{ {
NotificationContext notificationContext = new NotificationContext(); NotificationContext notificationContext = new NotificationContext();
notificationContext.setSubject(I18NUtil.getMessage(MSG_SUBJECT_RECORDS_DUE_FOR_REVIEW)); notificationContext.setSubject(I18NUtil.getMessage(MSG_SUBJECT_RECORDS_DUE_FOR_REVIEW));
notificationContext.setAsyncNotification(false); notificationContext.setAsyncNotification(false);
notificationContext.setIgnoreNotificationFailure(true); notificationContext.setIgnoreNotificationFailure(true);
notificationContext.setBodyTemplate(getDueForReviewTemplate()); notificationContext.setBodyTemplate(getDueForReviewTemplate());
Map<String, Serializable> args = new HashMap<String, Serializable>(1, 1.0f); Map<String, Serializable> args = new HashMap<String, Serializable>(1, 1.0f);
args.put("records", (Serializable)records); args.put("records", (Serializable)records);
args.put("site", getSiteName(root)); args.put("site", getSiteName(root));
notificationContext.setTemplateArgs(args); notificationContext.setTemplateArgs(args);
notificationContext.addTo(groupName); notificationContext.addTo(groupName);
notificationService.sendNotification(EMailNotificationProvider.NAME, notificationContext); notificationService.sendNotification(EMailNotificationProvider.NAME, notificationContext);
} }
else else
@@ -247,39 +260,39 @@ public class RecordsManagementNotificationHelper
{ {
logger.warn("Unable to send record due for review email notification, because notification group was empty."); logger.warn("Unable to send record due for review email notification, because notification group was empty.");
} }
throw new AlfrescoRuntimeException("Unable to send record due for review email notification, because notification group was empty."); throw new AlfrescoRuntimeException("Unable to send record due for review email notification, because notification group was empty.");
} }
} }
} }
/** /**
* Sends record superseded email notification. * Sends record superseded email notification.
* *
* @param record superseded record * @param record superseded record
*/ */
public void recordSupersededEmailNotification(final NodeRef record) public void recordSupersededEmailNotification(final NodeRef record)
{ {
ParameterCheck.mandatory("record", record); ParameterCheck.mandatory("record", record);
NodeRef root = getRMRoot(record); NodeRef root = getRMRoot(record);
String groupName = getGroupName(root); String groupName = getGroupName(root);
if (doesGroupContainUsers(groupName) == true) if (doesGroupContainUsers(groupName) == true)
{ {
NotificationContext notificationContext = new NotificationContext(); NotificationContext notificationContext = new NotificationContext();
notificationContext.setSubject(I18NUtil.getMessage(MSG_SUBJECT_RECORD_SUPERCEDED)); notificationContext.setSubject(I18NUtil.getMessage(MSG_SUBJECT_RECORD_SUPERCEDED));
notificationContext.setAsyncNotification(false); notificationContext.setAsyncNotification(false);
notificationContext.setIgnoreNotificationFailure(true); notificationContext.setIgnoreNotificationFailure(true);
notificationContext.setBodyTemplate(supersededTemplate); notificationContext.setBodyTemplate(supersededTemplate);
Map<String, Serializable> args = new HashMap<String, Serializable>(1, 1.0f); Map<String, Serializable> args = new HashMap<String, Serializable>(1, 1.0f);
args.put("record", record); args.put("record", record);
args.put("site", getSiteName(root)); args.put("site", getSiteName(root));
notificationContext.setTemplateArgs(args); notificationContext.setTemplateArgs(args);
notificationContext.addTo(groupName); notificationContext.addTo(groupName);
notificationService.sendNotification(EMailNotificationProvider.NAME, notificationContext); notificationService.sendNotification(EMailNotificationProvider.NAME, notificationContext);
} }
else else
@@ -290,10 +303,59 @@ public class RecordsManagementNotificationHelper
} }
} }
} }
/**
* Sends record rejected email notification.
*
* @param record rejected record
* @param reason reason for rejection
* @param userId the user id who rejected the record
*/
public void recordRejectedEmailNotification(NodeRef record, String reason, String userId)
{
ParameterCheck.mandatory("record", record);
ParameterCheck.mandatoryString("reason", reason);
ParameterCheck.mandatoryString("userId", userId);
String recordCreator = (String) nodeService.getProperty(record, PROP_RECORD_USER_ID);
if (StringUtils.isNotBlank(recordCreator) == true)
{
SiteInfo site = siteService.getSite(record);
if (site == null)
{
throw new AlfrescoRuntimeException("Could not find the site which should contain the node '" + record.toString() + "'.");
}
NotificationContext notificationContext = new NotificationContext();
notificationContext.addTo(recordCreator);
notificationContext.setSubject(I18NUtil.getMessage(MSG_SUBJECT_RECORD_REJECTED));
notificationContext.setBodyTemplate(getRejectedTemplate());
Map<String, Serializable> args = new HashMap<String, Serializable>(6);
args.put("site", site.getShortName());
args.put("record", record);
args.put("userName", recordCreator);
args.put("rejectReason", reason);
args.put("rejectDate", new Date());
args.put("rejectedPerson", userId);
notificationContext.setTemplateArgs(args);
notificationService.sendNotification(EMailNotificationProvider.NAME, notificationContext);
}
else
{
if (logger.isWarnEnabled() == true)
{
logger.warn("Unable to send record rejected email notification, because notification user was empty.");
}
}
}
/** /**
* Gets the rm root given a context node. * Gets the rm root given a context node.
* *
* @param context context node reference * @param context context node reference
* @return {@link NodeRef} rm root node reference * @return {@link NodeRef} rm root node reference
*/ */
@@ -305,15 +367,15 @@ public class RecordsManagementNotificationHelper
public NodeRef doWork() throws Exception public NodeRef doWork() throws Exception
{ {
return recordsManagementService.getFilePlan(context); return recordsManagementService.getFilePlan(context);
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
/** /**
* Gets the group name for the notification role. * Gets the group name for the notification role.
* *
* @param root rm root node * @param root rm root node
* @return String notification role's group name * @return String notification role's group name
*/ */
@@ -326,11 +388,11 @@ public class RecordsManagementNotificationHelper
{ {
// Find the authority for the given role // Find the authority for the given role
Role role = filePlanRoleService.getRole(root, notificationRole); Role role = filePlanRoleService.getRole(root, notificationRole);
return role.getRoleGroupName(); return role.getRoleGroupName();
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
private boolean doesGroupContainUsers(final String groupName) private boolean doesGroupContainUsers(final String groupName)
{ {
return AuthenticationUtil.runAs(new RunAsWork<Boolean>() return AuthenticationUtil.runAs(new RunAsWork<Boolean>()
@@ -343,10 +405,10 @@ public class RecordsManagementNotificationHelper
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
/** /**
* Get the site name, default if none/undetermined. * Get the site name, default if none/undetermined.
* *
* @param root rm root * @param root rm root
* @return String site name * @return String site name
*/ */
@@ -358,16 +420,16 @@ public class RecordsManagementNotificationHelper
public String doWork() throws Exception public String doWork() throws Exception
{ {
String result = DEFAULT_SITE; String result = DEFAULT_SITE;
SiteInfo siteInfo = siteService.getSite(root); SiteInfo siteInfo = siteService.getSite(root);
if (siteInfo != null) if (siteInfo != null)
{ {
result = siteInfo.getShortName(); result = siteInfo.getShortName();
} }
return result; return result;
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
} }

View File

@@ -44,36 +44,37 @@ import org.springframework.beans.factory.BeanNameAware;
/** /**
* @author Roy Wetherall * @author Roy Wetherall
*/ */
public class NotificationTemplatePatch extends AbstractModuleComponent public class NotificationTemplatePatch extends AbstractModuleComponent
implements BeanNameAware implements BeanNameAware
{ {
/** Last patch update property */ /** Last patch update property */
private static final QName PROP_LAST_PATCH_UPDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastPatchUpdate"); private static final QName PROP_LAST_PATCH_UPDATE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "lastPatchUpdate");
private static final String PATH_DUE_FOR_REVIEW = "alfresco/module/org_alfresco_module_rm/bootstrap/content/notify-records-due-for-review-email.ftl"; private static final String PATH_DUE_FOR_REVIEW = "alfresco/module/org_alfresco_module_rm/bootstrap/content/notify-records-due-for-review-email.ftl";
private static final String PATH_SUPERSEDED = "alfresco/module/org_alfresco_module_rm/bootstrap/content/record-superseded-email.ftl"; private static final String PATH_SUPERSEDED = "alfresco/module/org_alfresco_module_rm/bootstrap/content/record-superseded-email.ftl";
private static final String PATH_REJECTED = "alfresco/module/org_alfresco_module_rm/bootstrap/content/record-rejected-email.ftl";
/** Logger */ /** Logger */
private static Log logger = LogFactory.getLog(NotificationTemplatePatch.class); private static Log logger = LogFactory.getLog(NotificationTemplatePatch.class);
/** Records management notification helper */ /** Records management notification helper */
private RecordsManagementNotificationHelper notificationHelper; private RecordsManagementNotificationHelper notificationHelper;
/** Node service */ /** Node service */
private NodeService nodeService; private NodeService nodeService;
/** Content service */ /** Content service */
private ContentService contentService; private ContentService contentService;
/** Version service */ /** Version service */
private VersionService versionService; private VersionService versionService;
/** Audit service */ /** Audit service */
private AuditService auditService; private AuditService auditService;
/** Bean name */ /** Bean name */
private String name; private String name;
/** /**
* @param notificationHelper notification helper * @param notificationHelper notification helper
*/ */
@@ -81,7 +82,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.notificationHelper = notificationHelper; this.notificationHelper = notificationHelper;
} }
/** /**
* @param nodeService node service * @param nodeService node service
*/ */
@@ -89,7 +90,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.nodeService = nodeService; this.nodeService = nodeService;
} }
/** /**
* @param contentService content service * @param contentService content service
*/ */
@@ -97,7 +98,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.contentService = contentService; this.contentService = contentService;
} }
/** /**
* @param versionService version service * @param versionService version service
*/ */
@@ -105,7 +106,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.versionService = versionService; this.versionService = versionService;
} }
/** /**
* @param auditService audit service * @param auditService audit service
*/ */
@@ -113,7 +114,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.auditService = auditService; this.auditService = auditService;
} }
/** /**
* @see org.alfresco.repo.module.AbstractModuleComponent#setBeanName(java.lang.String) * @see org.alfresco.repo.module.AbstractModuleComponent#setBeanName(java.lang.String)
*/ */
@@ -122,7 +123,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
this.name = name; this.name = name;
} }
/** /**
* @see org.alfresco.repo.module.AbstractModuleComponent#executeInternal() * @see org.alfresco.repo.module.AbstractModuleComponent#executeInternal()
*/ */
@@ -133,17 +134,20 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
logger.debug("RM Module NotificationTemplatePatch ..."); logger.debug("RM Module NotificationTemplatePatch ...");
} }
NodeRef supersededTemplate = notificationHelper.getSupersededTemplate(); NodeRef supersededTemplate = notificationHelper.getSupersededTemplate();
updateTemplate(supersededTemplate, PATH_SUPERSEDED); updateTemplate(supersededTemplate, PATH_SUPERSEDED);
NodeRef dueForReviewTemplate = notificationHelper.getDueForReviewTemplate(); NodeRef dueForReviewTemplate = notificationHelper.getDueForReviewTemplate();
updateTemplate(dueForReviewTemplate, PATH_DUE_FOR_REVIEW); updateTemplate(dueForReviewTemplate, PATH_DUE_FOR_REVIEW);
NodeRef rejectedTemplate = notificationHelper.getRejectedTemplate();
updateTemplate(rejectedTemplate, PATH_REJECTED);
} }
/** /**
* Attempt to update the template with the updated version * Attempt to update the template with the updated version
* *
* @param template * @param template
* @param updatedTemplate * @param updatedTemplate
*/ */
@@ -159,7 +163,7 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
else else
{ {
System.out.println(nodeService.getProperty(template, ContentModel.PROP_DESCRIPTION)); System.out.println(nodeService.getProperty(template, ContentModel.PROP_DESCRIPTION));
// Check to see if this template has already been updated // Check to see if this template has already been updated
String lastPatchUpdate = (String)nodeService.getProperty(template, PROP_LAST_PATCH_UPDATE); String lastPatchUpdate = (String)nodeService.getProperty(template, PROP_LAST_PATCH_UPDATE);
if (lastPatchUpdate == null || name.equals(lastPatchUpdate) == false) if (lastPatchUpdate == null || name.equals(lastPatchUpdate) == false)
@@ -168,24 +172,24 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
{ {
logger.debug("Applying update to template. (template=" + template.toString() + ", templateUpdate=" + templateUpdate + ")"); logger.debug("Applying update to template. (template=" + template.toString() + ", templateUpdate=" + templateUpdate + ")");
} }
// Make sure the template is versionable // Make sure the template is versionable
if (nodeService.hasAspect(template, ContentModel.ASPECT_VERSIONABLE) == false) if (nodeService.hasAspect(template, ContentModel.ASPECT_VERSIONABLE) == false)
{ {
nodeService.addAspect(template, ContentModel.ASPECT_VERSIONABLE, null); nodeService.addAspect(template, ContentModel.ASPECT_VERSIONABLE, null);
// Create version (before template is updated) // Create version (before template is updated)
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(2); Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(2);
versionProperties.put(Version.PROP_DESCRIPTION, "Initial version"); versionProperties.put(Version.PROP_DESCRIPTION, "Initial version");
versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
versionService.createVersion(template, versionProperties); versionService.createVersion(template, versionProperties);
} }
// Update the content of the template // Update the content of the template
InputStream is = getClass().getClassLoader().getResourceAsStream(templateUpdate); InputStream is = getClass().getClassLoader().getResourceAsStream(templateUpdate);
ContentWriter writer = contentService.getWriter(template, ContentModel.PROP_CONTENT, true); ContentWriter writer = contentService.getWriter(template, ContentModel.PROP_CONTENT, true);
writer.putContent(is); writer.putContent(is);
boolean enabled = auditService.isAuditEnabled(); boolean enabled = auditService.isAuditEnabled();
auditService.setAuditEnabled(false); auditService.setAuditEnabled(false);
try try
@@ -206,5 +210,5 @@ public class NotificationTemplatePatch extends AbstractModuleComponent
} }
} }
} }
} }
} }

View File

@@ -36,20 +36,18 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.notification.RecordsManagementNotificationHelper;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordServiceImpl; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordServiceImpl;
import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.notification.EMailNotificationProvider; import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.notification.NotificationContext;
import org.alfresco.service.cmr.notification.NotificationService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
@@ -57,11 +55,9 @@ import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.mail.MailPreparationException;
/** /**
* Record service implementation * Record service implementation
@@ -101,8 +97,8 @@ public class RecordServiceImpl implements RecordService,
/** File plan service */ /** File plan service */
private FilePlanService filePlanService; private FilePlanService filePlanService;
/** Notification service */ /** Records management notification helper */
private NotificationService notificationService; private RecordsManagementNotificationHelper notificationHelper;
/** Policy component */ /** Policy component */
private PolicyComponent policyComponent; private PolicyComponent policyComponent;
@@ -187,11 +183,11 @@ public class RecordServiceImpl implements RecordService,
} }
/** /**
* @param notificationService notification service * @param notificationHelper notification helper
*/ */
public void setNotificationService(NotificationService notificationService) public void setNotificationHelper(RecordsManagementNotificationHelper notificationHelper)
{ {
this.notificationService = notificationService; this.notificationHelper = notificationHelper;
} }
/** /**
@@ -455,6 +451,9 @@ public class RecordServiceImpl implements RecordService,
ParameterCheck.mandatory("NodeRef", nodeRef); ParameterCheck.mandatory("NodeRef", nodeRef);
ParameterCheck.mandatoryString("Reason", reason); ParameterCheck.mandatoryString("Reason", reason);
// Save the id of the currently logged in user
final String userId = AuthenticationUtil.getRunAsUser();
// do the work of rejecting the record as the system user // do the work of rejecting the record as the system user
AuthenticationUtil.runAsSystem(new RunAsWork<Void>() AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{ {
@@ -490,23 +489,7 @@ public class RecordServiceImpl implements RecordService,
extendedSecurityService.removeAllExtendedReaders(nodeRef); extendedSecurityService.removeAllExtendedReaders(nodeRef);
// Send an email to the record creator // Send an email to the record creator
String recordCreator = (String) nodeService.getProperty(nodeRef, PROP_RECORD_USER_ID); notificationHelper.recordRejectedEmailNotification(nodeRef, reason, userId);
if (StringUtils.isNotBlank(recordCreator))
{
NotificationContext context = new NotificationContext();
context.addTo(recordCreator);
// FIXME: Subject -> i18n
context.setSubject("Record rejected");
// FIXME: Use email template
context.setBody(reason);
notificationService.sendNotification(EMailNotificationProvider.NAME, context);
}
else
{
throw new MailPreparationException("The id of the record creator cannot be found!");
}
return null; return null;
} }