package com.constellio.app.modules.rm.model.calculators.document;
import static com.constellio.app.modules.rm.model.enums.DecommissioningDateBasedOn.OPEN_DATE;
import static com.constellio.app.modules.rm.model.enums.RetentionRuleScope.DOCUMENTS;
import static com.constellio.app.modules.rm.wrappers.RetentionRule.SCOPE;
import static com.constellio.data.utils.LangUtils.max;
import static java.util.Arrays.asList;
import java.util.List;
import org.joda.time.LocalDate;
import com.constellio.app.modules.rm.RMConfigs;
import com.constellio.app.modules.rm.model.CopyRetentionRule;
import com.constellio.app.modules.rm.model.calculators.CalculatorUtils;
import com.constellio.app.modules.rm.model.enums.DecommissioningDateBasedOn;
import com.constellio.app.modules.rm.model.enums.RetentionRuleScope;
import com.constellio.app.modules.rm.wrappers.Document;
import com.constellio.app.modules.rm.wrappers.Folder;
import com.constellio.model.entities.calculators.CalculatorParameters;
import com.constellio.model.entities.calculators.DynamicDependencyValues;
import com.constellio.model.entities.calculators.MetadataValueCalculator;
import com.constellio.model.entities.calculators.dependencies.ConfigDependency;
import com.constellio.model.entities.calculators.dependencies.Dependency;
import com.constellio.model.entities.calculators.dependencies.LocalDependency;
import com.constellio.model.entities.calculators.dependencies.ReferenceDependency;
import com.constellio.model.entities.schemas.MetadataValueType;
public class DocumentExpectedTransferDateCalculator implements MetadataValueCalculator<LocalDate> {
ReferenceDependency<LocalDate> expectedTransferDateParam = ReferenceDependency
.toADate(Document.FOLDER, Folder.EXPECTED_TRANSFER_DATE);
ReferenceDependency<LocalDate> folderOpenDateParam = ReferenceDependency
.toADate(Document.FOLDER, Folder.OPENING_DATE);
ReferenceDependency<LocalDate> folderCloseDateParam = ReferenceDependency
.toADate(Document.FOLDER, Folder.CLOSING_DATE);
ReferenceDependency<LocalDate> folderExpectedTransferDateParam = ReferenceDependency
.toADate(Document.FOLDER, Folder.EXPECTED_TRANSFER_DATE);
LocalDependency<LocalDate> actualTransferDateParam = LocalDependency.toADate(Document.FOLDER_ACTUAL_TRANSFER_DATE);
LocalDependency<CopyRetentionRule> copyParam = LocalDependency.toAStructure(Document.MAIN_COPY_RULE);
ConfigDependency<DecommissioningDateBasedOn> decommissioningDateBasedOnParam
= RMConfigs.DECOMMISSIONING_DATE_BASED_ON.dependency();
ConfigDependency<Integer> numberOfYearWhenSemiActiveVariableDelayParam =
RMConfigs.CALCULATED_SEMIACTIVE_DATE_NUMBER_OF_YEAR_WHEN_VARIABLE_PERIOD.dependency();
ConfigDependency<Integer> requiredDaysBeforeYearEndParam = RMConfigs.REQUIRED_DAYS_BEFORE_YEAR_END_FOR_NOT_ADDING_A_YEAR
.dependency();
ConfigDependency<Boolean> documentRetentionRulesEnabledParam = RMConfigs.DOCUMENT_RETENTION_RULES.dependency();
ConfigDependency<Boolean> calculatedMetadatasBasedOnFirstTimerangePartParam = RMConfigs.CALCULATED_METADATAS_BASED_ON_FIRST_TIMERANGE_PART
.dependency();
DocumentDecomDatesDynamicLocalDependency datesAndDateTimesParam = new DocumentDecomDatesDynamicLocalDependency();
ReferenceDependency<RetentionRuleScope> retentionRuleScopeParam = ReferenceDependency
.toAnEnum(Document.FOLDER_RETENTION_RULE, SCOPE);
LocalDependency<String> documentTypeParam = LocalDependency.toAReference(Document.TYPE);
@Override
public LocalDate calculate(CalculatorParameters parameters) {
CalculatorInput input = new CalculatorInput(parameters);
if (!input.documentRetentionRulesEnabled || (input.retentionRuleScope != DOCUMENTS && input.documentType == null)) {
return input.folderExpectedTransferDate;
} else if (input.actualTransferDate != null || input.copy == null) {
return null;
} else {
LocalDate baseDateFromFolder = getBaseAjustedDate(input);
LocalDate baseDateFromSemiActiveDelay = input.getAdjustedBaseDateFromActiveDelay(parameters.get(yearEndParam));
LocalDate baseDate = max(baseDateFromFolder, baseDateFromSemiActiveDelay);
return input.calculateSemiActiveBasedOn(baseDate);
}
}
ConfigDependency<String> yearEndParam =
RMConfigs.YEAR_END_DATE.dependency();
private LocalDate getBaseAjustedDate(CalculatorInput input) {
if (input.preferedDecommissioningDateBasedOn == OPEN_DATE || input.folderCloseDate == null) {
return input.adjustToFinancialYear(input.folderOpenDate);
} else {
return input.folderCloseDate;
}
}
@Override
public LocalDate getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.DATE;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(expectedTransferDateParam, folderOpenDateParam, folderCloseDateParam, actualTransferDateParam, copyParam,
decommissioningDateBasedOnParam, numberOfYearWhenSemiActiveVariableDelayParam, yearEndParam,
requiredDaysBeforeYearEndParam, documentRetentionRulesEnabledParam, folderExpectedTransferDateParam,
datesAndDateTimesParam, calculatedMetadatasBasedOnFirstTimerangePartParam, retentionRuleScopeParam,
documentTypeParam);
}
private class CalculatorInput {
LocalDate expectedTransferDate;
LocalDate folderOpenDate;
LocalDate folderCloseDate;
DecommissioningDateBasedOn preferedDecommissioningDateBasedOn;
CopyRetentionRule copy;
LocalDate actualTransferDate;
int numberOfYearWhenSemiActiveVariableDelay;
String yearEnd;
int requiredDaysBeforeYearEnd;
boolean documentRetentionRulesEnabled;
LocalDate folderExpectedTransferDate;
DynamicDependencyValues datesAndDateTimes;
boolean calculatedMetadatasBasedOnFirstTimerangePart;
RetentionRuleScope retentionRuleScope;
String documentType;
public CalculatorInput(CalculatorParameters parameters) {
this.expectedTransferDate = parameters.get(expectedTransferDateParam);
this.folderOpenDate = parameters.get(folderOpenDateParam);
this.folderCloseDate = parameters.get(folderCloseDateParam);
this.preferedDecommissioningDateBasedOn = parameters.get(decommissioningDateBasedOnParam);
this.copy = parameters.get(copyParam);
this.actualTransferDate = parameters.get(actualTransferDateParam);
this.numberOfYearWhenSemiActiveVariableDelay = parameters.get(numberOfYearWhenSemiActiveVariableDelayParam);
this.yearEnd = parameters.get(yearEndParam);
this.requiredDaysBeforeYearEnd = parameters.get(requiredDaysBeforeYearEndParam);
this.documentRetentionRulesEnabled = parameters.get(documentRetentionRulesEnabledParam);
this.folderExpectedTransferDate = parameters.get(folderExpectedTransferDateParam);
this.datesAndDateTimes = parameters.get(datesAndDateTimesParam);
this.calculatedMetadatasBasedOnFirstTimerangePart = parameters.get(calculatedMetadatasBasedOnFirstTimerangePartParam);
this.retentionRuleScope = parameters.get(retentionRuleScopeParam);
this.documentType = parameters.get(documentTypeParam);
}
LocalDate calculateSemiActiveBasedOn(LocalDate baseDate) {
return CalculatorUtils.calculateExpectedTransferDate(copy, baseDate, numberOfYearWhenSemiActiveVariableDelay);
}
LocalDate adjustToFinancialYear(LocalDate date) {
return CalculatorUtils.toNextEndOfYearDateIfNotAlready(date, yearEnd, requiredDaysBeforeYearEnd);
}
public LocalDate getAdjustedBaseDateFromActiveDelay(String yearEnd) {
String metadata = copy.getActiveDateMetadata();
LocalDate date = datesAndDateTimesParam
.getDate(metadata, datesAndDateTimes, yearEnd, calculatedMetadatasBasedOnFirstTimerangePart);
return date == null ? null : adjustToFinancialYear(date);
}
}
}