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 java.util.Collection;
019 import java.util.HashMap;
020 import java.util.Map;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.kfs.coa.businessobject.Chart;
024 import org.kuali.kfs.coa.businessobject.ObjectCode;
025 import org.kuali.kfs.coa.businessobject.Organization;
026 import org.kuali.kfs.coa.businessobject.SubFundGroup;
027 import org.kuali.kfs.coa.service.AccountService;
028 import org.kuali.kfs.coa.service.ChartService;
029 import org.kuali.kfs.module.purap.PurapKeyConstants;
030 import org.kuali.kfs.module.purap.businessobject.ReceivingThreshold;
031 import org.kuali.kfs.module.purap.util.ThresholdField;
032 import org.kuali.kfs.sys.context.SpringContext;
033 import org.kuali.kfs.vnd.businessobject.CommodityCode;
034 import org.kuali.kfs.vnd.businessobject.VendorDetail;
035 import org.kuali.rice.kns.document.MaintenanceDocument;
036 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
037
038 public class ThresholdRule extends MaintenanceDocumentRuleBase {
039
040 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ThresholdRule.class);
041 protected ChartService chartService;
042 protected AccountService accountService;
043 protected ReceivingThreshold newThreshold;
044 protected ReceivingThreshold oldThreshold;
045
046 public ThresholdRule(){
047 chartService = SpringContext.getBean(ChartService.class);
048 accountService = SpringContext.getBean(AccountService.class);
049 }
050
051 @Override
052 protected boolean isDocumentValidForSave(MaintenanceDocument document) {
053 if (document.isNew() || document.isEdit() || document.isNewWithExisting()) {
054 newThreshold = (ReceivingThreshold) document.getNewMaintainableObject().getBusinessObject();
055 oldThreshold = document.getOldMaintainableObject() != null ? (ReceivingThreshold)document.getOldMaintainableObject().getBusinessObject() : null;
056
057 //boolean checkDuplicate = newThreshold.isActive(); // we only need to check duplicate if newThreshold is active
058 // compare oldThreshold and newThreshold, check if there's any update on the various code fields
059 // if yes, then we need to check duplicate of the new threshold among other thresholds; otherwise no need to check
060 boolean checkDuplicate = oldThreshold == null;
061 checkDuplicate |= !StringUtils.equals(newThreshold.getChartOfAccountsCode(), oldThreshold.getChartOfAccountsCode());
062 checkDuplicate |= !StringUtils.equals(newThreshold.getAccountTypeCode(), oldThreshold.getAccountTypeCode());
063 checkDuplicate |= !StringUtils.equals(newThreshold.getSubFundGroupCode(), oldThreshold.getSubFundGroupCode());
064 checkDuplicate |= !StringUtils.equals(newThreshold.getPurchasingCommodityCode(), oldThreshold.getPurchasingCommodityCode());
065 checkDuplicate |= !StringUtils.equals(newThreshold.getFinancialObjectCode(), oldThreshold.getFinancialObjectCode());
066 checkDuplicate |= !StringUtils.equals(newThreshold.getOrganizationCode(), oldThreshold.getOrganizationCode());
067 checkDuplicate |= !StringUtils.equals(newThreshold.getVendorNumber(), oldThreshold.getVendorNumber());
068 return isValidDocument(newThreshold, checkDuplicate);
069 }
070 return true;
071 }
072
073 protected boolean isValidDocument(ReceivingThreshold newThreshold, boolean checkDuplicate){
074
075 boolean valid = isValidThresholdCriteria(newThreshold);
076 if (!valid){
077 constructFieldError(newThreshold);
078 return false;
079 }
080
081 valid = isValidChartCode(newThreshold);
082 if (valid){
083 valid = isValidSubFund(newThreshold) &&
084 isValidCommodityCode(newThreshold) &&
085 isValidObjectCode(newThreshold) &&
086 isValidOrgCode(newThreshold) &&
087 isValidVendorNumber(newThreshold);
088 }
089
090 // check duplication if needed
091 if (valid && checkDuplicate){
092 valid = !isDuplicateEntry(newThreshold);
093 }
094 return valid;
095 }
096
097 protected void constructFieldError(ReceivingThreshold threshold){
098
099 if (StringUtils.isNotBlank(threshold.getAccountTypeCode())){
100 putFieldError(ThresholdField.ACCOUNT_TYPE_CODE.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
101 }
102 if (StringUtils.isNotBlank(threshold.getSubFundGroupCode())){
103 putFieldError(ThresholdField.SUBFUND_GROUP_CODE.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
104 }
105 if (StringUtils.isNotBlank(threshold.getPurchasingCommodityCode())){
106 putFieldError(ThresholdField.COMMODITY_CODE.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
107 }
108 if (StringUtils.isNotBlank(threshold.getFinancialObjectCode())){
109 putFieldError(ThresholdField.FINANCIAL_OBJECT_CODE.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
110 }
111 if (StringUtils.isNotBlank(threshold.getOrganizationCode())){
112 putFieldError(ThresholdField.ORGANIZATION_CODE.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
113 }
114 if (StringUtils.isNotBlank(threshold.getVendorNumber())){
115 putFieldError(ThresholdField.VENDOR_NUMBER.getName(), PurapKeyConstants.INVALID_THRESHOLD_CRITERIA);
116 }
117
118 }
119
120 protected boolean isValidChartCode(ReceivingThreshold threshold){
121 if (StringUtils.isNotBlank(threshold.getChartOfAccountsCode())){
122 Map pkMap = new HashMap();
123 pkMap.put(ThresholdField.CHART_OF_ACCOUNTS_CODE.getName(), newThreshold.getChartOfAccountsCode());
124
125 Chart chart = (Chart) getBoService().findByPrimaryKey(Chart.class, pkMap);
126 if (chart == null) {
127 putFieldError(ThresholdField.CHART_OF_ACCOUNTS_CODE.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getChartOfAccountsCode());
128 return false;
129 }else{
130 return true;
131 }
132 }
133 return false;
134 }
135
136 protected boolean isValidSubFund(ReceivingThreshold threshold){
137
138 if (StringUtils.isNotBlank(threshold.getSubFundGroupCode())){
139 Map pkMap = new HashMap();
140 pkMap.put(ThresholdField.SUBFUND_GROUP_CODE.getName(), newThreshold.getSubFundGroupCode());
141 SubFundGroup subFundGroup = (SubFundGroup) getBoService().findByPrimaryKey(SubFundGroup.class, pkMap);
142 if (subFundGroup == null) {
143 putFieldError(ThresholdField.SUBFUND_GROUP_CODE.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getSubFundGroupCode());
144 return false;
145 }
146 }
147 return true;
148 }
149
150 protected boolean isValidCommodityCode(ReceivingThreshold threshold){
151
152 if (StringUtils.isNotBlank(threshold.getPurchasingCommodityCode())){
153 Map pkMap = new HashMap();
154 pkMap.put(ThresholdField.COMMODITY_CODE.getName(), newThreshold.getPurchasingCommodityCode());
155
156 CommodityCode commodityCode = (CommodityCode) getBoService().findByPrimaryKey(CommodityCode.class, pkMap);
157 if (commodityCode == null) {
158 putFieldError(ThresholdField.COMMODITY_CODE.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getPurchasingCommodityCode());
159 return false;
160 }
161 }
162 return true;
163 }
164
165 protected boolean isValidObjectCode(ReceivingThreshold threshold){
166
167 if (StringUtils.isNotBlank(threshold.getFinancialObjectCode())){
168 Map pkMap = new HashMap();
169 pkMap.put(ThresholdField.FINANCIAL_OBJECT_CODE.getName(), newThreshold.getFinancialObjectCode());
170
171 ObjectCode objectCode = (ObjectCode) getBoService().findByPrimaryKey(ObjectCode.class, pkMap);
172 if (objectCode == null) {
173 putFieldError(ThresholdField.FINANCIAL_OBJECT_CODE.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getFinancialObjectCode());
174 return false;
175 }
176 }
177 return true;
178 }
179
180 protected boolean isValidOrgCode(ReceivingThreshold threshold){
181
182 if (StringUtils.isNotBlank(threshold.getOrganizationCode())){
183 Map pkMap = new HashMap();
184 pkMap.put(ThresholdField.ORGANIZATION_CODE.getName(), newThreshold.getOrganizationCode());
185
186 Organization org = (Organization) getBoService().findByPrimaryKey(Organization.class, pkMap);
187 if (org == null) {
188 putFieldError(ThresholdField.ORGANIZATION_CODE.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getOrganizationCode());
189 return false;
190 }
191 }
192 return true;
193 }
194
195 protected boolean isValidVendorNumber(ReceivingThreshold threshold){
196
197 if (StringUtils.isNotBlank(threshold.getVendorNumber())){
198 Map keys = new HashMap();
199 keys.put(ThresholdField.VENDOR_HEADER_GENERATED_ID.getName(), threshold.getVendorHeaderGeneratedIdentifier());
200 keys.put(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID.getName(), threshold.getVendorDetailAssignedIdentifier());
201
202 VendorDetail vendorDetail = (VendorDetail) getBoService().findByPrimaryKey(VendorDetail.class, keys);
203 if (vendorDetail == null) {
204 putFieldError(ThresholdField.VENDOR_NUMBER.getName(), PurapKeyConstants.THRESHOLD_FIELD_INVALID, newThreshold.getVendorNumber());
205 return false;
206 }
207 }
208 return true;
209 }
210
211 protected boolean isValidThresholdCriteria(ReceivingThreshold threshold){
212
213 if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
214 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
215 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
216 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
217 StringUtils.isBlank(threshold.getOrganizationCode()) &&
218 StringUtils.isBlank(threshold.getVendorNumber())){
219 return true;
220 }else if (StringUtils.isNotBlank(threshold.getAccountTypeCode()) &&
221 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
222 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
223 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
224 StringUtils.isBlank(threshold.getOrganizationCode()) &&
225 StringUtils.isBlank(threshold.getVendorNumber())){
226 return true;
227 }else if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
228 StringUtils.isNotBlank(threshold.getSubFundGroupCode()) &&
229 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
230 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
231 StringUtils.isBlank(threshold.getOrganizationCode()) &&
232 StringUtils.isBlank(threshold.getVendorNumber())){
233 return true;
234 }else if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
235 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
236 StringUtils.isNotBlank(threshold.getPurchasingCommodityCode()) &&
237 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
238 StringUtils.isBlank(threshold.getOrganizationCode()) &&
239 StringUtils.isBlank(threshold.getVendorNumber())){
240 return true;
241 }else if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
242 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
243 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
244 StringUtils.isNotBlank(threshold.getFinancialObjectCode()) &&
245 StringUtils.isBlank(threshold.getOrganizationCode()) &&
246 StringUtils.isBlank(threshold.getVendorNumber())){
247 return true;
248 }else if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
249 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
250 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
251 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
252 StringUtils.isNotBlank(threshold.getOrganizationCode()) &&
253 StringUtils.isBlank(threshold.getVendorNumber())){
254 return true;
255 }else if (StringUtils.isBlank(threshold.getAccountTypeCode()) &&
256 StringUtils.isBlank(threshold.getSubFundGroupCode()) &&
257 StringUtils.isBlank(threshold.getPurchasingCommodityCode()) &&
258 StringUtils.isBlank(threshold.getFinancialObjectCode()) &&
259 StringUtils.isBlank(threshold.getOrganizationCode()) &&
260 StringUtils.isNotBlank(threshold.getVendorNumber())){
261 return true;
262 }
263 return false;
264 }
265
266 protected boolean isDuplicateEntry(ReceivingThreshold newThreshold){
267
268 Map fieldValues = new HashMap();
269 fieldValues.put(ThresholdField.CHART_OF_ACCOUNTS_CODE.getName(), newThreshold.getChartOfAccountsCode());
270 //fieldValues.put("active", "Y"); // check duplicates only among active thresholds
271
272 if (StringUtils.isNotBlank(newThreshold.getAccountTypeCode())){
273 fieldValues.put(ThresholdField.ACCOUNT_TYPE_CODE.getName(), newThreshold.getAccountTypeCode());
274 }else if (StringUtils.isNotBlank(newThreshold.getSubFundGroupCode())){
275 fieldValues.put(ThresholdField.SUBFUND_GROUP_CODE.getName(), newThreshold.getSubFundGroupCode());
276 }else if (StringUtils.isNotBlank(newThreshold.getPurchasingCommodityCode())){
277 fieldValues.put(ThresholdField.COMMODITY_CODE.getName(), newThreshold.getPurchasingCommodityCode());
278 }else if (StringUtils.isNotBlank(newThreshold.getFinancialObjectCode())){
279 fieldValues.put(ThresholdField.FINANCIAL_OBJECT_CODE.getName(), newThreshold.getFinancialObjectCode());
280 }else if (StringUtils.isNotBlank(newThreshold.getOrganizationCode())){
281 fieldValues.put(ThresholdField.ORGANIZATION_CODE.getName(), newThreshold.getOrganizationCode());
282 }else if (StringUtils.isNotBlank(newThreshold.getVendorNumber())){
283 fieldValues.put(ThresholdField.VENDOR_HEADER_GENERATED_ID.getName(), newThreshold.getVendorHeaderGeneratedIdentifier());
284 fieldValues.put(ThresholdField.VENDOR_DETAIL_ASSIGNED_ID.getName(), newThreshold.getVendorDetailAssignedIdentifier());
285 }
286
287 Collection<ReceivingThreshold> result = (Collection<ReceivingThreshold>)getBoService().findMatching(ReceivingThreshold.class, fieldValues);
288 if (result != null && result.size() > 0) {
289 putGlobalError(PurapKeyConstants.PURAP_GENERAL_POTENTIAL_DUPLICATE);
290 return true;
291 }
292 return false;
293 }
294 }