/*
* 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.coa.document.validation.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.kuali.kfs.coa.businessobject.IndirectCostRecoveryExclusionAccount;
import org.kuali.kfs.coa.businessobject.ObjectCode;
import org.kuali.kfs.coa.businessobject.ObjectCodeGlobal;
import org.kuali.kfs.coa.businessobject.ObjectCodeGlobalDetail;
import org.kuali.kfs.coa.businessobject.ObjectLevel;
import org.kuali.kfs.coa.businessobject.OffsetDefinition;
import org.kuali.kfs.coa.service.ObjectCodeService;
import org.kuali.kfs.coa.service.ObjectLevelService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.service.UniversityDateService;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.kns.maintenance.Maintainable;
import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.bo.GlobalBusinessObject;
import org.kuali.rice.krad.bo.PersistableBusinessObject;
import org.kuali.rice.krad.datadictionary.InactivationBlockingMetadata;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.InactivationBlockingDetectionService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.util.ObjectUtils;
import org.kuali.rice.krad.util.UrlFactory;
/**
* This class represents the business rules for the maintenance of {@link ObjectCodeGlobal} business objects
*/
public class ObjectCodeGlobalRule extends MaintenanceDocumentRuleBase {
protected ObjectCodeGlobal objectCodeGlobal;
protected ObjectCodeService objectCodeService;
protected ObjectLevelService objectLevelService;
public ObjectCodeGlobalRule() {
super();
setObjectCodeService(SpringContext.getBean(ObjectCodeService.class));
setObjectLevelService(SpringContext.getBean(ObjectLevelService.class));
}
/**
* This method sets the convenience objects like objectCodeGlobal, so you have short and easy handles to the new and
* old objects contained in the maintenance document. It also calls the BusinessObjectBase.refresh(), which will attempt to load
* all sub-objects from the DB by their primary keys, if available.
*
* @param document - the maintenanceDocument being evaluated
*/
@Override
public void setupConvenienceObjects() {
// setup ObjectCodeGlobal convenience objects,
// make sure all possible sub-objects are populated
objectCodeGlobal = (ObjectCodeGlobal) super.getNewBo();
// forces refreshes on all the sub-objects in the lists
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobal.getObjectCodeGlobalDetails()) {
objectCodeGlobalDetail.refreshNonUpdateableReferences();
}
}
/**
* This performs rules checks on document approve
* <ul>
* <li>{@link ObjectCodeGlobalRule#checkSimpleRulesAllLines()}</li>
* </ul>
* This rule fails on business rule failures
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
boolean success = true;
setupConvenienceObjects();
// check simple rules
success &= checkSimpleRulesAllLines();
return success;
}
/**
* This performs rules checks on document route
* <ul>
* <li>{@link ObjectCodeGlobalRule#checkSimpleRulesAllLines()}</li>
* </ul>
* This rule fails on business rule failures
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
boolean success = true;
setupConvenienceObjects();
// check simple rules
success &= checkSimpleRulesAllLines();
return success;
}
@Override
protected boolean processInactivationBlockChecking(MaintenanceDocument maintenanceDocument) {
boolean success = true;
if (!objectCodeGlobal.isFinancialObjectActiveIndicator()) {
// we can only inactivate if the new active status will be false, now check whether the object codes on the document exist and are currently true
Collection<? extends ObjectCodeGlobalDetail> objectCodeGlobalDetails = objectCodeGlobal.getObjectCodeGlobalDetails();
int i = 0;
for ( ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobalDetails ) {
// get current object code from the DB
ObjectCode objectCode = objectCodeService.getByPrimaryId(objectCodeGlobalDetail.getUniversityFiscalYear(), objectCodeGlobalDetail.getChartOfAccountsCode(), objectCodeGlobal.getFinancialObjectCode());
if (objectCode != null) {
if (objectCode.isActive()) {
// now we know that the document intends to inactivate this object code... check to see whether a record blocks it
success &= processInactivationBlockChecking(maintenanceDocument.getNewMaintainableObject(), objectCode, i);
}
}
i++;
}
}
return success;
}
protected boolean processInactivationBlockChecking(Maintainable maintainable, ObjectCode objectCode, int index) {
Set<InactivationBlockingMetadata> inactivationBlockingMetadatas = ddService.getAllInactivationBlockingDefinitions(ObjectCode.class);
for (InactivationBlockingMetadata inactivationBlockingMetadata : inactivationBlockingMetadatas) {
String inactivationBlockingDetectionServiceBeanName = inactivationBlockingMetadata.getInactivationBlockingDetectionServiceBeanName();
InactivationBlockingDetectionService inactivationBlockingDetectionService;
if (StringUtils.isBlank(inactivationBlockingDetectionServiceBeanName)) {
inactivationBlockingDetectionService = SpringContext.getBean(InactivationBlockingDetectionService.class);
} else {
inactivationBlockingDetectionService = SpringContext.getBean(InactivationBlockingDetectionService.class, inactivationBlockingDetectionServiceBeanName);
}
Collection<BusinessObject> blockingBusinessObjects = inactivationBlockingDetectionService.listAllBlockerRecords(objectCode, inactivationBlockingMetadata);
blockingBusinessObjects = addAdditionalBlockingBusinessObjects(blockingBusinessObjects, objectCode);
if (blockingBusinessObjects != null && !blockingBusinessObjects.isEmpty()) {
final List<PersistableBusinessObject> persistingChanges = ((GlobalBusinessObject)maintainable.getBusinessObject()).generateGlobalChangesToPersist();
if (!isOnlyPersistingChangesInBlockingBusinessObjects(blockingBusinessObjects, persistingChanges)) {
putInactivationBlockingErrorOnPage(objectCode, inactivationBlockingMetadata, index);
return false;
}
}
}
return true;
}
protected void putInactivationBlockingErrorOnPage(ObjectCode objectCode, InactivationBlockingMetadata inactivationBlockingMetadata, int index) {
String objectCodeSummaryString = objectCode.getUniversityFiscalYear() + " - " + objectCode.getChartOfAccountsCode() + " - " + objectCode.getFinancialObjectCode();
Properties parameters = new Properties();
parameters.put(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, inactivationBlockingMetadata.getBlockedBusinessObjectClass().getName());
parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.METHOD_DISPLAY_ALL_INACTIVATION_BLOCKERS);
parameters.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, objectCode.getUniversityFiscalYear().toString());
parameters.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, objectCode.getChartOfAccountsCode());
parameters.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, objectCode.getFinancialObjectCode());
String blockingUrl = UrlFactory.parameterizeUrl(KRADConstants.DISPLAY_ALL_INACTIVATION_BLOCKERS_ACTION, parameters);
String errorPropertyPath = KFSConstants.MAINTENANCE_NEW_MAINTAINABLE + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + index + "]." + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
// post an error about the locked document
GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(errorPropertyPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INACTIVATION_BLOCKING, objectCodeSummaryString, blockingUrl);
}
/**
* Determines if all of the given blocking business objects are among the persisting changes
* @param blockingBusinessObjects the Collection of blocking business objects
* @param persistingChanges the List of Object Codes which will be persisted by this document
* @return true if all the blocking business objects are persisting changes
*/
protected boolean isOnlyPersistingChangesInBlockingBusinessObjects(Collection<BusinessObject> blockingBusinessObjects, List<PersistableBusinessObject> persistingChanges) {
for (BusinessObject bo : blockingBusinessObjects) {
if (bo instanceof ObjectCode) {
if (!isObjectCodeInPersistingChanges(persistingChanges, (ObjectCode)bo)) {
return false;
}
} else {
return false;
}
}
return true;
}
/**
* Determines if the given object code is within the list of persisting changes
* @param persistingChanges the changes to persist
* @param objectCode the blocking object code to look for in the persisting changes
* @return true if the object code was found in the list of persisting changes, false otherwise
*/
protected boolean isObjectCodeInPersistingChanges(List<PersistableBusinessObject> persistingChanges, ObjectCode objectCode) {
for (PersistableBusinessObject persistingObjectCodeAsObject : persistingChanges) {
if (isEqualObjectCode(objectCode, (ObjectCode)persistingObjectCodeAsObject)) {
return true;
}
}
return false;
}
/**
* Determines if the two given object codes are roughly equal
* @param castor an object code
* @param pollux another, though perhaps very similar, object code
* @return true if the two object codes share primary key values, false otherwise
*/
protected boolean isEqualObjectCode(ObjectCode castor, ObjectCode pollux) {
return org.springframework.util.ObjectUtils.nullSafeEquals(castor.getUniversityFiscalYear(), pollux.getUniversityFiscalYear())
&& org.springframework.util.ObjectUtils.nullSafeEquals(castor.getChartOfAccountsCode(), pollux.getChartOfAccountsCode())
&& org.springframework.util.ObjectUtils.nullSafeEquals(castor.getFinancialObjectCode(), pollux.getFinancialObjectCode());
}
/**
* Retrieves any additional blocking objects not handled by the inactivation framework
* @param blockingBusinessObjects the current list of blocking business objects
* @param objectCode the object code to find additional blocking objects for
* @return the perhaps fuller Collection of blocking business objects
*/
protected Collection<BusinessObject> addAdditionalBlockingBusinessObjects(Collection<BusinessObject> blockingBusinessObjects, ObjectCode objectCode) {
List<BusinessObject> additionalBlockingObjects = new ArrayList<BusinessObject>();
retrieveBlockingOffsetDefinitions(objectCode, additionalBlockingObjects);
retrieveBlockingIndirectCostRecoveryExclusionAccounts(objectCode, additionalBlockingObjects);
if (!additionalBlockingObjects.isEmpty()) {
additionalBlockingObjects.addAll(blockingBusinessObjects);
return additionalBlockingObjects;
}
return blockingBusinessObjects;
}
/**
* Retrieves all Offset Definitions blocking the given object code and puts them in the List of additional blocking objects
* @param objectCode the object code to find additional blocking objects for
* @param additionalBlockingObjects the List of additional blocking objects to populate
*/
protected void retrieveBlockingOffsetDefinitions(ObjectCode objectCode, List<BusinessObject> additionalBlockingObjects) {
final BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class);
Map<String, Object> keys = new HashMap<String, Object>();
keys.put("universityFiscalYear", objectCode.getUniversityFiscalYear());
keys.put("chartOfAccountsCode", objectCode.getChartOfAccountsCode());
keys.put("financialObjectCode", objectCode.getFinancialObjectCode());
Collection<OffsetDefinition> offsetDefinitions = businessObjectService.findMatching(OffsetDefinition.class, keys);
if (offsetDefinitions != null && !offsetDefinitions.isEmpty()) {
additionalBlockingObjects.addAll(offsetDefinitions);
}
}
/**
* Retrieves all Indirect Cost Recovery Exclusion by Account records blocking the given object code and puts them in the List of additional blocking objects
* @param objectCode the object code to find additional blocking objects for
* @param additionalBlockingObjects the List of additional blocking objects to populate
*/
protected void retrieveBlockingIndirectCostRecoveryExclusionAccounts(ObjectCode objectCode, List<BusinessObject> additionalBlockingObjects) {
final UniversityDateService universityDateService = SpringContext.getBean(UniversityDateService.class);
if (objectCode.getUniversityFiscalYear() != null && objectCode.getUniversityFiscalYear().equals(universityDateService.getCurrentFiscalYear())) {
final BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class);
Map<String, Object> keys = new HashMap<String, Object>();
keys.put("financialObjectChartOfAccountCode", objectCode.getChartOfAccountsCode());
keys.put("financialObjectCode", objectCode.getFinancialObjectCode());
Collection<IndirectCostRecoveryExclusionAccount> icrExclusionAccounts = businessObjectService.findMatching(IndirectCostRecoveryExclusionAccount.class, keys);
if (icrExclusionAccounts != null && !icrExclusionAccounts.isEmpty()) {
additionalBlockingObjects.addAll(icrExclusionAccounts);
}
}
}
/**
* This performs rules checks on document save
* <ul>
* <li>{@link ObjectCodeGlobalRule#checkSimpleRulesAllLines()}</li>
* </ul>
* This rule does not fail on business rule failures
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
setupConvenienceObjects();
// check simple rules
checkSimpleRulesAllLines();
return true;
}
/**
* This method checks to make sure that each new {@link ObjectCodeGlobalDetail} has:
* <ul>
* <li>valid chart of accounts code</li>
* <li>valid fiscal year</li>
* <li>unique identifiers (not currently implemented)</li>
* </ul>
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
*/
@Override
public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject bo) {
boolean success = true;
if (bo instanceof ObjectCodeGlobalDetail) {
ObjectCodeGlobalDetail detail = (ObjectCodeGlobalDetail) bo;
if (!checkEmptyValue(detail.getChartOfAccountsCode())) {
// put an error about chart code
GlobalVariables.getMessageMap().putError("chartOfAccountsCode", KFSKeyConstants.ERROR_REQUIRED, "Chart of Accounts Code");
success &= false;
}
if (!checkEmptyValue(detail.getUniversityFiscalYear())) {
// put an error about fiscal year
GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_REQUIRED, "University Fiscal Year");
success &= false;
}
if (!checkUniqueIdentifiers(detail)) {
// TODO: put an error about unique identifier fields must not exist more than once.
success &= false;
}
// both keys are present and satisfy the unique identifiers requirement, go ahead and proces the rest of the rules
if (success) {
success &= checkObjectCodeDetails(detail);
}
}
return success;
}
/**
*
* This method (will)put an error about unique identifier fields must not exist more than once.
* @param dtl
* @return true (not currently implemented fully)
*/
protected boolean checkUniqueIdentifiers(ObjectCodeGlobalDetail dtl) {
boolean success = true;
return success;
}
/**
*
* This checks the following conditions:
* <ul>
* <li>{@link ObjectCodeGlobalRule#checkObjectLevelCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} </li>
* <li>{@link ObjectCodeGlobalRule#checkNextYearObjectCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} </li>
* <li>{@link ObjectCodeGlobalRule#checkReportsToObjectCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)}</li>
* </ul>
* @param dtl
* @return true if sub-rules succeed
*/
public boolean checkObjectCodeDetails(ObjectCodeGlobalDetail dtl) {
boolean success = true;
int originalErrorCount = GlobalVariables.getMessageMap().getErrorCount();
getDictionaryValidationService().validateBusinessObject(dtl);
dtl.refreshNonUpdateableReferences();
// here is where we need our checks for level code nd next year object code
success &= checkObjectLevelCode(objectCodeGlobal, dtl, 0, true);
success &= checkNextYearObjectCode(objectCodeGlobal, dtl, 0, true);
success &= checkReportsToObjectCode(objectCodeGlobal, dtl, 0, true);
success &= GlobalVariables.getMessageMap().getErrorCount() == originalErrorCount;
return success;
}
/**
* This method checks that the reports to object code input on the top level of the global document is valid for a given chart's
* reportToChart in the detail section
*
* @param dtl
* @return true if the reports to object is valid for the given reports to chart
*/
protected boolean checkReportsToObjectCode(ObjectCodeGlobal objectCodeGlobal, ObjectCodeGlobalDetail dtl, int lineNum, boolean add) {
boolean success = true;
String errorPath = KFSConstants.EMPTY_STRING;
if (checkEmptyValue(objectCodeGlobal.getReportsToFinancialObjectCode())) {
// objectCodeGlobal.refreshReferenceObject("reportsToFinancialObject");
String reportsToObjectCode = objectCodeGlobal.getReportsToFinancialObjectCode();
String reportsToChartCode = dtl.getChartOfAccounts().getReportsToChartOfAccountsCode();
Integer fiscalYear = dtl.getUniversityFiscalYear();
// verify that this combination exists in the db
ObjectCode objCode = objectCodeService.getByPrimaryId(fiscalYear, reportsToChartCode, reportsToObjectCode);
if (ObjectUtils.isNull(objCode)) {
success &= false;
String[] errorParameters = { reportsToObjectCode, reportsToChartCode, fiscalYear.toString() };
if (add) {
errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_RPTS_TO_OBJ_CODE, errorParameters);
}
else {
errorPath = KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + lineNum + "]." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_RPTS_TO_OBJ_CODE, errorParameters);
}
}
return success;
}
else {
GlobalVariables.getMessageMap().putError("reportsToFinancialObjectCode", KFSKeyConstants.ERROR_REQUIRED, "Reports to Object Code");
success &= false;
}
return success;
}
/**
* This method checks that the next year object code specified in the change document is a valid object code for a given chart
* and year
*
* @param dtl
* @return false if this object code doesn't exist in the next fiscal year
*/
protected boolean checkNextYearObjectCode(ObjectCodeGlobal objectCodeGlobal, ObjectCodeGlobalDetail dtl, int lineNum, boolean add) {
boolean success = true;
String errorPath = KFSConstants.EMPTY_STRING;
// first check to see if the Next Year object code was filled in
if (checkEmptyValue(objectCodeGlobal.getNextYearFinancialObjectCode())) {
// then this value must also exist as a regular financial object code currently
ObjectCode objCode = objectCodeService.getByPrimaryId(dtl.getUniversityFiscalYear(), dtl.getChartOfAccountsCode(), objectCodeGlobal.getNextYearFinancialObjectCode());
if (ObjectUtils.isNull(objCode)) {
success &= false;
String[] errorParameters = { objectCodeGlobal.getNextYearFinancialObjectCode(), dtl.getChartOfAccountsCode(), dtl.getUniversityFiscalYear().toString() };
if (add) {
errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_NEXT_YEAR_OBJ_CODE, errorParameters);
}
else {
errorPath = KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + lineNum + "]." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_NEXT_YEAR_OBJ_CODE, errorParameters);
}
}
return success;
}
return success;
}
/**
* This method checks that the object level code from the object code change document actually exists for the chart object
* specified in the detail
*
* @param dtl
* @return false if object level doesn't exist for the chart, and level code filled in
*/
protected boolean checkObjectLevelCode(ObjectCodeGlobal objectCodeGlobal, ObjectCodeGlobalDetail dtl, int lineNum, boolean add) {
boolean success = true;
String errorPath = KFSConstants.EMPTY_STRING;
// first check to see if the level code is filled in
if (checkEmptyValue(objectCodeGlobal.getFinancialObjectLevelCode())) {
ObjectLevel objLevel = objectLevelService.getByPrimaryId(dtl.getChartOfAccountsCode(), objectCodeGlobal.getFinancialObjectLevelCode());
if (ObjectUtils.isNull(objLevel)) {
success &= false;
String[] errorParameters = { objectCodeGlobal.getFinancialObjectLevelCode(), dtl.getChartOfAccountsCode() };
if (add) {
errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_OBJ_LEVEL, errorParameters);
}
else {
errorPath = KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + lineNum + "]." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_INVALID_OBJ_LEVEL, errorParameters);
}
}
return success;
}
else {
GlobalVariables.getMessageMap().putError("financialObjectLevelCode", KFSKeyConstants.ERROR_REQUIRED, "Object Level Code");
success &= false;
}
return success;
}
/**
* This method checks the simple rules for all lines at once and gets called on save, submit, etc. but not on add
*
* <ul>
* <li>{@link ObjectCodeGlobalRule#checkFiscalYearAllLines(ObjectCodeGlobal)} </li>
* <li>{@link ObjectCodeGlobalRule#checkChartAllLines(ObjectCodeGlobal)} </li>
* <li>{@link ObjectCodeGlobalRule#checkObjectLevelCodeAllLines(ObjectCodeGlobal)} </li>
* <li>{@link ObjectCodeGlobalRule#checkNextYearObjectCodeAllLines(ObjectCodeGlobal)} </li>
* <li>{@link ObjectCodeGlobalRule#checkReportsToObjectCodeAllLines(ObjectCodeGlobal)} </li>
* </ul>
* @return
*/
protected boolean checkSimpleRulesAllLines() {
boolean success = true;
// check if there are any object codes and accounts, if either fails this should fail
if (!checkForObjectCodeGlobalDetails(objectCodeGlobal.getObjectCodeGlobalDetails())) {
success = false;
}
else {
// check object codes
success &= checkFiscalYearAllLines(objectCodeGlobal);
// check chart code
success &= checkChartAllLines(objectCodeGlobal);
// check object level code
success &= checkObjectLevelCodeAllLines(objectCodeGlobal);
// check next year object code
success &= checkNextYearObjectCodeAllLines(objectCodeGlobal);
// check reports to object code
success &= checkReportsToObjectCodeAllLines(objectCodeGlobal);
}
return success;
}
/**
*
* This checks to make sure that there is at least one {@link ObjectCodeGlobalDetail} in the collection
* @param objectCodeGlobalDetails
* @return false if the collection is empty or null
*/
protected boolean checkForObjectCodeGlobalDetails(Collection<? extends PersistableBusinessObject> objectCodeGlobalDetails) {
if (objectCodeGlobalDetails == null || objectCodeGlobalDetails.size() == 0) {
putFieldError(KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + KFSPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_NO_CHART_FISCAL_YEAR);
return false;
}
return true;
}
/**
*
* This method calls {@link ObjectCodeGlobalRule#checkFiscalYear(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} on each detail object
* @param objectCodeGlobal
* @return true if all lines pass
*/
protected boolean checkFiscalYearAllLines(ObjectCodeGlobal objectCodeGlobal) {
boolean success = true;
int i = 0;
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobal.getObjectCodeGlobalDetails()) {
// check fiscal year first
success &= checkFiscalYear(objectCodeGlobal, objectCodeGlobalDetail, i, false);
// increment counter for sub object changes list
i++;
}
return success;
}
/**
*
* This method calls {@link ObjectCodeGlobalRule#checkChartOnObjCodeDetails(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} on each detail object
*
* @param ocChangeDocument
* @return true if all lines pass
*/
protected boolean checkChartAllLines(ObjectCodeGlobal ocChangeDocument) {
boolean success = true;
int i = 0;
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : ocChangeDocument.getObjectCodeGlobalDetails()) {
// check chart
success &= checkChartOnObjCodeDetails(ocChangeDocument, objectCodeGlobalDetail, i, false);
// increment counter for sub object changes list
i++;
}
return success;
}
/**
*
* This method calls {@link ObjectCodeGlobalRule#checkReportsToObjectCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} on each detail object
*
* @param objectCodeGlobalDocument2
* @return true if all lines pass
*/
protected boolean checkReportsToObjectCodeAllLines(ObjectCodeGlobal objectCodeGlobalDocument2) {
boolean success = true;
int i = 0;
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobal.getObjectCodeGlobalDetails()) {
// check fiscal year first
success &= checkReportsToObjectCode(objectCodeGlobal, objectCodeGlobalDetail, i, false);
// increment counter for sub object changes list
i++;
}
return success;
}
/**
*
* This method calls {@link ObjectCodeGlobalRule#checkNextYearObjectCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} on each detail object
*
* @param objectCodeGlobalDocument2
* @return true if all lines pass
*/
protected boolean checkNextYearObjectCodeAllLines(ObjectCodeGlobal objectCodeGlobalDocument2) {
boolean success = true;
int i = 0;
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobal.getObjectCodeGlobalDetails()) {
// check fiscal year first
success &= checkNextYearObjectCode(objectCodeGlobal, objectCodeGlobalDetail, i, false);
// increment counter for sub object changes list
i++;
}
return success;
}
/**
*
* This method calls {@link ObjectCodeGlobalRule#checkObjectLevelCode(ObjectCodeGlobal, ObjectCodeGlobalDetail, int, boolean)} on each detail object
*
* @param objectCodeGlobalDocument2
* @return true if all lines pass
*/
protected boolean checkObjectLevelCodeAllLines(ObjectCodeGlobal objectCodeGlobalDocument2) {
boolean success = true;
int i = 0;
for (ObjectCodeGlobalDetail objectCodeGlobalDetail : objectCodeGlobal.getObjectCodeGlobalDetails()) {
// check fiscal year first
success &= checkObjectLevelCode(objectCodeGlobal, objectCodeGlobalDetail, i, false);
// increment counter for sub object changes list
i++;
}
return success;
}
/**
*
* This checks to make sure that the fiscal year has been entered
* @param objectCodeGlobal
* @param objectCodeGlobalDetail
* @param lineNum
* @param add
* @return false if no fiscal year value
*/
protected boolean checkFiscalYear(ObjectCodeGlobal objectCodeGlobal, ObjectCodeGlobalDetail objectCodeGlobalDetail, int lineNum, boolean add) {
boolean success = true;
String errorPath = KFSConstants.EMPTY_STRING;
// first must have an actual fiscal year
if (objectCodeGlobalDetail.getUniversityFiscalYear() == null) {
if (add) {
errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + "universityFiscalYear";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_FISCAL_YEAR_MUST_EXIST);
}
else {
errorPath = KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + lineNum + "]." + "universityFiscalYear";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_FISCAL_YEAR_MUST_EXIST);
}
success &= false;
return success;
}
return success;
}
/**
*
* This checks to make sure that the chart of accounts for the detail object has been filled in
* @param objectCodeGlobal
* @param objectCodeGlobalDetail
* @param lineNum
* @param add
* @return false if chart of accounts code null
*/
protected boolean checkChartOnObjCodeDetails(ObjectCodeGlobal objectCodeGlobal, ObjectCodeGlobalDetail objectCodeGlobalDetail, int lineNum, boolean add) {
boolean success = true;
String errorPath = KFSConstants.EMPTY_STRING;
// first must have an actual fiscal year
if (objectCodeGlobalDetail.getChartOfAccounts() == null) {
if (add) {
errorPath = KFSConstants.MAINTENANCE_ADD_PREFIX + KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_CHART_MUST_EXIST);
}
else {
errorPath = KFSPropertyConstants.OBJECT_CODE_GLOBAL_DETAILS + "[" + lineNum + "]." + "chartOfAccountsCode";
putFieldError(errorPath, KFSKeyConstants.ERROR_DOCUMENT_GLOBAL_OBJECTMAINT_CHART_MUST_EXIST);
}
success &= false;
return success;
}
return success;
}
protected void setObjectCodeService(ObjectCodeService objectCodeService) {
this.objectCodeService = objectCodeService;
}
protected void setObjectLevelService(ObjectLevelService objectLevelService) {
this.objectLevelService = objectLevelService;
}
}