1 /* 2 * Copyright 2008 The Kuali Foundation 3 * 4 * Licensed under the Educational Community License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.opensource.org/licenses/ecl2.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.kuali.ole.module.purap.document.validation.impl; 17 18 import org.kuali.ole.coa.document.validation.impl.MaintenancePreRulesBase; 19 import org.kuali.ole.module.purap.PurapConstants; 20 import org.kuali.ole.module.purap.PurapKeyConstants; 21 import org.kuali.ole.module.purap.PurapPropertyConstants; 22 import org.kuali.ole.module.purap.businessobject.ReceivingAddress; 23 import org.kuali.ole.module.purap.document.service.ReceivingAddressService; 24 import org.kuali.ole.sys.context.SpringContext; 25 import org.kuali.rice.kns.document.MaintenanceDocument; 26 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 27 import org.kuali.rice.krad.util.GlobalVariables; 28 29 /** 30 * Business Prerules applicable to ReceivingAddressMaintenanceDocument. 31 * These prerules check whether the maintenance action to a Receiving Address business objects abide certain constraint rules. 32 */ 33 public class ReceivingAddressPreRules extends MaintenancePreRulesBase { 34 35 /** 36 * Checks whether the maintenance action to a Receiving Address business objects abide to the contraint that, 37 * there is one and only one active default receiving address for each chart or chart/org at any given time, 38 * if there exists at least one active receiving address for this chart or chart/org. 39 * If the contraint would be broken as a result of the update, the method will present an error or warning 40 * to the user; and if proceed, enforce the rule by updating the related receiving address as well. 41 * Note: this method relies on the condition that the current status of the DB satisfies the constraints. 42 * 43 * @see org.kuali.ole.coa.document.validation.impl.MaintenancePreRulesBase#doCustomPreRules(org.kuali.rice.kns.document.MaintenanceDocument) 44 */ 45 @Override 46 protected boolean doCustomPreRules(MaintenanceDocument document) { 47 ReceivingAddress raOld = (ReceivingAddress) document.getOldMaintainableObject().getBusinessObject(); 48 ReceivingAddress raNew = (ReceivingAddress) document.getNewMaintainableObject().getBusinessObject(); 49 50 /* The fields that affect the rule are the default and active indicators. 51 * According to the create/copy/edit action, and various combinations of updates to these two fields, 52 * including unchanged (No->NO or Yes->Yes), set (No->Yes), unset (Yes->No), the rule checking will 53 * proceed respectively. The following boolean variables indicates the various updates and combinations. 54 */ 55 boolean isNew = document.isNew(); 56 boolean isEdit = document.isEdit(); 57 boolean wasActive = isEdit && raOld.isActive(); 58 boolean wasDefault = isEdit && raOld.isDefaultIndicator(); 59 boolean isActive = raNew.isActive(); 60 boolean isDefault = raNew.isDefaultIndicator(); 61 boolean stayActive = wasActive && isActive; 62 boolean stayDefault = wasDefault && isDefault; 63 boolean setActive = (isNew || !wasActive) && isActive; 64 boolean unsetActive = wasActive && !isActive; 65 boolean setDefault = (isNew || !wasDefault) && isDefault; 66 boolean unsetDefault = wasDefault && !isDefault; 67 68 /* Check whether there're other active RA exist. 69 * We only need to search within the same chart/org group, since we don't allow editting on chart/org. 70 * However, we need to exclude the current address being edited if it is not a new one and was active. 71 */ 72 /* 73 Map criteria = new HashMap(); 74 criteria.put(OLEPropertyConstants.CHART_OF_ACCOUNTS_CODE, raNew.getChartOfAccountsCode()); 75 criteria.put(OLEPropertyConstants.ORGANIZATION_CODE, raNew.getOrganizationCode()); 76 //criteria.put(PurapPropertyConstants.RCVNG_ADDR_DFLT_IND, true); 77 criteria.put(PurapPropertyConstants.RCVNG_ADDR_ACTIVE, true); 78 int count = SpringContext.getBean(BusinessObjectService.class).countMatching(ReceivingAddress.class, criteria); 79 */ 80 int count = SpringContext.getBean(ReceivingAddressService.class).countActiveByChartOrg(raNew.getChartOfAccountsCode(), raNew.getOrganizationCode()); 81 boolean existOther = wasActive ? (count > 1) : (count > 0); 82 83 /* Case 1 - adding the first active address: 84 * Force it to be the default one. 85 */ 86 if (setActive && !isDefault && !existOther) { 87 raNew.setDefaultIndicator(true); 88 } 89 /* Case 2 - switching the default address from another one to this one: 90 * Give warning; if proceed, will unset the other default address in post-processing. 91 */ 92 else if ((stayActive && setDefault) || (setActive && isDefault && existOther)) { 93 if (!super.askOrAnalyzeYesNoQuestion(PurapConstants.CONFIRM_CHANGE_DFLT_RVNG_ADDR, PurapConstants.CONFIRM_CHANGE_DFLT_RVNG_ADDR_TXT)) { 94 abortRulesCheck(); 95 } 96 } 97 /* Case 3 - unsetting the default address that's still active: 98 * Give error: Can't unset the default address; you must set another default address to replace this one. 99 */ 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 protected void putFieldError(String propertyName, String errorConstant) { 128 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(MaintenanceDocumentRuleBase.MAINTAINABLE_ERROR_PREFIX + propertyName, errorConstant); 129 } 130 131 }