org.kuali.kpme.tklm.time.missedpunch.MissedPunchServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kpme.tklm.time.missedpunch.MissedPunchServiceImpl.java

Source

/**
 * Copyright 2004-2014 The Kuali Foundation
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.kuali.kpme.tklm.time.missedpunch;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.kuali.kpme.core.api.assignment.Assignment;
import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey;
import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
import org.kuali.kpme.core.service.HrServiceLocator;
import org.kuali.kpme.core.util.HrContext;
import org.kuali.kpme.core.util.TKUtils;
import org.kuali.kpme.tklm.api.common.TkConstants;
import org.kuali.kpme.tklm.api.leave.block.LeaveBlock;
import org.kuali.kpme.tklm.api.time.clocklog.ClockLog;
import org.kuali.kpme.tklm.api.time.clocklog.ClockLogService;
import org.kuali.kpme.tklm.api.time.missedpunch.MissedPunch;
import org.kuali.kpme.tklm.api.time.missedpunch.MissedPunchService;
import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock;
import org.kuali.kpme.tklm.api.time.timeblock.TimeBlockService;
import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
import org.kuali.kpme.tklm.time.clocklog.ClockLogBo;
import org.kuali.kpme.tklm.time.detail.web.ActionFormUtils;
import org.kuali.kpme.tklm.time.missedpunch.dao.MissedPunchDao;
import org.kuali.kpme.tklm.time.rules.TkRuleControllerService;
import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
import org.kuali.kpme.tklm.time.timesheet.TimesheetUtils;
import org.kuali.kpme.tklm.time.timesheet.service.TimesheetService;
import org.kuali.rice.core.api.mo.ModelObjectUtils;
import org.kuali.rice.krad.service.BusinessObjectService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class MissedPunchServiceImpl implements MissedPunchService {
    private MissedPunchDao missedPunchDao;

    private BusinessObjectService businessObjectService;
    private ClockLogService clockLogService;
    private TimeBlockService timeBlockService;
    private TimesheetService timesheetService;
    private TkRuleControllerService tkRuleControllerService;

    @Override
    public List<MissedPunch> getMissedPunchByTimesheetDocumentId(String timesheetDocumentId) {
        return ModelObjectUtils.transform(missedPunchDao.getMissedPunchesByTimesheetDocumentId(timesheetDocumentId),
                MissedPunchBo.toMissedPunch);
    }

    @Override
    public MissedPunch getMissedPunchByClockLogId(String clockLogId) {
        return MissedPunchBo.to(missedPunchDao.getMissedPunchByClockLogId(clockLogId));
    }

    @Override
    public MissedPunch addClockLog(MissedPunch missedPunch, String ipAddress) {
        MissedPunch.Builder builder = MissedPunch.Builder.create(missedPunch);
        TimesheetDocument timesheetDocument = timesheetService
                .getTimesheetDocument(missedPunch.getTimesheetDocumentId());
        AssignmentDescriptionKey assignmentDescriptionKey = new AssignmentDescriptionKey(
                missedPunch.getGroupKeyCode(), missedPunch.getJobNumber(), missedPunch.getWorkArea(),
                missedPunch.getTask());
        Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment(missedPunch.getPrincipalId(),
                assignmentDescriptionKey, missedPunch.getActionLocalDate());
        CalendarEntry calendarEntry = timesheetDocument.getCalendarEntry();

        // use the actual date and time from the document to build the date time with user zone, then apply system time zone to it
        String dateString = TKUtils.formatDateTimeShort(missedPunch.getActionFullDateTime());
        String longDateString = TKUtils.formatDateTimeLong(missedPunch.getActionFullDateTime());
        String timeString = TKUtils.formatTimeShort(longDateString);

        DateTime dateTimeWithUserZone = TKUtils.convertDateStringToDateTime(dateString, timeString);
        DateTime actionDateTime = dateTimeWithUserZone.withZone(TKUtils.getSystemDateTimeZone());

        String clockAction = missedPunch.getClockAction();
        String principalId = timesheetDocument.getPrincipalId();

        ClockLog clockLog = clockLogService.processClockLog(principalId, timesheetDocument.getDocumentId(),
                actionDateTime, assignment, calendarEntry, ipAddress, LocalDate.now(), clockAction, false);

        clockLog = clockLogService.saveClockLog(clockLog);
        builder.setTkClockLogId(clockLog.getTkClockLogId());

        if (StringUtils.equals(clockLog.getClockAction(), TkConstants.CLOCK_OUT)
                || StringUtils.equals(clockLog.getClockAction(), TkConstants.LUNCH_OUT)) {
            ClockLog lastClockLog = clockLogService.getLastClockLog(missedPunch.getPrincipalId());
            // KPME-2735 This is where it creates a zero timeblock...  So we will check the clock id of clockLog and lastClockLog and 
            // if they are the same, we will assume it's trying to create a zero timeblock for the same clock action, therefore skip the code 
            if (!clockLog.getTkClockLogId().equals(lastClockLog.getTkClockLogId())) {
                String earnCode = assignment.getJob().getPayTypeObj().getRegEarnCode();
                buildTimeBlockRunRules(lastClockLog, clockLog, timesheetDocument, assignment, earnCode,
                        lastClockLog.getClockDateTime(), clockLog.getClockDateTime());
            }
        }
        return builder.build();
    }

    @Override
    public MissedPunch updateClockLog(MissedPunch missedPunch, String ipAddress) {
        DateTime actionDateTime = missedPunch.getActionFullDateTime();

        ClockLog clockLog = clockLogService.getClockLog(missedPunch.getTkClockLogId());
        if (clockLog != null) {
            DateTime clockDtInUserTimeZone = clockLog.getClockDateTime()
                    .withZone(DateTimeZone.forID(clockLog.getClockTimestampTimezone()));
            if (!clockDtInUserTimeZone.equals(actionDateTime)) {
                String clockLogEndId = null;
                String clockLogBeginId = null;

                List<TimeBlock> timeBlocks = timeBlockService
                        .getTimeBlocksForClockLogEndId(clockLog.getTkClockLogId());
                if (timeBlocks.isEmpty()) {
                    timeBlocks = timeBlockService.getTimeBlocksForClockLogBeginId(clockLog.getTkClockLogId());
                    if (!timeBlocks.isEmpty()) {
                        clockLogEndId = timeBlocks.get(0).getClockLogEndId();
                    }
                } else {
                    clockLogBeginId = timeBlocks.get(0).getClockLogBeginId();
                }

                deleteClockLogAndTimeBlocks(clockLog, timeBlocks);

                missedPunch = addClockLogAndTimeBlocks(missedPunch, ipAddress, clockLogEndId, clockLogBeginId);
            }
        }
        return missedPunch;
    }

    protected void deleteClockLogAndTimeBlocks(ClockLog clockLog, List<TimeBlock> timeBlocks) {
        if (clockLog != null) {
            ClockLogBo bo = ClockLogBo.from(clockLog);
            businessObjectService.delete(bo);
        }

        if (CollectionUtils.isNotEmpty(timeBlocks)) {
            for (TimeBlock timeBlock : timeBlocks) {
                timeBlockService.deleteTimeBlock(timeBlock);
            }
        }
    }

    protected MissedPunch addClockLogAndTimeBlocks(MissedPunch missedPunch, String ipAddress, String logEndId,
            String logBeginId) {
        MissedPunch.Builder builder = MissedPunch.Builder.create(missedPunch);
        TimesheetDocument timesheetDocument = timesheetService
                .getTimesheetDocument(missedPunch.getTimesheetDocumentId());
        AssignmentDescriptionKey assignmentDescriptionKey = new AssignmentDescriptionKey(
                missedPunch.getGroupKeyCode(), missedPunch.getJobNumber(), missedPunch.getWorkArea(),
                missedPunch.getTask());
        Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment(missedPunch.getPrincipalId(),
                assignmentDescriptionKey, missedPunch.getActionLocalDate());
        CalendarEntry calendarEntry = timesheetDocument.getCalendarEntry();
        String dateString = TKUtils.formatDateTimeShort(missedPunch.getActionFullDateTime());
        String longDateString = TKUtils.formatDateTimeLong(missedPunch.getActionFullDateTime());
        String timeString = TKUtils.formatTimeShort(longDateString);

        String userTimezone = HrServiceLocator.getTimezoneService().getUserTimezone(missedPunch.getPrincipalId());
        DateTimeZone userTimeZone = DateTimeZone.forID(userTimezone);
        DateTime dateTimeWithUserZone = TKUtils.convertDateStringToDateTimeWithTimeZone(dateString, timeString,
                userTimeZone);
        DateTime userActionDateTime = missedPunch.getActionFullDateTime();

        DateTime actionDateTime = dateTimeWithUserZone.withZone(TKUtils.getSystemDateTimeZone());
        String clockAction = missedPunch.getClockAction();
        String principalId = timesheetDocument.getPrincipalId();

        ClockLog clockLog = clockLogService.processClockLog(principalId, timesheetDocument.getDocumentId(),
                actionDateTime, assignment, calendarEntry, ipAddress, LocalDate.now(), clockAction, false);

        clockLogService.saveClockLog(clockLog);
        builder.setActionFullDateTime(missedPunch.getActionFullDateTime());
        builder.setTkClockLogId(clockLog.getTkClockLogId());

        if (logEndId != null || logBeginId != null) {
            ClockLog endLog;
            ClockLog beginLog;

            if (logEndId != null) {
                endLog = clockLogService.getClockLog(logEndId);
            } else {
                endLog = clockLog;
            }

            if (logBeginId != null) {
                beginLog = clockLogService.getClockLog(logBeginId);
            } else {
                beginLog = clockLog;
            }

            if (beginLog != null && endLog != null
                    && beginLog.getClockDateTime().isBefore(endLog.getClockDateTime())) {
                String earnCode = assignment.getJob().getPayTypeObj().getRegEarnCode();
                buildTimeBlockRunRules(beginLog, endLog, timesheetDocument, assignment, earnCode,
                        beginLog.getClockDateTime(), endLog.getClockDateTime());
            }
        }
        return builder.build();
    }

    /**
     * Helper method to build time blocks and fire the rules processing. This
     * should be called only if there was a CLOCK_OUT action.
     */
    private void buildTimeBlockRunRules(ClockLog beginClockLog, ClockLog endClockLog, TimesheetDocument tdoc,
            Assignment currentAssignment, String earnCode, DateTime beginDateTime, DateTime endDateTime) {
        // New Time Blocks, pointer reference
        List<TimeBlock> newTimeBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(tdoc, true);
        List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>();
        boolean createNewTb = true;
        for (TimeBlock tb : newTimeBlocks) {
            if (beginClockLog != null && StringUtils.isNotBlank(tb.getClockLogBeginId())
                    && tb.getClockLogBeginId().equals(beginClockLog.getTkClockLogId()) && endClockLog != null
                    && StringUtils.isNotBlank(tb.getClockLogEndId())
                    && tb.getClockLogEndId().equals(endClockLog.getTkClockLogId())) {
                // if there's already time block created with the same clock logs, don't create timeblock for it again
                createNewTb = false;
            }
            referenceTimeBlocks.add(TimeBlock.Builder.create(tb).build());
        }

        if (createNewTb) {
            // Add TimeBlocks after we store our reference object!
            List<TimeBlock> blocks = timeBlockService.buildTimeBlocks(tdoc.getPrincipalId(),
                    tdoc.getCalendarEntry(), currentAssignment, earnCode, tdoc.getDocumentId(), beginDateTime,
                    endDateTime, BigDecimal.ZERO, BigDecimal.ZERO, true, false, HrContext.getPrincipalId(),
                    beginClockLog != null ? beginClockLog.getTkClockLogId() : null,
                    endClockLog != null ? endClockLog.getTkClockLogId() : null);

            newTimeBlocks.addAll(blocks);
        }

        List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdoc);
        TimesheetUtils.processTimeBlocksWithRuleChange(newTimeBlocks, referenceTimeBlocks, leaveBlocks,
                tdoc.getCalendarEntry(), tdoc, tdoc.getPrincipalId());
    }

    public void setMissedPunchDao(MissedPunchDao missedPunchDao) {
        this.missedPunchDao = missedPunchDao;
    }

    public void setBusinessObjectService(BusinessObjectService businessObjectService) {
        this.businessObjectService = businessObjectService;
    }

    public void setClockLogService(ClockLogService clockLogService) {
        this.clockLogService = clockLogService;
    }

    public void setTimeBlockService(TimeBlockService timeBlockService) {
        this.timeBlockService = timeBlockService;
    }

    public void setTimesheetService(TimesheetService timesheetService) {
        this.timesheetService = timesheetService;
    }

    public void setTkRuleControllerService(TkRuleControllerService tkRuleControllerService) {
        this.tkRuleControllerService = tkRuleControllerService;
    }
}