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