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 }