/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.ar.document.validation;
import org.apache.commons.collections.CollectionUtils;
import org.kuali.kfs.module.ar.ArConstants;
import org.kuali.kfs.module.ar.ArKeyConstants;
import org.kuali.kfs.module.ar.ArPropertyConstants;
import org.kuali.kfs.module.ar.businessobject.CostCategory;
import org.kuali.kfs.module.ar.businessobject.CostCategoryDetail;
import org.kuali.kfs.module.ar.businessobject.CostCategoryObjectCode;
import org.kuali.kfs.module.ar.businessobject.CostCategoryObjectConsolidation;
import org.kuali.kfs.module.ar.businessobject.CostCategoryObjectLevel;
import org.kuali.kfs.module.ar.service.CostCategoryService;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase;
import org.kuali.rice.core.api.util.RiceKeyConstants;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.krad.bo.PersistableBusinessObject;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Validates content of a <code>{@link AccountDelegate}</code> maintenance document upon triggering of a approve, save, or route
* event.
*/
public class CostCategoryRule extends KfsMaintenanceDocumentRuleBase {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CostCategoryRule.class);
protected CostCategory oldCategories;
protected CostCategory newCategories;
private volatile static CostCategoryService costCategoryService;
@Override
protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
LOG.debug("Entering processCustomSaveDocumentBusinessRules()");
setupConvenienceObjects(document);
// check simple rules
if (!isInactivation()) {
checkSimpleRules();
}
return true;
}
@Override
protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
LOG.debug("Entering processCustomRouteDocumentBusinessRules()");
setupConvenienceObjects(document);
// check simple rules
boolean success = true;
if (!isInactivation()) {
success &= checkSimpleRules();
}
return success;
}
protected void setupConvenienceObjects(MaintenanceDocument document) {
// setup oldAccount convenience objects, make sure all possible sub-objects are populated
oldCategories = (CostCategory) super.getOldBo();
// setup newAccount convenience objects, make sure all possible sub-objects are populated
newCategories = (CostCategory) super.getNewBo();
}
/**
* Test if we're inactivating the cost category
* @return true if we're inactivating an entire cost category, false otherwise
*/
protected boolean isInactivation() {
if (!ObjectUtils.isNull(oldCategories)) {
return oldCategories.isActive() && !newCategories.isActive();
}
return false;
}
/**
* Checks that there are details on the cost control and that none of the details are used by other cost categories
* @return true if validations passed, false otherwise
*/
protected boolean checkSimpleRules() {
boolean success = true;
// check that there is something - at least one object code or level or consolidation
if (CollectionUtils.isEmpty(newCategories.getObjectCodes()) && CollectionUtils.isEmpty(newCategories.getObjectLevels()) && CollectionUtils.isEmpty(newCategories.getObjectConsolidations())) {
putGlobalError(ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_NO_DETAILS);
success = false;
} else {
if (!CollectionUtils.isEmpty(newCategories.getObjectCodes())) {
int count = 0;
for (CostCategoryObjectCode objectCode : newCategories.getObjectCodes()) {
if (objectCode.isActive()) {
final boolean objectCodeExists = checkObjectCodeExists(objectCode);
if (objectCodeExists) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectCodeUnique(objectCode);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
putFieldError(ArPropertyConstants.OBJECT_CODES+"["+count+"]."+KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_CODE_NOT_UNIQUE, new String[] {objectCode.getChartOfAccountsCode(), objectCode.getFinancialObjectCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
} else {
success = false;
}
count += 1;
}
}
}
if (!CollectionUtils.isEmpty(newCategories.getObjectLevels())) {
int count = 0;
for (CostCategoryObjectLevel objectLevel : newCategories.getObjectLevels()) {
if (objectLevel.isActive()) {
final boolean objectLevelExists = checkObjectLevelExists(objectLevel);
if (objectLevelExists) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectLevelUnique(objectLevel);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
putFieldError(ArPropertyConstants.OBJECT_LEVELS+"["+count+"]."+KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_LEVEL_NOT_UNIQUE, new String[] {objectLevel.getChartOfAccountsCode(), objectLevel.getFinancialObjectLevelCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
} else {
success = false;
}
count += 1;
}
}
}
if (!CollectionUtils.isEmpty(newCategories.getObjectConsolidations())) {
int count = 0;
for (CostCategoryObjectConsolidation objectConsolidation : newCategories.getObjectConsolidations()) {
if (objectConsolidation.isActive()) {
final boolean objectConsolidationExists = checkObjectConsolidationExists(objectConsolidation);
if (objectConsolidationExists) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectConsolidationUnique(objectConsolidation);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
putFieldError(ArPropertyConstants.OBJECT_CONSOLIDATIONS+"["+count+"]."+KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_CONSOLIDATION_NOT_UNIQUE, new String[] {objectConsolidation.getChartOfAccountsCode(), objectConsolidation.getFinConsolidationObjectCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
} else {
success = false;
}
count += 1;
}
}
}
}
return success;
}
@Override
public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
boolean success = super.processCustomAddCollectionLineBusinessRules(document, collectionName, line);
if (line instanceof CostCategoryObjectCode) {
CostCategoryObjectCode newObjectCode = (CostCategoryObjectCode)line;
success &= checkObjectCodeExists(newObjectCode);
if (success) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectCodeUnique(newObjectCode);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
GlobalVariables.getMessageMap().putErrorForSectionId(ArConstants.CostCategoryMaintenanceSections.EDIT_OBJECT_CODES, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_CODE_NOT_UNIQUE, new String[] {newObjectCode.getChartOfAccountsCode(), newObjectCode.getFinancialObjectCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
}
} else if (line instanceof CostCategoryObjectLevel) {
CostCategoryObjectLevel newObjectLevel = (CostCategoryObjectLevel)line;
success &= checkObjectLevelExists(newObjectLevel);
if (success) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectLevelUnique(newObjectLevel);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
GlobalVariables.getMessageMap().putErrorForSectionId(ArConstants.CostCategoryMaintenanceSections.EDIT_OBJECT_LEVELS, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_CODE_NOT_UNIQUE, new String[] {newObjectLevel.getChartOfAccountsCode(), newObjectLevel.getFinancialObjectLevelCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
}
} else if (line instanceof CostCategoryObjectConsolidation) {
CostCategoryObjectConsolidation newObjectConsolidation = (CostCategoryObjectConsolidation)line;
success &= checkObjectConsolidationExists(newObjectConsolidation);
if (success) {
final CostCategoryDetail conflictingDetail = getCostCategoryService().isCostCategoryObjectConsolidationUnique(newObjectConsolidation);
if (!ObjectUtils.isNull(conflictingDetail)) {
final String conflictingDetailObjectLabel = getDataDictionaryService().getDataDictionary().getBusinessObjectEntryForConcreteClass(conflictingDetail.getClass().getName()).getObjectLabel();
GlobalVariables.getMessageMap().putErrorForSectionId(ArConstants.CostCategoryMaintenanceSections.EDIT_OBJECT_CONSOLIDATIONS, ArKeyConstants.ERROR_DOCUMENT_COST_CATEGORY_OBJECT_CODE_NOT_UNIQUE, new String[] {newObjectConsolidation.getChartOfAccountsCode(), newObjectConsolidation.getFinConsolidationObjectCode(), conflictingDetailObjectLabel, conflictingDetail.getCategoryCode()});
success = false;
}
}
}
return success;
}
/**
* Determines if the object code on a cost category object code actually exists
* @param objectCode the cost category object code to check
* @return true if the object code exists, false (and an error message) otherwise
*/
protected boolean checkObjectCodeExists(CostCategoryObjectCode objectCode) {
boolean success = true;
objectCode.refreshReferenceObject(KFSPropertyConstants.OBJECT_CODE_CURRENT);
if (ObjectUtils.isNull(objectCode.getObjectCodeCurrent())) {
final String label = getDataDictionaryService().getAttributeLabel(CostCategoryObjectCode.class, KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
GlobalVariables.getMessageMap().putError(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, RiceKeyConstants.ERROR_EXISTENCE, label);
success = false;
}
return success;
}
/**
* Determines if the object level on a cost category object level actually exists
* @param objectLevel the cost category object level to check
* @return true if the object level exists, false (and an error message) otherwise
*/
protected boolean checkObjectLevelExists(CostCategoryObjectLevel objectLevel) {
boolean success = true;
objectLevel.refreshReferenceObject(ArPropertyConstants.OBJECT_LEVEL);
if (ObjectUtils.isNull(objectLevel.getObjectLevel())) {
final String label = getDataDictionaryService().getAttributeLabel(CostCategoryObjectLevel.class, KFSPropertyConstants.FINANCIAL_OBJECT_LEVEL_CODE);
GlobalVariables.getMessageMap().putError(KFSPropertyConstants.FINANCIAL_OBJECT_LEVEL_CODE, RiceKeyConstants.ERROR_EXISTENCE, label);
success = false;
}
return success;
}
/**
* Determines if the object code on a cost category object code actually exists
* @param objectCode the cost category object code to check
* @return true if the object code exists, false (and an error message) otherwise
*/
protected boolean checkObjectConsolidationExists(CostCategoryObjectConsolidation objectConsolidation) {
boolean success = true;
objectConsolidation.refreshReferenceObject(ArPropertyConstants.OBJECT_CONSOLIDATION);
if (ObjectUtils.isNull(objectConsolidation.getObjectConsolidation())) {
final String label = getDataDictionaryService().getAttributeLabel(CostCategoryObjectConsolidation.class, KFSPropertyConstants.FIN_CONSOLIDATION_OBJECT_CODE);
GlobalVariables.getMessageMap().putError(KFSPropertyConstants.FIN_CONSOLIDATION_OBJECT_CODE, RiceKeyConstants.ERROR_EXISTENCE, label);
success = false;
}
return success;
}
public static CostCategoryService getCostCategoryService() {
if (costCategoryService == null) {
costCategoryService = SpringContext.getBean(CostCategoryService.class);
}
return costCategoryService;
}
}