def create_shared_ride_for_order(ride_data, order):
    logging.info(u"creating shared ride from ride_data %s" % ride_data)

    ride = SharedRide()
    ride.debug = order.debug
    ride.depart_time = order.depart_time
    ride.arrive_time = order.depart_time + datetime.timedelta(seconds=ride_data.duration)
    ride.distance = ride_data.distance
    ride.cost_data =  ride_data.cost_data
    if order.type == OrderType.PRIVATE:
        ride.can_be_joined = False
    ride.save()

    for point_data in ride_data.points:
        create_ride_point(ride, point_data)

    for p in ride.points.all():
        if p.type == StopType.PICKUP:
            order.pickup_point = p
        else:
            order.dropoff_point = p

    order.ride = ride

    order.price_data = ride_data.order_price_data(NEW_ORDER_ID)
    order.save()

    logging.info("created new ride [%s] for order [%s]" % (ride.id, order.id))

    return ride
示例#2
0
def ride_status_sentinel(ride_id):
    logging.info("ride_status_sentinel: %s" % ride_id)
    ride = SharedRide.by_id(ride_id)
    if ride.status != ACCEPTED:
        send_ride_in_risk_notification(
            u"Ride not accepted by station %d minutes before depart time" %
            (RIDE_SENTINEL_GRACE.seconds / 60), ride_id)
示例#3
0
def ride_viewed(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    if ride and ride.station == work_station.station:
        if ride.change_status(old_status=RideStatus.ASSIGNED, new_status=RideStatus.VIEWED):
            return HttpResponse("OK")

    return HttpResponseForbidden()
def billing_approved_book_order(callback_args, order):
    from sharing.station_controller import send_ride_in_risk_notification

    ride_id = callback_args.get("ride_id")
    ride_data = callback_args.get("ride_data")
    discount_data = callback_args.get("discount_data")
    discount_data = DiscountData.load(discount_data) if discount_data else None

    if not (ride_id is not None and ride_data):
        logging.error("no ride_id or ride_data for on_billing_trx_approved")
        return

    try:
        if ride_id == NEW_ORDER_ID:
            ride = create_shared_ride_for_order(ride_data, order)
        else:
            ride = SharedRide.by_id(ride_id)
            if ride and ride.lock(): # try joining existing ride
                try:
                    update_ride_add_order(ride, ride_data, order)
                    ride.unlock()

                except Exception, e:
                    #TODO_WB: handle this error in some way - try again, create a new ride
                    logging.error(traceback.format_exc())
                    ride.unlock()

                    raise Exception(e.message)
            else:
示例#5
0
def ride_viewed(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    if ride and ride.station == work_station.station:
        if ride.change_status(old_status=RideStatus.ASSIGNED,
                              new_status=RideStatus.VIEWED):
            return HttpResponse("OK")

    return HttpResponseForbidden()
示例#6
0
def resend_to_fleet_manager(request, ride_id):
    resend_result = False

    ride = SharedRide.by_id(ride_id)
    cancel_result = fleet_manager.cancel_ride(ride)
    if cancel_result:
        resend_result = fleet_manager.create_ride(ride)

    return JSONResponse({'result': resend_result})
示例#7
0
def resend_to_fleet_manager(request, ride_id):
    resend_result = False

    ride = SharedRide.by_id(ride_id)
    cancel_result = fleet_manager.cancel_ride(ride)
    if cancel_result:
        resend_result = fleet_manager.create_ride(ride)

    return JSONResponse({'result': resend_result})
示例#8
0
 def _add_shared_ride(ride_id):
     ride = SharedRide.by_id(ride_id)
     shared_rides[ride_id] = {
         "id"        : ride.id,
         "type"      : "sharing",
         "taxi"      : ride.taxi_number,
         "stops"     : [p.serialize_for_status_page() for p in sorted(ride.points.all(), key=lambda p: p.stop_time)],
         "events"    : []
     }
     return ride
示例#9
0
def reassign_ride(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    if ride and ride.station == work_station.station:
        ride.update(taxi_number=None)
        if fleet_manager.cancel_ride(ride) and fleet_manager.create_ride(ride):
            return HttpResponse("OK")
        else:
            logging.error("could not reassign ride: %s" % ride_id)

    return HttpResponseForbidden()
示例#10
0
def reassign_ride(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    if ride and ride.station == work_station.station:
        ride.update(taxi_number=None)
        if fleet_manager.cancel_ride(ride) and fleet_manager.create_ride(ride):
            return HttpResponse("OK")
        else:
            logging.error("could not reassign ride: %s" % ride_id)

    return HttpResponseForbidden()
示例#11
0
def manual_assign_ride(request):
    from sharing.sharing_dispatcher import assign_ride

    ride_id = request.POST.get("ride_id")
    station_id = request.POST.get("station_id")
    ride = SharedRide.by_id(ride_id)
    station = Station.by_id(station_id)
    if station and ride.station != station:
        fleet_manager.cancel_ride(ride)
        assign_ride(ride, station)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#12
0
def print_voucher(printer_id, html, title, ride_id):
    print_backend = DEFAULT_BACKEND
    logging.info(u"print_voucher: printer_id: %s" % printer_id)
    job_id = _do_voucher_send(printer_id, html, title, ride_id, print_backend, check_print_job_status)
    if not job_id:
        ride = SharedRide.by_id(ride_id)
        if ride.station.fax_number:
            notify_by_email(u"WARNING: Voucher printing failed, will try to send fax for ride: %s" % ride_id)
            logging.warning("printing failed, will send fax")
            fax_voucher(ride.station.fax_number, html, title, ride_id)
        else:
            send_ride_in_risk_notification(u"Ride voucher failed to print and station has no fax number defined.", ride_id)
示例#13
0
def manual_assign_ride(request):
    from sharing.sharing_dispatcher import assign_ride

    ride_id = request.POST.get("ride_id")
    station_id = request.POST.get("station_id")
    ride = SharedRide.by_id(ride_id)
    station = Station.by_id(station_id)
    if station and ride.station != station:
        fleet_manager.cancel_ride(ride)
        assign_ride(ride, station)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#14
0
def send_ride_texts(sender, signal_type, positions, **kwargs):
    from ordering.models import SharedRide, RideStatus
    from fleet.fleet_manager import  send_ride_point_text

    for position in positions:
        ride = SharedRide.by_uuid(position.ride_uuid)
        if ride and ride.status == RideStatus.ACCEPTED:
            active_points = ride.points.filter(dispatched=False).order_by("stop_time")
            if active_points:
                current_point = active_points[0]
                next_point = active_points[1] if len(active_points) > 1 else None

                if distance_between_points(position.lat, position.lon, current_point.lat, current_point.lon) < RIDE_TEXT_THRESHOLD:
                    send_ride_point_text(ride, current_point, next_point=next_point)
示例#15
0
def send_ride_in_risk_notification(msg, ride_id):
    msg_key = u"%s_%s" % (ride_id, msg)
    namespace = "ride_in_risk_notifications"

    msg_sent = memcache.get(msg_key, namespace=namespace)
    if msg_sent:
        logging.info(u"skipping sending: %s" % msg)
        return

    ride = SharedRide.by_id(ride_id)
    if ride and ride.debug:
        logging.info("skipping notification for debug ride %s" % ride_id)

    elif ride:
        t = get_template("ride_in_risk_email.html")
        orders = ride.orders.all()
        passengers = [o.passenger for o in orders.all()]
        station = ride.station
        try:
            sharing_ws = station.work_stations.filter(
                accept_shared_rides=True)[0]
        except Exception:
            sharing_ws = None

        html = t.render(
            Context({
                "passengers":
                [u"%s (%s)" % (p.full_name, p.phone) for p in passengers],
                "station_phones":
                station.phones.all() if station else [],
                "station_name":
                station.name if station else "[NO STATION]",
                "online_status":
                sharing_ws.is_online if sharing_ws else None,
                "ride_id":
                ride_id,
                "depart_time":
                ride.depart_time.strftime("%H:%M"),
                "ride_status":
                RideStatus.get_name(ride.status),
                "msg":
                msg
            }))
        logging.info("sending risk mail: %s" % html)

        notify_by_email("IMPORTANT: Ride In Risk [%s]" % ride_id, html=html)
        memcache.set(msg_key, True, namespace=namespace)

        for num in CRITICAL_MESSAGES_CONTACT_LIST:
            send_sms(num, msg)
示例#16
0
def check_print_job_status(job_id,
                           title,
                           ride_id,
                           html,
                           counter=1,
                           backend=None):
    try:
        status = get_status(job_id, backend=backend)

        logging.info("check_print_job_status(%s): '%s'" %
                     (job_id, FaxStatus.get_name(status)))

        if status != FaxStatus.DONE:
            if counter > PRINT_COMPLETE_TIMEOUT:
                logging.info("print failure: title=%s" % title)
                ride = SharedRide.by_id(ride_id)
                if ride.station.fax_number:
                    email_devs(
                        u"Ride voucher did not print after %d minutes: %s. (sending fax)"
                        % (PRINT_COMPLETE_TIMEOUT, title))
                    fax_voucher(ride.station.fax_number, html, title, ride_id)
                else:
                    send_ride_in_risk_notification(
                        u"Ride voucher did not print after %d minutes: %s.\nNo fax number defined!."
                        % (PRINT_COMPLETE_TIMEOUT, title), ride_id)
            else:
                logging.info("print still not done: counter=%s, title=%s" %
                             (counter, title))
                deferred.defer(check_print_job_status,
                               job_id,
                               title,
                               ride_id,
                               html,
                               counter=counter + 1,
                               backend=backend,
                               _countdown=60)
    except Exception, e:
        trace = traceback.format_exc()
        logging.error("check_print_job_status failed with exception: %s" %
                      trace)
        deferred.defer(check_print_job_status,
                       job_id,
                       title,
                       ride_id,
                       html,
                       counter=counter + 1,
                       backend=backend,
                       _countdown=60)
示例#17
0
def manual_dispatch(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    taxi_number = request.POST.get("taxi_number")
    pickup_estimate = request.POST.get("pickup_estimate")
    if taxi_number and pickup_estimate and ride and ride.station == work_station.station:
        ride.taxi_number = taxi_number
        ride.pickup_estimate = int(pickup_estimate)

        fleet_manager.cancel_ride(ride)
        fleet_manager.create_ride(ride)

        ride.change_status(old_status=RideStatus.VIEWED, new_status=RideStatus.ACCEPTED)

        return HttpResponse("OK")

    return HttpResponseForbidden()
示例#18
0
 def _add_shared_ride(ride_id):
     ride = SharedRide.by_id(ride_id)
     shared_rides[ride_id] = {
         "id":
         ride.id,
         "type":
         "sharing",
         "taxi":
         ride.taxi_number,
         "stops": [
             p.serialize_for_status_page()
             for p in sorted(ride.points.all(), key=lambda p: p.stop_time)
         ],
         "events": []
     }
     return ride
示例#19
0
def print_voucher(printer_id, html, title, ride_id):
    print_backend = DEFAULT_BACKEND
    logging.info(u"print_voucher: printer_id: %s" % printer_id)
    job_id = _do_voucher_send(printer_id, html, title, ride_id, print_backend,
                              check_print_job_status)
    if not job_id:
        ride = SharedRide.by_id(ride_id)
        if ride.station.fax_number:
            notify_by_email(
                u"WARNING: Voucher printing failed, will try to send fax for ride: %s"
                % ride_id)
            logging.warning("printing failed, will send fax")
            fax_voucher(ride.station.fax_number, html, title, ride_id)
        else:
            send_ride_in_risk_notification(
                u"Ride voucher failed to print and station has no fax number defined.",
                ride_id)
示例#20
0
def manual_dispatch(request, work_station, ride_id):
    ride = SharedRide.by_id(ride_id)
    taxi_number = request.POST.get("taxi_number")
    pickup_estimate = request.POST.get("pickup_estimate")
    if taxi_number and pickup_estimate and ride and ride.station == work_station.station:
        ride.taxi_number = taxi_number
        ride.pickup_estimate = int(pickup_estimate)

        fleet_manager.cancel_ride(ride)
        fleet_manager.create_ride(ride)

        ride.change_status(old_status=RideStatus.VIEWED,
                           new_status=RideStatus.ACCEPTED)

        return HttpResponse("OK")

    return HttpResponseForbidden()
示例#21
0
def save_search_req_and_offers(passenger, order_settings, offers):
    sr = SearchRequest.fromOrderSettings(order_settings, passenger)
    sr.save()

    for offer in offers:
        pickup_dt = offer['pickup_time'] / 1000
        pickup_dt = datetime.datetime.fromtimestamp(pickup_dt).replace(tzinfo=TZ_INFO["UTC"]).astimezone(TZ_INFO['Asia/Jerusalem'])
        ride_offer = RideOffer(search_req=sr, ride_key=offer.get('ride_id'), ride=SharedRide.by_id(offer.get('ride_id')), pickup_dt=pickup_dt, seats_left=offer['seats_left'], price=offer['price'], new_ride=offer['new_ride'])

        if str(offer.get('ride_id')).startswith(DISCOUNTED_OFFER_PREFIX):
            cached_discount_data = memcache.get(offer.get('ride_id'), namespace=DISCOUNTED_OFFERS_NS)
            if cached_discount_data:
                discount_data = DiscountData.load(cached_discount_data)
                ride_offer.discount_rule = discount_data.discount_rule
                ride_offer.promotion = discount_data.promotion
                ride_offer.promo_code = discount_data.promo_code
                ride_offer.new_ride = True # this is actually a new ride

        ride_offer.save()
示例#22
0
def create_ny_isr_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    if not ride:
        msg = "no SharedRide found with id=%s" % ride_id
        logging.error(msg)
        return HttpResponseBadRequest(msg)

    if settings.LOCAL:
        isrproxy_id = 2738544
        test_station_id = 1008
    else:
        isrproxy_id = 3673085
        test_station_id = 1713061  # amir_station_1

    if ride.debug:
        target_station_id = test_station_id
        target_station_isr_id = 8  # test station isr id
    else:
        # real rides created from stable - send to New York taxi station
        target_station_id = 1529226
        target_station_isr_id = 10

    logging.info(u"create_ny_isr_ride: %s" %
                 u", ".join([unicode(s) for s in [target_station_id, ride]]))

    if not (ride.station and ride.station.id == target_station_id):
        msg = "wrong station: ride.station=%s target_station=%s" % (
            ride.station, target_station_id)
        logging.error(msg)
        response = HttpResponseBadRequest(msg)
    else:
        # fix the station data since stable.Station does not have fleet field
        if not ride.station.fleet_station_id:
            ride.station.fleet_station_id = target_station_isr_id
            ride.station.save()

        ride.dn_fleet_manager_id = isrproxy_id
        ride.save()

        result = fleet_manager.create_ride(ride)
        response = HttpResponse(str(result))

    return response
示例#23
0
def create_ny_isr_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    if not ride:
        msg = "no SharedRide found with id=%s" % ride_id
        logging.error(msg)
        return HttpResponseBadRequest(msg)

    if settings.LOCAL:
        isrproxy_id = 2738544
        test_station_id = 1008
    else:
        isrproxy_id = 3673085
        test_station_id = 1713061 # amir_station_1

    if ride.debug:
        target_station_id = test_station_id
        target_station_isr_id = 8 # test station isr id
    else:
        # real rides created from stable - send to New York taxi station
        target_station_id = 1529226
        target_station_isr_id = 10

    logging.info(u"create_ny_isr_ride: %s" % u", ".join([unicode(s) for s in [target_station_id, ride]]))

    if not (ride.station and ride.station.id == target_station_id):
        msg = "wrong station: ride.station=%s target_station=%s" % (ride.station, target_station_id)
        logging.error(msg)
        response = HttpResponseBadRequest(msg)
    else:
        # fix the station data since stable.Station does not have fleet field
        if not ride.station.fleet_station_id:
            ride.station.fleet_station_id = target_station_isr_id
            ride.station.save()

        ride.dn_fleet_manager_id = isrproxy_id
        ride.save()

        result = fleet_manager.create_ride(ride)
        response = HttpResponse(str(result))

    return response
示例#24
0
def eagle_eye(request):
    from dateutil.parser import parse

    stations = []
    for station in Station.objects.all():
        try:
            sharing_ws = station.work_stations.filter(accept_shared_rides=True)[0]
        except Exception:
            sharing_ws = None

        stations.append({"name": station.name, "id": station.id, "debug": station.debug, "online_status": sharing_ws.is_online if sharing_ws else False})

    if request.is_ajax():
        ride_id = request.GET.get("ride_id")
        if ride_id:  # update specific ride's data
            return JSONResponse(SharedRide.by_id(ride_id).serialize_for_eagle_eye())

        # get all rides data
        start_date = parse(request.GET.get("start_date")).astimezone(IsraelTimeZone())
        end_date = parse(request.GET.get("end_date")).astimezone(IsraelTimeZone())

        start_date = datetime.combine(start_date, dt_time.min)
        end_date = datetime.combine(end_date, dt_time.max)

        rides = SharedRide.objects.filter(depart_time__gte=start_date, depart_time__lte=end_date).order_by("-depart_time")
        incomplete_orders = Order.objects.filter(depart_time__gte=start_date, depart_time__lte=end_date)
        incomplete_orders = filter(lambda o: o.status in [IGNORED, REJECTED, FAILED, ERROR, TIMED_OUT, CANCELLED], incomplete_orders)

        result = {
            'rides': [r.serialize_for_eagle_eye() for r in rides],
            'incomplete_orders': [o.serialize_for_eagle_eye() for o in incomplete_orders],
            'stations': stations
        }

        return JSONResponse(result)

    else:
        lib_ng = True
        stations = simplejson.dumps(stations)
        return render_to_response("eagle_eye.html", locals(), context_instance=RequestContext(request))
示例#25
0
def send_ride_in_risk_notification(msg, ride_id):
    msg_key = u"%s_%s" % (ride_id, msg)
    namespace = "ride_in_risk_notifications"

    msg_sent = memcache.get(msg_key, namespace=namespace)
    if msg_sent:
        logging.info(u"skipping sending: %s" % msg)
        return

    ride = SharedRide.by_id(ride_id)
    if ride and ride.debug:
        logging.info("skipping notification for debug ride %s" % ride_id)

    elif ride:
        t = get_template("ride_in_risk_email.html")
        orders = ride.orders.all()
        passengers = [o.passenger for o in orders.all()]
        station = ride.station
        try:
            sharing_ws = station.work_stations.filter(accept_shared_rides=True)[0]
        except Exception:
            sharing_ws = None

        html = t.render(Context({
            "passengers": [u"%s (%s)" % (p.full_name, p.phone) for p in passengers],
            "station_phones": station.phones.all() if station else [],
            "station_name": station.name if station else "[NO STATION]",
            "online_status": sharing_ws.is_online if sharing_ws else None,
            "ride_id": ride_id,
            "depart_time": ride.depart_time.strftime("%H:%M"),
            "ride_status": RideStatus.get_name(ride.status),
            "msg": msg
        }))
        logging.info("sending risk mail: %s" % html)

        notify_by_email("IMPORTANT: Ride In Risk [%s]" % ride_id, html=html)
        memcache.set(msg_key, True, namespace=namespace)

        for num in CRITICAL_MESSAGES_CONTACT_LIST:
            send_sms(num, msg)
示例#26
0
def create_single_order_ride(order):
    from sharing.signals import ride_created_signal

    if order.status != APPROVED:
        logging.error("denied creating ride for unapproved order [%s]" %
                      order.id)
        return None

    ride = SharedRide()
    ride.debug = order.debug
    ride.depart_time = order.depart_time
    ride.arrive_time = order.arrive_time
    ride.save()

    pickup = RidePoint()
    pickup.ride = ride
    pickup.stop_time = order.depart_time
    pickup.type = StopType.PICKUP
    pickup.address = order.from_raw
    pickup.lat = order.from_lat
    pickup.lon = order.from_lon
    pickup.save()

    dropoff = RidePoint()
    dropoff.ride = ride
    dropoff.stop_time = order.arrive_time
    dropoff.type = StopType.DROPOFF
    dropoff.address = order.to_raw or order.from_raw
    dropoff.lat = order.to_lat or order.from_lat
    dropoff.lon = order.to_lon or order.from_lon
    dropoff.save()

    order.ride = ride
    order.pickup_point = pickup
    order.dropoff_point = dropoff
    order.save()

    logging.info("created single order ride: order[%s] -> ride[%s]" %
                 (order.id, ride.id))
    ride_created_signal.send(sender='create_single_order_ride', obj=ride)
    return ride
示例#27
0
def check_print_job_status(job_id, title, ride_id, html, counter=1, backend=None):
    try:
        status = get_status(job_id, backend=backend)

        logging.info("check_print_job_status(%s): '%s'" % (job_id, FaxStatus.get_name(status)))

        if status != FaxStatus.DONE:
            if counter > PRINT_COMPLETE_TIMEOUT:
                logging.info("print failure: title=%s" % title)
                ride = SharedRide.by_id(ride_id)
                if ride.station.fax_number:
                    email_devs(u"Ride voucher did not print after %d minutes: %s. (sending fax)" % (PRINT_COMPLETE_TIMEOUT, title))
                    fax_voucher(ride.station.fax_number, html, title, ride_id)
                else:
                    send_ride_in_risk_notification(u"Ride voucher did not print after %d minutes: %s.\nNo fax number defined!." % (PRINT_COMPLETE_TIMEOUT, title), ride_id)
            else:
                logging.info("print still not done: counter=%s, title=%s" % (counter, title))
                deferred.defer(check_print_job_status, job_id, title, ride_id, html, counter=counter + 1, backend=backend,
                               _countdown=60)
    except Exception, e:
        trace = traceback.format_exc()
        logging.error("check_print_job_status failed with exception: %s" % trace)
        deferred.defer(check_print_job_status, job_id, title, ride_id, html, counter=counter + 1, backend=backend, _countdown=60)
示例#28
0
def create_single_order_ride(order):
    from sharing.signals import ride_created_signal

    if order.status != APPROVED:
        logging.error("denied creating ride for unapproved order [%s]" % order.id)
        return None

    ride = SharedRide()
    ride.debug = order.debug
    ride.depart_time = order.depart_time
    ride.arrive_time = order.arrive_time
    ride.save()

    pickup = RidePoint()
    pickup.ride = ride
    pickup.stop_time = order.depart_time
    pickup.type = StopType.PICKUP
    pickup.address = order.from_raw
    pickup.lat = order.from_lat
    pickup.lon = order.from_lon
    pickup.save()

    dropoff = RidePoint()
    dropoff.ride = ride
    dropoff.stop_time = order.arrive_time
    dropoff.type = StopType.DROPOFF
    dropoff.address = order.to_raw or order.from_raw
    dropoff.lat = order.to_lat or order.from_lat
    dropoff.lon = order.to_lon or order.from_lon
    dropoff.save()

    order.ride = ride
    order.pickup_point = pickup
    order.dropoff_point = dropoff
    order.save()

    logging.info("created single order ride: order[%s] -> ride[%s]" % (order.id, ride.id))
    ride_created_signal.send(sender='create_single_order_ride', obj=ride)
    return ride
示例#29
0
def book_ride(request):
    return JSONResponse({
        'status': 'failed',
        'error': SERVICE_NOT_AVAILABLE_MSG
    })

    passenger = Passenger.from_request(request)
    request_data = simplejson.loads(request.POST.get('data'))
    logging.info(u"book ride: %s\n%s" % (passenger, unicode(simplejson.dumps(request_data), "unicode-escape")))

    result = {
        'status': '',
        'order_id': None,
        'redirect': '',
        'error': '',
        'pickup_dt': None
    }

    if passenger and passenger.user and hasattr(passenger, "billing_info"): # we have logged-in passenger with billing_info - let's proceed
        order_settings = OrderSettings.fromRequest(request)
        ride_id = request_data.get("ride_id")

        new_ride = (ride_id == NEW_ORDER_ID)
        discounted_ride = (ride_id and str(ride_id).startswith(DISCOUNTED_OFFER_PREFIX))

        join_ride = not (new_ride or discounted_ride)
        ride_to_join = SharedRide.by_id(ride_id) if join_ride else None

        order = None
        if ride_to_join:  # check it is indeed a valid candidate
            if is_valid_candidate(ride_to_join, order_settings):
                order = create_order(order_settings, passenger, ride=ride_to_join)
            else:
                logging.warning("tried booking an invalid ride candidate")
                result['error'] = _("Sorry, but this ride has been closed for booking")

        else:  # new or discounted ride, check pickup time isn't before ASAP (minus a couple seconds to allow booking to exactly ASAP)
            if order_settings.pickup_dt <= default_tz_now() + datetime.timedelta(minutes=asap_interval()) - datetime.timedelta(seconds=10):
                logging.warning("tried booking to expired pickup time %s" % order_settings.pickup_dt)
                result['error'] = _("Please choose a later pickup time")
            else:
                if discounted_ride:
                    cached_discount_data = memcache.get(ride_id, namespace=DISCOUNTED_OFFERS_NS)
                    discount_data = DiscountData.load(cached_discount_data)
                    logging.info("[book_ride] discount_data = %s" % discount_data)
                    order = create_order(order_settings, passenger, discount_data=discount_data)
                else:
                    order = create_order(order_settings, passenger)


        if order:
            result['status'] = 'success'
            result['order_id'] = order.id
            result['pickup_formatted'] = order.from_raw
            result['pickup_dt'] = to_js_date(order.depart_time)
            result["price"] = order.get_billing_amount()

            ride_orders = [order] + ( list(ride_to_join.orders.all()) if ride_to_join else [] )
            result["passengers"] = [{'name': o.passenger.name, 'picture_url': o.passenger.picture_url, 'is_you': o==order} for o in ride_orders for seat in range(o.num_seats)]
            result["seats_left"] = MAX_SEATS - sum([o.num_seats for o in ride_orders])

            deferred.defer(join_offer_and_order, order, request_data)

        else:
            result['status'] = 'failed'

    else:  # not authorized for booking, save current booking state in session
        set_current_booking_data(request)

        if passenger and not hasattr(passenger, "billing_info"):
            result['status'] = 'billing_failed'
            result['redirect'] = get_token_url(request) # go to billing
        else:
            result['status'] = 'auth_failed'

    logging.info("book ride result: %s" % result)
    return JSONResponse(result)
示例#30
0
def accept_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    ride.change_status(new_status=RideStatus.ACCEPTED)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#31
0
def complete_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    ride.change_status(new_status=RideStatus.COMPLETED)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#32
0
def accept_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    ride.change_status(new_status=RideStatus.ACCEPTED)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#33
0
def complete_ride(request, ride_id):
    ride = SharedRide.by_id(ride_id)
    ride.change_status(new_status=RideStatus.COMPLETED)

    return JSONResponse({'ride': ride.serialize_for_eagle_eye()})
示例#34
0
def ride_status_sentinel(ride_id):
    logging.info("ride_status_sentinel: %s" % ride_id)
    ride = SharedRide.by_id(ride_id)
    if ride.status != ACCEPTED:
        send_ride_in_risk_notification(
            u"Ride not accepted by station %d minutes before depart time" % (RIDE_SENTINEL_GRACE.seconds / 60), ride_id)
示例#35
0
def send_ride_voucher(ride_id):
    ride = SharedRide.by_id(ride_id)
    if not (ride and ride.station):
        logging.error("can't send voucher ride_id=%s" % ride_id)
        return

    current_lang = translation.get_language()
    station_lang_code = settings.LANGUAGES[ride.station.language][0]
    translation.activate(station_lang_code)

    pickups = []
    dropoffs = []
    for p in sorted(ride.points.all(), key=lambda point: point.stop_time):
        orders = p.pickup_orders.all() if p.type == StopType.PICKUP else p.dropoff_orders.all()
        stop = {
            "count": sum([order.num_seats for order in orders]),
            "address": p.address
        }
        phones = ["%s - %s" % (o.passenger.name, o.passenger.phone) for o in orders]
        if len(phones) == 1:
            stop["phones"] = phones

        if p.type == StopType.PICKUP:
            pickups.append(stop)
        if p.type == StopType.DROPOFF:
            dropoffs.append(stop)

    tariff = RuleSet.get_active_set(ride.depart_time)
    srz_cost_details = CostDetails.serialize(ride.cost_details)
    template_args = {
        "ride": ride,
        "taxi": ride.taxi_number,
        "ride_date": ride.depart_time.strftime("%d/%m/%y"),
        "ride_time": (ride.first_pickup.stop_time - STATION_PICKUP_OFFSET).strftime("%H:%M"),
        "pickups": pickups,
        "dropoffs": dropoffs,
        "charged_stops": max(0, len(pickups) - 1),
        "cost_details": srz_cost_details,
        "distance": "%.1f" % float(ride.distance/1000.0) if ride.distance else "",
        "additional_km": "%.1f" % float(srz_cost_details["additional_meters"]/1000.0) if (srz_cost_details and srz_cost_details["additional_meters"]) else "",
        "tariff": tariff.name if tariff else ""
    }
    subject = "WAYBetter Ride: %s" % ride.id
    t = get_template("voucher_email.html")
    html = t.render(Context(template_args))
    # logging.info(html)

    if ride.station.vouchers_emails:
        emails = filter(lambda i: bool(i), COMMA_SPLITTER.split(ride.station.vouchers_emails))
        # let us know so we will contact the station
        resend_voucher_html = html.replace("</body>", "<br><br><a href='http://www.waybetter.com%s'>Resend Voucher</a></body>" % reverse(resend_voucher, kwargs={"ride_id": ride_id}))
        notify_by_email(u"Ride [%s] Voucher sent to %s [%s]" % (ride.id, ride.station.name, ",".join(emails)),
            html=resend_voucher_html,
            attachments=[("voucher.html", html.encode("utf-8"))])

        for email in emails:
            try:
                validate_email(email)
                send_mail_as_noreply(email, subject, html=html)
            except ValidationError:
                logging.warning(u"Strange email number: %s" % email)

    if ride.station.printer_id: # send print job to printer
        print_voucher(ride.station.printer_id, html, subject, ride_id)

    elif ride.station.fax_number: # send fax to station
        logging.warning("No printer_id defined. Sending Fax")
        fax_voucher(ride.station.fax_number, html, subject, ride_id)

    else:
        logging.info("no voucher sent for station [%s]" % ride.station)

    translation.activate(current_lang)

    logging.info("ride [%s] voucher sent" % ride.id)
示例#36
0
def get_offers(request):
    return JSONResponse({
        'status': 'failed',
        'error': SERVICE_NOT_AVAILABLE_MSG
    })

    order_settings = OrderSettings.fromRequest(request)

    # TODO_WB: save the requested search params and associate with a push_token from request for later notifications of similar searches

    if not order_settings.private:
        candidate_rides = get_candidate_rides(order_settings)
        look_for_discounts = True
    else:
        candidate_rides = []
        look_for_discounts = False

    matching_rides = get_matching_rides(candidate_rides, order_settings)
    if not matching_rides:
        return JSONResponse({'error': u'מצטערים, הכתובת המבוקשת אינה באיזורי הכיסוי עדיין'})

    offers = []

    start_ride_algo_data = None

    for ride_data in matching_rides:
        ride_id = ride_data.ride_id
        ride = SharedRide.by_id(ride_id)

        # get price for offer according to tariff
        tariff = RuleSet.get_active_set(order_settings.pickup_dt)
        price = ride_data.order_price(NEW_ORDER_ID, tariff)
        price_alone = ride_data.order_price(NEW_ORDER_ID, tariff, sharing=False)

        if not price > 0:
            logging.warning("get_offers missing price for %s" % order_settings.pickup_dt)
            continue

        if ride_id == NEW_ORDER_ID:  # start a new ride
            start_ride_algo_data = ride_data
            offer = {
                "asap": order_settings.asap,
                "pickup_time": to_js_date(order_settings.pickup_dt),
                "price": price,
                "seats_left": MAX_SEATS,
                "new_ride": True,
                "comment": _(u"You will be updated when someone joins")  # TODO_WB: sharing chances
            }

        else:  # sharing offers
            time_sharing = ride_data.order_time(NEW_ORDER_ID)
            time_alone = ride_data.order_time(NEW_ORDER_ID, sharing=False)
            time_addition = int((time_sharing - time_alone) / 60)

            pickup_point = ride_data.order_pickup_point(NEW_ORDER_ID)
            ride_orders = ride.orders.all()
            pickup_time = compute_new_departure(ride, ride_data) + datetime.timedelta(seconds=pickup_point.offset)
            if pickup_time < default_tz_now() + datetime.timedelta(minutes=asap_interval()):
                logging.info("skipping offer because pickup_time is too soon: %s" % pickup_time)
                continue

            offer = {
                "ride_id": ride_id,
                "pickup_time": to_js_date(pickup_time),
                "passengers": [{'name': order.passenger.name, 'picture_url': order.passenger.picture_url} for order in ride_orders for seat in range(order.num_seats)],
                "seats_left": MAX_SEATS - sum([order.num_seats for order in ride_orders]),
                "price": price,
                "new_ride": False,
                "comment": _(u"Money saved: %(money_saved)s NIS or more – additional time: %(time_added)s min") % {'time_added': time_addition, 'money_saved': "%g" % (price_alone - price)}
            }

            # good enough offer found, no discounts
            if order_settings.pickup_dt - datetime.timedelta(minutes=30) < pickup_time < order_settings.pickup_dt + datetime.timedelta(minutes=30):
                look_for_discounts = False

        offers.append(offer)

    # add discounted offers if relevant

    ## override
    look_for_discounts = True
    ## override

    if look_for_discounts and start_ride_algo_data:
        offers += get_discounted_offers(request, order_settings, start_ride_algo_data)

    offers = sorted(offers, key=lambda  o: o["pickup_time"], reverse=False)

    deferred.defer(save_search_req_and_offers, Passenger.from_request(request), order_settings, offers)
    return JSONResponse({'offers': offers})
示例#37
0
def send_ride_voucher(ride_id):
    ride = SharedRide.by_id(ride_id)
    if not (ride and ride.station):
        logging.error("can't send voucher ride_id=%s" % ride_id)
        return

    current_lang = translation.get_language()
    station_lang_code = settings.LANGUAGES[ride.station.language][0]
    translation.activate(station_lang_code)

    pickups = []
    dropoffs = []
    for p in sorted(ride.points.all(), key=lambda point: point.stop_time):
        orders = p.pickup_orders.all(
        ) if p.type == StopType.PICKUP else p.dropoff_orders.all()
        stop = {
            "count": sum([order.num_seats for order in orders]),
            "address": p.address
        }
        phones = [
            "%s - %s" % (o.passenger.name, o.passenger.phone) for o in orders
        ]
        if len(phones) == 1:
            stop["phones"] = phones

        if p.type == StopType.PICKUP:
            pickups.append(stop)
        if p.type == StopType.DROPOFF:
            dropoffs.append(stop)

    tariff = RuleSet.get_active_set(ride.depart_time)
    srz_cost_details = CostDetails.serialize(ride.cost_details)
    template_args = {
        "ride":
        ride,
        "taxi":
        ride.taxi_number,
        "ride_date":
        ride.depart_time.strftime("%d/%m/%y"),
        "ride_time": (ride.first_pickup.stop_time -
                      STATION_PICKUP_OFFSET).strftime("%H:%M"),
        "pickups":
        pickups,
        "dropoffs":
        dropoffs,
        "charged_stops":
        max(0,
            len(pickups) - 1),
        "cost_details":
        srz_cost_details,
        "distance":
        "%.1f" % float(ride.distance / 1000.0) if ride.distance else "",
        "additional_km":
        "%.1f" % float(srz_cost_details["additional_meters"] / 1000.0) if
        (srz_cost_details and srz_cost_details["additional_meters"]) else "",
        "tariff":
        tariff.name if tariff else ""
    }
    subject = "WAYBetter Ride: %s" % ride.id
    t = get_template("voucher_email.html")
    html = t.render(Context(template_args))
    # logging.info(html)

    if ride.station.vouchers_emails:
        emails = filter(lambda i: bool(i),
                        COMMA_SPLITTER.split(ride.station.vouchers_emails))
        # let us know so we will contact the station
        resend_voucher_html = html.replace(
            "</body>",
            "<br><br><a href='http://www.waybetter.com%s'>Resend Voucher</a></body>"
            % reverse(resend_voucher, kwargs={"ride_id": ride_id}))
        notify_by_email(u"Ride [%s] Voucher sent to %s [%s]" %
                        (ride.id, ride.station.name, ",".join(emails)),
                        html=resend_voucher_html,
                        attachments=[("voucher.html", html.encode("utf-8"))])

        for email in emails:
            try:
                validate_email(email)
                send_mail_as_noreply(email, subject, html=html)
            except ValidationError:
                logging.warning(u"Strange email number: %s" % email)

    if ride.station.printer_id:  # send print job to printer
        print_voucher(ride.station.printer_id, html, subject, ride_id)

    elif ride.station.fax_number:  # send fax to station
        logging.warning("No printer_id defined. Sending Fax")
        fax_voucher(ride.station.fax_number, html, subject, ride_id)

    else:
        logging.info("no voucher sent for station [%s]" % ride.station)

    translation.activate(current_lang)

    logging.info("ride [%s] voucher sent" % ride.id)
示例#38
0
def eagle_eye(request):
    from dateutil.parser import parse

    stations = []
    for station in Station.objects.all():
        try:
            sharing_ws = station.work_stations.filter(
                accept_shared_rides=True)[0]
        except Exception:
            sharing_ws = None

        stations.append({
            "name":
            station.name,
            "id":
            station.id,
            "debug":
            station.debug,
            "online_status":
            sharing_ws.is_online if sharing_ws else False
        })

    if request.is_ajax():
        ride_id = request.GET.get("ride_id")
        if ride_id:  # update specific ride's data
            return JSONResponse(
                SharedRide.by_id(ride_id).serialize_for_eagle_eye())

        # get all rides data
        start_date = parse(request.GET.get("start_date")).astimezone(
            IsraelTimeZone())
        end_date = parse(request.GET.get("end_date")).astimezone(
            IsraelTimeZone())

        start_date = datetime.combine(start_date, dt_time.min)
        end_date = datetime.combine(end_date, dt_time.max)

        rides = SharedRide.objects.filter(
            depart_time__gte=start_date,
            depart_time__lte=end_date).order_by("-depart_time")
        incomplete_orders = Order.objects.filter(depart_time__gte=start_date,
                                                 depart_time__lte=end_date)
        incomplete_orders = filter(
            lambda o: o.status in
            [IGNORED, REJECTED, FAILED, ERROR, TIMED_OUT, CANCELLED],
            incomplete_orders)

        result = {
            'rides': [r.serialize_for_eagle_eye() for r in rides],
            'incomplete_orders':
            [o.serialize_for_eagle_eye() for o in incomplete_orders],
            'stations':
            stations
        }

        return JSONResponse(result)

    else:
        lib_ng = True
        stations = simplejson.dumps(stations)
        return render_to_response("eagle_eye.html",
                                  locals(),
                                  context_instance=RequestContext(request))