001    /**
002     * Copyright 2004-2012 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.time.clocklog.service;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.hr.time.assignment.Assignment;
020    import org.kuali.hr.time.calendar.CalendarEntries;
021    import org.kuali.hr.time.clocklog.ClockLog;
022    import org.kuali.hr.time.clocklog.dao.ClockLogDao;
023    import org.kuali.hr.time.service.base.TkServiceLocator;
024    import org.kuali.hr.time.task.Task;
025    import org.kuali.hr.time.timeblock.TimeBlock;
026    import org.kuali.hr.time.timesheet.TimesheetDocument;
027    import org.kuali.hr.time.util.TKContext;
028    import org.kuali.hr.time.util.TkConstants;
029    
030    import java.math.BigDecimal;
031    import java.sql.Timestamp;
032    import java.util.ArrayList;
033    import java.util.List;
034    
035    public class ClockLogServiceImpl implements ClockLogService {
036    
037        private ClockLogDao clockLogDao;
038    
039        public ClockLogServiceImpl() {
040        }
041    
042        public void saveClockLog(ClockLog clockLog) {
043            clockLogDao.saveOrUpdate(clockLog);
044        }
045    
046        @Override
047        public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, String principalId) {
048            return processClockLog(clockTimeStamp, assignment, pe, ip, asOfDate, td, clockAction, principalId, TKContext.getPrincipalId());
049        }
050    
051        @Override
052        public ClockLog processClockLog(Timestamp clockTimeStamp, Assignment assignment,CalendarEntries pe, String ip, java.sql.Date asOfDate, TimesheetDocument td, String clockAction, String principalId, String userPrincipalId) {
053            // process rules
054            Timestamp roundedClockTimestamp = TkServiceLocator.getGracePeriodService().processGracePeriodRule(clockTimeStamp, new java.sql.Date(pe.getBeginPeriodDateTime().getTime()));
055    
056            ClockLog clockLog = TkServiceLocator.getClockLogService().buildClockLog(roundedClockTimestamp, new Timestamp(System.currentTimeMillis()), assignment, td, clockAction, ip, userPrincipalId);
057            TkServiceLocator.getClockLocationRuleService().processClockLocationRule(clockLog, asOfDate);
058    
059            // If the clock action is clock out or lunch out, create a time block besides the clock log
060            if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT) || StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
061                processTimeBlock(clockLog, assignment, pe, td, clockAction, principalId);
062            } else {
063                //Save current clock log to get id for timeblock building
064                TkServiceLocator.getClockLogService().saveClockLog(clockLog);
065            }
066    
067            return clockLog;
068        }
069    
070        private void processTimeBlock(ClockLog clockLog, Assignment assignment, CalendarEntries pe, TimesheetDocument td, String clockAction, String principalId) {
071            ClockLog lastLog = null;
072            Timestamp lastClockTimestamp = null;
073            String beginClockLogId = null;
074            String endClockLogId = null;
075    
076            if (StringUtils.equals(clockAction, TkConstants.LUNCH_OUT)) {
077                lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId, TkConstants.CLOCK_IN);
078            } else if (StringUtils.equals(clockAction, TkConstants.CLOCK_OUT)) {
079                lastLog = TkServiceLocator.getClockLogService().getLastClockLog(principalId);
080            }
081            if (lastLog != null) {
082                lastClockTimestamp = lastLog.getClockTimestamp();
083                beginClockLogId = lastLog.getTkClockLogId();
084            }
085            //Save current clock log to get id for timeblock building
086            TkServiceLocator.getClockLogService().saveClockLog(clockLog);
087            endClockLogId = clockLog.getTkClockLogId();
088    
089            long beginTime = lastClockTimestamp.getTime();
090            Timestamp beginTimestamp = new Timestamp(beginTime);
091            Timestamp endTimestamp = clockLog.getClockTimestamp();
092    
093            // New Time Blocks, pointer reference
094            List<TimeBlock> newTimeBlocks = td.getTimeBlocks();
095            List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(td.getTimeBlocks().size());
096            for (TimeBlock tb : td.getTimeBlocks()) {
097                referenceTimeBlocks.add(tb.copy());
098            }
099    
100            // Add TimeBlocks after we store our reference object!
101            List<TimeBlock> aList = TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment, assignment.getJob().getPayTypeObj().getRegEarnCode(), td, beginTimestamp, endTimestamp, BigDecimal.ZERO, BigDecimal.ZERO, true, false);
102            for (TimeBlock tb : aList) {
103                tb.setClockLogBeginId(beginClockLogId);
104                tb.setClockLogEndId(endClockLogId);
105            }
106            newTimeBlocks.addAll(aList);
107    
108            //reset time block
109            TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks);
110    
111            //apply any rules for this action
112            TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.CLOCK_OUT, newTimeBlocks, pe, td, principalId);
113    
114            //call persist method that only saves added/deleted/changed timeblocks
115            TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks);
116        }
117    
118        @Override
119        public ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip) {
120            return buildClockLog(clockTimestamp, originalTimestamp, assignment, timesheetDocument, clockAction, ip, TKContext.getPrincipalId());
121        }
122    
123        @Override
124        public ClockLog buildClockLog(Timestamp clockTimestamp, Timestamp originalTimestamp, Assignment assignment, TimesheetDocument timesheetDocument, String clockAction, String ip, String userPrincipalId) {
125            String principalId = timesheetDocument.getPrincipalId();
126    
127            ClockLog clockLog = new ClockLog();
128            clockLog.setPrincipalId(principalId);
129            //        AssignmentDescriptionKey assignmentDesc = TkServiceLocator.getAssignmentService().getAssignmentDescriptionKey(selectedAssign);
130            //        Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(timesheetDocument, selectedAssign);
131            clockLog.setJob(timesheetDocument.getJob(assignment.getJobNumber()));
132            clockLog.setJobNumber(assignment.getJobNumber());
133            clockLog.setWorkArea(assignment.getWorkArea());
134            clockLog.setTkWorkAreaId(assignment.getWorkAreaObj().getTkWorkAreaId());
135    
136            String tkTaskId = null;
137            for (Task task : assignment.getWorkAreaObj().getTasks()) {
138                if (task.getTask().compareTo(assignment.getTask()) == 0) {
139                    tkTaskId = task.getTkTaskId();
140                    break;
141                }
142            }
143            clockLog.setTask(assignment.getTask());
144            clockLog.setTkTaskId(tkTaskId);
145            clockLog.setClockTimestampTimezone(TkServiceLocator.getTimezoneService().getUserTimezone());
146            clockLog.setClockTimestamp(clockTimestamp);
147            clockLog.setClockAction(clockAction);
148            clockLog.setIpAddress(ip);
149            clockLog.setHrJobId(assignment.getJob().getHrJobId());
150            clockLog.setUserPrincipalId(userPrincipalId);
151            // timestamp should be the original time without Grace Period rule applied
152            clockLog.setTimestamp(originalTimestamp);
153    
154            return clockLog;
155        }
156    
157        public void setClockLogDao(ClockLogDao clockLogDao) {
158            this.clockLogDao = clockLogDao;
159        }
160    
161        public ClockLog getLastClockLog(String principalId) {
162            return clockLogDao.getLastClockLog(principalId);
163        }
164    
165        public ClockLog getLastClockLog(String principalId, String clockAction) {
166            return clockLogDao.getLastClockLog(principalId, clockAction);
167        }
168    
169        public List<ClockLog> getOpenClockLogs(  CalendarEntries payCalendarEntry) {
170            return clockLogDao.getOpenClockLogs(payCalendarEntry);
171        }
172    
173        @Override
174        public ClockLog getClockLog(String tkClockLogId) {
175            return clockLogDao.getClockLog(tkClockLogId);
176        }
177    
178    }