org.kuali.kpme.tklm.common.PayrollApprovalJob.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kpme.tklm.common.PayrollApprovalJob.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.common;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.kuali.kpme.core.api.assignment.Assignment;
import org.kuali.kpme.core.api.calendar.Calendar;
import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
import org.kuali.kpme.core.api.namespace.KPMENamespace;
import org.kuali.kpme.core.api.principal.PrincipalHRAttributes;
import org.kuali.kpme.core.batch.BatchJob;
import org.kuali.kpme.core.batch.BatchJobUtil;
import org.kuali.kpme.core.role.KPMERole;
import org.kuali.kpme.core.service.HrServiceLocator;
import org.kuali.kpme.core.util.HrConstants;
import org.kuali.kpme.tklm.leave.calendar.LeaveCalendarDocument;
import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
import org.kuali.kpme.tklm.leave.workflow.LeaveCalendarDocumentHeader;
import org.kuali.kpme.tklm.time.service.TkServiceLocator;
import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
import org.kuali.kpme.tklm.time.workflow.TimesheetDocumentHeader;
import org.kuali.rice.core.api.util.ConcreteKeyValue;
import org.kuali.rice.core.api.util.KeyValue;
import org.kuali.rice.kew.api.KewApiConstants;
import org.kuali.rice.kew.api.KewApiServiceLocator;
import org.kuali.rice.kew.api.action.ActionRequest;
import org.kuali.rice.kew.api.document.DocumentStatus;
import org.kuali.rice.kew.service.KEWServiceLocator;
import org.kuali.rice.kim.api.role.RoleMember;
import org.quartz.*;

import java.util.ArrayList;
import java.util.List;

public class PayrollApprovalJob extends BatchJob {

    private static final Logger LOG = Logger.getLogger(PayrollApprovalJob.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String batchUserPrincipalId = getBatchUserPrincipalId();

        if (batchUserPrincipalId != null) {
            JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
            String hrCalendarEntryId = jobDataMap.getString("hrCalendarEntryId");

            CalendarEntry calendarEntry = HrServiceLocator.getCalendarEntryService()
                    .getCalendarEntry(hrCalendarEntryId);
            Calendar calendar = HrServiceLocator.getCalendarService().getCalendar(calendarEntry.getHrCalendarId());
            DateTime beginDate = calendarEntry.getBeginPeriodFullDateTime();
            DateTime endDate = calendarEntry.getEndPeriodFullDateTime();

            List<RoleMember> roleMembers = new ArrayList<RoleMember>();
            String subject = "";
            List<Long> workAreas = new ArrayList<Long>();

            // used to flag if any document has be routed by this batch job. If true, 
            // we need to reschedule this job since the newly routed documents are not approved by this job, we need a new job to approve them
            boolean needToReschedule = false;

            if (StringUtils.equals(calendar.getCalendarTypes(), "Pay")) {
                List<TimesheetDocumentHeader> timesheetDocumentHeaders = TkServiceLocator
                        .getTimesheetDocumentHeaderService().getDocumentHeaders(beginDate, endDate);
                for (TimesheetDocumentHeader timesheetDocumentHeader : timesheetDocumentHeaders) {
                    if (timesheetDocumentHeader != null) {
                        String docId = timesheetDocumentHeader.getDocumentId();
                        TimesheetDocument timesheetDocument = TkServiceLocator.getTimesheetService()
                                .getTimesheetDocument(docId);
                        String documentStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(docId);

                        if (documentStatus.equals(DocumentStatus.ENROUTE.getCode())) {
                            PrincipalHRAttributes phraRecord = HrServiceLocator.getPrincipalHRAttributeService()
                                    .getPrincipalCalendar(timesheetDocument.getPrincipalId(),
                                            endDate.toLocalDate());

                            if (phraRecord != null
                                    && phraRecord.getPayCalendar().equals(calendar.getCalendarName())) {
                                // find all request actions and approve the document as the users with the request action
                                List<ActionRequest> requestList = KewApiServiceLocator.getWorkflowDocumentService()
                                        .getPendingActionRequests(docId);
                                for (ActionRequest aRequest : requestList) {
                                    if (aRequest.getActionRequested() != null
                                            && aRequest.getActionRequested().getCode()
                                                    .equals(KewApiConstants.ACTION_REQUEST_APPROVE_REQ)
                                            && StringUtils.isNotBlank(aRequest.getPrincipalId())
                                            && StringUtils.equals(aRequest.getQualifiedRoleNameLabel(),
                                                    KPMERole.PAYROLL_PROCESSOR.getRoleName())) {
                                        TkServiceLocator.getTimesheetService().approveTimesheet(
                                                aRequest.getPrincipalId(), timesheetDocument,
                                                HrConstants.BATCH_JOB_ACTIONS.PAYROLL_JOB_APPROVE);
                                        roleMembers = getRoleMembersInDepartment(
                                                timesheetDocument.getAllAssignments(), KPMENamespace.KPME_TK);
                                        subject = "Payroll Batch Approved Timesheet Document " + docId;
                                    }
                                }
                            }
                        } else if (documentStatus.equals(DocumentStatus.INITIATED.getCode())
                                || documentStatus.equals(DocumentStatus.SAVED.getCode())) {
                            // if there are documents still not submitted by the time payroll processor approval batch job runs, we need to route the document, then reschedule the payroll processor job
                            String principalId = timesheetDocument.getPrincipalId();
                            PrincipalHRAttributes phraRecord = HrServiceLocator.getPrincipalHRAttributeService()
                                    .getPrincipalCalendar(principalId, endDate.toLocalDate());
                            if (phraRecord != null
                                    && phraRecord.getPayCalendar().equals(calendar.getCalendarName())) {
                                TkServiceLocator.getTimesheetService().routeTimesheet(batchUserPrincipalId,
                                        timesheetDocument, HrConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE);
                                needToReschedule = true;
                            }
                        }
                    }
                }
            } else if (StringUtils.equals(calendar.getCalendarTypes(), "Leave")) {
                List<LeaveCalendarDocumentHeader> leaveCalendarDocumentHeaders = LmServiceLocator
                        .getLeaveCalendarDocumentHeaderService().getDocumentHeaders(beginDate, endDate);
                for (LeaveCalendarDocumentHeader leaveCalendarDocumentHeader : leaveCalendarDocumentHeaders) {
                    if (leaveCalendarDocumentHeader != null) {
                        String docId = leaveCalendarDocumentHeader.getDocumentId();
                        LeaveCalendarDocument leaveCalendarDocument = LmServiceLocator.getLeaveCalendarService()
                                .getLeaveCalendarDocument(docId);
                        String documentStatus = KEWServiceLocator.getRouteHeaderService().getDocumentStatus(docId);
                        // only approve documents in enroute status
                        if (documentStatus.equals(DocumentStatus.ENROUTE.getCode())) {
                            PrincipalHRAttributes phraRecord = HrServiceLocator.getPrincipalHRAttributeService()
                                    .getPrincipalCalendar(leaveCalendarDocument.getPrincipalId(),
                                            endDate.toLocalDate());
                            if (phraRecord != null
                                    && phraRecord.getLeaveCalendar().equals(calendar.getCalendarName())) {
                                // find all request actions and approve the document as the users with the request action
                                List<ActionRequest> requestList = KewApiServiceLocator.getWorkflowDocumentService()
                                        .getPendingActionRequests(docId);
                                for (ActionRequest aRequest : requestList) {
                                    if (aRequest.getActionRequested() != null
                                            && aRequest.getActionRequested().getCode()
                                                    .equals(KewApiConstants.ACTION_REQUEST_APPROVE_REQ)
                                            && StringUtils.isNotBlank(aRequest.getPrincipalId())
                                            && StringUtils.equals(aRequest.getQualifiedRoleNameLabel(),
                                                    KPMERole.PAYROLL_PROCESSOR.getRoleName())) {
                                        LmServiceLocator.getLeaveCalendarService().approveLeaveCalendar(
                                                aRequest.getPrincipalId(), leaveCalendarDocument,
                                                HrConstants.BATCH_JOB_ACTIONS.PAYROLL_JOB_APPROVE);
                                        roleMembers = getRoleMembersInDepartment(
                                                leaveCalendarDocument.getAssignments(), KPMENamespace.KPME_LM);
                                        subject = "Payroll Batch Approved Leave Calendar Document " + docId;
                                    }
                                }
                            }
                        } else if (documentStatus.equals(DocumentStatus.INITIATED.getCode())
                                || documentStatus.equals(DocumentStatus.SAVED.getCode())) {
                            String principalId = leaveCalendarDocument.getPrincipalId();
                            PrincipalHRAttributes phraRecord = HrServiceLocator.getPrincipalHRAttributeService()
                                    .getPrincipalCalendar(principalId, endDate.toLocalDate());
                            if (phraRecord != null
                                    && phraRecord.getLeaveCalendar().equals(calendar.getCalendarName())) {
                                LmServiceLocator.getLeaveCalendarService().routeLeaveCalendar(batchUserPrincipalId,
                                        leaveCalendarDocument, HrConstants.BATCH_JOB_ACTIONS.BATCH_JOB_ROUTE);
                                needToReschedule = true;
                            }
                        }
                    }
                }
            }
            sendNotifications(subject, roleMembers, workAreas);
            if (needToReschedule) {
                rescheduleJob(context);
            }

        } else {
            String principalName = getBatchUserPrincipalName();
            LOG.error("Could not run batch jobs due to missing batch user " + principalName);
        }
    }

    private List<RoleMember> getRoleMembersInDepartment(List<Assignment> assignments,
            final KPMENamespace namespace) {
        List<RoleMember> roleMembers = new ArrayList<RoleMember>();
        List<KeyValue> groupKeyDepts = new ArrayList<KeyValue>();
        for (Assignment assignment : assignments) {
            groupKeyDepts.add(new ConcreteKeyValue(assignment.getGroupKeyCode(), assignment.getDept()));
        }
        for (KeyValue grpKeyDept : groupKeyDepts) {
            List<RoleMember> roleMembersInDepartment = new ArrayList<RoleMember>();
            roleMembersInDepartment = HrServiceLocator.getKPMERoleService().getRoleMembersInDepartment(
                    namespace.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR.getRoleName(), grpKeyDept.getValue(),
                    grpKeyDept.getKey(), LocalDate.now().toDateTime(LocalTime.now()), true);
            for (RoleMember roleMember : roleMembersInDepartment) {
                if (!roleMembers.contains(roleMember)) {
                    roleMembers.add(roleMember);
                }
            }
        }
        return roleMembers;
    }

    private void sendNotifications(String subject, List<RoleMember> roleMembers, List<Long> workAreas) {
        String message = new String(
                "FYI, the document listed in the subject of this email has been batch approved by an automated Payroll approval job");
        //roleMembers should be non empty only if approval of leave calendar or timesheet has occured.
        List<String> roleMemberIdList = new ArrayList<String>();
        for (RoleMember roleMember : roleMembers) {
            roleMemberIdList.add(roleMember.getMemberId());
        }
        String[] roleMemberIds = new String[roleMemberIdList.size()];
        HrServiceLocator.getKPMENotificationService().sendNotification(subject, message,
                roleMemberIdList.toArray(roleMemberIds));
    }

    private void rescheduleJob(JobExecutionContext context) throws JobExecutionException {
        try {
            Scheduler scheduler = context.getScheduler();
            Trigger oldTrigger = context.getTrigger();

            DateTime newStartTime = new DateTime().plusMinutes(5);
            String newTriggerName = BatchJobUtil.getTriggerName(PayrollApprovalJob.class, newStartTime);
            Trigger newTrigger = new SimpleTrigger(newTriggerName, oldTrigger.getGroup(), newStartTime.toDate());
            newTrigger.setJobName(oldTrigger.getJobName());
            newTrigger.setJobGroup(oldTrigger.getJobGroup());

            LOG.info("Rescheduing " + newTrigger.getFullJobName() + " to be run on " + newTrigger.getStartTime());

            scheduler.rescheduleJob(oldTrigger.getName(), oldTrigger.getGroup(), newTrigger);
        } catch (SchedulerException se) {
            LOG.error("Failure to execute job due to SchedulerException", se);
            //         throw new JobExecutionException(se);
        }
    }

}