View Javadoc
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 }