mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merge feature-2.3/RM-3386_DispositionCreatedDate into release/V2.3.
RM-3386 Ensure that we always use the same method when calculating the "disposition as of" date for the next disposition step.
This commit is contained in:
@@ -154,6 +154,7 @@
|
|||||||
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.getLastCompletedDispostionAction=RM.Read.0
|
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.getLastCompletedDispostionAction=RM.Read.0
|
||||||
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.isDisposableItemCutoff=RM.Read.0
|
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.isDisposableItemCutoff=RM.Read.0
|
||||||
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.cutoffDisposableItem=RM.Read.0
|
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.cutoffDisposableItem=RM.Read.0
|
||||||
|
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.calculateAsOfDate=RM_ALLOW
|
||||||
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.*=RM_DENY
|
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.*=RM_DENY
|
||||||
]]>
|
]]>
|
||||||
</value>
|
</value>
|
||||||
|
@@ -237,17 +237,11 @@ public class BroadcastDispositionActionDefinitionUpdateAction extends RMActionEx
|
|||||||
* @param dispositionActionDef The disposition action definition node
|
* @param dispositionActionDef The disposition action definition node
|
||||||
* @param nextAction The next disposition action
|
* @param nextAction The next disposition action
|
||||||
*/
|
*/
|
||||||
private void persistPeriodChanges(NodeRef dispositionActionDef, DispositionAction nextAction)
|
protected void persistPeriodChanges(NodeRef dispositionActionDef, DispositionAction nextAction)
|
||||||
{
|
{
|
||||||
Date newAsOfDate = null;
|
NodeRef dispositionedNode = getNodeService().getPrimaryParent(nextAction.getNodeRef()).getParentRef();
|
||||||
Period dispositionPeriod = (Period) getNodeService().getProperty(dispositionActionDef, PROP_DISPOSITION_PERIOD);
|
DispositionActionDefinition definition = nextAction.getDispositionActionDefinition();
|
||||||
|
Date newAsOfDate = getDispositionService().calculateAsOfDate(dispositionedNode, definition, false);
|
||||||
if (dispositionPeriod != null)
|
|
||||||
{
|
|
||||||
// calculate the new as of date as we have been provided a new period
|
|
||||||
Date now = new Date();
|
|
||||||
newAsOfDate = dispositionPeriod.getNextDate(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
|
@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.disposition;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -232,4 +233,15 @@ public interface DispositionService
|
|||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
*/
|
*/
|
||||||
void refreshDispositionAction(NodeRef nodeRef);
|
void refreshDispositionAction(NodeRef nodeRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the "disposition as of" date (if necessary) for a disposition action and a node.
|
||||||
|
*
|
||||||
|
* @param nodeRef The node which the schedule applies to.
|
||||||
|
* @param dispositionActionDefinition The definition of the disposition action.
|
||||||
|
* @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
|
||||||
|
* @return The new "disposition as of" date.
|
||||||
|
*/
|
||||||
|
Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition,
|
||||||
|
boolean allowContextFromAsOf);
|
||||||
}
|
}
|
||||||
|
@@ -53,8 +53,8 @@ import org.alfresco.service.namespace.NamespaceService;
|
|||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.apache.commons.logging.Log;
|
import org.slf4j.Logger;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposition service implementation.
|
* Disposition service implementation.
|
||||||
@@ -68,7 +68,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
RecordsManagementPolicies.OnFileRecord
|
RecordsManagementPolicies.OnFileRecord
|
||||||
{
|
{
|
||||||
/** Logger */
|
/** Logger */
|
||||||
private static Log logger = LogFactory.getLog(DispositionServiceImpl.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(DispositionServiceImpl.class);
|
||||||
|
|
||||||
/** Behaviour filter */
|
/** Behaviour filter */
|
||||||
private BehaviourFilter behaviourFilter;
|
private BehaviourFilter behaviourFilter;
|
||||||
@@ -217,7 +217,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
DispositionActionDefinition nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
DispositionActionDefinition nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||||
|
|
||||||
// initialise the details of the next disposition action
|
// initialise the details of the next disposition action
|
||||||
initialiseDispositionAction(nodeRef, nextDispositionActionDefinition);
|
initialiseDispositionAction(nodeRef, nextDispositionActionDefinition, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,12 +387,10 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
{
|
{
|
||||||
// TODO in the future we should be able to support disposition schedule reuse, but for now just warn that
|
// TODO in the future we should be able to support disposition schedule reuse, but for now just warn that
|
||||||
// only the first disposition schedule will be considered
|
// only the first disposition schedule will be considered
|
||||||
if (logger.isWarnEnabled())
|
LOGGER.warn("Disposition schedule has more than one associated records management container. "
|
||||||
{
|
+ "This is not currently supported so only the first container will be considered. "
|
||||||
logger.warn("Disposition schedule has more than one associated records management container. " +
|
+ "(dispositionScheduleNodeRef={})",
|
||||||
"This is not currently supported so only the first container will be considered. " +
|
dispositionSchedule.getNodeRef().toString());
|
||||||
"(dispositionScheduleNodeRef=" + dispositionSchedule.getNodeRef().toString() + ")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the container reference
|
// Get the container reference
|
||||||
@@ -618,42 +616,16 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
* Initialises the details of the next disposition action based on the details of a disposition
|
* Initialises the details of the next disposition action based on the details of a disposition
|
||||||
* action definition.
|
* action definition.
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef node reference
|
||||||
* @param dispositionActionDefinition disposition action definition
|
* @param dispositionActionDefinition disposition action definition
|
||||||
|
* @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
|
||||||
*/
|
*/
|
||||||
private void initialiseDispositionAction(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition)
|
private void initialiseDispositionAction(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition, boolean allowContextFromAsOf)
|
||||||
{
|
{
|
||||||
// Create the properties
|
// Create the properties
|
||||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(10);
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(10);
|
||||||
|
|
||||||
// Calculate the asOf date
|
Date asOfDate = calculateAsOfDate(nodeRef, dispositionActionDefinition, allowContextFromAsOf);
|
||||||
Date asOfDate = null;
|
|
||||||
Period period = dispositionActionDefinition.getPeriod();
|
|
||||||
if (period != null)
|
|
||||||
{
|
|
||||||
Date contextDate = null;
|
|
||||||
|
|
||||||
// Get the period properties value
|
|
||||||
QName periodProperty = dispositionActionDefinition.getPeriodProperty();
|
|
||||||
if (periodProperty != null)
|
|
||||||
{
|
|
||||||
// doesn't matter if the period property isn't set ... the asOfDate will get updated later
|
|
||||||
// when the value of the period property is set
|
|
||||||
contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// for now use 'NOW' as the default context date
|
|
||||||
// TODO set the default period property ... cut off date or last disposition date depending on context
|
|
||||||
contextDate = new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the as of date
|
|
||||||
if (contextDate != null)
|
|
||||||
{
|
|
||||||
asOfDate = period.getNextDate(contextDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the property values
|
// Set the property values
|
||||||
props.put(PROP_DISPOSITION_ACTION_ID, dispositionActionDefinition.getId());
|
props.put(PROP_DISPOSITION_ACTION_ID, dispositionActionDefinition.getId());
|
||||||
@@ -681,6 +653,50 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the "disposition as of" date (if necessary) for a disposition action and a node.
|
||||||
|
*
|
||||||
|
* @param nodeRef The node which the schedule applies to.
|
||||||
|
* @param dispositionActionDefinition The definition of the disposition action.
|
||||||
|
* @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
|
||||||
|
* @return The new "disposition as of" date.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition,
|
||||||
|
boolean allowContextFromAsOf)
|
||||||
|
{
|
||||||
|
// Calculate the asOf date
|
||||||
|
Date asOfDate = null;
|
||||||
|
Period period = dispositionActionDefinition.getPeriod();
|
||||||
|
if (period != null)
|
||||||
|
{
|
||||||
|
Date contextDate = null;
|
||||||
|
|
||||||
|
// Get the period properties value
|
||||||
|
QName periodProperty = dispositionActionDefinition.getPeriodProperty();
|
||||||
|
if (periodProperty != null && (allowContextFromAsOf
|
||||||
|
|| !RecordsManagementModel.PROP_DISPOSITION_AS_OF.equals(periodProperty)))
|
||||||
|
{
|
||||||
|
// doesn't matter if the period property isn't set ... the asOfDate will get updated later
|
||||||
|
// when the value of the period property is set
|
||||||
|
contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// for now use 'NOW' as the default context date
|
||||||
|
// TODO set the default period property ... cut off date or last disposition date depending on context
|
||||||
|
contextDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the as of date
|
||||||
|
if (contextDate != null)
|
||||||
|
{
|
||||||
|
asOfDate = period.getNextDate(contextDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return asOfDate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#isNextDispositionActionEligible(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#isNextDispositionActionEligible(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@@ -898,63 +914,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
nodeService.addAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE, null);
|
nodeService.addAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the properties
|
initialiseDispositionAction(nodeRef, nextDispositionActionDefinition, false);
|
||||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(10);
|
|
||||||
|
|
||||||
// Calculate the asOf date
|
|
||||||
Date asOfDate = null;
|
|
||||||
Period period = nextDispositionActionDefinition.getPeriod();
|
|
||||||
if (period != null)
|
|
||||||
{
|
|
||||||
Date contextDate = null;
|
|
||||||
|
|
||||||
// Get the period properties value
|
|
||||||
QName periodProperty = nextDispositionActionDefinition.getPeriodProperty();
|
|
||||||
if (periodProperty != null &&
|
|
||||||
!RecordsManagementModel.PROP_DISPOSITION_AS_OF.equals(periodProperty))
|
|
||||||
{
|
|
||||||
// doesn't matter if the period property isn't set ... the asOfDate will get updated later
|
|
||||||
// when the value of the period property is set
|
|
||||||
contextDate = (Date) nodeService.getProperty(nodeRef, periodProperty);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// for now use 'NOW' as the default context date
|
|
||||||
// TODO set the default period property ... cut off date or last disposition date depending on context
|
|
||||||
contextDate = new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the as of date
|
|
||||||
if (contextDate != null)
|
|
||||||
{
|
|
||||||
asOfDate = period.getNextDate(contextDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the property values
|
|
||||||
props.put(PROP_DISPOSITION_ACTION_ID, nextDispositionActionDefinition.getId());
|
|
||||||
props.put(PROP_DISPOSITION_ACTION, nextDispositionActionDefinition.getName());
|
|
||||||
if (asOfDate != null)
|
|
||||||
{
|
|
||||||
props.put(PROP_DISPOSITION_AS_OF, asOfDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new disposition action object
|
|
||||||
NodeRef dispositionActionNodeRef = nodeService.createNode(
|
|
||||||
nodeRef,
|
|
||||||
ASSOC_NEXT_DISPOSITION_ACTION,
|
|
||||||
ASSOC_NEXT_DISPOSITION_ACTION,
|
|
||||||
TYPE_DISPOSITION_ACTION,
|
|
||||||
props).getChildRef();
|
|
||||||
DispositionAction da = new DispositionActionImpl(serviceRegistry, dispositionActionNodeRef);
|
|
||||||
|
|
||||||
// Create the events
|
|
||||||
List<RecordsManagementEvent> events = nextDispositionActionDefinition.getEvents();
|
|
||||||
for (RecordsManagementEvent event : events)
|
|
||||||
{
|
|
||||||
// For every event create an entry on the action
|
|
||||||
da.addEventCompletionDetails(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,7 +969,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
|||||||
recordFolderService.closeRecordFolder(nodeRef);
|
recordFolderService.closeRecordFolder(nodeRef);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -31,7 +31,8 @@ import org.junit.runners.Suite.SuiteClasses;
|
|||||||
@RunWith(Suite.class)
|
@RunWith(Suite.class)
|
||||||
@SuiteClasses(
|
@SuiteClasses(
|
||||||
{
|
{
|
||||||
CutOffTest.class
|
CutOffTest.class,
|
||||||
|
UpdateDispositionScheduleTest.class
|
||||||
})
|
})
|
||||||
public class DispositionTestSuite
|
public class DispositionTestSuite
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.test.integration.disposition;
|
||||||
|
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest.test;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.job.publish.DispositionActionDefinitionPublishExecutor;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.test.util.bdt.BehaviourTest;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.springframework.extensions.webscripts.GUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for updating the disposition schedule.
|
||||||
|
*
|
||||||
|
* @author Tom Page
|
||||||
|
* @since 2.3.1
|
||||||
|
*/
|
||||||
|
public class UpdateDispositionScheduleTest extends BaseRMTestCase
|
||||||
|
{
|
||||||
|
/** A unique prefix for the constants in this test. */
|
||||||
|
protected static final String TEST_PREFIX = UpdateDispositionScheduleTest.class.getName() + GUID.generate() + "_";
|
||||||
|
/** The name to use for the category. */
|
||||||
|
protected static final String CATEGORY_NAME = TEST_PREFIX + "Category";
|
||||||
|
/** The name to use for the folder. */
|
||||||
|
protected static final String FOLDER_NAME = TEST_PREFIX + "Folder";
|
||||||
|
/** The name to use for the record. */
|
||||||
|
protected static final String RECORD_NAME = TEST_PREFIX + "Record";
|
||||||
|
|
||||||
|
/** The executor for the disposition update job. */
|
||||||
|
private DispositionActionDefinitionPublishExecutor dispositionActionDefinitionPublishExecutor;
|
||||||
|
/** The internal disposition service is used to avoid permissions issues when updating the record. */
|
||||||
|
private DispositionService internalDispositionService;
|
||||||
|
|
||||||
|
/** The category node. */
|
||||||
|
private NodeRef category;
|
||||||
|
/** The folder node. */
|
||||||
|
private NodeRef folder;
|
||||||
|
/** The record node. */
|
||||||
|
private NodeRef record;
|
||||||
|
/** The 'disposition as of' date from before the 'when' step. */
|
||||||
|
private Date originalAsOfDate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
BehaviourTest.initBehaviourTests(retryingTransactionHelper);
|
||||||
|
|
||||||
|
// Get the application context
|
||||||
|
applicationContext = ApplicationContextHelper.getApplicationContext(getConfigLocations());
|
||||||
|
dispositionActionDefinitionPublishExecutor = applicationContext.getBean(DispositionActionDefinitionPublishExecutor.class);
|
||||||
|
internalDispositionService = (DispositionService) applicationContext.getBean("dispositionService");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="https://issues.alfresco.com/jira/browse/RM-3386">RM-3386</a>
|
||||||
|
* <p><pre>
|
||||||
|
* Given a record subject to a disposition schedule
|
||||||
|
* And the next step is due to run at some period after the date the content was created
|
||||||
|
* When I update the period of the next step (and wait for this to be processed)
|
||||||
|
* Then the "as of" date is updated to be at the new period after the creation date.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public void testUpdatePeriod()
|
||||||
|
{
|
||||||
|
test()
|
||||||
|
.given(() -> {
|
||||||
|
// Create a category.
|
||||||
|
category = filePlanService.createRecordCategory(filePlan, CATEGORY_NAME);
|
||||||
|
// Create a disposition schedule for the category (Cut off immediately, then Destroy 1 year after the creation date).
|
||||||
|
DispositionSchedule dispSched = utils.createBasicDispositionSchedule(category, "instructions", "authority", true, false);
|
||||||
|
Map<QName, Serializable> cutOffParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME,
|
||||||
|
PROP_DISPOSITION_DESCRIPTION, "description",
|
||||||
|
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY);
|
||||||
|
dispositionService.addDispositionActionDefinition(dispSched, cutOffParams);
|
||||||
|
Map<QName, Serializable> destroyParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME,
|
||||||
|
PROP_DISPOSITION_DESCRIPTION, "description",
|
||||||
|
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_YEAR,
|
||||||
|
PROP_DISPOSITION_PERIOD_PROPERTY, ContentModel.PROP_CREATED);
|
||||||
|
dispositionService.addDispositionActionDefinition(dispSched, destroyParams);
|
||||||
|
// Create a folder containing a record within the category.
|
||||||
|
folder = recordFolderService.createRecordFolder(category, FOLDER_NAME);
|
||||||
|
record = fileFolderService.create(folder, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
|
||||||
|
dispositionService.cutoffDisposableItem(record);
|
||||||
|
// Ensure the update has been applied to the record.
|
||||||
|
internalDispositionService.updateNextDispositionAction(record);
|
||||||
|
|
||||||
|
originalAsOfDate = dispositionService.getNextDispositionAction(record).getAsOfDate();
|
||||||
|
})
|
||||||
|
.when(() -> {
|
||||||
|
// Update the Destroy step to be 3 years after the creation date.
|
||||||
|
DispositionSchedule dispSched = dispositionService.getDispositionSchedule(category);
|
||||||
|
DispositionActionDefinition destroy = dispSched.getDispositionActionDefinitionByName(DestroyAction.NAME);
|
||||||
|
Map<QName, Serializable> destroyParams = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME,
|
||||||
|
PROP_DISPOSITION_DESCRIPTION, "description",
|
||||||
|
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_THREE_YEARS,
|
||||||
|
PROP_DISPOSITION_PERIOD_PROPERTY, ContentModel.PROP_CREATED);
|
||||||
|
dispositionService.updateDispositionActionDefinition(destroy, destroyParams);
|
||||||
|
|
||||||
|
// Make the disposition action definition update job run.
|
||||||
|
dispositionActionDefinitionPublishExecutor.publish(destroy.getNodeRef());
|
||||||
|
})
|
||||||
|
.then()
|
||||||
|
.expect(true)
|
||||||
|
.from(() -> aboutTwoYearsApart(originalAsOfDate, dispositionService.getNextDispositionAction(record).getAsOfDate()))
|
||||||
|
.because("Increasing the destroy period by two years should increase the 'as of' date by two years.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the two given dates are approximately two years apart.
|
||||||
|
* <p>
|
||||||
|
* This actually just checks that they're more than one and less than three years apart, because leap years make
|
||||||
|
* things hard to calculate.
|
||||||
|
*
|
||||||
|
* @return true if the two dates are about two years apart.
|
||||||
|
*/
|
||||||
|
private boolean aboutTwoYearsApart(Date start, Date end)
|
||||||
|
{
|
||||||
|
long days = daysBetween(start, end);
|
||||||
|
long yearInDays = 365;
|
||||||
|
return (yearInDays < days) && (days < 3 * yearInDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find the number of days between the two dates. */
|
||||||
|
private long daysBetween(Date start, Date end)
|
||||||
|
{
|
||||||
|
return TimeUnit.MILLISECONDS.toDays(end.getTime() - start.getTime());
|
||||||
|
}
|
||||||
|
}
|
@@ -56,7 +56,7 @@ import org.springframework.context.ApplicationContext;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Common RM test utility methods.
|
* Common RM test utility methods.
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
*/
|
*/
|
||||||
public class CommonRMTestUtils implements RecordsManagementModel
|
public class CommonRMTestUtils implements RecordsManagementModel
|
||||||
@@ -76,10 +76,12 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
public static final String DEFAULT_EVENT_NAME = "case_closed";
|
public static final String DEFAULT_EVENT_NAME = "case_closed";
|
||||||
public static final String PERIOD_NONE = "none|0";
|
public static final String PERIOD_NONE = "none|0";
|
||||||
public static final String PERIOD_IMMEDIATELY = "immediately|0";
|
public static final String PERIOD_IMMEDIATELY = "immediately|0";
|
||||||
|
public static final String PERIOD_ONE_YEAR = "year|1";
|
||||||
|
public static final String PERIOD_THREE_YEARS = "year|3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param applicationContext application context
|
* @param applicationContext application context
|
||||||
*/
|
*/
|
||||||
public CommonRMTestUtils(ApplicationContext applicationContext)
|
public CommonRMTestUtils(ApplicationContext applicationContext)
|
||||||
@@ -95,7 +97,7 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a disposition schedule
|
* Create a disposition schedule
|
||||||
*
|
*
|
||||||
* @param container record category
|
* @param container record category
|
||||||
* @return {@link DispositionSchedule} created disposition schedule node reference
|
* @return {@link DispositionSchedule} created disposition schedule node reference
|
||||||
*/
|
*/
|
||||||
@@ -129,15 +131,15 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
boolean extendedDispositionSchedule)
|
boolean extendedDispositionSchedule)
|
||||||
{
|
{
|
||||||
return createDispositionSchedule(
|
return createDispositionSchedule(
|
||||||
container,
|
container,
|
||||||
dispositionInstructions,
|
dispositionInstructions,
|
||||||
dispositionAuthority,
|
dispositionAuthority,
|
||||||
isRecordLevel,
|
isRecordLevel,
|
||||||
defaultDispositionActions,
|
defaultDispositionActions,
|
||||||
extendedDispositionSchedule,
|
extendedDispositionSchedule,
|
||||||
DEFAULT_EVENT_NAME);
|
DEFAULT_EVENT_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create test disposition schedule
|
* Create test disposition schedule
|
||||||
*/
|
*/
|
||||||
@@ -241,8 +243,8 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
modelSecurityService.setEnabled(false);
|
modelSecurityService.setEnabled(false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
nodeService.setProperty(record, RecordsManagementModel.PROP_DATE_FILED, new Date());
|
nodeService.setProperty(record, RecordsManagementModel.PROP_DATE_FILED, new Date());
|
||||||
nodeService.setProperty(record, ContentModel.PROP_TITLE, "titleValue");
|
nodeService.setProperty(record, ContentModel.PROP_TITLE, "titleValue");
|
||||||
actionService.executeRecordsManagementAction(record, "declareRecord");
|
actionService.executeRecordsManagementAction(record, "declareRecord");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -255,7 +257,7 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
|
|
||||||
}, AuthenticationUtil.getAdminUserName());
|
}, AuthenticationUtil.getAdminUserName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeFolder(final NodeRef recordFolder)
|
public void closeFolder(final NodeRef recordFolder)
|
||||||
{
|
{
|
||||||
@@ -293,10 +295,10 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
|
|
||||||
return filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities);
|
return filePlanRoleService.createRole(filePlan, roleName, roleName, capabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to complete event on disposable item
|
* Helper method to complete event on disposable item
|
||||||
*
|
*
|
||||||
* @param disposableItem disposable item (record or record folder)
|
* @param disposableItem disposable item (record or record folder)
|
||||||
* @param eventName event name
|
* @param eventName event name
|
||||||
*/
|
*/
|
||||||
@@ -305,8 +307,8 @@ public class CommonRMTestUtils implements RecordsManagementModel
|
|||||||
// build action properties
|
// build action properties
|
||||||
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
Map<String, Serializable> params = new HashMap<String, Serializable>(1);
|
||||||
params.put(CompleteEventAction.PARAM_EVENT_NAME, eventName);
|
params.put(CompleteEventAction.PARAM_EVENT_NAME, eventName);
|
||||||
|
|
||||||
// complete event
|
// complete event
|
||||||
actionService.executeRecordsManagementAction(disposableItem, CompleteEventAction.NAME, params);
|
actionService.executeRecordsManagementAction(disposableItem, CompleteEventAction.NAME, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.action.impl;
|
||||||
|
|
||||||
|
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_DISPOSITION_AS_OF;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
||||||
|
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link BroadcastDispositionActionDefinitionUpdateAction}.
|
||||||
|
*
|
||||||
|
* @author Tom Page
|
||||||
|
* @since 2.3.1
|
||||||
|
*/
|
||||||
|
public class BroadcastDispositionActionDefinitionUpdateActionUnitTest
|
||||||
|
{
|
||||||
|
/** The node under the category containing information about the definition of the action. */
|
||||||
|
private static final NodeRef DISPOSITION_ACTION_DEF_NODE = new NodeRef("disposition://Action/Def");
|
||||||
|
/** The node containing the details of the next disposition step for the content. */
|
||||||
|
private static final NodeRef NEXT_ACTION_NODE_REF = new NodeRef("next://Step/");
|
||||||
|
/** The node being subject to the disposition step. */
|
||||||
|
private static final NodeRef CONTENT_NODE_REF = new NodeRef("content://Node/Ref");
|
||||||
|
|
||||||
|
/** The class under test. */
|
||||||
|
private BroadcastDispositionActionDefinitionUpdateAction action = new BroadcastDispositionActionDefinitionUpdateAction();
|
||||||
|
|
||||||
|
private NodeService mockNodeService = mock(NodeService.class);
|
||||||
|
private DispositionService mockDispositionService = mock(DispositionService.class);
|
||||||
|
|
||||||
|
/** Inject the mock services into the class under test and link the content and next action nodes. */
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
action.setNodeService(mockNodeService);
|
||||||
|
action.setDispositionService(mockDispositionService);
|
||||||
|
|
||||||
|
ChildAssociationRef mockAssocRef = mock(ChildAssociationRef.class);
|
||||||
|
when(mockNodeService.getPrimaryParent(NEXT_ACTION_NODE_REF)).thenReturn(mockAssocRef);
|
||||||
|
when(mockAssocRef.getParentRef()).thenReturn(CONTENT_NODE_REF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the disposition service is used to determine the "disposition as of" date when changes are made to the
|
||||||
|
* disposition period.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testPersistPeriodChanges()
|
||||||
|
{
|
||||||
|
// Set up the data associated with the next disposition action.
|
||||||
|
DispositionAction mockAction = mock(DispositionAction.class);
|
||||||
|
when(mockAction.getNodeRef()).thenReturn(NEXT_ACTION_NODE_REF);
|
||||||
|
DispositionActionDefinition mockDispositionActionDefinition = mock(DispositionActionDefinition.class);
|
||||||
|
when(mockAction.getDispositionActionDefinition()).thenReturn(mockDispositionActionDefinition);
|
||||||
|
when(mockAction.getName()).thenReturn("mockAction");
|
||||||
|
// Set up the disposition service to return a known "disposition as of" date.
|
||||||
|
Date asOfDate = new Date();
|
||||||
|
when(mockDispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, false))
|
||||||
|
.thenReturn(asOfDate);
|
||||||
|
|
||||||
|
// Call the method under test.
|
||||||
|
action.persistPeriodChanges(DISPOSITION_ACTION_DEF_NODE, mockAction);
|
||||||
|
|
||||||
|
// Check that the "disposition as of" date has been set on the next action.
|
||||||
|
verify(mockNodeService).setProperty(NEXT_ACTION_NODE_REF, PROP_DISPOSITION_AS_OF, asOfDate);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2016 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.module.org_alfresco_module_rm.disposition;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.repository.Period;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link DispositionServiceImpl}.
|
||||||
|
*
|
||||||
|
* @author Tom Page
|
||||||
|
* @since 2.3.1
|
||||||
|
*/
|
||||||
|
public class DispositionServiceImplUnitTest
|
||||||
|
{
|
||||||
|
/** The node being subject to the disposition step. */
|
||||||
|
NodeRef CONTENT_NODE_REF = new NodeRef("content://node/");
|
||||||
|
|
||||||
|
/** The class under test. */
|
||||||
|
private DispositionServiceImpl dispositionService = new DispositionServiceImpl();
|
||||||
|
|
||||||
|
private NodeService mockNodeService = mock(NodeService.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
dispositionService.setNodeService(mockNodeService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the relevant information is retrieved from the DispositionActionDefinition in order to determine the
|
||||||
|
* "disposition as of" date.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCalculateAsOfDate()
|
||||||
|
{
|
||||||
|
// Set up a mock for the disposition action definition.
|
||||||
|
DispositionActionDefinition mockDispositionActionDefinition = mock(DispositionActionDefinition.class);
|
||||||
|
Period mockPeriod = mock(Period.class);
|
||||||
|
when(mockDispositionActionDefinition.getPeriod()).thenReturn(mockPeriod);
|
||||||
|
when(mockDispositionActionDefinition.getPeriodProperty()).thenReturn(ContentModel.PROP_CREATED);
|
||||||
|
// Set up a created date and another date that is some Period later.
|
||||||
|
Date createdDate = new Date(1234567890);
|
||||||
|
when(mockNodeService.getProperty(CONTENT_NODE_REF, ContentModel.PROP_CREATED)).thenReturn(createdDate);
|
||||||
|
Date nextDate = new Date(1240000000);
|
||||||
|
when(mockPeriod.getNextDate(createdDate)).thenReturn(nextDate);
|
||||||
|
|
||||||
|
// Call the method under test.
|
||||||
|
Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, true);
|
||||||
|
|
||||||
|
assertEquals("Unexpected calculation for 'as of' date", nextDate, asOfDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check that the calculated "disposition as of" date is null if a null period is given. */
|
||||||
|
@Test
|
||||||
|
public void testCalculateAsOfDate_nullPeriod()
|
||||||
|
{
|
||||||
|
DispositionActionDefinition mockDispositionActionDefinition = mock(DispositionActionDefinition.class);
|
||||||
|
when(mockDispositionActionDefinition.getPeriod()).thenReturn(null);
|
||||||
|
|
||||||
|
// Call the method under test.
|
||||||
|
Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, true);
|
||||||
|
|
||||||
|
assertNull("It should not be possible to determine the 'as of' date.", asOfDate);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user