public static Map getWorkEffortEventsByPeriod()

in applications/workeffort/src/main/java/org/apache/ofbiz/workeffort/workeffort/WorkEffortServices.java [498:776]


    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)) {
            // This is a bad idea. This causes the service to return only those work efforts that are assigned
            // to the current user even when the service parameters have nothing to do with the current user.
            calendarType = "CAL_PERSONAL";
        }
        String partyId = (String) context.get("partyId");
        Collection<String> partyIds = UtilGenerics.cast(context.get("partyIds"));
        String facilityId = (String) context.get("facilityId");
        String fixedAssetId = (String) context.get("fixedAssetId");
        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;
        }

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

        // get a timestamp (date) for the beginning of today and for beginning of numDays+1 days from now
        // Commenting this out because it interferes with periods that do not start at the beginning of the day
        Timestamp startStamp = startDay;
        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 = new HashSet<>();
        }
        if (UtilValidate.isNotEmpty(partyId)) {
            if (partyId.equals(userLogin.getString("partyId")) || security.hasEntityPermission("WORKEFFORTMGR", "_VIEW", userLogin)) {
                partyIdsToUse.add(partyId);
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(RES_ERROR,
                        "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.cast(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);

        try {
            List<GenericValue> tempWorkEfforts = null;
            if (UtilValidate.isNotEmpty(partyIdsToUse)) {
                tempWorkEfforts = EntityQuery.use(delegator).from("WorkEffortAndPartyAssignAndType").where(entityExprList)
                        .orderBy("estimatedStartDate").filterByDate().queryList();
            } else {
                tempWorkEfforts = EntityQuery.use(delegator).from("WorkEffort").where(entityExprList).orderBy("estimatedStartDate").queryList();
            }
            if (!"CAL_PERSONAL".equals(calendarType) && UtilValidate.isNotEmpty(fixedAssetId)) {
                // Get "new style" work efforts
                tempWorkEfforts.addAll(EntityQuery.use(delegator).from("WorkEffortAndFixedAssetAssign").where(entityExprList)
                        .orderBy("estimatedStartDate").filterByDate().queryList());
            }
            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 = new LinkedList<>();
        if (validWorkEfforts != null) {
            List<DateRange> periodRanges = new LinkedList<>();
            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 = new HashSet<>();
                Set<GenericValue> inclusions = new HashSet<>();
                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) && !"WES_PUBLIC".equals(workEffort.getString("scopeEnumId"))
                                && !partyIdsToUse.contains(workEffort.getString("partyId"))) {
                            continue;
                        }
                        // if the workeffort has actual date time, using temporal expression has no sense
                        if (UtilValidate.isNotEmpty(workEffort.getTimestamp("actualStartDate"))
                                || UtilValidate.isNotEmpty(workEffort.getTimestamp("actualCompletionDate"))) {
                            continue;
                        }
                        TemporalExpression tempExpr = TemporalExpressionWorker.getTemporalExpression(delegator, workEffort.getString("tempExprId"));
                        DateRange weRange = new DateRange(workEffort.getTimestamp("estimatedStartDate"),
                                workEffort.getTimestamp("estimatedCompletionDate"));

                        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());
                                    }
                                    if (weRange.includes(cloneWorkEffort.getTimestamp("estimatedStartDate"))) {
                                        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 = new LinkedList<>();
                Map<String, Object> entry = new HashMap<>();
                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 = new HashMap<>();
                        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);
                        if (length % periodLen == 0 && startDate.getTime() > periodRange.start().getTime()) {
                            periodSpan++;
                        }
                        calEntry.put("periodSpan", 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", 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 = new HashMap<>();
        result.put("periods", periods);
        result.put("maxConcurrentEntries", maxConcurrentEntries);
        return result;
    }