Search in sources :

Example 1 with DateRange

use of org.apache.ofbiz.base.util.DateRange in project ofbiz-framework by apache.

the class WorkEffortServices method getWorkEffortEventsByPeriod.

/**
 * 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>
 *   <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></li>
 * </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)) {
        // 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.checkCollection(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.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
    // 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(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);
    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", 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 = new HashMap<>();
    result.put("periods", periods);
    result.put("maxConcurrentEntries", Integer.valueOf(maxConcurrentEntries));
    return result;
}
Also used : Locale(java.util.Locale) HashMap(java.util.HashMap) EntityCondition(org.apache.ofbiz.entity.condition.EntityCondition) Security(org.apache.ofbiz.security.Security) Timestamp(java.sql.Timestamp) DateRange(org.apache.ofbiz.base.util.DateRange) TimeDuration(org.apache.ofbiz.base.util.TimeDuration) HashSet(java.util.HashSet) GenericValue(org.apache.ofbiz.entity.GenericValue) TemporalExpression(org.apache.ofbiz.service.calendar.TemporalExpression) Calendar(com.ibm.icu.util.Calendar) LinkedList(java.util.LinkedList) Date(java.util.Date) TimeZone(java.util.TimeZone) Delegator(org.apache.ofbiz.entity.Delegator) GenericEntityException(org.apache.ofbiz.entity.GenericEntityException) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 2 with DateRange

use of org.apache.ofbiz.base.util.DateRange in project ofbiz-framework by apache.

the class WorkEffortServices method groupCalendarEntriesByDateRange.

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<>();
    Set<Date> dateBoundaries = new TreeSet<>();
    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 = new LinkedList<>();
                    }
                    calendarEntryByDateRangeList.add(calendarEntry);
                    calendarEntriesByDateRange.put(dateRange, calendarEntryByDateRangeList);
                }
            }
        }
        prevDateBoundary = dateBoundary;
    }
    return calendarEntriesByDateRange;
}
Also used : TreeMap(java.util.TreeMap) Date(java.util.Date) DateRange(org.apache.ofbiz.base.util.DateRange) TreeSet(java.util.TreeSet) EntityConditionList(org.apache.ofbiz.entity.condition.EntityConditionList) LinkedList(java.util.LinkedList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap)

Aggregations

Date (java.util.Date)2 HashMap (java.util.HashMap)2 LinkedList (java.util.LinkedList)2 Map (java.util.Map)2 TreeMap (java.util.TreeMap)2 DateRange (org.apache.ofbiz.base.util.DateRange)2 Calendar (com.ibm.icu.util.Calendar)1 Timestamp (java.sql.Timestamp)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Locale (java.util.Locale)1 TimeZone (java.util.TimeZone)1 TreeSet (java.util.TreeSet)1 TimeDuration (org.apache.ofbiz.base.util.TimeDuration)1 Delegator (org.apache.ofbiz.entity.Delegator)1 GenericEntityException (org.apache.ofbiz.entity.GenericEntityException)1 GenericValue (org.apache.ofbiz.entity.GenericValue)1 EntityCondition (org.apache.ofbiz.entity.condition.EntityCondition)1 EntityConditionList (org.apache.ofbiz.entity.condition.EntityConditionList)1 Security (org.apache.ofbiz.security.Security)1