/* * Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de) * * Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://creativecommons.org/licenses/by-nc-sa/3.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 de.knurt.fam.template.controller.json; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import de.knurt.fam.core.aspects.logging.FamLog; import de.knurt.fam.core.aspects.security.auth.FamAuth; import de.knurt.fam.core.aspects.security.auth.SessionAuth; import de.knurt.fam.core.model.config.BookingRule; import de.knurt.fam.core.model.config.FacilityBookable; import de.knurt.fam.core.model.persist.User; import de.knurt.fam.core.model.persist.booking.Booking; import de.knurt.fam.core.model.persist.booking.FamShoppingCart; import de.knurt.fam.core.model.persist.booking.TimeBooking; import de.knurt.fam.core.util.booking.BookingFinder; import de.knurt.fam.core.util.booking.TimeBookingRequest; import de.knurt.fam.core.util.mvc.QueryStringBuilder; import de.knurt.fam.core.util.mvc.RequestInterpreter; import de.knurt.fam.core.view.html.factory.FamSubmitButtonFactory; import de.knurt.fam.core.view.text.FamDateFormat; import de.knurt.fam.core.view.text.FamText; import de.knurt.fam.template.util.TemplateHtml; import de.knurt.heinzelmann.ui.html.HtmlElement; import de.knurt.heinzelmann.ui.html.HtmlFactory; import de.knurt.heinzelmann.util.query.QueryString; import de.knurt.heinzelmann.util.time.TimeFrame; /** * controller for ajax request to book a facility. * * @author Daniel Oltmanns * @since 0.20090917 (09/17/2009) */ public class DirectBookingRequestController extends JSONController { private static final int NOT_POSSIBLE_THIS_WAY = -2; private static final int BOOKED_UP = -1; private static final int BOOKING_AVAILABLE = 1; /** * return an available possible booking. * * there are two different places where this is called: 1. the * "request booking" link in the navigation of the calendar 2. the drag and * drop action in same calendar * * the response depends on which place causes the request. * * @param rq * request * @param rs * response * @return an available possible booking. */ @Override public JSONObject getJSONObject(HttpServletRequest rq, HttpServletResponse rs) { JSONObject result = new JSONObject(); User authUser = SessionAuth.user(rq); TimeFrame tf = null; List<TimeBookingRequest> tbrs = null; FacilityBookable bd = RequestInterpreter.getBookableFacility(rq); Integer requestedCapacityUnits = null; boolean justEqualBookingIsAvailable = false; TimeBookingRequest perfectlyCandidate = null; if (authUser != null) { User user = SessionAuth.user(rq); int statusid = 0; if (bd != null && user != null) { BookingRule brule = bd.getBookingRule(); if (RequestInterpreter.isAjaxRequestFromRequestBookingLink(rq)) { tf = RequestInterpreter.getTimeFrameFromAjaxRequestBookingLink(rq); requestedCapacityUnits = RequestInterpreter.getCapacityUnits(rq); } else { // it's the drag and drop action if (bd.getBookingRule().getSmallestMinutesBookable() * bd.getBookingRule().getMinBookableTimeUnits(authUser) > 1440) { statusid = NOT_POSSIBLE_THIS_WAY; } else { tf = RequestInterpreter.getTimeFrameWithDayOfYearAndMinutesStartEnd(rq); } requestedCapacityUnits = 1; } if (tf != null && statusid != NOT_POSSIBLE_THIS_WAY) { perfectlyCandidate = BookingFinder.getValidFrom(brule, user, tf, requestedCapacityUnits); if (perfectlyCandidate.isAvailable()) { tbrs = new ArrayList<TimeBookingRequest>(); tbrs.add(perfectlyCandidate); statusid = BOOKING_AVAILABLE; TimeFrame now = perfectlyCandidate.getRequestedTimeFrame(); if (perfectlyCandidate.getRequestedCapacityUnits() != requestedCapacityUnits || !now.toString().equals(tf.toString())) { justEqualBookingIsAvailable = true; } } else { tbrs = BookingFinder.getBookingRequestNextTo(perfectlyCandidate); if (tbrs == null || tbrs.size() == 0) { statusid = BOOKED_UP; } else { justEqualBookingIsAvailable = true; statusid = BOOKING_AVAILABLE; } } } else if (statusid == 0) { // no time frame could be generated // from request statusid = BOOKED_UP; } } try { result.put("statusid", statusid); switch (statusid) { case NOT_POSSIBLE_THIS_WAY: String message = String.format("<div>It's not possible to book \"%s\" this way.</div>", bd.getLabel()); // INTLANG result.put("statusmessageShort", message); result.put("statusmessage_long", message); break; case BOOKED_UP: result.put("statusmessageShort", "<div>could not find a free slot</div>"); // INTLANG result.put("statusmessage_long", "<div>could not find a free slot</div>"); // INTLANG break; case BOOKING_AVAILABLE: // return all possibilities in an array FamShoppingCart sc = user.getShoppingCart(); JSONArray availableBookings = new JSONArray(); boolean isFirstIteration = true; for (TimeBookingRequest tbr : tbrs) { JSONObject tmpresult = new JSONObject(); Booking booking = TimeBooking.getNewBooking(tbr); sc.addArticle(booking); // build the form QueryString queryString = QueryStringBuilder.getArticleNumber(booking); HtmlElement form = HtmlFactory.get_form("post", TemplateHtml.me().getRelativeHref("bookfacilitiesdone")); HtmlElement button = FamSubmitButtonFactory.getButton(user.hasRight(FamAuth.DIRECT_BOOKING, tbr.getFacility()) ? "book!" : "apply!"); // INTLANG form = FamSubmitButtonFactory.getButtonAsForm(queryString, form, button); HtmlElement statusmessageShort = new HtmlElement("div"); String tmp = ""; if (RequestInterpreter.isAjaxRequestFromRequestBookingLink(rq) && justEqualBookingIsAvailable) { if (isFirstIteration) { tmp = "<strong>Not available!</strong><br />Available " + ((tbr.getRequestedCapacityUnits() > 1) ? "are" : "is");// INTLANG isFirstIteration = false; } else { tmp = "or";// INTLANG } tmp += " " + FamText.facilityNameWithCapacityUnits(booking); } else { // its available tmp = "available"; // INTLANG } String infoTimeFromTo = ""; if (perfectlyCandidate.getRequestedTimeFrame().overlaps(tbr.getRequestedTimeFrame())) { infoTimeFromTo = FamDateFormat.getTimeFormatted(tbr.getRequestedTimeFrame(), "this day from %s<br />to %s"); } else { infoTimeFromTo = FamDateFormat.getDateFormattedWithTime(tbr.getRequestedTimeFrame(), true); } statusmessageShort.add("<p>" + tmp + ":<br />" + infoTimeFromTo + "</p>"); // INTLANG statusmessageShort.add(form); tmpresult.put("statusmessageShort", statusmessageShort); // INTLANG HtmlElement statusmessageLong = new HtmlElement("div"); statusmessageLong.add("<p>" + tmp + ":</p>" + FamDateFormat.getDateFormattedWithTime(tbr.getRequestedTimeFrame(), true)); // INTLANG statusmessageLong.add(form); tmpresult.put("statusmessage_long", statusmessageLong); // INTLANG Calendar start = tbr.getRequestedTimeFrame().getCalendarStart(); Calendar end = tbr.getRequestedTimeFrame().getCalendarEnd(); tmpresult.put("newMinutesY1", start.get(Calendar.HOUR_OF_DAY) * 60 + start.get(Calendar.MINUTE)); // INTLANG tmpresult.put("newMinutesY2", end.get(Calendar.HOUR_OF_DAY) * 60 + end.get(Calendar.MINUTE)); // INTLANG availableBookings.put(tmpresult); if (!RequestInterpreter.isAjaxRequestFromRequestBookingLink(rq)) { // on possibility for drag and drop action break; } } result.put("availableBookings", availableBookings); break; } } catch (JSONException ex) { this.onException(ex); } } return result; } /** {@inheritDoc} */ @Override public void onException(IOException ex) { this.onException(ex); } private void onException(Exception ex) { FamLog.logException(this.getClass(), ex, "creating json failed", 201011271618l); } }