View Javadoc
1   /*
2    * Copyright 2009 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.pdp.document.validation.impl;
17  
18  import java.util.Collection;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.apache.log4j.Logger;
24  import org.kuali.ole.pdp.PdpConstants;
25  import org.kuali.ole.pdp.PdpKeyConstants;
26  import org.kuali.ole.pdp.PdpPropertyConstants;
27  import org.kuali.ole.pdp.businessobject.CustomerBank;
28  import org.kuali.ole.pdp.businessobject.CustomerProfile;
29  import org.kuali.ole.sys.businessobject.Bank;
30  import org.kuali.ole.sys.context.SpringContext;
31  import org.kuali.rice.kns.document.MaintenanceDocument;
32  import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
33  import org.kuali.rice.krad.bo.PersistableBusinessObject;
34  import org.kuali.rice.krad.service.BusinessObjectService;
35  import org.kuali.rice.krad.util.GlobalVariables;
36  import org.kuali.rice.krad.util.KRADConstants;
37  import org.kuali.rice.krad.util.MessageMap;
38  import org.kuali.rice.krad.util.ObjectUtils;
39  import org.kuali.rice.location.api.postalcode.PostalCode;
40  import org.kuali.rice.location.api.postalcode.PostalCodeService;
41  
42  public class CustomerProfileRule extends MaintenanceDocumentRuleBase {
43      protected static Logger LOG = org.apache.log4j.Logger.getLogger(CustomerProfileRule.class);
44  
45      /**
46       * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument, java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
47       */
48      @Override
49      public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
50          boolean isValid = true;
51          isValid &= super.processCustomAddCollectionLineBusinessRules(document, collectionName, line);
52          MessageMap errorMap = GlobalVariables.getMessageMap();
53          isValid &= !errorMap.hasErrors();
54  
55          if (isValid) {
56              if (collectionName.equals(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_BANKS)) {
57                  CustomerBank newCustomerBank = (CustomerBank) line;
58                  if(newCustomerBank.getDisbursementTypeCode()!=null){
59                      // does the same disbursement type code exist?
60                  CustomerProfile customerProfile = (CustomerProfile) document.getNewMaintainableObject().getBusinessObject();
61                  for (CustomerBank bank : customerProfile.getCustomerBanks()) {
62                      if (bank.getDisbursementTypeCode().equalsIgnoreCase(newCustomerBank.getDisbursementTypeCode())) {
63                              errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_ONE_BANK_PER_DISBURSEMENT_TYPE_CODE);
64                              isValid = false;
65                          }
66                      }
67                  }
68                  if(newCustomerBank.getBank()!=null){
69                      // check if the bank code type is allowed
70                      newCustomerBank.refreshReferenceObject(PdpPropertyConstants.CUSTOMER_BANK);
71                      Bank newBank = newCustomerBank.getBank();
72                      if (newCustomerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH) && !newBank.isBankAchIndicator()) {
73                          errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_NOT_ALLOWED, newBank.getBankCode() + " (" + newBank.getBankName() + ")");
74                          isValid = false;
75                      }
76                      if (newCustomerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK) && !newBank.isBankCheckIndicator()) {
77                          errorMap.putError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_NOT_ALLOWED, newBank.getBankCode() + " (" + newBank.getBankName() + ")");
78                          isValid = false;
79                      }
80                  }
81              }
82          }
83          return isValid;
84      }
85  
86      /**
87       * KFSMI-3771
88       * This method checks if the Disbursement Bank information is provided in the Customer profile.
89       * If Bank information is provided; It's required that a Check bank is present.
90       * If the Customer profile has ACH disbursement type information provided, it should have an ACH bank Information as well.
91       * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
92       * @param MaintenanceDocument  - CustomerProfileMaintenanceDocument
93       * @return boolean - true if business rules are satisfied; false otherwise.
94       */
95      @Override
96      protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
97  
98          boolean isValid = true;
99          isValid &= super.processCustomRouteDocumentBusinessRules(document);
100 
101         CustomerProfile customerProfile = (CustomerProfile) document.getNewMaintainableObject().getBusinessObject();
102 
103         if (customerProfile != null) {
104             customerProfile.refreshNonUpdateableReferences();
105             setStateFromZip(customerProfile);
106         }
107 
108         boolean checkBankPresent = false;
109         boolean ACHBankPresent = false;
110 
111         //Check if the customer profile has ACH transaction type information present.
112         boolean customerHasACHType = customerProfile.getAchTransactionType() != null ? true : false;
113 
114         //Check if customer profile has bank information
115         if (customerProfile.getCustomerBanks().isEmpty()){
116             putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.Format.ErrorMessages.ERROR_FORMAT_BANK_MISSING, customerProfile.getId().toString());
117 
118             isValid = false;
119         }else{
120             for (CustomerBank customerBank : customerProfile.getCustomerBanks()){
121 
122                 // check if the bank code type is allowed
123                 Bank bank = customerBank.getBank();
124                 if (customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH) && !bank.isBankAchIndicator()) {
125                     putFieldError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_NOT_ALLOWED, bank.getBankCode() + " (" + bank.getBankName() + ")");
126                     isValid = false;
127                 }
128                 if (customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK) && !bank.isBankCheckIndicator()) {
129                     putFieldError(PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_NOT_ALLOWED, bank.getBankCode() + " (" + bank.getBankName() + ")");
130                     isValid = false;
131                 }
132 
133                 //Check if customer profile has Check type Bank information
134                 if(customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.CHECK)){
135                     checkBankPresent = true;
136                 }
137                 //Check if customer profile has ACH type Bank information
138                 if(customerBank.getDisbursementTypeCode().equalsIgnoreCase(PdpConstants.DisbursementTypeCodes.ACH)){
139                         ACHBankPresent = true;
140                  }
141                 if(checkBankPresent && ACHBankPresent){
142                     break;
143                 }
144             }
145 
146             //Generate error message if check bank is not present.
147             if(!checkBankPresent){
148                 isValid = false;
149                 putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_CHECK_BANK_REQUIRED);
150             }
151 
152             //Generate error message if ACH bank is not present for profile with ACH disbursement type.
153             if(customerHasACHType && !ACHBankPresent){
154                 isValid = false;
155                 putFieldError(KRADConstants.MAINTENANCE_ADD_PREFIX+"customerBanks."+PdpPropertyConstants.DISBURSEMENT_TYPE_CODE, PdpKeyConstants.ERROR_PDP_ACH_BANK_REQUIRED);
156             }
157 
158         }
159 
160         // KFSMI-5158 Uniqueness check only for new Customer Profiles
161         if (document.isNew()) {
162             isValid &= verifyChartUnitSubUnitIsUnique(customerProfile);
163         }
164 
165         return isValid;
166     }
167 
168     //KFSMI-8330
169     /**
170      * sets city name and state code on the form
171      *
172      * @param customerProfile
173      */
174     protected void setStateFromZip(CustomerProfile customerProfile) {
175         if (StringUtils.isNotBlank(customerProfile.getZipCode()) && StringUtils.isNotBlank(customerProfile.getCountryCode()) ) {
176             PostalCode zip = SpringContext.getBean(PostalCodeService.class).getPostalCode( customerProfile.getCountryCode(), customerProfile.getZipCode() );
177 
178             // If user enters a valid zip code, override city name and state code entered by user
179             if (ObjectUtils.isNotNull(zip)) { // override old user inputs
180                 customerProfile.setCity(zip.getCityName());
181                 customerProfile.setStateCode(zip.getStateCode());
182             }
183         }
184     }
185 
186     /**
187      * Verifies that the chart/unit/sub-unit combination on this customer profile is unique
188      * @param customerProfile the customer profile to check
189      * @return true if the chart/unit/sub-unit is unique, false otherwise
190      */
191     protected boolean verifyChartUnitSubUnitIsUnique(CustomerProfile customerProfile) {
192         boolean result = true;
193 
194         if (!StringUtils.isBlank(customerProfile.getChartCode()) && !StringUtils.isBlank(customerProfile.getUnitCode()) && !StringUtils.isBlank(customerProfile.getSubUnitCode())) {
195             final BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class);
196             Map<String, Object> searchKeys = new HashMap<String, Object>();
197             searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_CHART_CODE, customerProfile.getChartCode());
198             searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_UNIT_CODE, customerProfile.getUnitCode());
199             searchKeys.put(PdpPropertyConstants.CustomerProfile.CUSTOMER_PROFILE_SUB_UNIT_CODE, customerProfile.getSubUnitCode());
200 
201             final Collection foundCustomerProfiles = businessObjectService.findMatching(CustomerProfile.class, searchKeys);
202             if (foundCustomerProfiles != null && foundCustomerProfiles.size() > 0) {
203                 result = false;
204                 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()});
205             }
206         }
207 
208         return result;
209     }
210 
211 }