Example #1
0
def log_connection_events(sender, signal_type, obj, **kwargs):
    from common.tz_support import utc_now
    from django.core.urlresolvers import reverse
    from google.appengine.api.taskqueue import taskqueue
    from analytics.models import AnalyticsEvent
    from common.util import  log_event, EventType, notify_by_email
    from ordering.signals import   SignalType
    from ordering.station_connection_manager import ALERT_DELTA, handle_dead_workstations

    last_event_qs = AnalyticsEvent.objects.filter(work_station=obj, type__in=[EventType.WORKSTATION_UP, EventType.WORKSTATION_DOWN]).order_by('-create_date')[:1]
    station = obj.station

    if signal_type == SignalType.WORKSTATION_ONLINE:
        if last_event_qs:
            # send workstation reconnect mail
            last_event = last_event_qs[0]
            if last_event.type == EventType.WORKSTATION_DOWN and (utc_now() - last_event.create_date) >= ALERT_DELTA and station.show_on_list:
                msg = u"Workstation is up again:\n\tid = %d station = %s" % (obj.id, obj.dn_station_name)
                notify_by_email(u"Workstation Reconnected", msg=msg)
        elif station.show_on_list:
            # send "new workstation" mail
            msg = u"A new workstation just connected: id = %d station = %s" % (obj.id, obj.dn_station_name)
            notify_by_email(u"New Workstation", msg=msg)

        log_event(EventType.WORKSTATION_UP, station=station, work_station=obj)

    elif signal_type == SignalType.WORKSTATION_OFFLINE:
        log_event(EventType.WORKSTATION_DOWN, station=station, work_station=obj)

        if station.show_on_list:
            # add task to check if workstation is still dead after ALERT_DELTA
            task = taskqueue.Task(url=reverse(handle_dead_workstations),
                                  countdown=ALERT_DELTA.seconds + 1,
                                  params={"workstation_id": obj.id})
            taskqueue.Queue('log-events').add(task)
def handle_dead_workstations(request):
    ws_id = request.POST.get("workstation_id")
    workstation = None
    try:
        workstation = WorkStation.objects.get(id=ws_id)
    except WorkStation.DoesNotExist:
        logging.error("handle_dead_workstations: invalid workstation_id '%s" %
                      ws_id)

    if workstation:
        last_event = AnalyticsEvent.objects.filter(
            work_station=workstation,
            type__in=[EventType.WORKSTATION_UP,
                      EventType.WORKSTATION_DOWN]).order_by('-create_date')[:1]
        if last_event:
            last_event = last_event[0]
            if last_event.type == EventType.WORKSTATION_DOWN and (
                    utc_now() - last_event.create_date) >= ALERT_DELTA:
                # send station down mail
                msg = u"Workstation has been down for the last %d minutes:\n\tid = %d station = %s" % (
                    ALERT_DELTA.seconds / 60, workstation.id,
                    workstation.dn_station_name)
                notify_by_email(u"Workstation down", msg)

    return HttpResponse("OK")
Example #3
0
def google_directions_request(start_lat,
                              start_lng,
                              end_lat,
                              end_lng,
                              output="json",
                              alternatives=False,
                              sensor=False,
                              departure_time=None):
    # see https://developers.google.com/maps/documentation/directions/
    params = {
        'origin':
        '%s,%s' % (start_lat, start_lng),
        'destination':
        '%s,%s' % (end_lat, end_lng),
        'sensor':
        simplejson.dumps(sensor),
        'alternatives':
        simplejson.dumps(alternatives),
        'departure_time':
        unix_time(departure_time) if departure_time else unix_time(utc_now())
    }

    url = "http://maps.googleapis.com/maps/api/directions/%s" % output
    logging.info("google_direction_request: %s" % url)
    response = sign_and_fetch(url, params)

    return response
Example #4
0
def book_order(request):
    """
    Book an order: send it to the dispatcher to get an order assignment,
    then pass the assignment to the station manager.
    """
    order_id = int(request.POST["order_id"])
    logging.info("book_order_task: %d" % order_id)
    order = get_object_or_404(Order, id=order_id)
    passenger = order.passenger

    # if this is the first order of this passenger, connect him with the station that originated the order
    if order.originating_station and passenger.orders.count() == 1:
        logging.info("assigning passenger %s to station %s" % (passenger, order.originating_station))
        passenger.originating_station = order.originating_station
        if not passenger.default_station:
            passenger.default_station = order.originating_station

        passenger.save()

    sorry_msg = ugettext_noop("We're sorry, but we could not find a taxi for you") # use dummy ugettext for makemessages)

    # check if dispatching should stop and return an answer to the user
    if (utc_now() - order.create_date).seconds > ORDER_HANDLE_TIMEOUT:
        try:
            order.change_status(new_status=TIMED_OUT)
            send_msg_to_passenger(passenger, translate_to_lang(sorry_msg, order.language_code))
            logging.warning("order time out: %d" % order_id)
            response = HttpResponse(ORDER_TIMEOUT)
        except UpdateStatusError:
            logging.error("book_order failed: cannot set order [%d] status to %s" % (order.id, "TIME_OUT"))
    else:
        try:
            # choose an assignment for the order and push it to the relevant workstation
            order_assignment = dispatcher.assign_order(order)
            push_order(order_assignment)
            enqueue_redispatch_orders(order_assignment, ORDER_TEASER_TIMEOUT, redispatch_pending_orders)
            response = HttpResponse(ORDER_HANDLED)

        except NoWorkStationFoundError:
            try:
                order.change_status(new_status=FAILED)
                send_msg_to_passenger(passenger, translate_to_lang(sorry_msg, order.language_code)) # use dummy ugettext for makemessages

                log_event(EventType.ORDER_FAILED, order=order, passenger=order.passenger)
                logging.warning("no matching workstation found for: %d" % order_id)
                response = HttpResponse(NO_MATCHING_WORKSTATIONS_FOUND)
            except UpdateStatusError:
                logging.error("book_order failed: cannot set order [%d] status to %s" % (order.id, "FAILED"))

        except Exception, e:
            try:
                order.change_status(new_status=ERROR)
                send_msg_to_passenger(passenger, translate_to_lang(ugettext_noop("We're sorry, but we have encountered an error while handling your request")
                             , order.language_code)) # use dummy ugettext for makemessages
                log_event(EventType.ORDER_ERROR, order=order, passenger=order.passenger)
                logging.error("book_order: OrderError: %d" % order_id)
                raise # handle exception in decorator 
            except UpdateStatusError:
                logging.error("book_order failed: cannot set order [%d] status to %s" % (order.id, "ERROR"))
Example #5
0
def google_directions_request(start_lat, start_lng, end_lat, end_lng, output="json", alternatives=False, sensor=False, departure_time=None):
    # see https://developers.google.com/maps/documentation/directions/
    params = {
        'origin': '%s,%s' % (start_lat, start_lng),
        'destination' : '%s,%s' % (end_lat, end_lng),
        'sensor': simplejson.dumps(sensor) ,
        'alternatives': simplejson.dumps(alternatives),
        'departure_time': unix_time(departure_time) if departure_time else unix_time(utc_now())
    }

    url = "http://maps.googleapis.com/maps/api/directions/%s" % output
    logging.info("google_direction_request: %s" % url)
    response = sign_and_fetch(url, params)

    return response
def handle_dead_workstations(request):
    ws_id = request.POST.get("workstation_id")
    workstation = None
    try:
        workstation = WorkStation.objects.get(id=ws_id)
    except WorkStation.DoesNotExist:
        logging.error("handle_dead_workstations: invalid workstation_id '%s" % ws_id)

    if workstation:
        last_event = AnalyticsEvent.objects.filter(work_station=workstation, type__in=[EventType.WORKSTATION_UP, EventType.WORKSTATION_DOWN]).order_by('-create_date')[:1]
        if last_event:
            last_event = last_event[0]
            if last_event.type == EventType.WORKSTATION_DOWN and (utc_now() - last_event.create_date) >= ALERT_DELTA:
                # send station down mail
                msg = u"Workstation has been down for the last %d minutes:\n\tid = %d station = %s" % (ALERT_DELTA.seconds / 60, workstation.id, workstation.dn_station_name)
                notify_by_email(u"Workstation down", msg)

    return HttpResponse("OK")
def get_previous_rides(request, passenger):
    data = []

    orders = passenger.orders.filter(depart_time__lt=utc_now(), status__in=ORDER_SUCCESS_STATUS).order_by('-depart_time')
    orders = orders.filter(type__in=[OrderType.PRIVATE, OrderType.SHARED])[:PREVIOUS_RIDES_TO_DISPLAY]
    seen_rides = []

    for order in orders:
        ride = order.ride
        if not ride:
            logging.error("order [%s] not valid for previous rides (order.ride is None" % order.id)
            continue
        if ride in seen_rides:
            continue  # skip duplicates (in case ride has multiple orders by same passenger)

        seen_rides.append(ride)

        ride_orders = ride.orders.all()
        ride_mates_orders = filter(lambda o: o != order, ride_orders)
        ride_mates = [{'name': mate_order.passenger.name, 'picture_url': mate_order.passenger.picture_url}
                                    for mate_order in ride_mates_orders for seat in range(order.num_seats)]

        dispatching_event = first(lambda e: e.taxi_id, ride.events.all())

        ride_data = {
            "order_id": order.id,
            "pickup_time": to_js_date(order.pickup_point.stop_time),
            "passengers": ride_mates,
            "seats_left": MAX_SEATS - sum([o.num_seats for o in ride_orders]),
            "your_seats": order.num_seats,
            "taxi_number": dispatching_event.taxi_id if dispatching_event else None,
            "station_name": ride.station.name if ride.station else WAYBETTER_STATION_NAME,
            "price": order.get_billing_amount(),
            "price_alone": order.price_alone,
            "billing_status": ugettext_lazy(order.get_status_display().title()),
            "pickup": order.from_raw,
            "dropoff": order.to_raw,
            "is_private": order.type == OrderType.PRIVATE,
            "comment": ""
            }

        data.append(ride_data)

    return JSONResponse(data)
Example #8
0
def log_connection_events(sender, signal_type, obj, **kwargs):
    from common.tz_support import utc_now
    from django.core.urlresolvers import reverse
    from google.appengine.api.taskqueue import taskqueue
    from analytics.models import AnalyticsEvent
    from common.util import log_event, EventType, notify_by_email
    from ordering.signals import SignalType
    from ordering.station_connection_manager import ALERT_DELTA, handle_dead_workstations

    last_event_qs = AnalyticsEvent.objects.filter(
        work_station=obj,
        type__in=[EventType.WORKSTATION_UP,
                  EventType.WORKSTATION_DOWN]).order_by('-create_date')[:1]
    station = obj.station

    if signal_type == SignalType.WORKSTATION_ONLINE:
        if last_event_qs:
            # send workstation reconnect mail
            last_event = last_event_qs[0]
            if last_event.type == EventType.WORKSTATION_DOWN and (
                    utc_now() - last_event.create_date
            ) >= ALERT_DELTA and station.show_on_list:
                msg = u"Workstation is up again:\n\tid = %d station = %s" % (
                    obj.id, obj.dn_station_name)
                notify_by_email(u"Workstation Reconnected", msg=msg)
        elif station.show_on_list:
            # send "new workstation" mail
            msg = u"A new workstation just connected: id = %d station = %s" % (
                obj.id, obj.dn_station_name)
            notify_by_email(u"New Workstation", msg=msg)

        log_event(EventType.WORKSTATION_UP, station=station, work_station=obj)

    elif signal_type == SignalType.WORKSTATION_OFFLINE:
        log_event(EventType.WORKSTATION_DOWN,
                  station=station,
                  work_station=obj)

        if station.show_on_list:
            # add task to check if workstation is still dead after ALERT_DELTA
            task = taskqueue.Task(url=reverse(handle_dead_workstations),
                                  countdown=ALERT_DELTA.seconds + 1,
                                  params={"workstation_id": obj.id})
            taskqueue.Queue('log-events').add(task)
Example #9
0
def show_order(order_id, work_station):
    """
    raises ShowOrderError
    """
    try:
        order_assignment = OrderAssignment.objects.get(order=order_id, work_station=work_station, status=PENDING)
        order_assignment.change_status(PENDING, ASSIGNED)
    #    except MultipleObjectsReturned:
    #        OrderAssignment.objects.filter(order=order_id, work_station=work_station, status=PENDING).delete()
    except OrderAssignment.DoesNotExist:
        logging.warning("No PENDING assignment for order %d in work station %d" % (order_id, work_station.id))
        raise ShowOrderError()
    except UpdateStatusError:
        raise ShowOrderError()

    order_assignment.show_date = utc_now()
    order_assignment.save()
    enqueue_redispatch_orders(order_assignment, ORDER_ASSIGNMENT_TIMEOUT, redispatch_ignored_orders)

    return order_assignment
Example #10
0
def show_order(order_id, work_station):
    """
    raises ShowOrderError
    """
    try:
        order_assignment = OrderAssignment.objects.get(
            order=order_id, work_station=work_station, status=PENDING)
        order_assignment.change_status(PENDING, ASSIGNED)
    #    except MultipleObjectsReturned:
    #        OrderAssignment.objects.filter(order=order_id, work_station=work_station, status=PENDING).delete()
    except OrderAssignment.DoesNotExist:
        logging.warning(
            "No PENDING assignment for order %d in work station %d" %
            (order_id, work_station.id))
        raise ShowOrderError()
    except UpdateStatusError:
        raise ShowOrderError()

    order_assignment.show_date = utc_now()
    order_assignment.save()
    enqueue_redispatch_orders(order_assignment, ORDER_ASSIGNMENT_TIMEOUT,
                              redispatch_ignored_orders)

    return order_assignment
def get_future_orders_for(passenger):
    future_order_qs = passenger.orders.filter(
        depart_time__gte=utc_now(), status__in=ORDER_SUCCESS_STATUS, type__in=[OrderType.PRIVATE, OrderType.SHARED]).order_by('-depart_time')
    return list(future_order_qs)
Example #12
0
def book_order(request):
    """
    Book an order: send it to the dispatcher to get an order assignment,
    then pass the assignment to the station manager.
    """
    order_id = int(request.POST["order_id"])
    logging.info("book_order_task: %d" % order_id)
    order = get_object_or_404(Order, id=order_id)
    passenger = order.passenger

    # if this is the first order of this passenger, connect him with the station that originated the order
    if order.originating_station and passenger.orders.count() == 1:
        logging.info("assigning passenger %s to station %s" %
                     (passenger, order.originating_station))
        passenger.originating_station = order.originating_station
        if not passenger.default_station:
            passenger.default_station = order.originating_station

        passenger.save()

    sorry_msg = ugettext_noop(
        "We're sorry, but we could not find a taxi for you"
    )  # use dummy ugettext for makemessages)

    # check if dispatching should stop and return an answer to the user
    if (utc_now() - order.create_date).seconds > ORDER_HANDLE_TIMEOUT:
        try:
            order.change_status(new_status=TIMED_OUT)
            send_msg_to_passenger(
                passenger, translate_to_lang(sorry_msg, order.language_code))
            logging.warning("order time out: %d" % order_id)
            response = HttpResponse(ORDER_TIMEOUT)
        except UpdateStatusError:
            logging.error(
                "book_order failed: cannot set order [%d] status to %s" %
                (order.id, "TIME_OUT"))
    else:
        try:
            # choose an assignment for the order and push it to the relevant workstation
            order_assignment = dispatcher.assign_order(order)
            push_order(order_assignment)
            enqueue_redispatch_orders(order_assignment, ORDER_TEASER_TIMEOUT,
                                      redispatch_pending_orders)
            response = HttpResponse(ORDER_HANDLED)

        except NoWorkStationFoundError:
            try:
                order.change_status(new_status=FAILED)
                send_msg_to_passenger(passenger,
                                      translate_to_lang(
                                          sorry_msg, order.language_code)
                                      )  # use dummy ugettext for makemessages

                log_event(EventType.ORDER_FAILED,
                          order=order,
                          passenger=order.passenger)
                logging.warning("no matching workstation found for: %d" %
                                order_id)
                response = HttpResponse(NO_MATCHING_WORKSTATIONS_FOUND)
            except UpdateStatusError:
                logging.error(
                    "book_order failed: cannot set order [%d] status to %s" %
                    (order.id, "FAILED"))

        except Exception, e:
            try:
                order.change_status(new_status=ERROR)
                send_msg_to_passenger(
                    passenger,
                    translate_to_lang(
                        ugettext_noop(
                            "We're sorry, but we have encountered an error while handling your request"
                        ), order.language_code
                    ))  # use dummy ugettext for makemessages
                log_event(EventType.ORDER_ERROR,
                          order=order,
                          passenger=order.passenger)
                logging.error("book_order: OrderError: %d" % order_id)
                raise  # handle exception in decorator
            except UpdateStatusError:
                logging.error(
                    "book_order failed: cannot set order [%d] status to %s" %
                    (order.id, "ERROR"))
Example #13
0
                            getattr(order, "%s_raw" % order_type))
            res = None

        return res

    form_data = request.POST
    if passenger.business and request.POST.get("business_order"):
        form_data = get_business_order_form_data(request, passenger)

    form = OrderForm(data=form_data, passenger=passenger)

    if form.is_valid():
        if passenger.orders.all()[:1]:
            last_order = passenger.orders.order_by("-create_date")[0]
            interval = BUSINESS_ORDERING_INTERVAL if passenger.business else ORDERING_INTERVAL
            if (utc_now() - last_order.create_date).seconds < interval:
                return error_response(
                    _("Ordering is not allowed so soon after another order"))

        app_udid = request.POST.get("APP_UDID")
        installed_app = None
        if app_udid:  # this came from a device that sends app specific id
            installed_app = InstalledApp.by_app_udid(app_udid)
            if not installed_app:
                return error_response(
                    _("Please register before attempting to order"))
            if installed_app.blocked:
                return error_response(
                    _("Your account has been suspended. Please contact [email protected]"
                      ))
            logging.warning("Could not fix missing house number: %s" % getattr(order, "%s_raw" % order_type))
            res = None

        return res

    form_data = request.POST
    if passenger.business and request.POST.get("business_order"):
        form_data = get_business_order_form_data(request, passenger)

    form = OrderForm(data=form_data, passenger=passenger)

    if form.is_valid():
        if passenger.orders.all()[:1]:
            last_order = passenger.orders.order_by("-create_date")[0]
            interval = BUSINESS_ORDERING_INTERVAL if passenger.business else ORDERING_INTERVAL
            if (utc_now() - last_order.create_date).seconds < interval:
                return error_response(_("Ordering is not allowed so soon after another order"))

        app_udid = request.POST.get("APP_UDID")
        installed_app = None
        if app_udid:  # this came from a device that sends app specific id
            installed_app = InstalledApp.by_app_udid(app_udid)
            if not installed_app:
                return error_response(_("Please register before attempting to order"))
            if installed_app.blocked:
                return error_response(_("Your account has been suspended. Please contact [email protected]"))

        order = form.save(commit=False)
        order.language_code = request.POST.get("language_code", get_language_from_request(request))
        order.debug = settings.DEV
        order.passenger = passenger