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 */
016package org.kuali.hr.time.overtime.daily.rule.service;
017
018import java.math.BigDecimal;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022
023import org.joda.time.DateTime;
024import org.joda.time.DateTimeZone;
025import org.junit.Assert;
026import org.junit.Test;
027import org.kuali.hr.KPMEWebTestCase;
028import org.kuali.kpme.core.FunctionalTest;
029import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
030import org.kuali.kpme.core.service.HrServiceLocator;
031import org.kuali.kpme.core.util.TKUtils;
032import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock;
033import org.kuali.kpme.tklm.time.rules.overtime.daily.DailyOvertimeRule;
034import org.kuali.kpme.tklm.time.rules.overtime.daily.service.DailyOvertimeRuleService;
035import org.kuali.kpme.tklm.time.service.TkServiceLocator;
036import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
037import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate;
038import org.kuali.kpme.tklm.utils.TkTestUtils;
039
040@FunctionalTest
041public class DailyOvertimeRuleServiceTest extends KPMEWebTestCase {
042
043        public static final String USER_PRINCIPAL_ID = "admin";
044        private DateTime JAN_AS_OF_DATE = new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
045
046        private void createDailyOvertimeRule(String groupKeyCode, String fromEarnGroup, String earnCode, 
047                        //String location, 
048                        String paytype, String dept, Long workArea, Long task, BigDecimal minHours, BigDecimal maxGap, String overtimePref) {
049                DailyOvertimeRuleService service = TkServiceLocator.getDailyOvertimeRuleService();
050                DailyOvertimeRule rule = new DailyOvertimeRule();
051                
052                rule.setGroupKeyCode("IU-IN");
053                rule.setEffectiveLocalDate(JAN_AS_OF_DATE.toLocalDate());
054                rule.setFromEarnGroup(fromEarnGroup);
055                rule.setEarnCode(earnCode);
056                //rule.setLocation(location);
057                rule.setPaytype(paytype);
058                rule.setDept(dept);
059                rule.setWorkArea(workArea);
060                rule.setMaxGap(maxGap);
061                rule.setMinHours(minHours);
062                rule.setActive(true);
063        rule.setUserPrincipalId("admin");
064
065                service.saveOrUpdate(rule);
066        }
067
068
069        @SuppressWarnings("serial")
070        @Test
071        public void testDailyOvertimeGapExceeded() throws Exception {
072                Long jobNumber = 30L;
073                Long workArea = 30L;
074                Long task = 30L;
075                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
076                                //"IN", // 05/08 remove location because adding groupkeycode to DailyOvertimeRule // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
077                                "BW", "TEST-DEPT", workArea,
078                                task, new BigDecimal(8), new BigDecimal("0.10"), null);
079                // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours first block, 5 the next.
080                // Should end up with 2 hours total OVT.
081        DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback();
082                DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
083        DateTime tbStart = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone);
084                List<TimeBlock> blocks = new ArrayList<TimeBlock>();
085                CalendarEntry payCalendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start);
086                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 2, new BigDecimal("4"), "REG", jobNumber, workArea, task));
087                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusHours(4).plusMinutes(15), 2, new BigDecimal("5"), "REG", jobNumber, workArea, task));
088                TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
089
090                // Verify pre-Rule Run
091                TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("OVT", BigDecimal.ZERO);put("REG", new BigDecimal(18));}},aggregate,2);
092
093                // Run Rule
094                TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin");
095                tdoc.setTimeBlocks(blocks);
096                TkServiceLocator.getDailyOvertimeRuleService().processDailyOvertimeRules(tdoc, aggregate);
097
098                // Verify post-Rule Run
099                TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("OVT", new BigDecimal(0));put("REG", new BigDecimal(18));}},aggregate,2);
100        }
101
102
103        @SuppressWarnings("serial")
104        @Test
105        public void testDailyOvertimeSimpleCase() throws Exception {
106                Long jobNumber = 30L;
107                Long workArea = 30L;
108                Long task = 30L;
109                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
110                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
111                                "BW", "TEST-DEPT", workArea,
112                                task, new BigDecimal(8), new BigDecimal("15.0"), null);
113
114                // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours first block, 5 the next.
115                // Should end up with 2 hours total OVT.
116        DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback();
117                DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
118        DateTime tbStart = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone);
119                List<TimeBlock> blocks = new ArrayList<TimeBlock>();
120                CalendarEntry payCalendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start);
121                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 2, new BigDecimal("4"), "REG", jobNumber, workArea, task));
122                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusHours(4).plusMinutes(15), 2, new BigDecimal("5"), "REG", jobNumber, workArea, task));
123                TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
124
125                // Verify pre-Rule Run
126                TkTestUtils.verifyAggregateHourSums("Pre-Check", new HashMap<String,BigDecimal>() {{put("OVT", BigDecimal.ZERO);put("REG", new BigDecimal(18));}},aggregate,2);
127
128                // Run Rule
129                TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin");
130                tdoc.setTimeBlocks(blocks);
131                TkServiceLocator.getDailyOvertimeRuleService().processDailyOvertimeRules(tdoc, aggregate);
132
133                // Verify post-Rule Run
134                TkTestUtils.verifyAggregateHourSums("Post Rules Check", new HashMap<String,BigDecimal>() {{put("OVT", new BigDecimal(2));put("REG", new BigDecimal(16));}},aggregate,2);
135        }
136
137        @Test
138        public void testRuleCreationAndRetrieval() throws Exception {
139                Long workArea = 0L;
140                Long task = 30L;
141                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
142                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
143                                "BW", "TEST-DEPT", workArea,
144                                task, new BigDecimal(8), new BigDecimal("0.25"), null);
145                DailyOvertimeRule rule = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRule("IU-IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
146                                "BW", "TEST-DEPT", workArea, JAN_AS_OF_DATE.toLocalDate());
147                Assert.assertNotNull("Rule not created.", rule);
148        }
149        
150        @Test
151        public void testSearchDailyOvertimeRules() throws Exception {
152                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
153                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
154                                "BW", "TEST-DEPT", 30L, 30L, new BigDecimal(8), new BigDecimal("0.10"), null);
155                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
156                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
157                                "BW", "TEST-DEPT5", 5555L, 30L, new BigDecimal(8), new BigDecimal("0.10"), null);
158                
159                //List<DailyOvertimeRule> allResults = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRules("IU-IN", "admin", null, null, null, null, "Y", "N");
160                //Assert.assertEquals("Search returned the wrong number of results.", 2, allResults.size());
161                
162                //List<DailyOvertimeRule> restrictedResults = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRules("IU-IN", "fran", null, null, null, null, "Y", "N");
163                //Assert.assertEquals("Search returned the wrong number of results.", 0, restrictedResults.size());
164        }
165
166}