Ejemplo n.º 1
7
 private boolean overlaps(TimeSlot timeSlot, List<TimeSlot> timeSlots) {
   for (TimeSlot slot : timeSlots) {
     if (timeSlot.getStartTime().equals(slot.getStartTime())) {
       return configMatches(timeSlot, slot);
     } else if (timeSlot.getStartTime().isBefore(slot.getStartTime())) {
       // make sure timeSlot ends before slot starts
       if (timeSlot.getEndTime().isAfter(slot.getStartTime())) {
         return configMatches(timeSlot, slot);
       }
     } else {
       // disabled, as we do want overlapping time slots from different calendar configurations
       //                //only test if these time slots come from different configurations as we
       // DO want overlapping time slots (when min interval is smaller than min duration)
       //                if (!timeSlot.getConfig().equals(slot.getConfig())){
       //
       //                    //if timeSlot starts after slot, make sure it also starts before slot
       // ends
       //                    if (timeSlot.getStartTime().isBefore(slot.getEndTime())){
       //                        return true;
       //                    }
       //                }
     }
   }
   return false;
 }
Ejemplo n.º 2
2
  public Long getBookingSlotsLeft(TimeSlot timeSlot, Offer offer, List<Booking> confirmedBookings) {
    checkForBookedCourts(timeSlot, confirmedBookings, true);

    Long bookingSlotsLeft = offer.getMaxConcurrentBookings();
    for (Booking existingBooking : timeSlot.getBookings()) {
      if (existingBooking.getOffer().equals(offer)) {
        bookingSlotsLeft--;
      }
    }
    return bookingSlotsLeft;
  }
Ejemplo n.º 3
0
  public void checkForBookedCourts(
      TimeSlot timeSlot, List<Booking> confirmedBookings, Boolean preventOverlapping) {
    LocalTime startTime = timeSlot.getStartTime();
    LocalTime endTime = timeSlot.getEndTime();

    for (Booking booking : confirmedBookings) {

      if (timeSlot.getDate().equals(booking.getBookingDate())) {
        LocalTime bookingStartTime = booking.getBookingTime();
        LocalTime bookingEndTime = bookingStartTime.plusMinutes(booking.getDuration().intValue());
        Boolean addBooking = false;
        if (preventOverlapping) {
          if (startTime.isBefore(bookingEndTime)) {
            if (endTime.isAfter(bookingStartTime)) {
              addBooking = true;
            }
          }
        } else {
          // for displaying allocations
          if (startTime.compareTo(bookingStartTime) >= 0) {
            if (endTime.compareTo(bookingEndTime) <= 0) {
              addBooking = true;
            }
          }
        }
        if (addBooking) {
          Offer offer = booking.getOffer();
          for (Offer timeSlotOffer : timeSlot.getConfig().getOffers()) {
            if (offer.equals(timeSlotOffer)) {
              timeSlot.addBooking(booking);
              break;
            }
          }
        }
      }
    }
  }
Ejemplo n.º 4
0
  private void addTimeSlot(
      List<TimeSlot> timeSlots,
      LocalDateTime time,
      CalendarConfig config,
      BigDecimal pricePerMinDuration) {
    TimeSlot timeSlot = new TimeSlot();
    timeSlot.setDate(time.toLocalDate());
    timeSlot.setStartTime(time.toLocalTime());
    timeSlot.setEndTime(time.toLocalTime().plusMinutes(config.getMinDuration()));
    timeSlot.setConfig(config);
    timeSlot.setPricePerMinDuration(pricePerMinDuration);

    // only add timeSlot if timeSlots does not already contain an entry that overlaps
    if (!overlaps(timeSlot, timeSlots)) {
      timeSlots.add(timeSlot);
    }
  }
Ejemplo n.º 5
0
  public OfferDurationPrice getOfferDurationPrice(
      LocalDate selectedDate, LocalTime selectedTime, Offer selectedOffer)
      throws CalendarConfigException {
    List<CalendarConfig> configs = calendarConfigDAO.findFor(selectedDate);
    List<Booking> confirmedBookings = bookingDAO.findBlockedBookingsForDate(selectedDate);

    // convert to required data structure
    Map<Offer, List<CalendarConfig>> offerConfigMap = new HashMap<>();
    for (CalendarConfig config : configs) {
      for (Offer offer : config.getOffers()) {
        if (offer.equals(selectedOffer)) {
          List<CalendarConfig> list = offerConfigMap.get(offer);
          if (list == null) {
            list = new ArrayList<>();
          }
          list.add(config);

          // sort by start time
          Collections.sort(list);
          offerConfigMap.put(offer, list);
        }
      }
    }

    OfferDurationPrice offerDurationPrices = null;

    Iterator<Map.Entry<Offer, List<CalendarConfig>>> iterator =
        offerConfigMap.entrySet().iterator();
    // for every offer
    while (iterator.hasNext()) {
      Map.Entry<Offer, List<CalendarConfig>> entry = iterator.next();
      Offer offer = entry.getKey();
      List<CalendarConfig> configsForOffer = entry.getValue();

      // make sure the first configuration starts before the requested booking time
      if (selectedTime.compareTo(configsForOffer.get(0).getStartTime()) < 0) {
        continue;
      }

      LocalDateTime endTime = null;
      Integer duration = configsForOffer.get(0).getMinDuration();
      BigDecimal pricePerMinute;
      BigDecimal price = null;
      CalendarConfig previousConfig = null;
      Map<Integer, BigDecimal> durationPriceMap = new TreeMap<>();
      Boolean isContiguous = true;
      for (CalendarConfig config : configsForOffer) {

        // make sure there is no gap between calendar configurations
        if (endTime == null) {
          // first run
          endTime =
              getLocalDateTime(selectedDate, selectedTime).plusMinutes(config.getMinDuration());
        } else {
          // break if there are durations available and calendar configs are not contiguous
          if (!durationPriceMap.isEmpty()) {
            // we substract min interval before the comparison as it has been added during the last
            // iteration
            LocalDateTime configStartDateTime =
                getLocalDateTime(selectedDate, config.getStartTime());
            if (!endTime.minusMinutes(config.getMinInterval()).equals(configStartDateTime)) {
              break;
            }
          }
        }

        Integer interval = config.getMinInterval();

        pricePerMinute = getPricePerMinute(config);

        // as long as the endTime is before the end time configured in the calendar
        LocalDateTime configEndDateTime = getLocalDateTime(selectedDate, config.getEndTime());
        while (endTime.compareTo(configEndDateTime) <= 0) {
          TimeSlot timeSlot = new TimeSlot();
          timeSlot.setDate(selectedDate);
          timeSlot.setStartTime(selectedTime);
          timeSlot.setEndTime(endTime.toLocalTime());
          timeSlot.setConfig(config);
          Long bookingSlotsLeft = getBookingSlotsLeft(timeSlot, offer, confirmedBookings);

          // we only allow contiguous bookings for any given offer
          if (bookingSlotsLeft < 1) {
            isContiguous = false;
            break;
          }

          if (price == null) {
            // see if previousConfig endTime - minInterval matches the selected time. if so, take
            // half of the previous config price as a basis
            if (previousConfig != null
                && previousConfig
                    .getEndTime()
                    .minusMinutes(previousConfig.getMinInterval())
                    .equals(selectedTime)) {
              BigDecimal previousConfigPricePerMinute = getPricePerMinute(previousConfig);
              price =
                  previousConfigPricePerMinute.multiply(
                      new BigDecimal(previousConfig.getMinInterval()), MathContext.DECIMAL128);
              price =
                  price.add(
                      pricePerMinute.multiply(
                          new BigDecimal(duration - previousConfig.getMinInterval()),
                          MathContext.DECIMAL128));
            } else {
              price =
                  pricePerMinute.multiply(
                      new BigDecimal(duration.toString()), MathContext.DECIMAL128);
            }
          } else {
            // add price for additional interval
            price =
                price.add(
                    pricePerMinute.multiply(
                        new BigDecimal(interval.toString()), MathContext.DECIMAL128));
          }
          price = price.setScale(2, RoundingMode.HALF_EVEN);
          durationPriceMap.put(duration, price);

          // increase the duration by the configured minimum interval and determine the new end time
          // for the next iteration
          duration += interval;
          endTime = endTime.plusMinutes(interval);
        }

        if (!durationPriceMap.isEmpty()) {
          OfferDurationPrice odp = new OfferDurationPrice();
          odp.setOffer(offer);
          odp.setDurationPriceMap(durationPriceMap);
          odp.setConfig(config);
          offerDurationPrices = odp;
        }

        if (!isContiguous) {
          // we only allow coniguous bookings for one offer. process next offer
          //                    previousConfig = null;
          break;
        }
        previousConfig = config;
      }
    }
    return offerDurationPrices;
  }
Ejemplo n.º 6
0
  public void addWeekView(
      LocalDate selectedDate,
      List<Facility> selectedFacilities,
      ModelAndView mav,
      Boolean preventOverlapping)
      throws JsonProcessingException {
    // calculate date configuration for datepicker
    LocalDate today = new LocalDate(DEFAULT_TIMEZONE);
    LocalDate firstDay = today.dayOfMonth().withMinimumValue();
    LocalDate lastDay = today.plusDays(Constants.CALENDAR_MAX_DATE).dayOfMonth().withMaximumValue();
    List<CalendarConfig> calendarConfigs = calendarConfigDAO.findBetween(firstDay, lastDay);
    Collections.sort(calendarConfigs);
    Map<String, DatePickerDayConfig> dayConfigs =
        getDayConfigMap(firstDay, lastDay, calendarConfigs);

    List<Booking> confirmedBookings = bookingDAO.findBlockedBookingsBetween(firstDay, lastDay);

    // calculate available time slots
    List<TimeSlot> timeSlots = new ArrayList<>();
    List<LocalDate> weekDays = new ArrayList<>();
    for (int i = 1; i <= CalendarWeekDay.values().length; i++) {
      LocalDate date = selectedDate.withDayOfWeek(i);
      weekDays.add(date);
      if (!date.isBefore(new LocalDate())) {
        try {
          // generate list of bookable time slots
          timeSlots.addAll(
              getTimeSlotsForDate(
                  date, calendarConfigs, confirmedBookings, true, preventOverlapping));
        } catch (CalendarConfigException e) {
          // safe to ignore
        }
      }
    }

    SortedSet<Offer> offers = new TreeSet<>();
    List<TimeRange> rangeList = new ArrayList<>();
    // Map<TimeRange, List<TimeSlot>> rangeList = new TreeMap<>();
    for (TimeSlot slot : timeSlots) {
      Set<Offer> slotOffers = slot.getConfig().getOffers();
      offers.addAll(slotOffers);

      TimeRange range = new TimeRange();
      range.setStartTime(slot.getStartTime());
      range.setEndTime(slot.getEndTime());

      if (rangeList.contains(range)) {
        range = rangeList.get(rangeList.indexOf(range));
      } else {
        rangeList.add(range);
      }

      List<TimeSlot> slotis = range.getTimeSlots();
      slotis.add(slot);
      range.setTimeSlots(slotis);
    }
    Collections.sort(rangeList);

    List<Offer> selectedOffers = new ArrayList<>();
    if (selectedFacilities.isEmpty()) {
      selectedOffers = offerDAO.findAll();
    } else {
      for (Facility facility : selectedFacilities) {
        selectedOffers.addAll(facility.getOffers());
      }
    }
    Collections.sort(selectedOffers);

    mav.addObject("dayConfigs", objectMapper.writeValueAsString(dayConfigs));
    mav.addObject("maxDate", lastDay.toString());
    mav.addObject("Day", selectedDate);
    mav.addObject("NextMonday", selectedDate.plusDays(8 - selectedDate.getDayOfWeek()));
    mav.addObject("PrevSunday", selectedDate.minusDays(selectedDate.getDayOfWeek()));
    mav.addObject("WeekDays", weekDays);
    mav.addObject("RangeMap", rangeList);
    mav.addObject("Offers", offers);
    mav.addObject("SelectedOffers", selectedOffers);
    mav.addObject("SelectedFacilities", selectedFacilities);
    mav.addObject("Facilities", facilityDAO.findAll());
  }
Ejemplo n.º 7
0
 private boolean configMatches(TimeSlot timeSlot, TimeSlot slot) {
   return timeSlot.getConfig().equals(slot.getConfig());
 }