View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    *
4    * Copyright 2005-2014 The Kuali Foundation
5    *
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   *
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.module.cg.document.validation.impl;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.log4j.Logger;
28  import org.kuali.kfs.integration.ar.AccountsReceivableCustomer;
29  import org.kuali.kfs.module.cg.CGConstants;
30  import org.kuali.kfs.module.cg.CGKeyConstants;
31  import org.kuali.kfs.module.cg.CGPropertyConstants;
32  import org.kuali.kfs.module.cg.businessobject.Agency;
33  import org.kuali.kfs.module.cg.businessobject.AgencyAddress;
34  import org.kuali.kfs.module.cg.businessobject.AgencyType;
35  import org.kuali.kfs.sys.KFSKeyConstants;
36  import org.kuali.kfs.sys.KFSPropertyConstants;
37  import org.kuali.kfs.sys.context.SpringContext;
38  import org.kuali.rice.kns.document.MaintenanceDocument;
39  import org.kuali.rice.kns.service.DataDictionaryService;
40  import org.kuali.rice.krad.bo.PersistableBusinessObject;
41  import org.kuali.rice.krad.service.BusinessObjectService;
42  import org.kuali.rice.krad.util.GlobalVariables;
43  import org.kuali.rice.krad.util.ObjectUtils;
44  
45  /**
46   * Rules for processing Agency instances.
47   */
48  public class AgencyRule extends CGMaintenanceDocumentRuleBase {
49      protected static Logger LOG = org.apache.log4j.Logger.getLogger(AgencyRule.class);
50  
51      protected Agency newAgency;
52      protected Agency oldAgency;
53  
54      BusinessObjectService businessObjectService;
55  
56      /**
57       * Default constructor.
58       */
59      public AgencyRule() {
60          super();
61          businessObjectService = SpringContext.getBean(BusinessObjectService.class);
62      }
63  
64      /**
65       * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
66       */
67      @Override
68      protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
69          LOG.debug("Entering AgencyRule.processCustomApproveDocumentBusinessRules");
70          boolean success = super.processCustomApproveDocumentBusinessRules(document);
71  
72          success &= checkAgencyReportsTo(document);
73  
74          LOG.info("Leaving AgencyRule.processCustomApproveDocumentBusinessRules");
75          return success;
76      }
77  
78      /**
79       * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
80       */
81      @Override
82      protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
83          LOG.debug("Entering AgencyRule.processCustomRouteDocumentBusinessRules");
84          boolean success = super.processCustomRouteDocumentBusinessRules(document);
85  
86          success &= checkAgencyReportsTo(document);
87  
88          // Only do further custom Contracts & Grants Billing validations for route document, if the enhancements are active
89          if (contractsGrantsBillingEnhancementActive) {
90              // There must be at least one primary Agency Address in Agency
91              success &= checkPrimary(newAgency.getAgencyAddresses(), AgencyAddress.class, KFSPropertyConstants.AGENCY_ADDRESSES, Agency.class);
92              success &= validateAddresses(newAgency);
93  
94              // Make sure new agency customers have a Customer Type
95              success &= validateCustomerType(newAgency);
96          }
97  
98          LOG.info("Leaving AgencyRule.processCustomRouteDocumentBusinessRules");
99          return success;
100     }
101 
102     /**
103      * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
104      */
105     @Override
106     protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
107         LOG.debug("Entering AgencyRule.processCustomSaveDocumentBusinessRules");
108         boolean success = super.processCustomSaveDocumentBusinessRules(document);
109 
110         success &= checkAgencyReportsTo(document);
111         success &= validateAgencyType(document);
112         success &= validateAgencyReportingName(document);
113 
114         LOG.info("Leaving AgencyRule.processCustomSaveDocumentBusinessRules");
115         return success;
116     }
117 
118     /**
119      * @param document
120      * @return
121      */
122     protected boolean validateAgencyType(MaintenanceDocument document) {
123         String agencyType = newAgency.getAgencyTypeCode();
124         Map params = new HashMap();
125         params.put("code", agencyType);
126         Object o = businessObjectService.findByPrimaryKey(AgencyType.class, params);
127         if (null == o) {
128             putFieldError("agencyTypeCode", KFSKeyConstants.ERROR_AGENCY_TYPE_NOT_FOUND, agencyType);
129             return false;
130         }
131         return true;
132     }
133 
134     /**
135      * @param document
136      * @return
137      */
138     protected boolean validateAgencyReportingName(MaintenanceDocument document) {
139         String agencyReportingName = newAgency.getReportingName();
140         String agencyExistsValue = newAgency.getCustomerCreationOptionCode();
141         if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(agencyExistsValue)) {
142             if (agencyReportingName.length() < 3) {
143                 putFieldError("reportingName", CGKeyConstants.AgencyConstants.ERROR_AGENCY_NAME_LESS_THAN_THREE_CHARACTERS);
144                 return false;
145             }
146             else if (agencyReportingName.substring(0, 3).contains(" ")) {
147                 putFieldError("reportingName", CGKeyConstants.AgencyConstants.ERROR_AGENCY_NAME_NO_SPACES_IN_FIRST_THREE_CHARACTERS);
148                 return false;
149             }
150         }
151         return true;
152     }
153 
154     /**
155      * @param document
156      * @return
157      */
158     protected boolean checkAgencyReportsTo(MaintenanceDocument document) {
159         boolean success = true;
160 
161         if (newAgency.getReportsToAgencyNumber() != null) {
162             if (newAgency.getReportsToAgency() == null) { // Agency must exist
163 
164                 putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_NOT_FOUND, newAgency.getReportsToAgencyNumber());
165                 success = false;
166 
167             }
168             else if (!newAgency.getReportsToAgency().isActive()) { // Agency must be active. See KULCG-263
169 
170                 putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_INACTIVE, newAgency.getReportsToAgencyNumber());
171                 success = false;
172 
173             }
174             else if (newAgency.getAgencyNumber().equals(newAgency.getReportsToAgencyNumber())) {
175 
176                 putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_REPORTS_TO_SELF, newAgency.getAgencyNumber());
177                 success = false;
178 
179             }
180             else { // No circular references
181 
182                 List agencies = new ArrayList();
183 
184                 Agency agency = newAgency;
185 
186                 while (agency.getReportsToAgency() != null && success) {
187                     if (!agencies.contains(agency.getAgencyNumber())) {
188                         agencies.add(agency.getAgencyNumber());
189                     }
190                     else {
191 
192                         putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_CIRCULAR_REPORTING, agency.getAgencyNumber());
193                         success = false;
194                     }
195 
196                     agency = agency.getReportsToAgency();
197                 }
198             }
199         }
200         return success;
201     }
202 
203     /**
204      * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects()
205      */
206     @Override
207     public void setupConvenienceObjects() {
208         newAgency = (Agency) super.getNewBo();
209         oldAgency = (Agency) super.getOldBo();
210     }
211 
212 
213     /**
214      * Overrides the method in MaintenanceDocumentRuleBase to give error message to the user when the user tries to add multiple
215      * Primary Agency Addresses. At most one Primary Agency Address is allowed. contract.
216      *
217      * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument,
218      *      java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
219      */
220     @Override
221     public boolean processAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
222 
223         // Only do if the CG Billing enhancements are turned on
224         if (contractsGrantsBillingEnhancementActive) {
225             if (line instanceof AgencyAddress) {
226                 AgencyAddress newAgencyAddress = (AgencyAddress) line;
227                 if (collectionName.equals(KFSPropertyConstants.AGENCY_ADDRESSES)) {
228                     newAgency = (Agency) document.getNewMaintainableObject().getBusinessObject();
229                     List<AgencyAddress> agencyAddresses = newAgency.getAgencyAddresses();
230                     String tmpCode = newAgencyAddress.getCustomerAddressTypeCode();
231 
232                     // Check if there is an Agency Primary Address in the collection lines or not.
233                     for (AgencyAddress agencyAddress : agencyAddresses) {
234                         String customerAddressTypeCode = agencyAddress.getCustomerAddressTypeCode();
235                         if (customerAddressTypeCode != null && customerAddressTypeCode.equals(CGConstants.AGENCY_PRIMARY_ADDRESSES_TYPE_CODE)) {
236                             if (ObjectUtils.isNotNull(tmpCode) && !tmpCode.isEmpty() && tmpCode.equals(CGConstants.AGENCY_PRIMARY_ADDRESSES_TYPE_CODE)) {
237                                 String elementLabel = SpringContext.getBean(DataDictionaryService.class).getCollectionElementLabel(Agency.class.getName(), collectionName, AgencyAddress.class);
238                                 putFieldError(collectionName, KFSKeyConstants.ERROR_MULTIPLE_PRIMARY, elementLabel);
239                                 return false;
240                             }
241                             else {
242                                 boolean isValid = checkAddressIsValid(newAgencyAddress);
243                                 if (!isValid) {
244                                     return isValid;
245                                 }
246                             }
247                         }
248                     }
249                 }
250             }
251 
252         }
253 
254         return super.processAddCollectionLineBusinessRules(document, collectionName, line);
255     }
256 
257     /**
258      * This method validates the addresses when Customer is created from Agency
259      *
260      * @param agencyAddress
261      * @return
262      */
263     public boolean checkAddressIsValid(AgencyAddress agencyAddress) {
264         boolean isValid = true;
265         // To validate only if the Agency agency exists field says "Create New Customer".
266         if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(newAgency.getCustomerCreationOptionCode())) {
267             if (CGKeyConstants.AgencyConstants.AGENCY_ADDRESS_TYPE_CODE_US.equalsIgnoreCase(agencyAddress.getAgencyCountryCode())) {
268                 if (StringUtils.isBlank(agencyAddress.getAgencyZipCode())) {
269                     isValid = false;
270                     GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_ZIP_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_ZIP_CODE_REQUIRED_WHEN_COUNTTRY_US);
271                 }
272                 if (StringUtils.isBlank(agencyAddress.getAgencyStateCode())) {
273                     isValid = false;
274                     GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_STATE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_STATE_CODE_REQUIRED_WHEN_COUNTTRY_US);
275                 }
276             }
277             else {
278                 if (StringUtils.isBlank(agencyAddress.getAgencyInternationalMailCode())) {
279                     isValid = false;
280                     GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE_REQUIRED_WHEN_COUNTTRY_NON_US);
281                 }
282                 if (StringUtils.isBlank(agencyAddress.getAgencyAddressInternationalProvinceName())) {
283                     isValid = false;
284                     GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME_REQUIRED_WHEN_COUNTTRY_NON_US);
285                 }
286             }
287         }
288         return isValid;
289     }
290 
291     /**
292      * This method validates the addresses when Customer is created from Agency
293      *
294      * @param agencyAddress
295      * @param ind
296      * @return
297      */
298     public boolean checkAddressIsValid(AgencyAddress agencyAddress, int ind) {
299         boolean isValid = true;
300         String propertyName = CGPropertyConstants.AgencyFields.AGENCY_TAB_ADDRESSES + "[" + ind + "].";
301         // To validate only if the Agency agencyexists field says "Create New Customer".
302         if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(newAgency.getCustomerCreationOptionCode())) {
303             if (CGKeyConstants.AgencyConstants.AGENCY_ADDRESS_TYPE_CODE_US.equalsIgnoreCase(agencyAddress.getAgencyCountryCode())) {
304                 if (StringUtils.isBlank(agencyAddress.getAgencyZipCode())) {
305                     isValid = false;
306                     putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_ZIP_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_ZIP_CODE_REQUIRED_WHEN_COUNTTRY_US);
307                 }
308                 if (StringUtils.isBlank(agencyAddress.getAgencyStateCode())) {
309                     isValid = false;
310                     putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_STATE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_STATE_CODE_REQUIRED_WHEN_COUNTTRY_US);
311                 }
312             }
313             else {
314                 if (StringUtils.isBlank(agencyAddress.getAgencyInternationalMailCode())) {
315                     isValid = false;
316                     putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE_REQUIRED_WHEN_COUNTTRY_NON_US);
317                 }
318                 if (StringUtils.isBlank(agencyAddress.getAgencyAddressInternationalProvinceName())) {
319                     isValid = false;
320                     putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME_REQUIRED_WHEN_COUNTTRY_NON_US);
321                 }
322             }
323         }
324         return isValid;
325     }
326 
327 
328     /**
329      * This method validates the addresses when Customer is created from Agency
330      *
331      * @param agency
332      * @return
333      */
334     public boolean validateAddresses(Agency agency) {
335         boolean isValid = true;
336         int i = 0;
337 
338         for (AgencyAddress agencyAddress : agency.getAgencyAddresses()) {
339             isValid &= checkAddressIsValid(agencyAddress, i);
340             i++;
341         }
342 
343 
344         return isValid;
345     }
346 
347     /**
348      * This method validates that a customer type is selected when the create new customer option is selected, and that if existing customer option
349      * is selected that customer number is filled in with an existing customer.
350      * @param agency agency record to verify
351      * @return true if agency passes verification, false otherwise
352      */
353     public boolean validateCustomerType(Agency agency) {
354         boolean isValid = true;
355 
356         // Only validate if new customer create option is selected
357         if ( StringUtils.equalsIgnoreCase(CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE, agency.getCustomerCreationOptionCode()) ){
358             // Customer Type must be filled-in
359             if( StringUtils.isEmpty(agency.getCustomerTypeCode()) ){
360                 putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_TYPE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_CUSTOMER_TYPE_CODE_REQUIRED_WHEN_AGENCY_CUSTOMER_NEW);
361                 isValid &= false;
362             }
363         } else if (StringUtils.equalsIgnoreCase(CGConstants.AGENCY_USE_EXISTING_CUSTOMER_CODE, agency.getCustomerCreationOptionCode())) {
364             if (StringUtils.isBlank(agency.getCustomerNumber())) {
365                 putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_NUMBER, CGKeyConstants.AgencyConstants.ERROR_AGECNY_CUSTOMER_NUMBER_REQUIRED_WHEN_AGENCY_CUSTOMER_EXISTING);
366                 isValid = false;
367             } else {
368                 final AccountsReceivableCustomer customer = agency.getCustomer();
369                 if (ObjectUtils.isNull(customer) || !customer.isActive()) {
370                     putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_NUMBER, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ACTUAL_CUSTOMER_REQUIRED_WHEN_AGENCY_CUSTOMER_EXISTING, new String[] { agency.getCustomerNumber() });
371                     isValid = false;
372                 }
373             }
374         }
375 
376         return isValid;
377     }
378 }