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 }