001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.purap.document.validation.impl; 017 018 import org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase; 019 import org.kuali.kfs.module.purap.PurapConstants; 020 import org.kuali.kfs.module.purap.PurapKeyConstants; 021 import org.kuali.kfs.module.purap.PurapPropertyConstants; 022 import org.kuali.kfs.module.purap.businessobject.ReceivingAddress; 023 import org.kuali.kfs.module.purap.document.service.ReceivingAddressService; 024 import org.kuali.kfs.sys.context.SpringContext; 025 import org.kuali.rice.kns.document.MaintenanceDocument; 026 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 027 import org.kuali.rice.kns.util.GlobalVariables; 028 029 /** 030 * Business Prerules applicable to ReceivingAddressMaintenanceDocument. 031 * These prerules check whether the maintenance action to a Receiving Address business objects abide certain constraint rules. 032 */ 033 public class ReceivingAddressPreRules extends MaintenancePreRulesBase { 034 035 /** 036 * Checks whether the maintenance action to a Receiving Address business objects abide to the contraint that, 037 * there is one and only one active default receiving address for each chart or chart/org at any given time, 038 * if there exists at least one active receiving address for this chart or chart/org. 039 * If the contraint would be broken as a result of the update, the method will present an error or warning 040 * to the user; and if proceed, enforce the rule by updating the related receiving address as well. 041 * Note: this method relies on the condition that the current status of the DB satisfies the constraints. 042 * 043 * @see org.kuali.kfs.coa.document.validation.impl.MaintenancePreRulesBase#doCustomPreRules(org.kuali.rice.kns.document.MaintenanceDocument) 044 */ 045 @Override 046 protected boolean doCustomPreRules( MaintenanceDocument document ) { 047 ReceivingAddress raOld = ( ReceivingAddress )document.getOldMaintainableObject().getBusinessObject(); 048 ReceivingAddress raNew = ( ReceivingAddress )document.getNewMaintainableObject().getBusinessObject(); 049 050 /* The fields that affect the rule are the default and active indicators. 051 * According to the create/copy/edit action, and various combinations of updates to these two fields, 052 * including unchanged (No->NO or Yes->Yes), set (No->Yes), unset (Yes->No), the rule checking will 053 * proceed respectively. The following boolean variables indicates the various updates and combinations. 054 */ 055 boolean isNew = document.isNew(); 056 boolean isEdit = document.isEdit(); 057 boolean wasActive = isEdit && raOld.isActive(); 058 boolean wasDefault = isEdit && raOld.isDefaultIndicator(); 059 boolean isActive = raNew.isActive(); 060 boolean isDefault = raNew.isDefaultIndicator(); 061 boolean stayActive = wasActive && isActive; 062 boolean stayDefault = wasDefault && isDefault; 063 boolean setActive = (isNew || !wasActive) && isActive; 064 boolean unsetActive = wasActive && !isActive; 065 boolean setDefault = (isNew || !wasDefault) && isDefault; 066 boolean unsetDefault = wasDefault && !isDefault; 067 068 /* Check whether there're other active RA exist. 069 * We only need to search within the same chart/org group, since we don't allow editting on chart/org. 070 * However, we need to exclude the current address being edited if it is not a new one and was active. 071 */ 072 /* 073 Map criteria = new HashMap(); 074 criteria.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, raNew.getChartOfAccountsCode()); 075 criteria.put(KFSPropertyConstants.ORGANIZATION_CODE, raNew.getOrganizationCode()); 076 //criteria.put(PurapPropertyConstants.RCVNG_ADDR_DFLT_IND, true); 077 criteria.put(PurapPropertyConstants.RCVNG_ADDR_ACTIVE, true); 078 int count = SpringContext.getBean(BusinessObjectService.class).countMatching(ReceivingAddress.class, criteria); 079 */ 080 int count = SpringContext.getBean(ReceivingAddressService.class).countActiveByChartOrg(raNew.getChartOfAccountsCode(),raNew.getOrganizationCode()); 081 boolean existOther = wasActive ? (count>1) : (count>0); 082 083 /* Case 1 - adding the first active address: 084 * Force it to be the default one. 085 */ 086 if ( setActive && !isDefault && !existOther ) { 087 raNew.setDefaultIndicator( true ); 088 } 089 /* Case 2 - switching the default address from another one to this one: 090 * Give warning; if proceed, will unset the other default address in post-processing. 091 */ 092 else if ( (stayActive && setDefault) || (setActive && isDefault && existOther) ) { 093 if (!super.askOrAnalyzeYesNoQuestion(PurapConstants.CONFIRM_CHANGE_DFLT_RVNG_ADDR, PurapConstants.CONFIRM_CHANGE_DFLT_RVNG_ADDR_TXT) ) { 094 abortRulesCheck(); 095 } 096 } 097 /* Case 3 - unsetting the default address that's still active: 098 * Give error: Can't unset the default address; you must set another default address to replace this one. 099 */ 100 else if ( stayActive && unsetDefault ) { 101 putFieldError(PurapPropertyConstants.RECEIVING_ADDRESS_DEFAULT_INDICATOR, PurapKeyConstants.ERROR_RCVNG_ADDR_UNSET_DFLT); 102 abortRulesCheck(); 103 return false; 104 } 105 /* Case 4 - deactivating the default address while there're still other active ones: 106 * Give error: Can't deactivate the default address when there're still other active ones; 107 * you must set another default address first. 108 */ 109 else if ( unsetActive && wasDefault && existOther ) { 110 putFieldError(PurapPropertyConstants.BO_ACTIVE, PurapKeyConstants.ERROR_RCVNG_ADDR_DEACTIVATE_DFLT); 111 abortRulesCheck(); 112 return false; 113 } 114 /* Other cases are harmless, i.e. won't break the constraint, so we can proceed without doing anything extra. 115 */ 116 117 return true; 118 } 119 120 /** 121 * Convenience method to add a property-specific error to the global errors list, with the correct prefix 122 * added to the property name so that it will display correctly on maintenance documents. 123 * 124 * @param propertyName Property name of the element that is associated with the error, to mark the field as errored in the UI. 125 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message. 126 * 127 */ 128 protected void putFieldError(String propertyName, String errorConstant) { 129 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(MaintenanceDocumentRuleBase.MAINTAINABLE_ERROR_PREFIX+propertyName, errorConstant); 130 } 131 132 }