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 }