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 }