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        String groupKey = "IU-IN";
076                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
077                                //"IN", // 05/08 remove location because adding groupkeycode to DailyOvertimeRule // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
078                                "BW", "TEST-DEPT", workArea,
079                                task, new BigDecimal(8), new BigDecimal("0.10"), null);
080                // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours first block, 5 the next.
081                // Should end up with 2 hours total OVT.
082        DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback();
083                DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
084        TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin");
085        DateTime tbStart = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone);
086                List<TimeBlock> blocks = new ArrayList<TimeBlock>();
087                CalendarEntry payCalendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start);
088                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 2, new BigDecimal("4"), "REG", jobNumber, workArea, task, groupKey, tdoc.getDocumentId()));
089                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusHours(4).plusMinutes(15), 2, new BigDecimal("5"), "REG", jobNumber, workArea, task, groupKey, tdoc.getDocumentId()));
090                TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
091
092                // Verify pre-Rule Run
093                TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("OVT", BigDecimal.ZERO);put("REG", new BigDecimal(18));}},aggregate,2);
094
095                // Run Rule
096
097                tdoc.setTimeBlocks(blocks);
098                TkServiceLocator.getDailyOvertimeRuleService().processDailyOvertimeRules(tdoc, aggregate);
099
100                // Verify post-Rule Run
101                TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("OVT", new BigDecimal(0));put("REG", new BigDecimal(18));}},aggregate,2);
102        }
103
104
105        @SuppressWarnings("serial")
106        @Test
107        public void testDailyOvertimeSimpleCase() throws Exception {
108                Long jobNumber = 30L;
109                Long workArea = 30L;
110                Long task = 30L;
111        String groupKey = "IU-IN";
112                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
113                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
114                                "BW", "TEST-DEPT", workArea,
115                                task, new BigDecimal(8), new BigDecimal("15.0"), null);
116
117                // Create Time Blocks (2 days, 2 blocks on each day, 15 minute gap between blocks, 4 hours first block, 5 the next.
118                // Should end up with 2 hours total OVT.
119        DateTimeZone zone = HrServiceLocator.getTimezoneService().getTargetUserTimezoneWithFallback();
120                DateTime start = new DateTime(2010, 3, 29, 14, 0, 0, 0, TKUtils.getSystemDateTimeZone());
121        TimesheetDocument tdoc = TkTestUtils.populateBlankTimesheetDocument(start, "admin");
122        DateTime tbStart = new DateTime(2010, 3, 29, 14, 0, 0, 0, zone);
123                List<TimeBlock> blocks = new ArrayList<TimeBlock>();
124                CalendarEntry payCalendarEntry =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates("admin", start);
125                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart, 2, new BigDecimal("4"), "REG", jobNumber, workArea, task, groupKey, tdoc.getDocumentId()));
126                blocks.addAll(TkTestUtils.createUniformTimeBlocks(tbStart.plusHours(4).plusMinutes(15), 2, new BigDecimal("5"), "REG", jobNumber, workArea, task, groupKey, tdoc.getDocumentId()));
127                TkTimeBlockAggregate aggregate = new TkTimeBlockAggregate(blocks, payCalendarEntry);
128
129                // Verify pre-Rule Run
130                TkTestUtils.verifyAggregateHourSums("admin","Pre-Check", new HashMap<String,BigDecimal>() {{put("OVT", BigDecimal.ZERO);put("REG", new BigDecimal(18));}},aggregate,2);
131
132                // Run Rule
133
134                tdoc.setTimeBlocks(blocks);
135                TkServiceLocator.getDailyOvertimeRuleService().processDailyOvertimeRules(tdoc, aggregate);
136
137                // Verify post-Rule Run
138                TkTestUtils.verifyAggregateHourSums("admin","Post Rules Check", new HashMap<String,BigDecimal>() {{put("OVT", new BigDecimal(2));put("REG", new BigDecimal(16));}},aggregate,2);
139        }
140
141        @Test
142        public void testRuleCreationAndRetrieval() throws Exception {
143                Long workArea = 0L;
144                Long task = 30L;
145                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
146                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
147                                "BW", "TEST-DEPT", workArea,
148                                task, new BigDecimal(8), new BigDecimal("0.25"), null);
149                DailyOvertimeRule rule = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRule("IU-IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
150                                "BW", "TEST-DEPT", workArea, JAN_AS_OF_DATE.toLocalDate());
151                Assert.assertNotNull("Rule not created.", rule);
152        }
153        
154        @Test
155        public void testSearchDailyOvertimeRules() throws Exception {
156                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
157                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
158                                "BW", "TEST-DEPT", 30L, 30L, new BigDecimal(8), new BigDecimal("0.10"), null);
159                createDailyOvertimeRule("IU-IN", "REG", "OVT", 
160                                //"IN", // changed from "SD1" to "IN" for changes of adding groupKeyCode to Job
161                                "BW", "TEST-DEPT5", 5555L, 30L, new BigDecimal(8), new BigDecimal("0.10"), null);
162                
163                //List<DailyOvertimeRule> allResults = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRules("IU-IN", "admin", null, null, null, null, "Y", "N");
164                //Assert.assertEquals("Search returned the wrong number of results.", 2, allResults.size());
165                
166                //List<DailyOvertimeRule> restrictedResults = TkServiceLocator.getDailyOvertimeRuleService().getDailyOvertimeRules("IU-IN", "fran", null, null, null, null, "Y", "N");
167                //Assert.assertEquals("Search returned the wrong number of results.", 0, restrictedResults.size());
168        }
169
170}