001/* 002 * Copyright 2008 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 */ 016package org.kuali.ole.module.purap.document.validation.impl; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.ole.coa.businessobject.Chart; 020import org.kuali.ole.coa.businessobject.ObjectCode; 021import org.kuali.ole.coa.businessobject.Organization; 022import org.kuali.ole.coa.businessobject.SubFundGroup; 023import org.kuali.ole.coa.service.AccountService; 024import org.kuali.ole.coa.service.ChartService; 025import org.kuali.ole.module.purap.PurapKeyConstants; 026import org.kuali.ole.module.purap.businessobject.ReceivingThreshold; 027import org.kuali.ole.module.purap.util.ThresholdField; 028import org.kuali.ole.sys.context.SpringContext; 029import org.kuali.ole.vnd.businessobject.CommodityCode; 030import org.kuali.ole.vnd.businessobject.VendorDetail; 031import org.kuali.rice.kns.document.MaintenanceDocument; 032import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 033 034import java.util.Collection; 035import java.util.HashMap; 036import java.util.Map; 037 038public 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}