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.ar.document.validation.impl; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.apache.log4j.Logger; 020 import org.kuali.kfs.coa.businessobject.ObjectCode; 021 import org.kuali.kfs.coa.service.ObjectTypeService; 022 import org.kuali.kfs.module.ar.ArConstants; 023 import org.kuali.kfs.module.ar.ArKeyConstants; 024 import org.kuali.kfs.module.ar.ArPropertyConstants; 025 import org.kuali.kfs.module.ar.businessobject.OrganizationAccountingDefault; 026 import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument; 027 import org.kuali.kfs.module.ar.document.CustomerInvoiceWriteoffDocument; 028 import org.kuali.kfs.sys.context.SpringContext; 029 import org.kuali.rice.kns.document.MaintenanceDocument; 030 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 031 import org.kuali.rice.kns.service.ParameterService; 032 import org.kuali.rice.kns.util.ObjectUtils; 033 034 public class OrganizationAccountingDefaultRule extends MaintenanceDocumentRuleBase { 035 protected static Logger LOG = org.apache.log4j.Logger.getLogger(OrganizationAccountingDefaultRule.class); 036 037 protected ObjectTypeService objectTypeService; 038 protected OrganizationAccountingDefault newOrganizationAccountingDefault; 039 protected OrganizationAccountingDefault oldOrganizationAccountingDefault; 040 041 public OrganizationAccountingDefaultRule() { 042 043 // insert object type service 044 this.setObjectTypeService(SpringContext.getBean(ObjectTypeService.class)); 045 } 046 047 @Override 048 public void setupConvenienceObjects() { 049 newOrganizationAccountingDefault = (OrganizationAccountingDefault) super.getNewBo(); 050 oldOrganizationAccountingDefault = (OrganizationAccountingDefault) super.getOldBo(); 051 } 052 053 @Override 054 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 055 056 boolean success = true; 057 success &= isWriteOffObjectValidExpense(newOrganizationAccountingDefault); 058 success &= isLateChargeObjectValidIncome(newOrganizationAccountingDefault); 059 success &= isDefaultInvoiceFinancialObjectValidIncome(newOrganizationAccountingDefault); 060 061 // validate receivable FAU line if system parameter for receivable is set to 3 062 String receivableOffsetOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceDocument.class, ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD); 063 if (ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD_FAU.equals(receivableOffsetOption)) { 064 success &= doesPaymentAccountNumberExist(newOrganizationAccountingDefault); 065 success &= doesPaymentChartOfAccountsCodeExist(newOrganizationAccountingDefault); 066 success &= doesPaymentFinancialObjectCodeExist(newOrganizationAccountingDefault); 067 } 068 069 // validate writeoff FAU line if system parameter for writeoff is set to 2 070 String writeoffOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceWriteoffDocument.class, ArConstants.GLPE_WRITEOFF_GENERATION_METHOD); 071 if (ArConstants.GLPE_WRITEOFF_GENERATION_METHOD_ORG_ACCT_DEFAULT.equals(writeoffOption)) { 072 success &= doesWriteoffAccountNumberExist(newOrganizationAccountingDefault); 073 success &= doesWriteoffChartOfAccountsCodeExist(newOrganizationAccountingDefault); 074 success &= doesWriteoffFinancialObjectCodeExist(newOrganizationAccountingDefault); 075 } 076 077 return success; 078 } 079 080 081 082 /** 083 * This method returns true if payment account number is provided and is valid. 084 * 085 * @param doc 086 * @return 087 */ 088 protected boolean doesWriteoffAccountNumberExist(OrganizationAccountingDefault organizationAccountingDefault) { 089 090 if (StringUtils.isEmpty(organizationAccountingDefault.getWriteoffAccountNumber())) { 091 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.WRITEOFF_ACCOUNT_NUMBER, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_WRITEOFF_ACCOUNT_NUMBER_REQUIRED); 092 return false; 093 } 094 095 return true; 096 } 097 098 /** 099 * This method returns true if payment chart of accounts code is provided and is valid 100 * 101 * @param doc 102 * @return 103 */ 104 protected boolean doesWriteoffChartOfAccountsCodeExist(OrganizationAccountingDefault organizationAccountingDefault) { 105 106 if (StringUtils.isEmpty(organizationAccountingDefault.getWriteoffChartOfAccountsCode())) { 107 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.WRITEOFF_CHART_OF_ACCOUNTS_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_WRITEOFF_CHART_OF_ACCOUNTS_CODE_REQUIRED); 108 return false; 109 } 110 111 return true; 112 } 113 114 /** 115 * This method returns true if payment financial object code is provided and is valid 116 * 117 * @param doc 118 * @return 119 */ 120 protected boolean doesWriteoffFinancialObjectCodeExist(OrganizationAccountingDefault organizationAccountingDefault) { 121 if (StringUtils.isEmpty(organizationAccountingDefault.getWriteoffFinancialObjectCode())) { 122 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.WRITEOFF_FINANCIAL_OBJECT_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_WRITEOFF_OBJECT_CODE_REQUIRED); 123 return false; 124 } 125 126 return true; 127 } 128 129 130 @Override 131 protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { 132 // always return true even if there are business rule failures. 133 processCustomRouteDocumentBusinessRules(document); 134 return true; 135 136 } 137 138 /** 139 * 140 * This method checks to see if the Org specified in this document has an Org Options record for it 141 * 142 * @return false if it does not have an OrgOptions record 143 */ 144 protected boolean checkOrgOptionsExists() { 145 return true; 146 } 147 148 /** 149 * 150 * This method checks that the Writeoff Object Code is of type Expense 151 * <ul> 152 * <li>EX</li> 153 * <li>EE</li> 154 * <li>ES</li> 155 * </ul> 156 * 157 * @return true if it is an expense object 158 */ 159 protected boolean isWriteOffObjectValidExpense(OrganizationAccountingDefault organizationAccountingDefault) { 160 161 boolean success = true; 162 Integer universityFiscalYear = organizationAccountingDefault.getUniversityFiscalYear(); 163 ObjectCode writeObject = organizationAccountingDefault.getWriteoffFinancialObject(); 164 165 if (ObjectUtils.isNotNull(universityFiscalYear) && ObjectUtils.isNotNull(writeObject)) { 166 167 success = objectTypeService.getBasicExpenseObjectTypes(universityFiscalYear).contains(writeObject.getFinancialObjectTypeCode()); 168 169 if (!success) { 170 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.WRITEOFF_FINANCIAL_OBJECT_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.WRITE_OFF_OBJECT_CODE_INVALID, writeObject.getCode()); 171 } 172 } 173 174 return success; 175 } 176 177 /** 178 * 179 * This method checks that the Late Charge Object Code is of type Income Using the ParameterService to find this valid value? 180 * <ul> 181 * <li>IN</li> 182 * <li>IC</li> 183 * <li>CH</li> 184 * </ul> 185 * 186 * @return true if it is an income object 187 */ 188 protected boolean isLateChargeObjectValidIncome(OrganizationAccountingDefault organizationAccountingDefault) { 189 boolean success = true; 190 Integer universityFiscalYear = organizationAccountingDefault.getUniversityFiscalYear(); 191 ObjectCode lateChargeObject = organizationAccountingDefault.getOrganizationLateChargeObject(); 192 193 if (ObjectUtils.isNotNull(universityFiscalYear) && ObjectUtils.isNotNull(lateChargeObject)) { 194 success = objectTypeService.getBasicIncomeObjectTypes(universityFiscalYear).contains(lateChargeObject.getFinancialObjectTypeCode()); 195 196 if (!success) { 197 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.LATE_CHARGE_OBJECT_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.LATE_CHARGE_OBJECT_CODE_INVALID, lateChargeObject.getCode()); 198 } 199 } 200 201 return success; 202 } 203 204 /** 205 * 206 * This method checks to see if the invoice object code is of type Income 207 * <ul> 208 * <li>IN</li> 209 * <li>IC</li> 210 * <li>CH</li> 211 * </ul> 212 * 213 * @return true if it is an income object 214 */ 215 protected boolean isDefaultInvoiceFinancialObjectValidIncome(OrganizationAccountingDefault organizationAccountingDefault) { 216 boolean success = true; 217 218 if (StringUtils.isNotEmpty(organizationAccountingDefault.getDefaultInvoiceFinancialObjectCode()) && 219 StringUtils.isEmpty(organizationAccountingDefault.getDefaultInvoiceChartOfAccountsCode())) { 220 221 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.INVOICE_CHART_OF_ACCOUNTS_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.DEFAULT_CHART_OF_ACCOUNTS_REQUIRED_IF_DEFAULT_OBJECT_CODE_EXISTS ); 222 success = false; 223 224 } else { 225 Integer universityFiscalYear = organizationAccountingDefault.getUniversityFiscalYear(); 226 227 228 ObjectCode defaultInvoiceFinancialObject = organizationAccountingDefault.getDefaultInvoiceFinancialObject(); 229 230 if (ObjectUtils.isNotNull(universityFiscalYear) && ObjectUtils.isNotNull(defaultInvoiceFinancialObject)) { 231 success = objectTypeService.getBasicIncomeObjectTypes(universityFiscalYear).contains(defaultInvoiceFinancialObject.getFinancialObjectTypeCode()); 232 233 if (!success) { 234 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.INVOICE_CHART_OF_ACCOUNTS_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.DEFAULT_INVOICE_FINANCIAL_OBJECT_CODE_INVALID, defaultInvoiceFinancialObject.getCode()); 235 } 236 } 237 } 238 239 return success; 240 } 241 242 /** 243 * This method returns true if payment account number is provided and is valid. 244 * 245 * @param doc 246 * @return 247 */ 248 protected boolean doesPaymentAccountNumberExist(OrganizationAccountingDefault organizationAccountingDefault) { 249 250 if (StringUtils.isEmpty(organizationAccountingDefault.getDefaultPaymentAccountNumber())) { 251 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.PAYMENT_ACCOUNT_NUMBER, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_PAYMENT_ACCOUNT_NUMBER_REQUIRED); 252 return false; 253 } 254 255 return true; 256 } 257 258 /** 259 * This method returns true if payment chart of accounts code is provided and is valid 260 * 261 * @param doc 262 * @return 263 */ 264 protected boolean doesPaymentChartOfAccountsCodeExist(OrganizationAccountingDefault organizationAccountingDefault) { 265 266 if (StringUtils.isEmpty(organizationAccountingDefault.getDefaultPaymentChartOfAccountsCode())) { 267 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.PAYMENT_CHART_OF_ACCOUNTS_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_PAYMENT_CHART_OF_ACCOUNTS_CODE_REQUIRED); 268 return false; 269 } 270 271 return true; 272 } 273 274 /** 275 * This method returns true if payment financial object code is provided and is valid 276 * 277 * @param doc 278 * @return 279 */ 280 protected boolean doesPaymentFinancialObjectCodeExist(OrganizationAccountingDefault organizationAccountingDefault) { 281 if (StringUtils.isEmpty(organizationAccountingDefault.getDefaultPaymentFinancialObjectCode())) { 282 putFieldError(ArPropertyConstants.OrganizationAccountingDefaultFields.PAYMENT_FINANCIAL_OBJECT_CODE, ArKeyConstants.OrganizationAccountingDefaultErrors.ERROR_PAYMENT_OBJECT_CODE_REQUIRED); 283 return false; 284 } 285 286 return true; 287 } 288 289 public ObjectTypeService getObjectTypeService() { 290 return objectTypeService; 291 } 292 293 public void setObjectTypeService(ObjectTypeService objectTypeService) { 294 this.objectTypeService = objectTypeService; 295 } 296 }