001/* 002 * The Kuali Financial System, a comprehensive financial management system for higher education. 003 * 004 * Copyright 2005-2014 The Kuali Foundation 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Affero General Public License as 008 * published by the Free Software Foundation, either version 3 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU Affero General Public License for more details. 015 * 016 * You should have received a copy of the GNU Affero General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.kuali.kfs.pdp.document.validation.impl; 020 021import java.util.Collection; 022import java.util.HashMap; 023import java.util.Map; 024 025import org.apache.commons.lang.StringUtils; 026import org.apache.log4j.Logger; 027import org.kuali.kfs.pdp.PdpConstants; 028import org.kuali.kfs.pdp.PdpKeyConstants; 029import org.kuali.kfs.pdp.PdpPropertyConstants; 030import org.kuali.kfs.pdp.businessobject.CustomerBank; 031import org.kuali.kfs.pdp.businessobject.CustomerProfile; 032import org.kuali.kfs.sys.businessobject.Bank; 033import org.kuali.kfs.sys.context.SpringContext; 034import org.kuali.rice.kns.document.MaintenanceDocument; 035import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 036import org.kuali.rice.krad.bo.PersistableBusinessObject; 037import org.kuali.rice.krad.service.BusinessObjectService; 038import org.kuali.rice.krad.util.GlobalVariables; 039import org.kuali.rice.krad.util.KRADConstants; 040import org.kuali.rice.krad.util.MessageMap; 041import org.kuali.rice.krad.util.ObjectUtils; 042import org.kuali.rice.location.api.postalcode.PostalCode; 043import org.kuali.rice.location.api.postalcode.PostalCodeService; 044 045public class CustomerProfileRule extends MaintenanceDocumentRuleBase { 046 protected static Logger LOG = org.apache.log4j.Logger.getLogger(CustomerProfileRule.class); 047 048 /** 049 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject) 050 */ 051 @Override 052 public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) { 053 boolean isValid = true; 054 isValid &= super.processCustomAddCollectionLineBusinessRules(document, collectionName, line); 055 MessageMap errorMap = GlobalVariables.getMessageMap(); 056 isValid &= !errorMap.hasErrors(); 057 058 if (isValid) { 059 if (collectionName.equals(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_BANKS)) { 060 CustomerBank newCustomerBank = (CustomerBank) line; 061 if(newCustomerBank.getDisbursementTypeCode()!=null){ 062 // does the same disbursement type code exist? 063 CustomerProfile customerProfile = (CustomerProfile) document.getNewMaintainableObject().getBusinessObject(); 064 for (CustomerBank bank : customerProfile.getCustomerBanks()) { 065 if (bank.getDisbursementTypeCode().equalsIgnoreCase(newCustomerBank.getDisbursementTypeCode())) { 066 errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_ONE_BANK_PER_DISBURSEMENT_TYPE_CODE); 067 isValid = false; 068 } 069 } 070 } 071 if(newCustomerBank.getBank()!=null){ 072 // check if the bank code type is allowed 073 newCustomerBank.refreshReferenceObject(PdpPropertyConstants.CUSTOMER_BANK); 074 Bank newBank = newCustomerBank.getBank(); 075 if (newCustomerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH) && !newBank.isBankAchIndicator()) { 076 errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_NOT_ALLOWED, newBank.getBankCode() + " (" + newBank.getBankName() + ")"); 077 isValid = false; 078 } 079 if (newCustomerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK) && !newBank.isBankCheckIndicator()) { 080 errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_NOT_ALLOWED, newBank.getBankCode() + " (" + newBank.getBankName() + ")"); 081 isValid = false; 082 } 083 } 084 } 085 } 086 return isValid; 087 } 088 089 /** 090 * KFSMI-3771 091 * This method checks if the Disbursement Bank information is provided in the Customer profile. 092 * If Bank information is provided; It's required that a Check bank is present. 093 * If the Customer profile has ACH disbursement type information provided, it should have an ACH bank Information as well. 094 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 095 * @param MaintenanceDocument - CustomerProfileMaintenanceDocument 096 * @return boolean - true if business rules are satisfied; false otherwise. 097 */ 098 @Override 099 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 100 101 boolean isValid = true; 102 isValid &= super.processCustomRouteDocumentBusinessRules(document); 103 104 CustomerProfile customerProfile = (CustomerProfile) document.getNewMaintainableObject().getBusinessObject(); 105 106 if (customerProfile != null) { 107 customerProfile.refreshNonUpdateableReferences(); 108 setStateFromZip(customerProfile); 109 } 110 111 boolean checkBankPresent = false; 112 boolean ACHBankPresent = false; 113 114 //Check if the customer profile has ACH transaction type information present. 115 boolean customerHasACHType = customerProfile.getAchTransactionType() != null ? true : false; 116 117 //Check if customer profile has bank information 118 if (customerProfile.getCustomerBanks().isEmpty()){ 119 putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.Format.ErrorMessages.ERROR_FORMAT_BANK_MISSING, customerProfile.getId().toString()); 120 121 isValid = false; 122 }else{ 123 for (CustomerBank customerBank : customerProfile.getCustomerBanks()){ 124 125 // check if the bank code type is allowed 126 Bank bank = customerBank.getBank(); 127 if (customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH) && !bank.isBankAchIndicator()) { 128 putFieldError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_NOT_ALLOWED, bank.getBankCode() + " (" + bank.getBankName() + ")"); 129 isValid = false; 130 } 131 if (customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK) && !bank.isBankCheckIndicator()) { 132 putFieldError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_NOT_ALLOWED, bank.getBankCode() + " (" + bank.getBankName() + ")"); 133 isValid = false; 134 } 135 136 //Check if customer profile has Check type Bank information 137 if(customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK)){ 138 checkBankPresent = true; 139 } 140 //Check if customer profile has ACH type Bank information 141 if(customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH)){ 142 ACHBankPresent = true; 143 } 144 if(checkBankPresent && ACHBankPresent){ 145 break; 146 } 147 } 148 149 //Generate error message if check bank is not present. 150 if(!checkBankPresent){ 151 isValid = false; 152 putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_REQUIRED); 153 } 154 155 //Generate error message if ACH bank is not present for profile with ACH disbursement type. 156 if(customerHasACHType && !ACHBankPresent){ 157 isValid = false; 158 putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_REQUIRED); 159 } 160 161 } 162 163 // KFSMI-5158 Uniqueness check only for new Customer Profiles 164 if (document.isNew()) { 165 isValid &= verifyChartUnitSubUnitIsUnique(customerProfile); 166 } 167 168 return isValid; 169 } 170 171 //KFSMI-8330 172 /** 173 * sets city name and state code on the form 174 * 175 * @param customerProfile 176 */ 177 protected void setStateFromZip(CustomerProfile customerProfile) { 178 if (StringUtils.isNotBlank(customerProfile.getZipCode()) && StringUtils.isNotBlank(customerProfile.getCountryCode()) ) { 179 PostalCode zip = SpringContext.getBean(PostalCodeService.class).getPostalCode( customerProfile.getCountryCode(), customerProfile.getZipCode() ); 180 181 // If user enters a valid zip code, override city name and state code entered by user 182 if (ObjectUtils.isNotNull(zip)) { // override old user inputs 183 customerProfile.setCity(zip.getCityName()); 184 customerProfile.setStateCode(zip.getStateCode()); 185 } 186 } 187 } 188 189 /** 190 * Verifies that the chart/unit/sub-unit combination on this customer profile is unique 191 * @param customerProfile the customer profile to check 192 * @return true if the chart/unit/sub-unit is unique, false otherwise 193 */ 194 protected boolean verifyChartUnitSubUnitIsUnique(CustomerProfile customerProfile) { 195 boolean result = true; 196 197 if (!StringUtils.isBlank(customerProfile.getChartCode()) && !StringUtils.isBlank(customerProfile.getUnitCode()) && !StringUtils.isBlank(customerProfile.getSubUnitCode())) { 198 final BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class); 199 Map<String, Object> searchKeys = new HashMap<String, Object>(); 200 searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_CHART_CODE, customerProfile.getChartCode()); 201 searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_UNIT_CODE, customerProfile.getUnitCode()); 202 searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_SUB_UNIT_CODE, customerProfile.getSubUnitCode()); 203 204 final Collection foundCustomerProfiles = businessObjectService.findMatching(CustomerProfile.class, searchKeys); 205 if (foundCustomerProfiles != null && foundCustomerProfiles.size() > 0) { 206 result = false; 207 putFieldError(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_UNIT_CODE, PdpKeyConstants.ERROR_CUSTOMER_PROFILE_CHART_UNIT_SUB_UNIT_NOT_UNIQUE, new String[] { customerProfile.getChartCode(), customerProfile.getUnitCode(), customerProfile.getSubUnitCode()}); 208 } 209 } 210 211 return result; 212 } 213 214}