org.kuali.kpme.tklm.leave.approval.service.LeaveApprovalServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.kuali.kpme.tklm.leave.approval.service.LeaveApprovalServiceImpl.java

Source

/**
 * Copyright 2004-2013 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.leave.approval.service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.kuali.kpme.core.accrualcategory.AccrualCategory;
import org.kuali.kpme.core.accrualcategory.rule.AccrualCategoryRule;
import org.kuali.kpme.core.assignment.Assignment;
import org.kuali.kpme.core.calendar.entry.CalendarEntry;
import org.kuali.kpme.core.principal.PrincipalHRAttributes;
import org.kuali.kpme.core.service.HrServiceLocator;
import org.kuali.kpme.core.util.HrConstants;
import org.kuali.kpme.tklm.common.LMConstants;
import org.kuali.kpme.tklm.leave.approval.web.ApprovalLeaveSummaryRow;
import org.kuali.kpme.tklm.leave.block.LeaveBlock;
import org.kuali.kpme.tklm.leave.calendar.validation.LeaveCalendarValidationUtil;
import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
import org.kuali.kpme.tklm.leave.summary.LeaveSummary;
import org.kuali.kpme.tklm.leave.summary.LeaveSummaryRow;
import org.kuali.kpme.tklm.leave.workflow.LeaveCalendarDocumentHeader;
import org.kuali.rice.kew.api.KewApiServiceLocator;
import org.kuali.rice.kew.api.note.Note;
import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
import org.kuali.rice.kim.api.services.KimApiServiceLocator;

public class LeaveApprovalServiceImpl implements LeaveApprovalService {

    public static final int DAYS_WINDOW_DELTA = 31;

    @Override
    public List<ApprovalLeaveSummaryRow> getLeaveApprovalSummaryRows(List<String> principalIds,
            CalendarEntry payCalendarEntry, List<Date> leaveSummaryDates) {
        DateTime payBeginDate = payCalendarEntry.getBeginPeriodFullDateTime();
        DateTime payEndDate = payCalendarEntry.getEndPeriodFullDateTime();
        List<ApprovalLeaveSummaryRow> rowList = new ArrayList<ApprovalLeaveSummaryRow>();

        for (String principalId : principalIds) {

            ApprovalLeaveSummaryRow aRow = new ApprovalLeaveSummaryRow();
            List<Note> notes = new ArrayList<Note>();
            //            List<String> warnings = new ArrayList<String>();
            EntityNamePrincipalName name = KimApiServiceLocator.getIdentityService()
                    .getDefaultNamesForPrincipalId(principalId);
            aRow.setName(name != null && name.getDefaultName() != null
                    && name.getDefaultName().getCompositeName() != null ? name.getDefaultName().getCompositeName()
                            : principalId);
            aRow.setPrincipalId(principalId);

            String lastApprovedString = "No previous approved leave calendar information";
            LeaveCalendarDocumentHeader lastApprovedDoc = LmServiceLocator.getLeaveCalendarDocumentHeaderService()
                    .getMaxEndDateApprovedLeaveCalendar(principalId);
            if (lastApprovedDoc != null) {
                lastApprovedString = "Last Approved: "
                        + (new SimpleDateFormat("MMM yyyy")).format(lastApprovedDoc.getBeginDate());
            }
            aRow.setLastApproveMessage(lastApprovedString);

            LeaveCalendarDocumentHeader aDoc = LmServiceLocator.getLeaveCalendarDocumentHeaderService()
                    .getDocumentHeader(principalId, payBeginDate, payEndDate);
            if (aDoc != null) {
                aRow.setDocumentId(aDoc.getDocumentId());
                aRow.setApprovalStatus(HrConstants.DOC_ROUTE_STATUS.get(aDoc.getDocumentStatus()));
                notes = getNotesForDocument(aDoc.getDocumentId());
            }
            List<LeaveCalendarDocumentHeader> docList = LmServiceLocator.getLeaveCalendarDocumentHeaderService()
                    .getApprovalDelinquentDocumentHeaders(principalId);
            if (docList.size() > LMConstants.DELINQUENT_LEAVE_CALENDARS_LIMIT) {
                aRow.setMoreThanOneCalendar(true);
            }

            List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId,
                    payBeginDate.toLocalDate(), payEndDate.toLocalDate());

            aRow.setLeaveBlockList(leaveBlocks);
            Map<Date, Map<String, BigDecimal>> earnCodeLeaveHours = getEarnCodeLeaveHours(leaveBlocks,
                    leaveSummaryDates);
            aRow.setEarnCodeLeaveHours(earnCodeLeaveHours);
            aRow.setNotes(notes);

            Map<String, Set<String>> allMessages = findWarnings(principalId, payCalendarEntry, leaveBlocks);

            Map<String, Set<String>> transactionalMessages = findTransactionsWithinPeriod(aDoc, payCalendarEntry);

            allMessages.get("infoMessages").addAll(transactionalMessages.get("infoMessages"));
            allMessages.get("warningMessages").addAll(transactionalMessages.get("warningMessages"));
            allMessages.get("actionMessages").addAll(transactionalMessages.get("actionMessages"));

            List<String> warningMessages = new ArrayList<String>();
            warningMessages.addAll(allMessages.get("warningMessages"));
            warningMessages.addAll(allMessages.get("infoMessages"));
            warningMessages.addAll(allMessages.get("actionMessages"));

            aRow.setWarnings(warningMessages); //these are only warning messages.

            rowList.add(aRow);

        }

        return rowList;
    }

    private Map<String, Set<String>> findTransactionsWithinPeriod(LeaveCalendarDocumentHeader aDoc,
            CalendarEntry payCalendarEntry) {
        Map<String, Set<String>> allMessages = new HashMap<String, Set<String>>();

        allMessages.put("actionMessages", new HashSet<String>());
        allMessages.put("infoMessages", new HashSet<String>());
        allMessages.put("warningMessages", new HashSet<String>());
        if (aDoc != null) {
            allMessages = LeaveCalendarValidationUtil.validatePendingTransactions(aDoc.getPrincipalId(),
                    payCalendarEntry.getBeginPeriodFullDateTime().toLocalDate(),
                    payCalendarEntry.getEndPeriodFullDateTime().toLocalDate());
        }
        return allMessages;
    }

    private Map<String, Set<String>> findWarnings(String principalId, CalendarEntry calendarEntry,
            List<LeaveBlock> leaveBlocks) {
        //        List<String> warnings = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks(leaveBlocks);
        Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil
                .getWarningMessagesForLeaveBlocks(leaveBlocks);
        //get LeaveSummary and check for warnings
        Map<String, Set<LeaveBlock>> eligibilities;
        try {
            eligibilities = LmServiceLocator.getAccrualCategoryMaxBalanceService()
                    .getMaxBalanceViolations(calendarEntry, principalId);
        } catch (Exception e) {
            eligibilities = null;
        }
        if (eligibilities != null) {
            for (Entry<String, Set<LeaveBlock>> entry : eligibilities.entrySet()) {
                for (LeaveBlock block : entry.getValue()) {

                    AccrualCategoryRule rule = HrServiceLocator.getAccrualCategoryRuleService()
                            .getAccrualCategoryRule(block.getAccrualCategoryRuleId());
                    if (rule != null) {
                        AccrualCategory accrualCategory = HrServiceLocator.getAccrualCategoryService()
                                .getAccrualCategory(rule.getLmAccrualCategoryId());
                        if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.TRANSFER)) {
                            //Todo: add link to balance transfer
                            allMessages.get("warningMessages").add("Accrual Category '"
                                    + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages
                        } else if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) {
                            //Todo: compute and display amount of time lost.
                            allMessages.get("warningMessages").add("Accrual Category '"
                                    + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages
                        } else if (rule.getActionAtMaxBalance().equals(HrConstants.ACTION_AT_MAX_BALANCE.PAYOUT)) {
                            //Todo: display information about the payout
                            allMessages.get("warningMessages").add("Accrual Category '"
                                    + accrualCategory.getAccrualCategory() + "' is over max balance."); //warningMessages

                        }

                    }
                }
            }
        }
        return allMessages;
    }

    @Override
    public Map<Date, Map<String, BigDecimal>> getEarnCodeLeaveHours(List<LeaveBlock> leaveBlocks,
            List<Date> leaveSummaryDates) {
        Map<Date, Map<String, BigDecimal>> earnCodeLeaveHours = new LinkedHashMap<Date, Map<String, BigDecimal>>();

        for (Date leaveSummaryDate : leaveSummaryDates) {
            earnCodeLeaveHours.put(leaveSummaryDate, new LinkedHashMap<String, BigDecimal>());
        }

        for (LeaveBlock lb : leaveBlocks) {
            DateTime leaveDate = lb.getLeaveLocalDate().toDateTimeAtStartOfDay();

            if (earnCodeLeaveHours.get(leaveDate.toDate()) != null) {
                Map<String, BigDecimal> leaveHours = earnCodeLeaveHours.get(leaveDate.toDate());

                BigDecimal amount = lb.getLeaveAmount();
                String key = lb.getEarnCode() + "|" + lb.getRequestStatus() + "|" + lb.getLeaveBlockType();
                if (leaveHours.get(key) != null) {
                    amount = leaveHours.get(key).add(lb.getLeaveAmount());
                }

                leaveHours.put(key, amount);
            }
        }

        return earnCodeLeaveHours;
    }

    @Override
    public List<Map<String, Object>> getLeaveApprovalDetailSections(LeaveCalendarDocumentHeader lcdh) {

        List<Map<String, Object>> acRows = new ArrayList<Map<String, Object>>();

        if (lcdh == null) {
            return acRows;
        }

        String principalId = lcdh.getPrincipalId();
        CalendarEntry calendarEntry = LmServiceLocator.getLeaveCalendarService()
                .getLeaveCalendarDocument(lcdh.getDocumentId()).getCalendarEntry();
        //CalendarEntries calendarEntry = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(lcdh.getBeginDate(), lcdh.getEndDate());
        if (calendarEntry != null) {
            DateTime beginDate = calendarEntry.getBeginPeriodFullDateTime();
            DateTime endDate = calendarEntry.getEndPeriodFullDateTime();
            LeaveSummary leaveSummary;
            List<Date> leaveSummaryDates = LmServiceLocator.getLeaveSummaryService()
                    .getLeaveSummaryDates(calendarEntry);
            try {
                leaveSummary = LmServiceLocator.getLeaveSummaryService().getLeaveSummary(principalId,
                        calendarEntry);
            } catch (Exception e) {
                leaveSummary = null;
            }
            List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocks(principalId,
                    beginDate.toLocalDate(), endDate.toLocalDate());
            Map<Date, Map<String, BigDecimal>> accrualCategoryLeaveHours = getAccrualCategoryLeaveHours(leaveBlocks,
                    leaveSummaryDates);

            //get all accrual categories of this employee
            PrincipalHRAttributes pha = HrServiceLocator.getPrincipalHRAttributeService()
                    .getPrincipalCalendar(principalId, endDate.toLocalDate());
            if (pha != null) {
                List<AccrualCategory> acList = HrServiceLocator.getAccrualCategoryService()
                        .getActiveAccrualCategoriesForLeavePlan(pha.getLeavePlan(), endDate.toLocalDate());
                for (AccrualCategory ac : acList) {
                    List<BigDecimal> acDayDetails = new ArrayList<BigDecimal>();
                    Map<String, Object> displayMap = new HashMap<String, Object>();
                    BigDecimal totalAmount = BigDecimal.ZERO;
                    displayMap.put("accrualCategory", ac.getAccrualCategory());
                    int index = 0;
                    for (Date leaveSummaryDate : leaveSummaryDates) {
                        acDayDetails.add(index, null);
                        if (accrualCategoryLeaveHours.get(leaveSummaryDate) != null) {
                            Map<String, BigDecimal> leaveHours = accrualCategoryLeaveHours.get(leaveSummaryDate);
                            if (leaveHours.containsKey(ac.getAccrualCategory())) {
                                BigDecimal amount = leaveHours.get(ac.getAccrualCategory());
                                totalAmount = totalAmount.add(amount);
                                acDayDetails.set(index, amount);
                            }
                        }
                        index++;
                    }
                    LeaveSummaryRow lsr = leaveSummary == null ? null
                            : leaveSummary.getLeaveSummaryRowForAccrualCtgy(ac.getAccrualCategory());
                    displayMap.put("periodUsage", totalAmount);
                    displayMap.put("availableBalance", BigDecimal.ZERO);
                    displayMap.put("availableBalance", lsr == null ? BigDecimal.ZERO : lsr.getLeaveBalance());
                    displayMap.put("daysDetail", acDayDetails);
                    displayMap.put("daysSize", acDayDetails.size());
                    acRows.add(displayMap);
                }
            }

        }
        return acRows;
    }

    @Override
    public List<Note> getNotesForDocument(String documentNumber) {
        return KewApiServiceLocator.getNoteService().getNotes(documentNumber);
    }

    @Override
    public Map<Date, Map<String, BigDecimal>> getAccrualCategoryLeaveHours(List<LeaveBlock> leaveBlocks,
            List<Date> leaveSummaryDates) {
        Map<Date, Map<String, BigDecimal>> accrualCategoryLeaveHours = new LinkedHashMap<Date, Map<String, BigDecimal>>();

        for (Date leaveSummaryDate : leaveSummaryDates) {
            accrualCategoryLeaveHours.put(leaveSummaryDate, new LinkedHashMap<String, BigDecimal>());
        }

        for (LeaveBlock lb : leaveBlocks) {
            DateTime leaveDate = lb.getLeaveLocalDate().toDateTimeAtStartOfDay();

            AccrualCategory ac = HrServiceLocator.getAccrualCategoryService()
                    .getAccrualCategory(lb.getAccrualCategory(), lb.getLeaveLocalDate());
            if (ac != null && ac.getShowOnGrid().equals("Y")) {
                if (accrualCategoryLeaveHours.get(leaveDate.toDate()) != null) {
                    Map<String, BigDecimal> leaveHours = accrualCategoryLeaveHours.get(leaveDate.toDate());

                    BigDecimal amount = lb.getLeaveAmount();
                    if (leaveHours.get(ac.getAccrualCategory()) != null) {
                        amount = leaveHours.get(ac.getAccrualCategory()).add(lb.getLeaveAmount());
                    }

                    leaveHours.put(ac.getAccrualCategory(), amount);
                }
            }
        }

        return accrualCategoryLeaveHours;
    }

    @Override
    public void removeNonLeaveEmployees(List<String> principalIds) {
        if (CollectionUtils.isNotEmpty(principalIds)) {
            LocalDate asOfDate = LocalDate.now();
            List<String> idList = new ArrayList<String>();
            idList.addAll(principalIds);
            for (String principalId : idList) {
                boolean leaveFlag = false;
                List<Assignment> activeAssignments = HrServiceLocator.getAssignmentService()
                        .getAssignments(principalId, asOfDate);
                if (CollectionUtils.isNotEmpty(activeAssignments)) {
                    for (Assignment assignment : activeAssignments) {
                        if (assignment != null && assignment.getJob() != null
                                && assignment.getJob().isEligibleForLeave()) {
                            leaveFlag = true;
                            break;
                        }
                    }
                    if (!leaveFlag) { // employee is not eligible for leave, remove the id from principalIds
                        principalIds.remove(principalId);
                    }
                }
            }
        }
    }

    @Override
    public List<String> getLeavePrincipalIdsWithSearchCriteria(List<String> workAreaList, String calendarGroup,
            LocalDate effdt, LocalDate beginDate, LocalDate endDate) {
        if (CollectionUtils.isEmpty(workAreaList)) {
            return new ArrayList<String>();
        }

        List<String> principalIds = HrServiceLocator.getAssignmentService().getPrincipalIds(workAreaList, effdt,
                beginDate, endDate);
        LmServiceLocator.getLeaveApprovalService().removeNonLeaveEmployees(principalIds);

        if (CollectionUtils.isEmpty(principalIds)) {
            return new ArrayList<String>();
        }
        // use unique principalIds and selected calendarGroup to get unique ids from principalHRAttributes table
        List<String> idList = CollectionUtils.isEmpty(principalIds) ? new ArrayList<String>()
                : HrServiceLocator.getPrincipalHRAttributeService()
                        .getActiveEmployeesIdForLeaveCalendarAndIdList(calendarGroup, principalIds, endDate);

        return idList;
    }

    @Override
    public Map<String, LeaveCalendarDocumentHeader> getPrincipalDocumentHeader(List<String> principalIds,
            DateTime payBeginDate, DateTime payEndDate) {
        Map<String, LeaveCalendarDocumentHeader> principalDocumentHeader = new LinkedHashMap<String, LeaveCalendarDocumentHeader>();
        for (String principalId : principalIds) {
            LeaveCalendarDocumentHeader lcdh = LmServiceLocator.getLeaveCalendarDocumentHeaderService()
                    .getDocumentHeader(principalId, payBeginDate, payEndDate);
            if (lcdh != null) {
                principalDocumentHeader.put(principalId, lcdh);
            }
        }

        return principalDocumentHeader;
    }

    @Override
    public boolean isActiveAssignmentFoundOnJobFlsaStatus(String principalId, String flsaStatus,
            boolean chkForLeaveEligible) {
        boolean isActiveAssFound = false;
        LocalDate asOfDate = LocalDate.now();
        List<Assignment> activeAssignments = HrServiceLocator.getAssignmentService().getAssignments(principalId,
                asOfDate);
        if (activeAssignments != null && !activeAssignments.isEmpty()) {
            for (Assignment assignment : activeAssignments) {
                if (assignment != null && assignment.getJob() != null && assignment.getJob().getFlsaStatus() != null
                        && assignment.getJob().getFlsaStatus().equalsIgnoreCase(flsaStatus)) {
                    if (chkForLeaveEligible) {
                        isActiveAssFound = assignment.getJob().isEligibleForLeave();
                        if (!isActiveAssFound) {
                            continue;
                        }
                    }
                    isActiveAssFound = true;
                    break;
                }
            }
        }
        return isActiveAssFound;
    }
}