Package org.ofbiz.workeffort.workeffort

Source Code of org.ofbiz.workeffort.workeffort.WorkEffortServices

/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache 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.apache.org/licenses/LICENSE-2.0
*
* 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.ofbiz.workeffort.workeffort;

import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;

import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;

import org.ofbiz.base.util.DateRange;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.TimeDuration;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityConditionList;
import org.ofbiz.entity.condition.EntityExpr;
import org.ofbiz.entity.condition.EntityJoinOperator;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.util.EntityListIterator;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.security.Security;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceUtil;
import org.ofbiz.service.calendar.TemporalExpression;
import org.ofbiz.service.calendar.TemporalExpressionWorker;

import com.ibm.icu.util.Calendar;

/**
* WorkEffortServices - WorkEffort related Services
*/
public class WorkEffortServices {

    public static final String module = WorkEffortServices.class.getName();
    public static final String resourceError = "WorkEffortUiLabels";

    public static Map<String, Object> getWorkEffortAssignedEventsForRole(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String roleTypeId = (String) context.get("roleTypeId");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> validWorkEfforts = null;

        if (userLogin != null && userLogin.get("partyId") != null) {
            try {
                EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(
                        EntityOperator.AND,
                        EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")),
                        EntityCondition.makeCondition("roleTypeId", EntityOperator.EQUALS, roleTypeId),
                        EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "EVENT"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED")
               );
                validWorkEfforts = EntityUtil.filterByDate(
                        delegator.findList("WorkEffortAndPartyAssign", ecl, null, UtilMisc.toList("estimatedStartDate", "priority"), null, false)
               );
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        Map<String, Object> result = FastMap.newInstance();
        if (validWorkEfforts == null) {
            validWorkEfforts = FastList.newInstance();
        }
        result.put("events", validWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffortAssignedEventsForRoleOfAllParties(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        String roleTypeId = (String) context.get("roleTypeId");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> validWorkEfforts = null;

        try {
            List<EntityExpr> conditionList = FastList.newInstance();
            conditionList.add(EntityCondition.makeCondition("roleTypeId", EntityOperator.EQUALS, roleTypeId));
            conditionList.add(EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "EVENT"));
            conditionList.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"));
            conditionList.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"));
            conditionList.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"));
            conditionList.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"));

            EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(conditionList, EntityOperator.AND);
            validWorkEfforts = EntityUtil.filterByDate(
                    delegator.findList("WorkEffortAndPartyAssign", ecl, null, UtilMisc.toList("estimatedStartDate", "priority"), null, false)
           );
        } catch (GenericEntityException e) {
            Debug.logWarning(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                    "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
        }

        Map<String, Object> result = FastMap.newInstance();
        if (validWorkEfforts == null) {
            validWorkEfforts = FastList.newInstance();
        }
        result.put("events", validWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffortAssignedTasks(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> validWorkEfforts = null;

        if (userLogin != null && userLogin.get("partyId") != null) {
            try {
                EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(
                        EntityOperator.AND,
                        EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")),
                        EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "TASK"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"),
                        EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PRTYASGN_UNASSIGNED"));
                validWorkEfforts = EntityUtil.filterByDate(delegator.findList("WorkEffortAndPartyAssign", ecl, null, UtilMisc.toList("priority"), null, false));
                ecl = EntityCondition.makeCondition(
                        EntityOperator.AND,
                        EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")),
                        EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "PROD_ORDER_TASK"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_CANCELLED "),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_COMPLETED"),
                        EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_CLOSED"));
                validWorkEfforts.addAll(EntityUtil.filterByDate(delegator.findList("WorkEffortAndPartyAssign", ecl, null, UtilMisc.toList("createdDate DESC"), null, false)));
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        Map<String, Object> result = FastMap.newInstance();
        if (validWorkEfforts == null) validWorkEfforts = FastList.newInstance();
        validWorkEfforts = WorkEffortWorker.removeDuplicateWorkEfforts(validWorkEfforts);
        result.put("tasks", validWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffortAssignedActivities(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> validWorkEfforts = null;

        if (userLogin != null && userLogin.get("partyId") != null) {
            try {
                List<EntityExpr> constraints = FastList.newInstance();

                constraints.add(EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")));
                constraints.add(EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "ACTIVITY"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PRTYASGN_UNASSIGNED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_TERMINATED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_ABORTED"));

                EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(constraints, EntityOperator.AND);
                validWorkEfforts = EntityUtil.filterByDate(delegator.findList("WorkEffortAndPartyAssign", ecl, null, UtilMisc.toList("priority"), null, false));
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        Map<String, Object> result = FastMap.newInstance();
        if (validWorkEfforts == null) validWorkEfforts = FastList.newInstance();
        result.put("activities", validWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffortAssignedActivitiesByRole(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> roleWorkEfforts = null;

        if (userLogin != null && userLogin.get("partyId") != null) {
            try {
                List<EntityExpr> constraints = FastList.newInstance();

                constraints.add(EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")));
                constraints.add(EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "ACTIVITY"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PRTYASGN_UNASSIGNED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_TERMINATED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_ABORTED"));

                EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(constraints);
                roleWorkEfforts = EntityUtil.filterByDate(
                        delegator.findList("WorkEffortPartyAssignByRole", ecl, null, UtilMisc.toList("priority"), null, false)
               );
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        Map<String, Object> result = FastMap.newInstance();
        if (roleWorkEfforts == null) roleWorkEfforts = FastList.newInstance();
        result.put("roleActivities", roleWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffortAssignedActivitiesByGroup(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");

        List<GenericValue> groupWorkEfforts = null;

        if (userLogin != null && userLogin.get("partyId") != null) {
            try {
                List<EntityExpr> constraints = FastList.newInstance();

                constraints.add(EntityCondition.makeCondition("partyId", EntityOperator.EQUALS, userLogin.get("partyId")));
                constraints.add(EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "ACTIVITY"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DECLINED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_DELEGATED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"));
                constraints.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "PRTYASGN_UNASSIGNED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_COMPLETED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_TERMINATED"));
                constraints.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "WF_ABORTED"));

                EntityConditionList<EntityExpr> ecl = EntityCondition.makeCondition(constraints);
                groupWorkEfforts = EntityUtil.filterByDate(
                        delegator.findList("WorkEffortPartyAssignByGroup", ecl, null, UtilMisc.toList("priority"), null, false)
               );
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortNotFound", UtilMisc.toMap("errorString", e.toString()), locale));
            }
        }

        Map<String, Object> result = FastMap.newInstance();
        if (groupWorkEfforts == null) groupWorkEfforts = FastList.newInstance();
        result.put("groupActivities", groupWorkEfforts);
        return result;
    }

    public static Map<String, Object> getWorkEffort(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Security security = ctx.getSecurity();
        Map<String, Object> resultMap = FastMap.newInstance();

        String workEffortId = (String) context.get("workEffortId");
        GenericValue workEffort = null;

        try {
            workEffort = delegator.findOne("WorkEffort", false, "workEffortId", workEffortId);
        } catch (GenericEntityException e) {
            Debug.logWarning(e, module);
        }

        Boolean canView = null;
        List<GenericValue> workEffortPartyAssignments = null;
        Boolean tryEntity = null;
        GenericValue currentStatus = null;

        if (workEffort == null) {
            tryEntity = Boolean.FALSE;
            canView = Boolean.TRUE;

            String statusId = (String) context.get("currentStatusId");

            if (UtilValidate.isNotEmpty(statusId)) {
                try {
                    currentStatus = delegator.findByPrimaryKeyCache("StatusItem", UtilMisc.toMap("statusId", statusId));
                } catch (GenericEntityException e) {
                    Debug.logWarning(e, module);
                }
            }
        } else {
            // get a list of workEffortPartyAssignments, if empty then this user CANNOT view the event, unless they have permission to view all
            if (userLogin != null && userLogin.get("partyId") != null && workEffortId != null) {
                try {
                    workEffortPartyAssignments = delegator.findByAnd("WorkEffortPartyAssignment", UtilMisc.toMap("workEffortId", workEffortId, "partyId", userLogin.get("partyId")));
                } catch (GenericEntityException e) {
                    Debug.logWarning(e, module);
                }
            }
            canView = (UtilValidate.isNotEmpty(workEffortPartyAssignments)) ? Boolean.TRUE : Boolean.FALSE;
            if (!canView.booleanValue() && security.hasEntityPermission("WORKEFFORTMGR", "_VIEW", userLogin)) {
                canView = Boolean.TRUE;
            }

            tryEntity = Boolean.TRUE;

            if (workEffort.get("currentStatusId") != null) {
                try {
                    currentStatus = delegator.findByPrimaryKeyCache("StatusItem", UtilMisc.toMap("statusId", workEffort.get("currentStatusId")));
                } catch (GenericEntityException e) {
                    Debug.logWarning(e, module);
                }
            }
        }

        if (workEffortId != null) resultMap.put("workEffortId", workEffortId);
        if (workEffort != null) resultMap.put("workEffort", workEffort);
        if (canView != null) resultMap.put("canView", canView);
        if (workEffortPartyAssignments != null) resultMap.put("partyAssigns", workEffortPartyAssignments);
        if (tryEntity != null) resultMap.put("tryEntity", tryEntity);
        if (currentStatus != null) resultMap.put("currentStatusItem", currentStatus);
        return resultMap;
    }

    private static TreeMap<DateRange, List<Map<String, Object>>> groupCalendarEntriesByDateRange(DateRange inDateRange, List<Map<String, Object>> calendarEntries) {
        TreeMap<DateRange, List<Map<String, Object>>> calendarEntriesByDateRange = new TreeMap<DateRange, List<Map<String, Object>>>();
        TreeSet<Date> dateBoundaries = new TreeSet<Date>();
        if (inDateRange != null) {
            dateBoundaries.add(inDateRange.start());
            dateBoundaries.add(inDateRange.end());
        }
        for (Map<String, Object>calendarEntry: calendarEntries) {
            DateRange calEntryRange = (DateRange)calendarEntry.get("calEntryRange");
            dateBoundaries.add(calEntryRange.start());
            dateBoundaries.add(calEntryRange.end());
        }
        Date prevDateBoundary = null;
        for (Date dateBoundary: dateBoundaries) {
            if (prevDateBoundary != null) {
                DateRange dateRange = new DateRange(prevDateBoundary, dateBoundary);
                for (Map<String, Object>calendarEntry: calendarEntries) {
                    DateRange calEntryRange = (DateRange)calendarEntry.get("calEntryRange");
                    if (calEntryRange.intersectsRange(dateRange) && !(calEntryRange.end().equals(dateRange.start()) || calEntryRange.start().equals(dateRange.end()))) {
                        List<Map<String, Object>> calendarEntryByDateRangeList = calendarEntriesByDateRange.get(dateRange);
                        if (calendarEntryByDateRangeList == null) {
                            calendarEntryByDateRangeList = FastList.newInstance();
                        }
                        calendarEntryByDateRangeList.add(calendarEntry);
                        calendarEntriesByDateRange.put(dateRange, calendarEntryByDateRangeList);
                    }
                }
            }
            prevDateBoundary = dateBoundary;
        }
        return calendarEntriesByDateRange;
    }

    private static List<EntityCondition> getDefaultWorkEffortExprList(String calendarType, Collection<String> partyIds, String workEffortTypeId, List<EntityCondition> cancelledCheckAndList) {
        List<EntityCondition> entityExprList = FastList.newInstance();
        if (cancelledCheckAndList != null) {
            entityExprList.addAll(cancelledCheckAndList);
        }
        List<EntityExpr> typesList = FastList.newInstance();
        if (UtilValidate.isNotEmpty(workEffortTypeId)) {
            typesList.add(EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, workEffortTypeId));
        }
        if ("CAL_PERSONAL".equals(calendarType)) {
            // public events are always included to the "personal calendar"
            List<EntityCondition> publicEvents = UtilMisc.<EntityCondition>toList(
                    EntityCondition.makeCondition("scopeEnumId", EntityOperator.EQUALS, "WES_PUBLIC"),
                    EntityCondition.makeCondition("parentTypeId", EntityOperator.EQUALS, "EVENT")
                    );
            if (UtilValidate.isNotEmpty(partyIds)) {
                entityExprList.add(
                        EntityCondition.makeCondition(UtilMisc.toList(
                                EntityCondition.makeCondition("partyId", EntityOperator.IN, partyIds),
                                EntityCondition.makeCondition(publicEvents, EntityJoinOperator.AND)
                        ), EntityJoinOperator.OR));
            }
        }
        if ("CAL_MANUFACTURING".equals(calendarType)) {
            entityExprList.add(
                    EntityCondition.makeCondition(UtilMisc.toList(
                            EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "PROD_ORDER_HEADER"),
                            EntityCondition.makeCondition("workEffortTypeId", EntityOperator.EQUALS, "PROD_ORDER_TASK")
                    ), EntityJoinOperator.OR));
        }
        EntityCondition typesCondition = null;
        if (typesList.size() == 0) {
            return entityExprList;
        } else if (typesList.size() == 1) {
            typesCondition = typesList.get(0);
        } else {
            typesCondition = EntityCondition.makeCondition(typesList, EntityJoinOperator.OR);
        }
        entityExprList.add(typesCondition);
        return entityExprList;
    }

    /**
     * Get Work Efforts by period.
     * <p>
     * This method takes the following parameters:
     * </p>
     * <ul>
     * <li>start - TimeStamp (Period start date/time)</li>
     * <li>numPeriods - Integer</li>
     * <li>periodType - Integer (see java.util.Calendar)</li>
     * <li>eventStatus - String</li>
     * <li>partyId - String</li>
     * <li>partyIds - List</li>
     * <li>facilityId - String</li>
     * <li>fixedAssetId - String</li>
     * <li>filterOutCanceledEvents - Boolean</li>
     * <li>entityExprList - List</li>
     * </ul>
     * <p>
     * The method will find all matching Work Effort events and return them as a List called
     * <b>periods</b> - one List element per period. It also returns a
     * <b>maxConcurrentEntries</b> Integer - which indicates the maximum number of
     * Work Efforts found in one period.
     * </p>
     * <p>
     * Each <b>periods</b> list element is a Map containing the following
     * key/value pairs:
     * </p>
     * <ul>
     * <li>start - TimeStamp (Period start date/time)</li>
     * <li>end - TimeStamp (Period end date/time)</li>
     * <li>calendarEntries - List of Maps. Each Map contains the following
     * key/value pairs:</li>
     * <ul>
     * <li>workEffort - GenericValue</li>
     * <li>periodSpan - Integer (Number of periods this Work Effort spans)</li>
     * <li>startOfPeriod - Boolean (true if this is the first occurrence in the period range)</li>
     * </ul>
     * </ul>
     */

    public static Map<String, Object> getWorkEffortEventsByPeriod(DispatchContext ctx, Map<String, ? extends Object> context) {

        /*
         To create testdata for  this function for  fixedasset/facility

        1) go to Manufacturing -> JobShop, then click on "create new Production run":
                https://localhost:8443/manufacturing/control/CreateProductionRun
        2) enter as productId "PROD_MANUF", quantity 1, start date tomorrow and press the submit button
    `    3) in the next screen, click on the "Confirm" link (top part of the sccreen)

        Now you have a confirmed production run (starting tomorrow) happening in facility "WebStoreWarehouse",
        with a task happening in fixed asset "WORKCENTER_COST"

        In the calendars screen, selecting the proper facility you should see the work effort associated to the production run;
        if you select the proper fixed asset you should see the task.

         */
        Delegator delegator = ctx.getDelegator();
        Security security = ctx.getSecurity();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        TimeZone timeZone = (TimeZone) context.get("timeZone");

        Timestamp startDay = (Timestamp) context.get("start");
        Integer numPeriodsInteger = (Integer) context.get("numPeriods");

        String calendarType = (String) context.get("calendarType");
        if (UtilValidate.isEmpty(calendarType)) {
            calendarType = "CAL_PERSONAL";
        }
        String partyId = (String) context.get("partyId");
        Collection<String> partyIds = UtilGenerics.checkCollection(context.get("partyIds"));
        String facilityId = (String) context.get("facilityId");
        String fixedAssetId = (String) context.get("fixedAssetId");
        // Debug.logInfo("======by period for fixedAsset: " + fixedAssetId + " facilityId: " + facilityId + "partyId: " + partyId + " entityExprList:" + (List) context.get("entityExprList"));
        String workEffortTypeId = (String) context.get("workEffortTypeId");
        Boolean filterOutCanceledEvents = (Boolean) context.get("filterOutCanceledEvents");
        if (filterOutCanceledEvents == null) {
            filterOutCanceledEvents = Boolean.FALSE;
        }

        // To be returned, the max concurrent entries for a single period
        int maxConcurrentEntries = 0;

        Integer periodTypeObject = (Integer) context.get("periodType");
        int periodType = 0;
        if (periodTypeObject != null) {
            periodType = periodTypeObject.intValue();
        }

        int numPeriods = 0;
        if (numPeriodsInteger != null) {
            numPeriods = numPeriodsInteger.intValue();
        }

        // get a timestamp (date) for the beginning of today and for beginning of numDays+1 days from now
        Timestamp startStamp = UtilDateTime.getDayStart(startDay, timeZone, locale);
        Timestamp endStamp = UtilDateTime.adjustTimestamp(startStamp, periodType, 1, timeZone, locale);
        long periodLen = endStamp.getTime() - startStamp.getTime();
        endStamp = UtilDateTime.adjustTimestamp(startStamp, periodType, numPeriods, timeZone, locale);

        // Get the WorkEfforts
        List<GenericValue> validWorkEfforts = null;
        Collection<String> partyIdsToUse = partyIds;
        if (partyIdsToUse == null) {
            partyIdsToUse = FastSet.newInstance();
        }
        if (UtilValidate.isNotEmpty(partyId)) {
            if (partyId.equals(userLogin.getString("partyId")) || security.hasEntityPermission("WORKEFFORTMGR", "_VIEW", userLogin)) {
                partyIdsToUse.add(partyId);
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortPartyPermissionError", UtilMisc.toMap("partyId", partyId), locale));
            }
        } else {
            if ("CAL_PERSONAL".equals(calendarType) && UtilValidate.isNotEmpty(userLogin.getString("partyId"))) {
                partyIdsToUse.add(userLogin.getString("partyId"));
            }
        }

        // cancelled status id's
        List<EntityCondition> cancelledCheckAndList = UtilMisc.<EntityCondition>toList(
                EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "EVENT_CANCELLED"),
                EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "CAL_CANCELLED"),
                EntityCondition.makeCondition("currentStatusId", EntityOperator.NOT_EQUAL, "PRUN_CANCELLED"));


        List<EntityCondition> entityExprList = UtilGenerics.checkList(context.get("entityExprList"));
        if (entityExprList == null) {
            entityExprList = getDefaultWorkEffortExprList(calendarType, partyIdsToUse, workEffortTypeId, cancelledCheckAndList);
        }

        if (UtilValidate.isNotEmpty(facilityId)) {
            entityExprList.add(EntityCondition.makeCondition("facilityId", EntityOperator.EQUALS, facilityId));
        }
        if (UtilValidate.isNotEmpty(fixedAssetId)) {
            entityExprList.add(EntityCondition.makeCondition("fixedAssetId", EntityOperator.EQUALS, fixedAssetId));
        }

        // should have at least a start date
        EntityCondition startDateRequired = EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                EntityCondition.makeCondition("estimatedStartDate", EntityOperator.NOT_EQUAL, null),
                EntityCondition.makeCondition("actualStartDate", EntityOperator.NOT_EQUAL, null)
        ), EntityJoinOperator.OR);

        List<EntityCondition> periodCheckAndlList = UtilMisc.<EntityCondition>toList(
                startDateRequired,
                // the startdate should be less than the period end
                EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                        EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                                EntityCondition.makeCondition("actualStartDate", EntityOperator.EQUALS, null),
                                EntityCondition.makeCondition("estimatedStartDate", EntityOperator.NOT_EQUAL, null),
                                EntityCondition.makeCondition("estimatedStartDate", EntityOperator.LESS_THAN_EQUAL_TO, endStamp)
                        ), EntityJoinOperator.AND),
                        EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                                EntityCondition.makeCondition("actualStartDate", EntityOperator.NOT_EQUAL, null),
                                EntityCondition.makeCondition("actualStartDate", EntityOperator.LESS_THAN_EQUAL_TO, endStamp)
                        ), EntityJoinOperator.AND)
                ), EntityJoinOperator.OR),
                // if the completion date is not null then it should be larger than the period start
                EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                        // can also be empty
                        EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                                EntityCondition.makeCondition("estimatedCompletionDate", EntityOperator.EQUALS, null),
                                EntityCondition.makeCondition("actualCompletionDate", EntityOperator.EQUALS, null)
                        ), EntityJoinOperator.AND),
                        // check estimated value if the actual is not provided
                        EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                                EntityCondition.makeCondition("actualCompletionDate", EntityOperator.EQUALS, null),
                                EntityCondition.makeCondition("estimatedCompletionDate", EntityOperator.NOT_EQUAL, null),
                                EntityCondition.makeCondition("estimatedCompletionDate", EntityOperator.GREATER_THAN_EQUAL_TO, startStamp)
                        ), EntityJoinOperator.AND),
                        // at last check the actual value
                        EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(
                                EntityCondition.makeCondition("actualCompletionDate", EntityOperator.NOT_EQUAL, null),
                                EntityCondition.makeCondition("actualCompletionDate", EntityOperator.GREATER_THAN_EQUAL_TO, startStamp)
                        ), EntityJoinOperator.AND)
                ), EntityJoinOperator.OR));

        entityExprList.addAll(periodCheckAndlList);

        // (non cancelled) recurring events
        List<EntityCondition> recurringEvents = UtilMisc.<EntityCondition>toList(EntityCondition.makeCondition("tempExprId", EntityOperator.NOT_EQUAL, null));
        if (filterOutCanceledEvents.booleanValue()) {
            recurringEvents.addAll(cancelledCheckAndList);
        }

        EntityCondition eclTotal = EntityCondition.makeCondition(UtilMisc.toList(
                EntityCondition.makeCondition(entityExprList, EntityJoinOperator.AND),
                EntityCondition.makeCondition(recurringEvents, EntityJoinOperator.AND)
                ), EntityJoinOperator.OR);

        List<String> orderByList = UtilMisc.toList("estimatedStartDate");
        try {
            List<GenericValue> tempWorkEfforts = null;
            if (UtilValidate.isNotEmpty(partyIdsToUse)) {
                // Debug.logInfo("=====conditions for party: " + eclTotal);
                tempWorkEfforts = EntityUtil.filterByDate(delegator.findList("WorkEffortAndPartyAssignAndType", eclTotal, null, orderByList, null, false));
            } else {
                tempWorkEfforts = delegator.findList("WorkEffort", eclTotal, null, orderByList, null, false);
            }
            if (!"CAL_PERSONAL".equals(calendarType) && UtilValidate.isNotEmpty(fixedAssetId)) {
                // Get "new style" work efforts
                tempWorkEfforts.addAll(EntityUtil.filterByDate(delegator.findList("WorkEffortAndFixedAssetAssign", eclTotal, null, orderByList, null, false)));
            }
            validWorkEfforts = WorkEffortWorker.removeDuplicateWorkEfforts(tempWorkEfforts);
        } catch (GenericEntityException e) {
            Debug.logWarning(e, module);
        }

        // Split the WorkEffort list into a map with entries for each period, period start is the key
        List<Map<String, Object>> periods = FastList.newInstance();
        if (validWorkEfforts != null) {
            List<DateRange> periodRanges = FastList.newInstance();
            for (int i = 0; i < numPeriods; i++) {
                Timestamp curPeriodStart = UtilDateTime.adjustTimestamp(startStamp, periodType, i, timeZone, locale);
                Timestamp curPeriodEnd = UtilDateTime.adjustTimestamp(curPeriodStart, periodType, 1, timeZone, locale);
                curPeriodEnd = new Timestamp(curPeriodEnd.getTime() - 1);
                periodRanges.add(new DateRange(curPeriodStart, curPeriodEnd));
            }
            try {
                // Process recurring work efforts
                Set<GenericValue> exclusions = FastSet.newInstance();
                Set<GenericValue> inclusions = FastSet.newInstance();
                DateRange range = new DateRange(startStamp, endStamp);
                Calendar cal = UtilDateTime.toCalendar(startStamp, timeZone, locale);
                for (GenericValue workEffort : validWorkEfforts) {
                    if (UtilValidate.isNotEmpty(workEffort.getString("tempExprId"))) {
                        // check if either the workeffort is public or the requested party is a member
                        if (UtilValidate.isNotEmpty(partyIdsToUse) && !workEffort.getString("scopeEnumId").equals("WES_PUBLIC") && !partyIdsToUse.contains(workEffort.getString("partyId"))) {
                            continue;
                        }
                        TemporalExpression tempExpr = TemporalExpressionWorker.getTemporalExpression(delegator, workEffort.getString("tempExprId"));
                        Set<Date> occurrences = tempExpr.getRange(range, cal);
                        for (Date occurrence : occurrences) {
                            for (DateRange periodRange : periodRanges) {
                                if (periodRange.includesDate(occurrence)) {
                                    GenericValue cloneWorkEffort = (GenericValue) workEffort.clone();
                                    TimeDuration duration = TimeDuration.fromNumber(workEffort.getDouble("estimatedMilliSeconds"));
                                    if (!duration.isZero()) {
                                        Calendar endCal = UtilDateTime.toCalendar(occurrence, timeZone, locale);
                                        Date endDate = duration.addToCalendar(endCal).getTime();
                                        cloneWorkEffort.set("estimatedStartDate", new Timestamp(occurrence.getTime()));
                                        cloneWorkEffort.set("estimatedCompletionDate", new Timestamp(endDate.getTime()));
                                    } else {
                                        cloneWorkEffort.set("estimatedStartDate", periodRange.startStamp());
                                        cloneWorkEffort.set("estimatedCompletionDate", periodRange.endStamp());
                                    }
                                    inclusions.add(cloneWorkEffort);
                                }
                            }
                        }
                        exclusions.add(workEffort);
                    }
                }
                validWorkEfforts.removeAll(exclusions);
                validWorkEfforts.addAll(inclusions);
            } catch (GenericEntityException e) {
                Debug.logWarning(e, module);
            }

            // For each period in the set we check all work efforts to see if they fall within range
            boolean firstEntry = true;
            for (DateRange periodRange : periodRanges) {
                List<Map<String, Object>> curWorkEfforts = FastList.newInstance();
                Map<String, Object> entry = FastMap.newInstance();
                for (GenericValue workEffort : validWorkEfforts) {
                    Timestamp startDate = workEffort.getTimestamp("estimatedStartDate");
                    if (workEffort.getTimestamp("actualStartDate") != null) {
                        startDate = workEffort.getTimestamp("actualStartDate");
                    }
                    Timestamp endDate = workEffort.getTimestamp("estimatedCompletionDate");
                    if (workEffort.getTimestamp("actualCompletionDate") != null) {
                        endDate = workEffort.getTimestamp("actualCompletionDate");
                    }
                    if (endDate == null) endDate = startDate;
                    DateRange weRange = new DateRange(startDate, endDate);
                    if (periodRange.intersectsRange(weRange)) {
                        Map<String, Object> calEntry = FastMap.newInstance();
                        calEntry.put("workEffort", workEffort);
                        long length = ((weRange.end().after(endStamp) ? endStamp.getTime() : weRange.end().getTime()) - (weRange.start().before(startStamp) ? startStamp.getTime() : weRange.start().getTime()));
                        int periodSpan = (int) Math.ceil((double) length / periodLen);
                        calEntry.put("periodSpan", Integer.valueOf(periodSpan));
                        DateRange calEntryRange = new DateRange((weRange.start().before(startStamp) ? startStamp : weRange.start()), (weRange.end().after(endStamp) ? endStamp : weRange.end()));
                        calEntry.put("calEntryRange", calEntryRange);
                        if (firstEntry) {
                            // If this is the first period any valid entry is starting here
                            calEntry.put("startOfPeriod", Boolean.TRUE);
                            firstEntry = false;
                        } else {
                            boolean startOfPeriod = ((weRange.start().getTime() - periodRange.start().getTime()) >= 0);
                            calEntry.put("startOfPeriod", Boolean.valueOf(startOfPeriod));
                        }
                        curWorkEfforts.add(calEntry);
                    }
                }
                int numEntries = curWorkEfforts.size();
                if (numEntries > maxConcurrentEntries) {
                    maxConcurrentEntries = numEntries;
                }
                entry.put("start", periodRange.startStamp());
                entry.put("end", periodRange.endStamp());
                entry.put("calendarEntries", curWorkEfforts);
                entry.put("calendarEntriesByDateRange", groupCalendarEntriesByDateRange(periodRange, curWorkEfforts));
                periods.add(entry);
            }
        }
        Map<String, Object> result = FastMap.newInstance();
        result.put("periods", periods);
        result.put("maxConcurrentEntries", Integer.valueOf(maxConcurrentEntries));
        return result;
    }

    public static Map<String, Object> getProductManufacturingSummaryByFacility(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        String productId = (String) context.get("productId");
        String facilityId = (String) context.get("facilityId"); // optional
        Locale locale = (Locale) context.get("locale");

        Map<String, Map<String, Object>> summaryInByFacility = FastMap.newInstance();
        Map<String, Map<String, Object>> summaryOutByFacility = FastMap.newInstance();
        try {
            //
            // Information about the running production runs that are going
            // to produce units of productId by facility.
            //
            List<EntityCondition> findIncomingProductionRunsConds = FastList.newInstance();

            findIncomingProductionRunsConds.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, productId));
            findIncomingProductionRunsConds.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "WEGS_CREATED"));
            findIncomingProductionRunsConds.add(EntityCondition.makeCondition("workEffortGoodStdTypeId", EntityOperator.EQUALS, "PRUN_PROD_DELIV"));
            if (facilityId != null) {
                findIncomingProductionRunsConds.add(EntityCondition.makeCondition("facilityId", EntityOperator.EQUALS, facilityId));
            }

            List<EntityCondition> findIncomingProductionRunsStatusConds = FastList.newInstance();
            findIncomingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_CREATED"));
            findIncomingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_SCHEDULED"));
            findIncomingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_DOC_PRINTED"));
            findIncomingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_RUNNING"));
            findIncomingProductionRunsConds.add(EntityCondition.makeCondition(findIncomingProductionRunsStatusConds, EntityOperator.OR));

            EntityConditionList<EntityCondition> findIncomingProductionRunsCondition = EntityCondition.makeCondition(findIncomingProductionRunsConds, EntityOperator.AND);

            List<GenericValue> incomingProductionRuns = delegator.findList("WorkEffortAndGoods", findIncomingProductionRunsCondition, null, UtilMisc.toList("-estimatedCompletionDate"), null, false);
            for (GenericValue incomingProductionRun: incomingProductionRuns) {
                double producedQtyTot = 0.0;
                if (incomingProductionRun.getString("currentStatusId").equals("PRUN_COMPLETED")) {
                    List<GenericValue> inventoryItems = delegator.findByAnd("WorkEffortAndInventoryProduced", UtilMisc.toMap("productId", productId, "workEffortId", incomingProductionRun.getString("workEffortId")));
                    for (GenericValue inventoryItem: inventoryItems) {
                        GenericValue inventoryItemDetail = EntityUtil.getFirst(delegator.findByAnd("InventoryItemDetail", UtilMisc.toMap("inventoryItemId", inventoryItem.getString("inventoryItemId")), UtilMisc.toList("inventoryItemDetailSeqId")));
                        if (inventoryItemDetail != null && inventoryItemDetail.get("quantityOnHandDiff") != null) {
                            Double inventoryItemQty = inventoryItemDetail.getDouble("quantityOnHandDiff");
                            producedQtyTot = producedQtyTot + inventoryItemQty.doubleValue();
                        }
                    }
                }
                double estimatedQuantity = 0.0;
                if (incomingProductionRun.get("estimatedQuantity") != null) {
                    estimatedQuantity = incomingProductionRun.getDouble("estimatedQuantity").doubleValue();
                }
                double remainingQuantity = estimatedQuantity - producedQtyTot; // the qty that still needs to be produced
                if (remainingQuantity > 0) {
                    incomingProductionRun.set("estimatedQuantity", Double.valueOf(remainingQuantity));
                } else {
                    continue;
                }
                String weFacilityId = incomingProductionRun.getString("facilityId");

                Map<String, Object> quantitySummary = UtilGenerics.checkMap(summaryInByFacility.get(weFacilityId));
                if (quantitySummary == null) {
                    quantitySummary = FastMap.newInstance();
                    quantitySummary.put("facilityId", weFacilityId);
                    summaryInByFacility.put(weFacilityId, quantitySummary);
                }
                Double remainingQuantityTot = (Double)quantitySummary.get("estimatedQuantityTotal");
                if (remainingQuantityTot == null) {
                    quantitySummary.put("estimatedQuantityTotal", Double.valueOf(remainingQuantity));
                } else {
                    quantitySummary.put("estimatedQuantityTotal", Double.valueOf(remainingQuantity + remainingQuantityTot.doubleValue()));
                }

                List<GenericValue> incomingProductionRunList = UtilGenerics.checkList(quantitySummary.get("incomingProductionRunList"));
                if (incomingProductionRunList == null) {
                    incomingProductionRunList = FastList.newInstance();
                    quantitySummary.put("incomingProductionRunList", incomingProductionRunList);
                }
                incomingProductionRunList.add(incomingProductionRun);
            }
            //
            // Information about the running production runs that are going
            // to consume units of productId by facility.
            //
            List<EntityCondition> findOutgoingProductionRunsConds = FastList.newInstance();

            findOutgoingProductionRunsConds.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, productId));
            findOutgoingProductionRunsConds.add(EntityCondition.makeCondition("statusId", EntityOperator.EQUALS, "WEGS_CREATED"));
            findOutgoingProductionRunsConds.add(EntityCondition.makeCondition("workEffortGoodStdTypeId", EntityOperator.EQUALS, "PRUNT_PROD_NEEDED"));
            if (facilityId != null) {
                findOutgoingProductionRunsConds.add(EntityCondition.makeCondition("facilityId", EntityOperator.EQUALS, facilityId));
            }

            List<EntityCondition> findOutgoingProductionRunsStatusConds = FastList.newInstance();
            findOutgoingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_CREATED"));
            findOutgoingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_SCHEDULED"));
            findOutgoingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_DOC_PRINTED"));
            findOutgoingProductionRunsStatusConds.add(EntityCondition.makeCondition("currentStatusId", EntityOperator.EQUALS, "PRUN_RUNNING"));
            findOutgoingProductionRunsConds.add(EntityCondition.makeCondition(findOutgoingProductionRunsStatusConds, EntityOperator.OR));

            EntityConditionList<EntityCondition> findOutgoingProductionRunsCondition = EntityCondition.makeCondition(findOutgoingProductionRunsConds, EntityOperator.AND);
            List<GenericValue> outgoingProductionRuns = delegator.findList("WorkEffortAndGoods", findOutgoingProductionRunsCondition, null, UtilMisc.toList("-estimatedStartDate"), null, false);
            for (GenericValue outgoingProductionRun: outgoingProductionRuns) {
                String weFacilityId = outgoingProductionRun.getString("facilityId");
                Double neededQuantity = outgoingProductionRun.getDouble("estimatedQuantity");
                if (neededQuantity == null) {
                    neededQuantity = Double.valueOf(0);
                }

                Map<String, Object> quantitySummary = UtilGenerics.checkMap(summaryOutByFacility.get(weFacilityId));
                if (quantitySummary == null) {
                    quantitySummary = FastMap.newInstance();
                    quantitySummary.put("facilityId", weFacilityId);
                    summaryOutByFacility.put(weFacilityId, quantitySummary);
                }
                Double remainingQuantityTot = (Double)quantitySummary.get("estimatedQuantityTotal");
                if (remainingQuantityTot == null) {
                    quantitySummary.put("estimatedQuantityTotal", neededQuantity);
                } else {
                    quantitySummary.put("estimatedQuantityTotal", Double.valueOf(neededQuantity.doubleValue() + remainingQuantityTot.doubleValue()));
                }

                List<GenericValue> outgoingProductionRunList = UtilGenerics.checkList(quantitySummary.get("outgoingProductionRunList"));
                if (outgoingProductionRunList == null) {
                    outgoingProductionRunList = FastList.newInstance();
                    quantitySummary.put("outgoingProductionRunList", outgoingProductionRunList);
                }
                outgoingProductionRunList.add(outgoingProductionRun);
            }

        } catch (GenericEntityException gee) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                    "WorkEffortManufacturingError", UtilMisc.toMap("productId", productId, "errorString", gee.getMessage()), locale));
        }
        Map<String, Object> resultMap = ServiceUtil.returnSuccess();
        resultMap.put("summaryInByFacility", summaryInByFacility);
        resultMap.put("summaryOutByFacility", summaryOutByFacility);
        return resultMap;
    }

    /** Process work effort event reminders. This service is used by the job scheduler.
     * @param ctx
     * @param context
     * @return
     */
    public static Map<String, Object> processWorkEffortEventReminders(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        LocalDispatcher dispatcher = ctx.getDispatcher();
        Locale localePar = (Locale) context.get("locale");
        Timestamp now = new Timestamp(System.currentTimeMillis());
        List<GenericValue> eventReminders = null;
        try {
            eventReminders = delegator.findList("WorkEffortEventReminder", EntityCondition.makeCondition(UtilMisc.<EntityCondition>toList(EntityCondition.makeCondition("reminderDateTime", EntityOperator.EQUALS, null), EntityCondition.makeCondition("reminderDateTime", EntityOperator.LESS_THAN_EQUAL_TO, now)), EntityOperator.OR), null, null, null, false);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                    "WorkEffortEventRemindersRetrivingError", UtilMisc.toMap("errorString", e), localePar));
        }
        for (GenericValue reminder : eventReminders) {
            if (UtilValidate.isEmpty(reminder.get("contactMechId"))) {
                continue;
            }
            int repeatCount = reminder.get("repeatCount") == null ? 0 : reminder.getLong("repeatCount").intValue();
            int currentCount = reminder.get("currentCount") == null ? 0 : reminder.getLong("currentCount").intValue();
            GenericValue workEffort = null;
            try {
                workEffort = reminder.getRelatedOne("WorkEffort");
            } catch (GenericEntityException e) {
                Debug.logWarning("Error while getting work effort: " + e, module);
            }
            if (workEffort == null) {
                try {
                    reminder.remove();
                } catch (GenericEntityException e) {
                    Debug.logWarning("Error while removing work effort event reminder: " + e, module);
                }
                continue;
            }
            Locale locale = reminder.getString("localeId") == null ? Locale.getDefault() : new Locale(reminder.getString("localeId"));
            TimeZone timeZone = reminder.getString("timeZoneId") == null ? TimeZone.getDefault() : TimeZone.getTimeZone(reminder.getString("timeZoneId"));
            Map<String, Object> parameters = UtilMisc.toMap("locale", locale, "timeZone", timeZone, "workEffortId", reminder.get("workEffortId"));

            Map<String, Object> processCtx = UtilMisc.toMap("reminder", reminder, "bodyParameters", parameters, "userLogin", context.get("userLogin"));

            Calendar cal = UtilDateTime.toCalendar(now, timeZone, locale);
            Timestamp reminderStamp = reminder.getTimestamp("reminderDateTime");
            Date eventDateTime = workEffort.getTimestamp("estimatedStartDate");
            String tempExprId = workEffort.getString("tempExprId");
            if (UtilValidate.isNotEmpty(tempExprId)) {
                TemporalExpression temporalExpression = null;
                try {
                    temporalExpression = TemporalExpressionWorker.getTemporalExpression(delegator, tempExprId);
                } catch (GenericEntityException e) {
                    Debug.logWarning("Error while getting temporal expression, id = " + tempExprId + ": " + e, module);
                }
                if (temporalExpression != null) {
                    eventDateTime = temporalExpression.first(cal).getTime();
                    Date reminderDateTime = null;
                    long reminderOffset = reminder.get("reminderOffset") == null ? 0 : reminder.getLong("reminderOffset").longValue();
                    if (reminderStamp == null) {
                        if (reminderOffset != 0) {
                            cal.setTime(eventDateTime);
                            TimeDuration duration = TimeDuration.fromLong(reminderOffset);
                            duration.addToCalendar(cal);
                            reminderDateTime = cal.getTime();
                        } else {
                            reminderDateTime = eventDateTime;
                        }
                    } else {
                        reminderDateTime = new Date(reminderStamp.getTime());
                    }
                    if (reminderDateTime.before(now) && reminderStamp != null) {
                        try {
                            parameters.put("eventDateTime", new Timestamp(eventDateTime.getTime()));

                            dispatcher.runSync("processWorkEffortEventReminder", processCtx);
                            if (repeatCount != 0 && currentCount + 1 >= repeatCount) {
                                reminder.remove();
                            } else {
                                cal.setTime(reminderDateTime);
                                Date newReminderDateTime = null;
                                if (reminderOffset != 0) {
                                    TimeDuration duration = TimeDuration.fromLong(-reminderOffset);
                                    duration.addToCalendar(cal);
                                    cal.setTime(temporalExpression.next(cal).getTime());
                                    duration = TimeDuration.fromLong(reminderOffset);
                                    duration.addToCalendar(cal);
                                    newReminderDateTime = cal.getTime();
                                } else {
                                    newReminderDateTime = temporalExpression.next(cal).getTime();
                                }
                                reminder.set("currentCount", Long.valueOf(currentCount + 1));
                                reminder.set("reminderDateTime", new Timestamp(newReminderDateTime.getTime()));
                                reminder.store();
                            }
                        } catch (GenericEntityException e) {
                            Debug.logWarning("Error while processing temporal expression reminder, id = " + tempExprId + ": " + e, module);
                        } catch (GenericServiceException e) {
                            Debug.logError(e, module);
                        }
                    } else if (reminderStamp == null) {
                        try {
                            reminder.set("reminderDateTime", new Timestamp(reminderDateTime.getTime()));
                            reminder.store();
                        } catch (GenericEntityException e) {
                            Debug.logWarning("Error while processing temporal expression reminder, id = " + tempExprId + ": " + e, module);
                        }
                    }
                }
                continue;
            }
            if (reminderStamp != null) {
                Date reminderDateTime = new Date(reminderStamp.getTime());
                if (reminderDateTime.before(now)) {
                    try {
                        parameters.put("eventDateTime", eventDateTime);
                        dispatcher.runSync("processWorkEffortEventReminder", processCtx);
                        TimeDuration duration = TimeDuration.fromNumber(reminder.getLong("repeatInterval"));
                        if ((repeatCount != 0 && currentCount + 1 >= repeatCount) || duration.isZero()) {
                            reminder.remove();
                        } else {
                            cal.setTime(now);
                            duration.addToCalendar(cal);
                            reminderDateTime = cal.getTime();
                            reminder.set("currentCount", Long.valueOf(currentCount + 1));
                            reminder.set("reminderDateTime", new Timestamp(reminderDateTime.getTime()));
                            reminder.store();
                        }
                    } catch (GenericEntityException e) {
                        Debug.logWarning("Error while processing event reminder: " + e, module);
                    } catch (GenericServiceException e) {
                        Debug.logError(e, module);
                    }
                }
            }
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> processWorkEffortEventReminder(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Map<String, Object> parameters = UtilGenerics.checkMap(context.get("bodyParameters"));
        GenericValue reminder = (GenericValue) context.get("reminder");
        GenericValue contactMech = null;
        try {
            contactMech = reminder.getRelatedOne("ContactMech");
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }
        if (contactMech != null && "EMAIL_ADDRESS".equals(contactMech.get("contactMechTypeId"))) {
            String toAddress = contactMech.getString("infoString");

            GenericValue emailTemplateSetting = null;
            try {
                emailTemplateSetting = delegator.findOne("EmailTemplateSetting", true, "emailTemplateSettingId", "WEFF_EVENT_REMINDER");
            } catch (GenericEntityException e1) {
                Debug.logError(e1, module);
            }
            if (emailTemplateSetting != null) {
                Map<String, Object> emailCtx = UtilMisc.toMap("emailTemplateSettingId", "WEFF_EVENT_REMINDER", "sendTo", toAddress, "bodyParameters", parameters);
                try {
                    dispatcher.runAsync("sendMailFromTemplateSetting", emailCtx);
                } catch (Exception e) {
                    Debug.logWarning("Error while emailing event reminder - workEffortId = " + reminder.get("workEffortId") + ", contactMechId = " + reminder.get("contactMechId") + ": " + e, module);
                }
            } else {
                // TODO: Remove this block after the next release 2010-11-29
                String screenLocation = UtilProperties.getPropertyValue("EventReminders", "eventReminders.emailScreenWidgetLocation");
                String fromAddress = UtilProperties.getPropertyValue("EventReminders", "eventReminders.emailFromAddress");
                String subject = UtilProperties.getMessage("WorkEffortUiLabels", "WorkEffortEventReminder", (Locale) parameters.get("locale"));
                Map<String, Object> emailCtx = UtilMisc.toMap("sendFrom", fromAddress, "sendTo", toAddress, "subject", subject, "bodyParameters", parameters, "bodyScreenUri", screenLocation);
                try {
                    dispatcher.runAsync("sendMailFromScreen", emailCtx);
                } catch (Exception e) {
                    Debug.logWarning("Error while emailing event reminder - workEffortId = " + reminder.get("workEffortId") + ", contactMechId = " + reminder.get("contactMechId") + ": " + e, module);
                }
            }
            return ServiceUtil.returnSuccess();
        }
        // TODO: Other contact mechanism types
        Debug.logWarning("Invalid event reminder contact mech, workEffortId = " + reminder.get("workEffortId") + ", contactMechId = " + reminder.get("contactMechId"), module);
        return ServiceUtil.returnSuccess();
    }

    @Deprecated
    protected static void processEventReminder(DispatchContext ctx, GenericValue reminder, Map<String, Object> parameters) throws GenericEntityException {
        LocalDispatcher dispatcher = ctx.getDispatcher();
        GenericValue contactMech = reminder.getRelatedOne("ContactMech");
        if (contactMech != null && "EMAIL_ADDRESS".equals(contactMech.get("contactMechTypeId"))) {
            String screenLocation = UtilProperties.getPropertyValue("EventReminders", "eventReminders.emailScreenWidgetLocation");
            String fromAddress = UtilProperties.getPropertyValue("EventReminders", "eventReminders.emailFromAddress");
            String toAddress = contactMech.getString("infoString");
            String subject = UtilProperties.getMessage("WorkEffortUiLabels", "WorkEffortEventReminder", (Locale) parameters.get("locale"));
            Map<String, Object> emailCtx = UtilMisc.toMap("sendFrom", fromAddress, "sendTo", toAddress, "subject", subject, "bodyParameters", parameters, "bodyScreenUri", screenLocation);
            try {
                dispatcher.runAsync("sendMailFromScreen", emailCtx);
            } catch (Exception e) {
                Debug.logWarning("Error while emailing event reminder - workEffortId = " + reminder.get("workEffortId") + ", contactMechId = " + reminder.get("contactMechId") + ": " + e, module);
            }
            return;
        }
        // TODO: Other contact mechanism types
        Debug.logWarning("Invalid event reminder contact mech, workEffortId = " + reminder.get("workEffortId") + ", contactMechId = " + reminder.get("contactMechId"), module);
    }

    /** Migrate work effort event reminders.
     * @param ctx
     * @param context
     * @return
     */
    public static Map<String, Object> migrateWorkEffortEventReminders(DispatchContext ctx, Map<String, ? extends Object> context) {
        Delegator delegator = ctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        ModelEntity modelEntity = delegator.getModelEntity("WorkEffortEventReminder");
        if (modelEntity != null && modelEntity.getField("recurrenceOffset") != null) {
            List<GenericValue> eventReminders = null;
            try {
                eventReminders = delegator.findList("WorkEffortEventReminder", null, null, null, null, false);
                for (GenericValue reminder : eventReminders) {
                    if (UtilValidate.isNotEmpty(reminder.get("recurrenceOffset"))) {
                        reminder.set("reminderOffset", reminder.get("recurrenceOffset"));
                        reminder.store();
                    }
                }
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError,
                        "WorkEffortEventRemindersMigrationError", UtilMisc.toMap("errorString", e), locale));
            }
        }
        return ServiceUtil.returnSuccess();
    }

    public static Map<String, Object> removeDuplicateWorkEfforts(DispatchContext ctx, Map<String, ? extends Object> context) {
        List<GenericValue> resultList = null;
        EntityListIterator eli = (EntityListIterator) context.get("workEffortIterator");
        if (eli != null) {
            try {
                Set<String> keys = FastSet.newInstance();
                resultList = FastList.newInstance();
                GenericValue workEffort = eli.next();
                while (workEffort != null) {
                    String workEffortId = workEffort.getString("workEffortId");
                    if (!keys.contains(workEffortId)) {
                        resultList.add(workEffort);
                        keys.add(workEffortId);
                    }
                    workEffort = eli.next();
                }
            } catch (Exception e) {
                Debug.logError(e, module);
            } finally {
                try {
                    eli.close();
                } catch (GenericEntityException e) {
                    Debug.logError(e, "Error while closing EntityListIterator: ", module);
                }
            }
        } else {
            List<GenericValue> workEfforts = UtilGenerics.checkList(context.get("workEfforts"));
            if (workEfforts != null) {
                resultList = WorkEffortWorker.removeDuplicateWorkEfforts(workEfforts);
            }
        }
        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("workEfforts", resultList);
        return result;
    }
}
TOP

Related Classes of org.ofbiz.workeffort.workeffort.WorkEffortServices

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.