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