Merge branch 'feature-2.3/RM-4280_UpdateDispositionWhenLinking&Unlinking' into 'release/V2.3.1.x'

Feature 2.3/rm 4280 update disposition when linking&unlinking

This should also fix RM-4292.

See merge request !589
This commit is contained in:
Roxana Lucanu-Ghetu
2016-11-02 12:36:46 +00:00
6 changed files with 98 additions and 5 deletions

View File

@@ -142,6 +142,7 @@
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.updateDispositionActionDefinition=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.isNextDispositionActionEligible=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.getNextDispositionAction=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.recalculateNextDispositionStep=RM.Read.0
org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService.getCompletedDispositionActions=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

View File

@@ -264,4 +264,12 @@ public interface DispositionService
* @return the initial disposition
*/
DispositionSchedule getOriginDispositionSchedule(NodeRef nodeRef);
/**
* Updates disposition action step when linking or unlinking
* the given record to/from a record folder
*
* @param record
*/
void recalculateNextDispositionStep(NodeRef record);
}

View File

@@ -1094,6 +1094,32 @@ public class DispositionServiceImpl extends ServiceBaseImpl
}
return null;
}
public void recalculateNextDispositionStep(NodeRef record)
{
List<NodeRef> recordFolders = recordFolderService.getRecordFolders(record);
DispositionAction nextDispositionAction = getNextDispositionAction(record);
if (nextDispositionAction != null)
{
NextActionFromDisposition dsNextAction = getNextDispositionAction(record, recordFolders, nextDispositionAction);
if (dsNextAction != null)
{
final NodeRef action = dsNextAction.getNextActionNodeRef();
final Date dispositionActionDate = dsNextAction.getNextActionDateAsOf();
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
{
nodeService.setProperty(action, PROP_DISPOSITION_AS_OF, dispositionActionDate);
return null;
}
});
}
}
}
/**
* Helper method to determine if a node is frozen or has frozen children

View File

@@ -34,14 +34,12 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.BeforeFileRecord;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnFileRecord;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionScheduleImpl;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -547,6 +545,8 @@ public class RecordServiceImpl extends BaseBehaviourBean
// create and file the content as a record
file(nodeRef);
// recalculate disposition schedule for the record when linking it
dispositionService.recalculateNextDispositionStep(nodeRef);
}
}
}
@@ -1695,7 +1695,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
// ensure we are linking a record to a record folder
if(isRecord(record) && isRecordFolder(recordFolder))
{
// ensure that we are not linking a record to an exisiting location
// ensure that we are not linking a record to an existing location
List<ChildAssociationRef> parents = nodeService.getParentAssocs(record);
for (ChildAssociationRef parent : parents)
{
@@ -1718,6 +1718,9 @@ public class RecordServiceImpl extends BaseBehaviourBean
record,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name));
// recalculate disposition schedule for the record when linking it
dispositionService.recalculateNextDispositionStep(record);
}
else
{
@@ -1774,6 +1777,9 @@ public class RecordServiceImpl extends BaseBehaviourBean
// remove the link
nodeService.removeChild(recordFolder, record);
// recalculate disposition schedule for record after unlinking it
dispositionService.recalculateNextDispositionStep(record);
}
else
{

View File

@@ -34,6 +34,10 @@ public class MultipleSchedulesTest extends BaseRMTestCase
protected static final String CATEGORY_B_NAME = TEST_PREFIX + "CategoryB";
/** The name to use for the folder within the second category. */
protected static final String FOLDER_B_NAME = TEST_PREFIX + "FolderB";
/** The name to use for the third category. */
protected static final String CATEGORY_C_NAME = TEST_PREFIX + "CategoryC";
/** The name to use for the folder within the third category. */
protected static final String FOLDER_C_NAME = TEST_PREFIX + "FolderC";
/** The name to use for the record. */
protected static final String RECORD_NAME = TEST_PREFIX + "Record";
@@ -48,6 +52,10 @@ public class MultipleSchedulesTest extends BaseRMTestCase
private NodeRef categoryB;
/** The folder node within the second category. */
private NodeRef folderB;
/** The third category node. */
private NodeRef categoryC;
/** The folder node within the third category. */
private NodeRef folderC;
/** The record node. */
private NodeRef record;
@@ -82,6 +90,7 @@ public class MultipleSchedulesTest extends BaseRMTestCase
// Create two categories.
categoryA = filePlanService.createRecordCategory(filePlan, CATEGORY_A_NAME);
categoryB = filePlanService.createRecordCategory(filePlan, CATEGORY_B_NAME);
categoryC = filePlanService.createRecordCategory(filePlan, CATEGORY_C_NAME);
// Create a disposition schedule for category A (Cut off immediately, then Destroy immediately).
DispositionSchedule dispSchedA = utils.createBasicDispositionSchedule(categoryA, "instructions", "authority", true, false);
Map<QName, Serializable> cutOffParamsA = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME,
@@ -103,9 +112,21 @@ public class MultipleSchedulesTest extends BaseRMTestCase
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_WEEK,
PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE);
dispositionService.addDispositionActionDefinition(dispSchedB, destroyParamsB);
// Create a disposition schedule for category C (Cut off immediately, then Destroy one year after cutoff).
DispositionSchedule dispSchedC = utils.createBasicDispositionSchedule(categoryC, "instructions", "authority", true, false);
Map<QName, Serializable> cutOffParamsC = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, CutOffAction.NAME,
PROP_DISPOSITION_DESCRIPTION, "description",
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_IMMEDIATELY);
dispositionService.addDispositionActionDefinition(dispSchedC, cutOffParamsC);
Map<QName, Serializable> destroyParamsC = ImmutableMap.of(PROP_DISPOSITION_ACTION_NAME, DestroyAction.NAME,
PROP_DISPOSITION_DESCRIPTION, "description",
PROP_DISPOSITION_PERIOD, CommonRMTestUtils.PERIOD_ONE_YEAR,
PROP_DISPOSITION_PERIOD_PROPERTY, PROP_CUT_OFF_DATE);
dispositionService.addDispositionActionDefinition(dispSchedC, destroyParamsC);
// Create a folder within each category.
folderA = recordFolderService.createRecordFolder(categoryA, FOLDER_A_NAME);
folderB = recordFolderService.createRecordFolder(categoryB, FOLDER_B_NAME);
folderC = recordFolderService.createRecordFolder(categoryC, FOLDER_C_NAME);
}
/**
@@ -123,6 +144,7 @@ public class MultipleSchedulesTest extends BaseRMTestCase
test()
.given(() -> {
setUpFilePlan();
// Create a record filed under category A and linked to category B.
record = fileFolderService.create(folderA, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef();
recordService.link(record, folderB);
@@ -173,4 +195,36 @@ public class MultipleSchedulesTest extends BaseRMTestCase
.from(() -> dispositionService.getNextDispositionAction(record).getAsOfDate())
.because("Record should follow largest rentention schedule period, which is one week.");
}
/**
* <a href="https://issues.alfresco.com/jira/browse/RM-4292">RM-4292</a>
* <p><pre>
* Given a record subject to a mixed disposition schedule
* When the record is unlinked from one of its secondary parents
* Then the next disposition action is recalculated.
* </pre>
*/
public void testRecalculateDispositionWhenUnlinking()
{
test()
.given(() -> {
setUpFilePlan();
// Create a record filed under category A and linked to category B and C.
record = fileFolderService.create(folderA, RECORD_NAME, ContentModel.TYPE_CONTENT).getNodeRef();
recordService.link(record, folderB);
recordService.link(record, folderC);
// Cut off the record.
dispositionService.cutoffDisposableItem(record);
// Ensure the update has been applied to the record.
internalDispositionService.updateNextDispositionAction(record);
})
.when(() -> {
// Unlink the record from folder B.
recordService.unlink(record, folderB);
})
.then()
.expect(false)
.from(() -> dispositionService.isNextDispositionActionEligible(record))
.because("Destroy action shouldn't be available, as the record should follow disposition schedule from category C.");
}
}

View File

@@ -26,13 +26,11 @@ import static org.alfresco.util.GUID.generate;
import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
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.action.impl.EditDispositionActionAsOfDateAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.TransferAction;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;