Java tutorial
/** * 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); } } }