001/* 002 * The Kuali Financial System, a comprehensive financial management system for higher education. 003 * 004 * Copyright 2005-2014 The Kuali Foundation 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Affero General Public License as 008 * published by the Free Software Foundation, either version 3 of the 009 * License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU Affero General Public License for more details. 015 * 016 * You should have received a copy of the GNU Affero General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.kuali.kfs.fp.document.validation.impl; 020 021import static org.kuali.kfs.sys.KFSConstants.GL_CREDIT_CODE; 022import static org.kuali.kfs.sys.KFSConstants.GL_DEBIT_CODE; 023import static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapContains; 024import static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapEmpty; 025import static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapNotContains; 026import static org.kuali.kfs.sys.KualiTestAssertionUtils.assertGlobalMessageMapSize; 027import static org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleTestUtils.testAddAccountingLineRule_ProcessAddAccountingLineBusinessRules; 028import static org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleTestUtils.testGenerateGeneralLedgerPendingEntriesRule_ProcessGenerateGeneralLedgerPendingEntries; 029import static org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleTestUtils.testRouteDocumentRule_processRouteDocument; 030import static org.kuali.kfs.sys.document.validation.impl.AccountingDocumentRuleTestUtils.testSaveDocumentRule_ProcessSaveDocument; 031import static org.kuali.kfs.sys.fixture.AccountingLineFixture.EXPENSE_LINE; 032import static org.kuali.kfs.sys.fixture.AccountingLineFixture.EXPENSE_LINE2; 033import static org.kuali.kfs.sys.fixture.AccountingLineFixture.EXTERNAL_ENCUMBRANCE_LINE; 034import static org.kuali.kfs.sys.fixture.AccountingLineFixture.LINE11; 035import static org.kuali.kfs.sys.fixture.AccountingLineFixture.LINE8; 036import static org.kuali.kfs.sys.fixture.AccountingLineFixture.LINE9; 037import static org.kuali.kfs.sys.fixture.AccountingLineFixture.SOURCE_LINE; 038import static org.kuali.kfs.sys.fixture.GeneralLedgerPendingEntryFixture.EXPECTED_JV_EXPLICIT_SOURCE_PENDING_ENTRY; 039import static org.kuali.kfs.sys.fixture.GeneralLedgerPendingEntryFixture.EXPECTED_JV_EXPLICIT_SOURCE_PENDING_ENTRY_FOR_EXPENSE; 040import static org.kuali.kfs.sys.fixture.UserNameFixture.dfogle; 041 042import java.util.ArrayList; 043import java.util.List; 044 045import org.apache.commons.lang.StringUtils; 046import org.apache.log4j.Logger; 047import org.kuali.kfs.fp.businessobject.VoucherSourceAccountingLine; 048import org.kuali.kfs.fp.document.JournalVoucherDocument; 049import org.kuali.kfs.sys.ConfigureContext; 050import org.kuali.kfs.sys.DocumentTestUtils; 051import org.kuali.kfs.sys.KFSConstants; 052import org.kuali.kfs.sys.KFSKeyConstants; 053import org.kuali.kfs.sys.KFSPropertyConstants; 054import org.kuali.kfs.sys.businessobject.AccountingLine; 055import org.kuali.kfs.sys.businessobject.SourceAccountingLine; 056import org.kuali.kfs.sys.businessobject.TargetAccountingLine; 057import org.kuali.kfs.sys.context.KualiTestBase; 058import org.kuali.kfs.sys.context.SpringContext; 059import org.kuali.kfs.sys.document.AccountingDocument; 060import org.kuali.kfs.sys.document.validation.Validation; 061import org.kuali.kfs.sys.document.validation.event.AddAccountingLineEvent; 062import org.kuali.kfs.sys.document.validation.impl.AccountingLineValueAllowedValidation; 063import org.kuali.kfs.sys.document.validation.impl.AccountingLineValuesAllowedValidationHutch; 064import org.kuali.kfs.sys.service.IsDebitTestUtils; 065import org.kuali.rice.kns.service.DataDictionaryService; 066import org.kuali.rice.krad.service.DocumentService; 067import org.kuali.rice.krad.service.KualiRuleService; 068import org.kuali.rice.krad.util.GlobalVariables; 069 070@ConfigureContext(session = dfogle) 071public class JournalVoucherDocumentRuleTest extends KualiTestBase { 072 private static final Logger LOG = Logger.getLogger(JournalVoucherDocumentRuleTest.class); 073 074 public static final Class<JournalVoucherDocument> DOCUMENT_CLASS = JournalVoucherDocument.class; 075 076 public void testProcessAddAccountingLineBusinessRules_irrelevantReferenceOriginCode() throws Exception { 077 testProcessAddAccountingLineBusinessRules(EXPENSE_LINE2.createVoucherSourceAccountingLine(), null, null); 078 } 079 080 public void testProcessAddAccountingLineBusinessRules_emptyReferenceOriginCode() throws Exception { 081 AccountingLine line = EXTERNAL_ENCUMBRANCE_LINE.createVoucherSourceAccountingLine(); 082 line.setEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD); 083 line.setReferenceOriginCode(""); 084 testProcessAddAccountingLineBusinessRules(line, KFSPropertyConstants.REFERENCE_ORIGIN_CODE, KFSKeyConstants.ERROR_REQUIRED); 085 } 086 087 public void testProcessAddAccountingLineBusinessRules_emptyReferences() throws Exception { 088 AccountingLine line = EXTERNAL_ENCUMBRANCE_LINE.createVoucherSourceAccountingLine(); 089 line.setEncumbranceUpdateCode(KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD); 090 line.setReferenceOriginCode(""); 091 line.setReferenceNumber(""); 092 line.setReferenceTypeCode(""); 093 testProcessAddAccountingLineBusinessRules(line, KFSPropertyConstants.REFERENCE_ORIGIN_CODE, KFSKeyConstants.ERROR_REQUIRED); 094 assertGlobalMessageMapContains(KFSKeyConstants.ERROR_REQUIRED+"."+KFSPropertyConstants.REFERENCE_NUMBER, KFSKeyConstants.ERROR_REQUIRED); 095 assertGlobalMessageMapContains(KFSKeyConstants.ERROR_REQUIRED+"."+KFSPropertyConstants.REFERENCE_TYPE_CODE, KFSKeyConstants.ERROR_REQUIRED); 096 } 097 098 public void testProcessAddAccountingLineBusinessRules_validReferences() throws Exception { 099 testProcessAddAccountingLineBusinessRules(EXTERNAL_ENCUMBRANCE_LINE.createVoucherSourceAccountingLine(), null, null); 100 } 101 102 public void testProcessAddAccountingLineBusinessRules_invalidReferenceOriginCode() throws Exception { 103 AccountingLine line = EXTERNAL_ENCUMBRANCE_LINE.createVoucherSourceAccountingLine(); 104 line.setReferenceOriginCode("42"); 105 testProcessAddAccountingLineBusinessRules(line, KFSPropertyConstants.REFERENCE_ORIGIN_CODE, KFSKeyConstants.ERROR_EXISTING_WITH_IDENTIFYING_ACCOUNTING_LINE); 106 } 107 108 public void testProcessAddAccountingLineBusinessRules_invalidReferenceTypeCode() throws Exception { 109 AccountingLine line = EXTERNAL_ENCUMBRANCE_LINE.createVoucherSourceAccountingLine(); 110 line.setReferenceTypeCode("42"); 111 testProcessAddAccountingLineBusinessRules(line, KFSPropertyConstants.REFERENCE_TYPE_CODE, KFSKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_NON_ACTIVE_CURRENT_ACCOUNTING_DOCUMENT_TYPE); 112 assertGlobalMessageMapNotContains(line.toString(), KFSPropertyConstants.REFERENCE_TYPE_CODE, KFSKeyConstants.ERROR_REQUIRED); 113 assertGlobalMessageMapSize(line.toString(), 1); 114 } 115 116 private void testProcessAddAccountingLineBusinessRules(AccountingLine line, String expectedErrorFieldName, String expectedErrorKey) throws Exception { 117 line.refresh(); 118 assertGlobalMessageMapEmpty(); 119 boolean wasValid = SpringContext.getBean(KualiRuleService.class).applyRules(new AddAccountingLineEvent(expectedErrorKey, createDocumentUnbalanced(), line)); 120 if (LOG.isDebugEnabled()) { 121 LOG.debug(StringUtils.join(GlobalVariables.getMessageMap().getAllPropertiesWithErrors(),", ")+"; "+StringUtils.join(GlobalVariables.getMessageMap().getPropertiesWithErrors(), ", ")); 122 } 123 if (expectedErrorFieldName == null) { 124 assertGlobalMessageMapEmpty(line.toString()); // fail printing error map for debugging before failing on simple result 125 assertEquals("wasValid " + line, true, wasValid); 126 } 127 else { 128 assertGlobalMessageMapContains(line.toString(), expectedErrorKey+"."+expectedErrorFieldName, expectedErrorKey); 129 assertEquals("wasValid " + line, false, wasValid); 130 } 131 } 132 133 134 public void testIsDebit_debitCode() throws Exception { 135 AccountingDocument accountingDocument = IsDebitTestUtils.getDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 136 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 137 accountingLine.setDebitCreditCode(GL_DEBIT_CODE); 138 139 assertTrue(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 140 } 141 142 public void testIsDebit_creditCode() throws Exception { 143 AccountingDocument accountingDocument = IsDebitTestUtils.getDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 144 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 145 accountingLine.setDebitCreditCode(GL_CREDIT_CODE); 146 147 assertFalse(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 148 } 149 150 public void testIsDebit_blankValue() throws Exception { 151 AccountingDocument accountingDocument = IsDebitTestUtils.getDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 152 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 153 accountingLine.setDebitCreditCode(" "); 154 155 assertTrue(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 156 157 } 158 159 public void testIsDebit_errorCorrection_crediCode() throws Exception { 160 AccountingDocument accountingDocument = IsDebitTestUtils.getErrorCorrectionDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 161 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 162 accountingLine.setDebitCreditCode(GL_CREDIT_CODE); 163 164 assertFalse(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 165 } 166 167 public void testIsDebit_errorCorrection_debitCode() throws Exception { 168 AccountingDocument accountingDocument = IsDebitTestUtils.getErrorCorrectionDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 169 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 170 accountingLine.setDebitCreditCode(GL_DEBIT_CODE); 171 172 assertTrue(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 173 } 174 175 public void testIsDebit_errorCorrection_blankValue() throws Exception { 176 AccountingDocument accountingDocument = IsDebitTestUtils.getErrorCorrectionDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 177 AccountingLine accountingLine = (AccountingLine) accountingDocument.getSourceAccountingLineClass().newInstance(); 178 accountingLine.setDebitCreditCode(" "); 179 180 assertTrue(IsDebitTestUtils.isDebit(SpringContext.getBean(DataDictionaryService.class), SpringContext.getBean(DataDictionaryService.class), accountingDocument, accountingLine)); 181 182 } 183 184 public void testIsObjectTypeAllowed_InvalidObjectType() throws Exception { 185 testAddAccountingLineRule_IsObjectTypeAllowed(getInvalidObjectTypeSourceLine(), false); 186 } 187 188 public void testIsObjectTypeAllowed_Valid() throws Exception { 189 testAddAccountingLineRule_IsObjectTypeAllowed(getValidObjectTypeSourceLine(), true); 190 } 191 192 public void testIsObjectCodeAllowed_Valid() throws Exception { 193 testAddAccountingLineRule_IsObjectCodeAllowed(getValidObjectCodeSourceLine(), true); 194 } 195 196 public void testAddAccountingLine_Valid() throws Exception { 197 AccountingDocument doc = createDocumentWithValidObjectSubType(); 198 testAddAccountingLineRule_ProcessAddAccountingLineBusinessRules(doc, true); 199 } 200 201 public void testIsObjectSubTypeAllowed_ValidSubType() throws Exception { 202 boolean result = true; 203 JournalVoucherDocument document = buildDocument(); 204 AccountingLineValueAllowedValidation validation = (AccountingLineValueAllowedValidation)SpringContext.getBean(Validation.class,"AccountingDocument-IsObjectSubTypeAllowed-DefaultValidation"); 205 if (validation == null) { 206 throw new IllegalStateException("No object sub type value allowed validation"); 207 } 208 validation.setAccountingDocumentForValidation(document); 209 validation.setAccountingLineForValidation(getValidObjectSubTypeTargetLine()); 210 result = validation.validate(null); 211 assertEquals(true, result); 212 } 213 214 public void testProcessSaveDocument_Valid() throws Exception { 215 testSaveDocumentRule_ProcessSaveDocument(buildDocument(), true); 216 } 217 218 public void testProcessSaveDocument_Invalid() throws Exception { 219 testSaveDocumentRule_ProcessSaveDocument(createDocumentInvalidForSave(), false); 220 } 221 222 public void testProcessSaveDocument_Invalid1() throws Exception { 223 try { 224 testSaveDocumentRule_ProcessSaveDocument(null, false); 225 fail("validated null doc"); 226 } 227 catch (Exception e) { 228 assertTrue(true); 229 } 230 } 231 232 public void testProcessRouteDocument_Valid() throws Exception { 233 testRouteDocumentRule_processRouteDocument(createDocumentValidForRouting(), true); 234 } 235 236 public void testProcessRouteDocument_Invalid() throws Exception { 237 testRouteDocumentRule_processRouteDocument(buildDocument(), false); 238 } 239 240 public void testProcessRouteDocument_NoAccountingLines() throws Exception { 241 testRouteDocumentRule_processRouteDocument(buildDocument(), false); 242 } 243 244 public void testProcessRouteDocument_Unbalanced() throws Exception { 245 testRouteDocumentRule_processRouteDocument(createDocumentUnbalanced(), false); 246 } 247 248 public void testProcessGenerateGeneralLedgerPendingEntries_validSourceExpense() throws Exception { 249 testGenerateGeneralLedgerPendingEntriesRule_ProcessGenerateGeneralLedgerPendingEntries(buildDocument(), EXPENSE_LINE.createVoucherSourceAccountingLine(), EXPECTED_JV_EXPLICIT_SOURCE_PENDING_ENTRY_FOR_EXPENSE, null); 250 } 251 252 public void testProcessGenerateGeneralLedgerPendingEntries_validSourceAsset() throws Exception { 253 testGenerateGeneralLedgerPendingEntriesRule_ProcessGenerateGeneralLedgerPendingEntries(buildDocument(), getAssetSourceLine(), EXPECTED_JV_EXPLICIT_SOURCE_PENDING_ENTRY, null); 254 } 255 256 private JournalVoucherDocument createDocumentValidForRouting() throws Exception { 257 return createDocumentWithValidObjectSubType(); 258 } 259 260 private JournalVoucherDocument createDocumentInvalidForSave() throws Exception { 261 return createDocumentInvalidDescription(); 262 } 263 264 private JournalVoucherDocument buildDocument() throws Exception { 265 JournalVoucherDocument retval = DocumentTestUtils.createDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 266 retval.setBalanceTypeCode(KFSConstants.BALANCE_TYPE_ACTUAL); 267 return retval; 268 } 269 270 private JournalVoucherDocument createDocumentWithValidObjectSubType() throws Exception { 271 JournalVoucherDocument retval = buildDocument(); 272 retval.setSourceAccountingLines(getValidObjectSubTypeSourceLines()); 273 return retval; 274 } 275 276 private JournalVoucherDocument createDocumentInvalidDescription() throws Exception { 277 JournalVoucherDocument retval = DocumentTestUtils.createDocument(SpringContext.getBean(DocumentService.class), JournalVoucherDocument.class); 278 279 retval.getDocumentHeader().setDocumentDescription(new String()); 280 return retval; 281 } 282 283 private TargetAccountingLine getValidObjectSubTypeTargetLine() throws Exception { 284 return LINE11.createTargetAccountingLine(); 285 } 286 287 private List<VoucherSourceAccountingLine> getValidObjectSubTypeSourceLines() throws Exception { 288 List<VoucherSourceAccountingLine> retval = new ArrayList<VoucherSourceAccountingLine>(); 289 retval.add(LINE11.createVoucherSourceAccountingLine()); 290 return retval; 291 } 292 293 private List<TargetAccountingLine> getValidObjectSubTypeTargetLines() throws Exception { 294 List<TargetAccountingLine> retval = new ArrayList<TargetAccountingLine>(); 295 retval.add(LINE11.createTargetAccountingLine()); 296 retval.add(LINE11.createTargetAccountingLine()); 297 return retval; 298 } 299 300 private SourceAccountingLine getValidObjectTypeSourceLine() throws Exception { 301 return LINE8.createVoucherSourceAccountingLine(); 302 } 303 304 private SourceAccountingLine getInvalidObjectTypeSourceLine() throws Exception { 305 VoucherSourceAccountingLine retval = LINE9.createVoucherSourceAccountingLine(); 306 retval.setObjectTypeCode(new String()); 307 return retval; 308 } 309 310 private SourceAccountingLine getValidObjectCodeSourceLine() throws Exception { 311 return LINE11.createVoucherSourceAccountingLine(); 312 } 313 314 private SourceAccountingLine getAssetSourceLine() throws Exception { 315 return SOURCE_LINE.createVoucherSourceAccountingLine(); 316 } 317 318 private JournalVoucherDocument createDocumentUnbalanced() throws Exception { 319 return buildDocument(); 320 } 321 322 private void testAddAccountingLineRule_IsObjectTypeAllowed(AccountingLine accountingLine, boolean expected) throws Exception { 323 boolean result = true; 324 JournalVoucherDocument document = buildDocument(); 325 AccountingLineValuesAllowedValidationHutch hutch = (AccountingLineValuesAllowedValidationHutch)SpringContext.getBean(Validation.class,"JournalVoucher-accountingLineValuesAllowedValidation"); 326 AccountingLineValueAllowedValidation validation = (AccountingLineValueAllowedValidation)hutch.getObjectTypeAllowedValidation(); 327 if (validation != null) { 328 validation.setAccountingDocumentForValidation(document); 329 validation.setAccountingLineForValidation(accountingLine); 330 result = validation.validate(null); 331 } else { 332 result = true; 333 } 334 assertEquals(expected, result); 335 } 336 337 private boolean testAddAccountingLineRule_IsObjectCodeAllowed(AccountingLine accountingLine, boolean expected) throws Exception { 338 boolean result = true; 339 JournalVoucherDocument document = buildDocument(); 340 AccountingLineValuesAllowedValidationHutch hutch = (AccountingLineValuesAllowedValidationHutch)SpringContext.getBean(Validation.class,"JournalVoucher-accountingLineValuesAllowedValidation"); 341 AccountingLineValueAllowedValidation validation = (AccountingLineValueAllowedValidation)hutch.getObjectCodeAllowedValidation(); 342 if (validation != null) { 343 validation.setAccountingDocumentForValidation(document); 344 validation.setAccountingLineForValidation(accountingLine); 345 result = validation.validate(null); 346 } else { 347 result = true; 348 } 349 350 return result; 351 } 352} 353