001 /** 002 * Copyright 2004-2014 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.hr.lm.leaveCalendar.validation; 017 018 import java.math.BigDecimal; 019 import java.util.ArrayList; 020 import java.util.List; 021 import java.util.Map; 022 import java.util.Set; 023 024 import org.joda.time.DateTime; 025 import org.joda.time.LocalDate; 026 import org.junit.After; 027 import org.junit.Assert; 028 import org.junit.Before; 029 import org.junit.Test; 030 import org.kuali.hr.KPMEWebTestCase; 031 import org.kuali.kpme.core.FunctionalTest; 032 import org.kuali.kpme.tklm.leave.block.LeaveBlock; 033 import org.kuali.kpme.tklm.leave.calendar.validation.LeaveCalendarValidationUtil; 034 import org.kuali.kpme.tklm.leave.summary.LeaveSummary; 035 import org.kuali.kpme.tklm.leave.summary.LeaveSummaryRow; 036 037 @FunctionalTest 038 public class LeaveCalendarValidationServiceTest extends KPMEWebTestCase { 039 040 @Before 041 public void setUp() throws Exception { 042 super.setUp(); 043 } 044 045 @After 046 public void tearDown() throws Exception { 047 super.tearDown(); 048 } 049 050 @Test 051 public void testValidateAvailableLeaveBalance() throws Exception { 052 LeaveSummary ls = new LeaveSummary(); 053 LeaveSummaryRow lsr = new LeaveSummaryRow(); 054 lsr.setAccrualCategory("testAC"); 055 lsr.setAccrualCategoryId("5000"); 056 lsr.setLeaveBalance(new BigDecimal(5)); 057 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 058 lsrList.add(lsr); 059 ls.setLeaveSummaryRows(lsrList); 060 061 // adding brand new leave blocks 062 // earn code "EC" does not allow negative accrual balance 063 List<String> errors = LeaveCalendarValidationUtil.validateAvailableLeaveBalanceForUsage("EC", "02/15/2012", "02/15/2012", new BigDecimal(8), null); 064 Assert.assertEquals("Incorrect number of error messages", 1, errors.size()); 065 String anError = errors.get(0); 066 Assert.assertTrue("error message not correct" , anError.equals("Requested leave amount 8 is greater than available leave balance 0.00")); 067 068 // earn code "EC1" allows negative accrual balance 069 errors = LeaveCalendarValidationUtil.validateAvailableLeaveBalanceForUsage("EC1", "02/15/2012", "02/15/2012", new BigDecimal(8), null); 070 Assert.assertTrue("There should NOT be error message(s)" , errors.isEmpty()); 071 072 //updating an existing leave block 073 LeaveBlock aLeaveBlock = new LeaveBlock(); 074 aLeaveBlock.setEarnCode("EC"); 075 aLeaveBlock.setLeaveAmount(new BigDecimal(-10)); 076 077 errors = LeaveCalendarValidationUtil.validateAvailableLeaveBalanceForUsage("EC", "02/15/2012", "02/15/2012", new BigDecimal(3), aLeaveBlock); 078 Assert.assertTrue("There should NOT be error message(s)" , errors.isEmpty()); 079 080 aLeaveBlock.setLeaveAmount(new BigDecimal(-2)); 081 errors = LeaveCalendarValidationUtil.validateAvailableLeaveBalanceForUsage("EC", "02/15/2012", "02/15/2012", new BigDecimal(10), aLeaveBlock); 082 anError = errors.get(0); 083 Assert.assertTrue("error message not correct" , anError.equals("Requested leave amount 10 is greater than available leave balance 2.00")); 084 } 085 086 @Test 087 public void testValidateLeaveSpanOverMaxUsageRule() throws Exception { 088 LeaveSummary ls = new LeaveSummary(); 089 LeaveSummaryRow lsr = new LeaveSummaryRow(); 090 lsr.setAccrualCategory("testAC"); 091 lsr.setUsageLimit(new BigDecimal(39)); 092 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 093 lsrList.add(lsr); 094 ls.setLeaveSummaryRows(lsrList); 095 // adding brand new leave blocks 096 List<String> errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/19/2012", new BigDecimal(8), null); 097 Assert.assertEquals("There should be 1 error message" , 1, errors.size()); 098 String anError = errors.get(0); 099 Assert.assertTrue("error message not correct" , anError.equals("This leave request would exceed the usage limit for " + lsr.getAccrualCategory())); 100 } 101 102 @Test 103 public void testValidateLeaveSpanUnderMaxUsageRule() throws Exception { 104 LeaveSummary ls = new LeaveSummary(); 105 LeaveSummaryRow lsr = new LeaveSummaryRow(); 106 lsr.setAccrualCategory("testAC"); 107 lsr.setUsageLimit(new BigDecimal(41)); 108 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 109 lsrList.add(lsr); 110 ls.setLeaveSummaryRows(lsrList); 111 // adding brand new leave blocks 112 List<String> errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/19/2012", new BigDecimal(8), null); 113 Assert.assertEquals("There should be no error message" , 0, errors.size()); 114 } 115 116 @Test 117 public void testValidateLeaveSpanEqualMaxUsageRule() throws Exception { 118 LeaveSummary ls = new LeaveSummary(); 119 LeaveSummaryRow lsr = new LeaveSummaryRow(); 120 lsr.setAccrualCategory("testAC"); 121 lsr.setUsageLimit(new BigDecimal(40)); 122 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 123 lsrList.add(lsr); 124 ls.setLeaveSummaryRows(lsrList); 125 // adding brand new leave blocks 126 List<String> errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/19/2012", new BigDecimal(8), null); 127 Assert.assertEquals("There should be no error message" , 0, errors.size()); 128 } 129 130 @Test 131 public void testValidateLeaveNonSpanOverMaxUsageRule() throws Exception { 132 LeaveSummary ls = new LeaveSummary(); 133 LeaveSummaryRow lsr = new LeaveSummaryRow(); 134 lsr.setAccrualCategory("testAC"); 135 lsr.setUsageLimit(new BigDecimal(5)); 136 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 137 lsrList.add(lsr); 138 ls.setLeaveSummaryRows(lsrList); 139 // adding brand new leave blocks 140 List<String> errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(8), null); 141 Assert.assertEquals("There should be 1 error message" , 1, errors.size()); 142 String anError = errors.get(0); 143 Assert.assertTrue("error message not correct" , anError.equals("This leave request would exceed the usage limit for " + lsr.getAccrualCategory())); 144 } 145 146 @Test 147 public void testValidateLeaveNonSpanEqualsMaxUsageRule() throws Exception { 148 LeaveSummary ls = new LeaveSummary(); 149 LeaveSummaryRow lsr = new LeaveSummaryRow(); 150 lsr.setAccrualCategory("testAC"); 151 lsr.setUsageLimit(new BigDecimal(5)); 152 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 153 lsrList.add(lsr); 154 ls.setLeaveSummaryRows(lsrList); 155 156 List<String> errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(5), null); 157 Assert.assertEquals("There should be no error message" , 0, errors.size()); 158 159 } 160 161 @Test 162 public void testValidateEditLeaveBlockMaxUsageRuleCaseOne() throws Exception { 163 //Leave Amount increases, Earn Code unchanged 164 LeaveSummary ls = new LeaveSummary(); 165 LeaveSummaryRow lsr = new LeaveSummaryRow(); 166 lsr.setAccrualCategory("testAC"); 167 lsr.setUsageLimit(new BigDecimal(50)); 168 lsr.setPendingLeaveRequests(new BigDecimal(25)); 169 lsr.setYtdApprovedUsage(new BigDecimal(15)); 170 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 171 lsrList.add(lsr); 172 ls.setLeaveSummaryRows(lsrList); 173 174 //updating an existing leave block 175 LeaveBlock aLeaveBlock = new LeaveBlock(); 176 aLeaveBlock.setEarnCode("EC"); 177 aLeaveBlock.setLeaveAmount(new BigDecimal(-10)); //this amount, multiplied by the days in the span, is considered to be part of the pending leave requests. 178 List<String> errors = new ArrayList<String>(); 179 180 // EC1 belongs to the accrual category testAC 181 // should still be under 50 effective difference is +9, over 1 days = 9 -> 40+12 < 50 182 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(19), aLeaveBlock); 183 Assert.assertTrue("There should be no error message test 1" , errors.size()== 0); 184 185 // should be right at 50 effective difference is +10, over 1 days = 10 -> 40+10 = 50 186 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(20), aLeaveBlock); 187 Assert.assertTrue("There should be no error message test 2" , errors.size()== 0); 188 189 // should be over 50 effective difference is +11, over 1 day = 11 -> 40+11 > 50 190 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(21), aLeaveBlock); 191 Assert.assertTrue("There should be 1 error message test 3" , errors.size()== 1); 192 193 // should be over 50 effective difference is +2, over 6 days = 12 -> 40+12 > 50 194 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/20/2012", new BigDecimal(12), aLeaveBlock); 195 Assert.assertTrue("There should be 1 error message test 5" , errors.size()== 1); 196 197 // should be under effective difference is +2, over 4 days = 8 -> 40+8 < 50 198 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/18/2012", new BigDecimal(12), aLeaveBlock); 199 Assert.assertTrue("There should be 1 error message test 6" , errors.size()== 1); 200 } 201 202 @Test 203 public void testValidateEditLeaveBlockMaxUsageRuleCaseTwo() throws Exception { 204 //Leave Amount decreases, earn code remains the same. 205 LeaveSummary ls = new LeaveSummary(); 206 LeaveSummaryRow lsr = new LeaveSummaryRow(); 207 lsr.setAccrualCategory("testAC"); 208 lsr.setUsageLimit(new BigDecimal(50)); 209 lsr.setPendingLeaveRequests(new BigDecimal(25)); 210 lsr.setYtdApprovedUsage(new BigDecimal(30)); 211 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 212 lsrList.add(lsr); 213 ls.setLeaveSummaryRows(lsrList); 214 215 //updating an existing leave block 216 //Somehow a block enters the system that exceeds max_usage. The only way for it to be saved 217 //is if the net change drops below the usage limit. 218 LeaveBlock aLeaveBlock = new LeaveBlock(); 219 aLeaveBlock.setEarnCode("EC"); 220 aLeaveBlock.setLeaveAmount(new BigDecimal(-10)); 221 List<String> errors = new ArrayList<String>(); 222 223 // effective difference is (-2), over 1 days = -2 -> 55+(-2) > 50 224 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/15/2012", new BigDecimal(8), aLeaveBlock); 225 Assert.assertTrue("There should be 1 error message" , errors.size()== 1); 226 227 // should be equal effective difference is (-0.5), over 5 days = -2.5 -> 55+(-2.5) > 50 228 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC", "02/15/2012", "02/19/2012", new BigDecimal(9.5), aLeaveBlock); 229 Assert.assertTrue("There should be 1 error message" , errors.size()== 1); 230 } 231 232 @Test 233 public void testValidateEditLeaveBlockMaxUsageRuleCaseThree() throws Exception { 234 //Leave Amount static, earn code changes. 235 LeaveSummary ls = new LeaveSummary(); 236 LeaveSummaryRow lsr = new LeaveSummaryRow(); 237 lsr.setAccrualCategory("testAC"); 238 lsr.setUsageLimit(new BigDecimal(50)); 239 lsr.setPendingLeaveRequests(new BigDecimal(25)); 240 lsr.setYtdApprovedUsage(new BigDecimal(15)); 241 242 LeaveSummaryRow lsr2 = new LeaveSummaryRow(); 243 lsr2.setAccrualCategory("testAC2"); 244 lsr2.setUsageLimit(new BigDecimal(15)); 245 lsr2.setPendingLeaveRequests(new BigDecimal(5)); 246 lsr2.setYtdApprovedUsage(new BigDecimal(4)); 247 248 List<LeaveSummaryRow> lsrList = new ArrayList<LeaveSummaryRow>(); 249 lsrList.add(lsr); 250 lsrList.add(lsr2); 251 ls.setLeaveSummaryRows(lsrList); 252 253 //updating an existing leave block 254 LeaveBlock aLeaveBlock = new LeaveBlock(); 255 aLeaveBlock.setEarnCode("EC"); 256 aLeaveBlock.setAccrualCategory("testAC"); 257 aLeaveBlock.setLeaveAmount(new BigDecimal(-10)); 258 List<String> errors = new ArrayList<String>(); 259 260 //Changing to an earn code with different accrual category, testAC2 261 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/15/2012", new BigDecimal(6), aLeaveBlock); 262 Assert.assertTrue("There should be no error message. reached usage limit." , errors.size()== 0); 263 264 //Changing to an earn code with different accrual category, testAC2 265 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/15/2012", new BigDecimal(7), aLeaveBlock); 266 Assert.assertTrue("There should be 1 error message, there were " + errors.size() + " errors" , errors.size()== 1); 267 268 //Changing to an earn code with different accrual category, testAC2 with spanning days. 269 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/19/2012", new BigDecimal(1), aLeaveBlock); 270 Assert.assertTrue("There should be no error message, there were " + errors.size() + " errors" , errors.size()== 0); 271 272 //Changing to an earn code with different accrual category, testAC2 with spanning days. 273 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/20/2012", new BigDecimal(1), aLeaveBlock); 274 Assert.assertTrue("There should be no error message, there were " + errors.size() + " errors" , errors.size()== 0); 275 276 //Changing to an earn code with different accrual category, testAC2 with spanning days. 277 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/21/2012", new BigDecimal(1), aLeaveBlock); 278 Assert.assertTrue("There should be 1 error message, there were " + errors.size() + " errors" , errors.size()== 1); 279 280 //Changing to an earn code within same accrual category, testAC 281 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC1", "02/15/2012", "02/15/2012", new BigDecimal(10), aLeaveBlock); 282 Assert.assertTrue("There should be no error message, there were " + errors.size() + " errors" , errors.size()== 0); 283 284 //Changing to an earn code within same accrual category, testAC with spanning days. 285 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC1", "02/15/2012", "02/19/2012", new BigDecimal(2), aLeaveBlock); 286 Assert.assertTrue("There should be 0 error message, there were " + errors.size() + " errors" , errors.size()== 0); 287 288 //Changing to an earn code within same accrual category, testAC with spanning days. 289 errors = LeaveCalendarValidationUtil.validateLeaveAccrualRuleMaxUsage(ls, "EC2", "02/15/2012", "02/25/2012", new BigDecimal(1), aLeaveBlock); 290 Assert.assertTrue("There should be 1 error message, there were " + errors.size() + " errors" , errors.size()== 1); 291 292 } 293 @Test 294 public void testGetWarningTextForLeaveBlocks() throws Exception { 295 // create two leave blocks with two different earn codes 296 // earn code "ECA" has fmla=Y, has earn code group with warning messages 297 // earn Code "ECB" has fmla = N, has earn code group with warning messages 298 // earn code "ECC" does not have earn code group with warning messages 299 300 List<LeaveBlock> leaveBlocs = new ArrayList<LeaveBlock>(); 301 LeaveBlock lbA = new LeaveBlock(); 302 lbA.setEarnCode("ECA"); 303 lbA.setLeaveDate(LocalDate.now().toDate()); 304 leaveBlocs.add(lbA); 305 306 LeaveBlock lbB = new LeaveBlock(); 307 lbB.setEarnCode("ECB"); 308 lbB.setLeaveDate(LocalDate.now().toDate()); 309 leaveBlocs.add(lbB); 310 311 LeaveBlock lbC = new LeaveBlock(); 312 lbC.setEarnCode("ECC"); 313 lbC.setLeaveDate(LocalDate.now().toDate()); 314 leaveBlocs.add(lbC); 315 316 Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks(leaveBlocs, LocalDate.now().toDateTimeAtStartOfDay().toDate(), new DateTime().plusDays(1).toDate()); 317 int numberOfMessages = 0; 318 for (Set<String> msgs : allMessages.values()){ 319 numberOfMessages += msgs.size(); 320 } 321 Assert.assertTrue("There should be 2 warning messages, not " + numberOfMessages, numberOfMessages== 2); 322 323 for (Set<String> msgs : allMessages.values()){ 324 for (String message : msgs) { 325 Assert.assertTrue("Warning message should be 'Test Message' or 'Test Message1'", message.equals("Test Message") || message.equals("Test Message1")); 326 } 327 } 328 } 329 330 /* In order for tests of the following form to work, need to change status of a document to enroute/approved 331 * without actually routing / approving the document. OR, set up a context within which these actions can be performed. 332 */ 333 /* @Test 334 public void testValidatePendingTransactions() throws Exception { 335 Assert.assertNull(null); 336 BalanceTransfer bt = new BalanceTransfer(); 337 bt.setAmountTransferred(new BigDecimal(1.0)); 338 bt.setTransferAmount(new BigDecimal(1.0)); 339 bt.setForfeitedAmount(new BigDecimal(1.0)); 340 bt.setAccrualCategoryRule(""); 341 bt.setEffectiveDate(TKUtils.getCurrentDate()); 342 bt.setFromAccrualCategory("testAC"); 343 bt.setToAccrualCategory("testAC2"); 344 bt.setPrincipalId("admin"); 345 346 mockSubmitToWorkflow(bt); 347 348 Calendar cal = Calendar.getInstance(); 349 cal.setTime(TKUtils.getCurrentDate()); 350 cal.add(Calendar.MONTH, -1); 351 Date from = cal.getTime(); 352 cal.add(Calendar.MONTH, 2); 353 Date to = cal.getTime(); 354 Map<String,Set<String>> allMessages = new HashMap<String, Set<String>>(); 355 allMessages.putAll(LeaveCalendarValidationUtil.validatePendingTransactions("admin", LocalDate.fromDateFields(from), LocalDate.fromDateFields(to))); 356 357 Assert.assertTrue(allMessages.get("actionMessages").size() > 0); 358 Set<String> actionMessages = allMessages.get("actionMessage"); 359 360 Assert.assertTrue("Should contain warning message for pending transaction", actionMessages.contains("A pending balance transfer exists on this calendar. " + 361 "It must be finalized before this calendar can be approved")); 362 } 363 364 private void mockSubmitToWorkflow(BalanceTransfer balanceTransfer) { 365 // TODO Auto-generated method stub 366 //balanceTransfer.setStatus(HrConstants.ROUTE_STATUS.ENROUTE); 367 EntityNamePrincipalName principalName = null; 368 if (balanceTransfer.getPrincipalId() != null) { 369 principalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(balanceTransfer.getPrincipalId()); 370 } 371 372 MaintenanceDocument document = KRADServiceLocatorWeb.getMaintenanceDocumentService().setupNewMaintenanceDocument(BalanceTransfer.class.getName(), 373 "BalanceTransferDocumentType",KRADConstants.MAINTENANCE_NEW_ACTION); 374 375 String personName = (principalName != null && principalName.getDefaultName() != null) ? principalName.getDefaultName().getCompositeName() : StringUtils.EMPTY; 376 String date = TKUtils.formatDate(balanceTransfer.getEffectiveLocalDate()); 377 document.getDocumentHeader().setDocumentDescription(personName + " (" + balanceTransfer.getPrincipalId() + ") - " + date); 378 Map<String,String[]> params = new HashMap<String,String[]>(); 379 380 KRADServiceLocatorWeb.getMaintenanceDocumentService().setupMaintenanceObject(document, KRADConstants.MAINTENANCE_NEW_ACTION, params); 381 BalanceTransfer btObj = (BalanceTransfer) document.getNewMaintainableObject().getDataObject(); 382 383 btObj.setAccrualCategoryRule(balanceTransfer.getAccrualCategoryRule()); 384 btObj.setEffectiveDate(balanceTransfer.getEffectiveDate()); 385 btObj.setForfeitedAmount(balanceTransfer.getForfeitedAmount()); 386 btObj.setFromAccrualCategory(balanceTransfer.getFromAccrualCategory()); 387 btObj.setPrincipalId(balanceTransfer.getPrincipalId()); 388 btObj.setToAccrualCategory(balanceTransfer.getToAccrualCategory()); 389 btObj.setTransferAmount(balanceTransfer.getTransferAmount()); 390 btObj.setAmountTransferred(balanceTransfer.getAmountTransferred()); 391 btObj.setSstoId(balanceTransfer.getSstoId()); 392 btObj.setDocumentHeaderId(document.getDocumentHeader().getWorkflowDocument().getDocumentId()); 393 //LmServiceLocator.getBalanceTransferService().saveOrUpdate(btObj); 394 document.getNewMaintainableObject().setDataObject(btObj); 395 try { 396 KRADServiceLocatorWeb.getDocumentService().saveDocument(document); 397 } catch (WorkflowException e) { 398 // TODO Auto-generated catch block 399 Assert.fail("Caught workflow exception while saving document"); 400 } 401 document.getDocumentHeader().getWorkflowDocument().saveDocument(""); 402 403 balanceTransfer = LmServiceLocator.getBalanceTransferService().transfer(btObj); 404 405 }*/ 406 407 }