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.endow.document.validation.impl;
017
018 import java.math.BigDecimal;
019
020 import org.apache.commons.lang.StringUtils;
021 import org.kuali.kfs.module.endow.EndowConstants;
022 import org.kuali.kfs.module.endow.EndowKeyConstants;
023 import org.kuali.kfs.module.endow.EndowPropertyConstants;
024 import org.kuali.kfs.module.endow.businessobject.ClassCode;
025 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine;
026 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine;
027 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionSecurity;
028 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine;
029 import org.kuali.kfs.module.endow.businessobject.RegistrationCode;
030 import org.kuali.kfs.module.endow.businessobject.Security;
031 import org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocument;
032 import org.kuali.kfs.module.endow.document.EndowmentTransactionalDocument;
033 import org.kuali.kfs.module.endow.document.service.RegistrationCodeService;
034 import org.kuali.kfs.module.endow.document.service.SecurityService;
035 import org.kuali.kfs.sys.context.SpringContext;
036 import org.kuali.rice.kns.document.Document;
037 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
038 import org.kuali.rice.kns.rules.TransactionalDocumentRuleBase;
039 import org.kuali.rice.kns.util.GlobalVariables;
040 import org.kuali.rice.kns.util.KNSConstants;
041 import org.kuali.rice.kns.util.ObjectUtils;
042
043 public class EndowmentTransactionalDocumentBaseRule extends TransactionalDocumentRuleBase {
044 /**
045 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but
046 * applicable to the whole document).
047 *
048 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
049 */
050 protected void putGlobalError(String errorConstant) {
051 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) {
052 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant);
053 }
054 }
055
056 /**
057 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but
058 * applicable to the whole document).
059 *
060 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
061 * @param parameter - Replacement value for part of the error message.
062 */
063 protected void putGlobalError(String errorConstant, String parameter) {
064 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) {
065 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant, parameter);
066 }
067 }
068
069 /**
070 * This method is a convenience method to easily add a Document level error (ie, one not tied to a specific field, but
071 * applicable to the whole document).
072 *
073 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
074 * @param parameters - Array of replacement values for part of the error message.
075 */
076 protected void putGlobalError(String errorConstant, String[] parameters) {
077 if (!errorAlreadyExists(KNSConstants.DOCUMENT_ERRORS, errorConstant)) {
078 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(KNSConstants.DOCUMENT_ERRORS, errorConstant, parameters);
079 }
080 }
081
082 /**
083 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that
084 * the correct prefix is added to the property name so that it will display correctly on maintenance documents.
085 *
086 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in
087 * the UI.
088 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
089 */
090 protected void putFieldError(String propertyName, String errorConstant) {
091 if (!errorAlreadyExists(propertyName, errorConstant)) {
092 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant);
093 }
094 }
095
096 /**
097 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that
098 * the correct prefix is added to the property name so that it will display correctly on maintenance documents.
099 *
100 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in
101 * the UI.
102 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
103 * @param parameter - Single parameter value that can be used in the message so that you can display specific values to the
104 * user.
105 */
106 protected void putFieldError(String propertyName, String errorConstant, String parameter) {
107 if (!errorAlreadyExists(propertyName, errorConstant)) {
108 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameter);
109 }
110 }
111
112 /**
113 * This method is a convenience method to add a property-specific error to the global errors list. This method makes sure that
114 * the correct prefix is added to the property name so that it will display correctly on maintenance documents.
115 *
116 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in
117 * the UI.
118 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
119 * @param parameters - Array of strings holding values that can be used in the message so that you can display specific values
120 * to the user.
121 */
122 protected void putFieldError(String propertyName, String errorConstant, String[] parameters) {
123 if (!errorAlreadyExists(propertyName, errorConstant)) {
124 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameters);
125 }
126 }
127
128 /**
129 * This method is a convenience method to add a property-specific document error to the global errors list. This method makes
130 * sure that the correct prefix is added to the property name so that it will display correctly on maintenance documents.
131 *
132 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in
133 * the UI.
134 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
135 * @param parameter - Single parameter value that can be used in the message so that you can display specific values to the
136 * user.
137 */
138 protected void putDocumentError(String propertyName, String errorConstant, String parameter) {
139 if (!errorAlreadyExists(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant)) {
140 GlobalVariables.getMessageMap().putError(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant, parameter);
141 }
142 }
143
144 /**
145 * This method is a convenience method to add a property-specific document error to the global errors list. This method makes
146 * sure that the correct prefix is added to the property name so that it will display correctly on maintenance documents.
147 *
148 * @param propertyName - Property name of the element that is associated with the error. Used to mark the field as errored in
149 * the UI.
150 * @param errorConstant - Error Constant that can be mapped to a resource for the actual text message.
151 * @param parameters - Array of String parameters that can be used in the message so that you can display specific values to the
152 * user.
153 */
154 protected void putDocumentError(String propertyName, String errorConstant, String[] parameters) {
155 GlobalVariables.getMessageMap().putError(MaintenanceDocumentRuleBase.DOCUMENT_ERROR_PREFIX + propertyName, errorConstant, parameters);
156 }
157
158 /**
159 * Convenience method to determine whether the field already has the message indicated. This is useful if you want to suppress
160 * duplicate error messages on the same field.
161 *
162 * @param propertyName - propertyName you want to test on
163 * @param errorConstant - errorConstant you want to test
164 * @return returns True if the propertyName indicated already has the errorConstant indicated, false otherwise
165 */
166 protected boolean errorAlreadyExists(String propertyName, String errorConstant) {
167
168 if (GlobalVariables.getMessageMap().fieldHasMessage(propertyName, errorConstant)) {
169 return true;
170 }
171 else {
172 return false;
173 }
174 }
175
176 /**
177 * This method specifically doesn't put any prefixes before the error so that the developer can do things specific to the
178 * globals errors (like newDelegateChangeDocument errors)
179 *
180 * @param propertyName
181 * @param errorConstant
182 */
183 protected void putGlobalsError(String propertyName, String errorConstant) {
184 if (!errorAlreadyExists(propertyName, errorConstant)) {
185 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant);
186 }
187 }
188
189 /**
190 * This method specifically doesn't put any prefixes before the error so that the developer can do things specific to the
191 * globals errors (like newDelegateChangeDocument errors)
192 *
193 * @param propertyName
194 * @param errorConstant
195 * @param parameter
196 */
197 protected void putGlobalsError(String propertyName, String errorConstant, String parameter) {
198 if (!errorAlreadyExists(propertyName, errorConstant)) {
199 GlobalVariables.getMessageMap().putErrorWithoutFullErrorPath(propertyName, errorConstant, parameter);
200 }
201 }
202
203
204 /**
205 * This method obtains the Prefix for displaying errors on the UI for Source & Target lines.
206 *
207 * @param document
208 * @param isSource
209 * @return
210 */
211 protected String getEndowmentTransactionSecurityPrefix(EndowmentTransactionalDocument document, boolean isSource) {
212 if (isSource)
213 return EndowPropertyConstants.TRANSACTION_SOURCE_SECURITY_PREFIX;
214 else
215 return EndowPropertyConstants.TRANSACTION_TARGET_SECURITY_PREFIX;
216 }
217
218 /**
219 * This method returns the Security line associated with a Transaction.
220 *
221 * @param document
222 * @param isSource
223 * @return
224 */
225 protected EndowmentTransactionSecurity getEndowmentTransactionSecurity(EndowmentTransactionalDocument document, boolean isSource) {
226 if (isSource)
227 return ((EndowmentSecurityDetailsDocument) document).getSourceTransactionSecurity();
228 else
229 return ((EndowmentSecurityDetailsDocument) document).getTargetTransactionSecurity();
230 }
231
232 /**
233 * This method validate the Security code.
234 *
235 * @param tranSecurity
236 * @return
237 */
238 protected boolean isSecurityCodeEmpty(EndowmentTransactionalDocument document, boolean isSource) {
239 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
240
241 if (StringUtils.isEmpty(tranSecurity.getSecurityID())) {
242 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_REQUIRED);
243 return true;
244 }
245
246 return false;
247 }
248
249 /**
250 * This method validates the Registration code.
251 *
252 * @param tranSecurity
253 * @return
254 */
255 protected boolean isRegistrationCodeEmpty(EndowmentTransactionalDocument document, boolean isSource) {
256 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
257
258 if (StringUtils.isEmpty(tranSecurity.getRegistrationCode())) {
259 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_REQUIRED);
260 return true;
261 }
262
263 return false;
264 }
265
266
267 /**
268 * This method validates the Security code by trying to create a Security object from the code.
269 *
270 * @param document
271 * @param isSource
272 * @return
273 */
274 protected boolean validateSecurityCode(EndowmentSecurityDetailsDocument document, boolean isSource) {
275 boolean success = true;
276 String prefix = null;
277
278 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
279
280 Security security = (Security) SpringContext.getBean(SecurityService.class).getByPrimaryKey(tranSecurity.getSecurityID());
281 tranSecurity.setSecurity(security);
282 if (null == security) {
283 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_INVALID);
284 success = false;
285 }
286
287 return success;
288 }
289
290 /**
291 * This method validates the Registration code by trying to create a RegistrationCode object from the code.
292 *
293 * @param document
294 * @param isSource
295 * @return
296 */
297 protected boolean validateRegistrationCode(EndowmentSecurityDetailsDocument document, boolean isSource) {
298 boolean success = true;
299 String prefix = null;
300
301 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
302
303 RegistrationCode registrationCode = (RegistrationCode) SpringContext.getBean(RegistrationCodeService.class).getByPrimaryKey(tranSecurity.getRegistrationCode());
304 tranSecurity.setRegistrationCodeObj(registrationCode);
305 if (null == registrationCode) {
306 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_INVALID);
307 success = false;
308 }
309
310 return success;
311 }
312
313 /**
314 * This method checks if the Security is Active.
315 *
316 * @param document
317 * @param isSource
318 * @return
319 */
320 protected boolean isSecurityActive(EndowmentSecurityDetailsDocument document, boolean isSource) {
321 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
322
323 if (tranSecurity.getSecurity().isActive())
324 return true;
325 else {
326 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_INACTIVE);
327 return false;
328 }
329 }
330
331 /**
332 * Validates that the security class code type is not Liability.
333 *
334 * @param endowmentTransactionSecurity
335 * @return true is valid, false otherwise
336 */
337 protected boolean validateSecurityClassCodeTypeNotLiability(EndowmentSecurityDetailsDocument document, boolean isSource) {
338 boolean isValid = true;
339 EndowmentTransactionSecurity endowmentTransactionSecurity = getEndowmentTransactionSecurity(document, isSource);
340 Security security = endowmentTransactionSecurity.getSecurity();
341 if (ObjectUtils.isNotNull(security)) {
342 ClassCode classCode = security.getClassCode();
343 if (ObjectUtils.isNotNull(classCode)) {
344 String classCodeType = classCode.getClassCodeType();
345 if (EndowConstants.ClassCodeTypes.LIABILITY.equalsIgnoreCase(classCodeType)) {
346 isValid = false;
347
348 if (isSource) {
349 putFieldError(EndowPropertyConstants.TRANSACTION_SOURCE_SECURITY_PREFIX + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_NOT_LIABILITY);
350 }
351 else {
352 putFieldError(EndowPropertyConstants.TRANSACTION_TARGET_SECURITY_PREFIX + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_NOT_LIABILITY);
353 }
354 }
355 }
356 }
357
358 return isValid;
359
360 }
361
362 /**
363 * This method checks if the Registration Code is Active.
364 *
365 * @param document
366 * @param isSource
367 * @return
368 */
369 protected boolean isRegistrationCodeActive(EndowmentSecurityDetailsDocument document, boolean isSource) {
370 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
371
372 if (tranSecurity.getRegistrationCodeObj().isActive())
373 return true;
374 else {
375 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_REGISTRATION_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_REGISTRATION_CODE_INACTIVE);
376 return false;
377 }
378 }
379
380 /**
381 * This method validates the Security Class Type Code.
382 *
383 * @param document
384 * @param isSource
385 * @param classCodeType
386 * @return
387 */
388 protected boolean validateSecurityClassTypeCode(EndowmentSecurityDetailsDocument document, boolean isSource, String classCodeType) {
389 EndowmentTransactionSecurity tranSecurity = getEndowmentTransactionSecurity(document, isSource);
390 tranSecurity.getSecurity().refreshNonUpdateableReferences();
391
392 if (tranSecurity.getSecurity().getClassCode().getClassCodeType().equalsIgnoreCase(classCodeType))
393 return true;
394 else {
395 putFieldError(getEndowmentTransactionSecurityPrefix(document, isSource) + EndowPropertyConstants.TRANSACTION_SECURITY_ID, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_SECURITY_CLASS_CODE_MISMATCH);
396 return false;
397 }
398 }
399
400 /**
401 * @see org.kuali.rice.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.Document)
402 */
403 @Override
404 protected boolean processCustomRouteDocumentBusinessRules(Document document) {
405 boolean isValid = super.processCustomSaveDocumentBusinessRules(document);
406 isValid &= !GlobalVariables.getMessageMap().hasErrors();
407
408 EndowmentTransactionalDocument endowmentTransactionalDocument = null;
409
410 if (isValid) {
411 endowmentTransactionalDocument = (EndowmentTransactionalDocument) document;
412
413 // Validates Tx Sub Type Code
414 isValid &= isSubTypeEmpty(endowmentTransactionalDocument);
415 }
416
417 return GlobalVariables.getMessageMap().getErrorCount() == 0;
418 }
419
420 /**
421 * This method validates the Sub Type Code.
422 *
423 * @param document
424 * @return
425 */
426 protected boolean isSubTypeEmpty(EndowmentTransactionalDocument document) {
427 boolean success = true;
428
429 if (StringUtils.isEmpty(document.getTransactionSubTypeCode())) {
430 putFieldError(EndowConstants.TRANSACTION_DETAILS_ERRORS, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_DETAILS_SUB_TYPE_REQUIRED);
431 success = false;
432 }
433
434 return success;
435 }
436
437 }