def track_order(request, order_id):
    order = Order.by_id(order_id)
    use_mock = False
    ride = None
    expiration_date = default_tz_now()
    if order:
        try:
            ride = order.ride or order.pickmeapp_ride
        except (SharedRide.DoesNotExist, PickMeAppRide.DoesNotExist):
            pass
    else:
        error_message = _("This ride is invalid")

    if not ride:
        error_message = _("This ride is invalid")
    else:
        expiration_date = ride.arrive_time + timedelta(minutes=15)
        if expiration_date < default_tz_now():
            error_message = _("This ride has expired")

    if ride.station:
        station_icon_url = ride.station.app_icon_url
        station_phone = ride.station.phone

    if request.GET.get("use_mock"):
        error_message = ""
        station_icon_url = "https://s3.amazonaws.com/stations_icons/ny_icon.png"
        use_mock = True
        expiration_date = default_tz_now() + timedelta(minutes=15)

    expiration_date = to_js_date(expiration_date)  # prepare for JS consumption

    return custom_render_to_response("track_order.html", locals(), context_instance=RequestContext(request))
Example #2
0
def track_order(request, order_id):
    order = Order.by_id(order_id)
    use_mock = False
    ride = None
    expiration_date = default_tz_now()
    if order:
        try:
            ride = order.ride or order.pickmeapp_ride
        except (SharedRide.DoesNotExist, PickMeAppRide.DoesNotExist):
            pass
    else:
        error_message = _("This ride is invalid")

    if not ride:
        error_message = _("This ride is invalid")
    else:
        expiration_date = ride.arrive_time + timedelta(minutes=15)
        if expiration_date < default_tz_now():
            error_message = _("This ride has expired")

    if ride.station:
        station_icon_url = ride.station.app_icon_url
        station_phone = ride.station.phone

    if request.GET.get("use_mock"):
        error_message = ""
        station_icon_url = "https://s3.amazonaws.com/stations_icons/ny_icon.png"
        use_mock = True
        expiration_date = default_tz_now() + timedelta(minutes=15)

    expiration_date = to_js_date(expiration_date)  # prepare for JS consumption

    return custom_render_to_response('track_order.html',
                                     locals(),
                                     context_instance=RequestContext(request))
Example #3
0
def calc_passenger_ride_freq(offset=0, data=None):
    if not data:
        data = [["id", "orders", "days"]]
    else:
        data = pickle.loads(gzip.zlib.decompress(data))

    batch_size = 500
    logging.info("querying passengers %s->%s" % (offset, offset + batch_size))
    passengers = Passenger.objects.all()[offset: offset + batch_size]

    for p in passengers:
        try:
            bi = p.billing_info
        except BillingInfo.DoesNotExist:
            continue

        days = (default_tz_now() - bi.create_date).days
        if days:
            orders = list(Order.objects.filter(passenger=p, type__in=[OrderType.SHARED, OrderType.PRIVATE]))
            orders = filter(lambda o: o.ride, orders)
            data.append([p.id, len(orders), days])

    if passengers:
        data = gzip.zlib.compress(pickle.dumps(data), 9)
        deferred.defer(calc_passenger_ride_freq, offset=offset + batch_size + 1, data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        csv_string = ""
        for line in data:
            csv_string += ",".join([str(i) for i in line]) + "\n"

        send_mail_as_noreply("*****@*****.**", "Passenger ride freq", attachments=[("passenger_freq.csv", csv_string)])
Example #4
0
    def _create_order_stop(cls, order):
        order_stop = cls._create_ISR_object("Order_Stop")
        order_stop.Address = cls._create_stop_address(order)

        stop_number = 0  # TODO_WB: the pickup order, change when ISR supports more than 1 stop

        key_value_string_passenger = cls._create_array_object(
            "KeyValueOfstringPassanger8pH_SfiQv")
        key_value_string_passenger.Key = stop_number
        key_value_string_passenger.Value = cls._create_passenger(
            order.passenger)

        array_of_string_passenger = cls._create_array_object(
            "ArrayOfKeyValueOfstringPassanger8pH_SfiQv")
        array_of_string_passenger.KeyValueOfstringPassanger8pH_SfiQv.append(
            key_value_string_passenger)

        order_stop.Passangers = array_of_string_passenger
        order_stop.Stop_Order = stop_number

        # this field is used as the start time in ISR client UI
        order_stop.Stop_Time = (order.depart_time
                                or (default_tz_now() +
                                    DEFAULT_TIMEDELTA)).isoformat()

        return order_stop
    def fromRequest(cls, request):
        request_data = simplejson.loads(request.REQUEST.get("data"))
        request_data = dict_to_str_keys(request_data)

        pickup = request_data.get("pickup")
        dropoff = request_data.get("dropoff")
        booking_settings = request_data.get("settings")
        asap = request_data.get("asap")


        inst = cls()
        inst.debug = settings.DEV
        inst.num_seats = int(booking_settings["num_seats"])
        inst.luggage = int(booking_settings["luggage"])
        inst.private = bool(booking_settings["private"])
        inst.pickup_address = Address(**pickup)
        inst.dropoff_address = Address(**dropoff)

        # TODO_WB: save extra data when pickup/dropoff have place_id field
        logging.info("pickup_place_id: %s" % pickup.get("place_id"))
        logging.info("dropoff_place_id: %s" % dropoff.get("place_id"))

        if asap:
            inst.asap = True
            inst.pickup_dt = default_tz_now() + datetime.timedelta(minutes=asap_interval())
            logging.info("ASAP set as %s" % inst.pickup_dt.strftime("%H:%M"))
        else:
            inst.pickup_dt = dateutil.parser.parse(request_data.get("pickup_dt"))

        inst.mobile = request.mobile
        inst.language_code = request.POST.get("language_code", get_language_from_request(request))
        inst.user_agent = request.META.get("HTTP_USER_AGENT")

        return inst
Example #6
0
def send_message(ride, message):
    logging.info(u"send_message '%s' to ride: %s" % (message, ride.id))
    try:
        station = ride.station
        assert station, "ride [%s] is not assigned to a station" % ride.id
        assert station.fleet_station_id, "station %s has no fleet_station_id" % ride.station.name
        assert ride.dn_fleet_manager_id, "ride [%s] is not associated with a fleet manager" % ride.id
        assert ride.taxi_number, "ride [%s] is not associated with a taxi number" % ride.id

        ride_fm = FleetManager.by_id(ride.dn_fleet_manager_id)
        result = ride_fm.send_message(message, ride.station.fleet_station_id,
                                      ride.taxi_number)

        # log a RideEvent about his message
        rp = get_ride_position(ride)
        e = RideEvent(pickmeapp_ride=None,
                      shared_ride=ride,
                      status=FleetManagerRideStatus.MESSAGE_SENT,
                      raw_status=message,
                      lat=rp.lat if rp else None,
                      lon=rp.lon if rp else None,
                      taxi_id=ride.taxi_number,
                      timestamp=default_tz_now())
        e.save()

        return result
    except Exception, e:
        logging.error(traceback.format_exc())
        return False
def sync_app_state(request):
    earliest_pickup_time = ceil_datetime(trim_seconds(default_tz_now()) + datetime.timedelta(minutes=asap_interval()), minutes=booking_interval())
    latest_pickup_time = earliest_pickup_time + datetime.timedelta(hours=(24*14))
    dt_options = list(datetimeIterator(earliest_pickup_time, latest_pickup_time, delta=datetime.timedelta(minutes=booking_interval())))

    response = {
        "logged_in": request.user.is_authenticated(),
        "pickup_datetime_options": [to_js_date(opt) for opt in dt_options],
        "pickup_datetime_default_idx": 0,
        "asap_as_default": True,
        "booking_data": request.session.get(CURRENT_BOOKING_DATA_KEY)
    }

    passenger = Passenger.from_request(request)
    response["show_url"] = "" # change to cause child browser to open with passed url

    if passenger:
        response["authenticated"] = True
        response["passenger_picture_url"] = passenger.picture_url

        ongoing_order = get_ongoing_order(passenger)
        if ongoing_order:
            response["ongoing_order_id"] = ongoing_order.id

        future_orders = get_future_orders_for(passenger)
        response["future_orders_count"] = len(future_orders)

    trimed_response = response.copy()
    trimed_response['pickup_datetime_options'] = response['pickup_datetime_options'][:9] + ['...']
    logging.info("get_initial_status: %s" % trimed_response)

    return JSONResponse(response)
Example #8
0
def invoices_task(request):
    action = int(request.POST.get("action", -1))

    now = default_tz_now()
    last_month_date = (now - timedelta(days=now.day))
    month = last_month_date.month
    year = last_month_date.year

    start_date = datetime.combine(date(year=year, month=month, day=1), default_tz_time_min())
    end_date = datetime.combine(date(year=year, month=month, day=calendar.monthrange(year, month)[1]), default_tz_time_max())

    trx_qs = BillingTransaction.objects.filter(debug=False, invoice_sent=False, status=BillingStatus.CHARGED, charge_date__gte=start_date, charge_date__lte=end_date)

    if action == InvoiceActions.CREATE_ID:
        logging.info("Creating invoice ids: %s - %s" % (start_date, end_date))
        failed = do_create_invoice_ids(trx_qs)
    elif action == InvoiceActions.SEND:
        logging.info("Sending invoices: %s - %s" % (start_date, end_date))
        failed = do_send_invoices(trx_qs)
    else:
        raise RuntimeError("NOT A VALID INVOICE ACTION")

    action_name = InvoiceActions.get_name(action)
    if failed:
        notify_by_email("Error %s invoices for month %s/%s" % (action_name, month, year), "failed with following passenger ids %s" % failed)
    else:
        notify_by_email("Success %s invoices for month %s/%s" % (action_name, month, year))

    return HttpResponse("OK")
Example #9
0
    def _create_order_stop(cls, order, stop_number):
        return {
            'Address': cls._create_stop_address(order),
            'Passengers': [cls._create_passenger(order.passenger)],
            'Stop_Order': stop_number,

            # this field is used as the start time in ISR client UI
            'Stop_Time': (order.depart_time or (default_tz_now() + DEFAULT_TIMEDELTA)).isoformat()
        }
def get_discounted_offers(request, order_settings, start_ride_algo_data):
    user = request.user if request.user.is_authenticated() else None

    discounted_offers = []

    earliest_offer_dt = ceil_datetime(max(trim_seconds(default_tz_now()) + datetime.timedelta(minutes=asap_interval()), order_settings.pickup_dt - OFFERS_TIMEDELTA), minutes=booking_interval())
    discounts_data = compute_discounts_data(order_settings,
        earliest_offer_dt,
        order_settings.pickup_dt + OFFERS_TIMEDELTA,
        datetime.timedelta(minutes=booking_interval()),
        user = user
    )

    for discount_data in discounts_data:
        discount_rule = discount_data.discount_rule
        discount_dt = discount_data.pickup_dt

        tariff_for_discount_offer = RuleSet.get_active_set(discount_dt)
        base_price_for_discount_offer = start_ride_algo_data.order_price(NEW_ORDER_ID, tariff_for_discount_offer)
        if base_price_for_discount_offer:
            discount = discount_rule.get_discount(base_price_for_discount_offer)
            if discount == 0:
                logging.info(u"skipping %s: grants zero discount" % discount_rule.name)
                continue

            offer_key = "%s_%s" % (DISCOUNTED_OFFER_PREFIX, get_uuid())
            memcache.set(offer_key, DiscountData.dump(discount_data), namespace=DISCOUNTED_OFFERS_NS)

            offer_text = _(u"The price includes a discount of %g NIS") % discount
            if discount_rule.offer_text:
                offer_text = discount_rule.offer_text
                if offer_text.find("%g") > -1:  # render discount amount
                    offer_text %= discount

            discount_offer_data = {
                "ride_id": offer_key,
                "pickup_time": to_js_date(discount_dt),
                "discount_picture_url": discount_rule.picture_url,
                "discount_name": discount_rule.display_name,
                "passengers": [],
                "seats_left": MAX_SEATS,
                "price": base_price_for_discount_offer - discount,
                "new_ride": True,
                "comment": offer_text
            }


            user_agent = request.META.get("HTTP_USER_AGENT", "")
            if RE_2_1_AGENT.match(user_agent) is None:  # only for client < 1.2.1
                discount_offer_data.update({
                    "seats_left": MAX_SEATS - 1,
                    "passengers": [{'name': discount_rule.display_name, 'picture_url': discount_rule.picture_url}]
                })

            discounted_offers.append(discount_offer_data)

    return discounted_offers
def get_order_msg(ride, order):
    t = get_template("passenger_notification_msg.html")
    pickup_time = None
    position = get_position_for_order(order)
    if position:
        logging.info("use actual position for pickup estimate")
        duration = get_shortest_duration(position.lat,
                                         position.lon,
                                         order.from_lat,
                                         order.from_lon,
                                         sensor=True)
        logging.info("[get_order_msg] duration = '%s'" % duration)

        if duration:
            pickup_time = duration / 60

    if not pickup_time:
        if ride.pickup_estimate:  # this is an estimate from the station
            duration = get_duration_to_point(ride, order.pickup_point)
            pickup_time = (duration / 60) + ride.pickup_estimate
        else:  # no estimate given, use algo values
            if order.pickup_point.stop_time > default_tz_now():
                td = order.pickup_point.stop_time - default_tz_now()
                pickup_time = td.seconds / 60
            else:
                pickup_time = 1  # 'now'

    current_lang = translation.get_language()

    translation.activate(order.language_code)
    template_data = {
        'pickup_time': pickup_time,
        'station_name': ride.station.name,
        'taxi_number': ride.taxi_number
    }

    msg = t.render(Context(template_data))
    translation.activate(current_lang)

    logging.info(u"order message %s" % msg)

    return msg
Example #12
0
def get_ongoing_rides(backend=None):
    delta = default_tz_now() - timedelta(minutes=15)
    pickmeapp_rides = list(PickMeAppRide.objects.filter(arrive_time__gt=delta))
    shared_rides = list(SharedRide.objects.filter(arrive_time__gt=delta))

    rides = pickmeapp_rides + shared_rides
    if backend:
        rides = filter(lambda r: r.dn_fleet_manager_id == backend.id, rides)

    logging.info("get ongoing rides for fleet %s: %s" % (backend.name if backend else "ALL", rides))
    return rides
Example #13
0
def get_ongoing_rides(backend=None):
    delta = default_tz_now() - timedelta(minutes=15)
    pickmeapp_rides = list(PickMeAppRide.objects.filter(arrive_time__gt=delta))
    shared_rides = list(SharedRide.objects.filter(arrive_time__gt=delta))

    rides = pickmeapp_rides + shared_rides
    if backend:
        rides = filter(lambda r: r.dn_fleet_manager_id == backend.id, rides)

    logging.info("get ongoing rides for fleet %s: %s" %
                 (backend.name if backend else "ALL", rides))
    return rides
Example #14
0
    def _create_order_stop(cls, order, stop_number):
        return {
            'Address':
            cls._create_stop_address(order),
            'Passengers': [cls._create_passenger(order.passenger)],
            'Stop_Order':
            stop_number,

            # this field is used as the start time in ISR client UI
            'Stop_Time':
            (order.depart_time
             or (default_tz_now() + DEFAULT_TIMEDELTA)).isoformat()
        }
def get_candidate_rides(order_settings):
    """
    Get rides that might be a match for the given order_settings
    @param order_settings: C{OrderSettings}
    @return:
    """
    requested_pickup_dt = order_settings.pickup_dt
    earliest = max(default_tz_now(), requested_pickup_dt - OFFERS_TIMEDELTA)
    latest = requested_pickup_dt + OFFERS_TIMEDELTA

    candidates = SharedRide.objects.filter(depart_time__gt=earliest, depart_time__lte=latest)
    candidates = filter(lambda candidate: is_valid_candidate(candidate, order_settings), candidates)

    return candidates
Example #16
0
        def get_query_date_range_by_month_offset(month_offset):
            now = default_tz_now()
            if now.month > month_offset:
                d = now.replace(month=now.month - month_offset)
            else:
                d = now.replace(month=now.month - month_offset + 12, year=now.year -1)


            start_day, end_day = calendar.monthrange(d.year, d.month)

            start_date = default_tz_now_min().replace(day=1, month=d.month, year=d.year)
            end_date = default_tz_now_max().replace(day=end_day, month=d.month, year=d.year)

            return start_date, end_date
def get_order_msg(ride, order):
    t = get_template("passenger_notification_msg.html")
    pickup_time = None
    position = get_position_for_order(order)
    if position:
        logging.info("use actual position for pickup estimate")
        duration = get_shortest_duration(position.lat, position.lon, order.from_lat, order.from_lon, sensor=True)
        logging.info("[get_order_msg] duration = '%s'" % duration)

        if duration:
            pickup_time = duration / 60

    if not pickup_time:
        if ride.pickup_estimate: # this is an estimate from the station
            duration = get_duration_to_point(ride, order.pickup_point)
            pickup_time = (duration / 60) + ride.pickup_estimate
        else: # no estimate given, use algo values
            if order.pickup_point.stop_time > default_tz_now():
                td = order.pickup_point.stop_time - default_tz_now()
                pickup_time = td.seconds / 60
            else:
                pickup_time = 1 # 'now'

    current_lang = translation.get_language()

    translation.activate(order.language_code)
    template_data = {'pickup_time': pickup_time,
                     'station_name': ride.station.name,
                     'taxi_number': ride.taxi_number
                     }

    msg = t.render(Context(template_data))
    translation.activate(current_lang)

    logging.info(u"order message %s" % msg)

    return msg
Example #18
0
def dispatching_cron(request):
    from sharing.station_controller import send_ride_in_risk_notification

    rides_to_dispatch = SharedRide.objects.filter(debug=settings.DEV, status=RideStatus.PENDING, depart_time__lte=default_tz_now() + DISPATCHING_TIME)
    logging.info(u"cron: dispatch rides: %s" % rides_to_dispatch)
    for ride in rides_to_dispatch:
        deferred.defer(dispatch_ride, ride)

    rides_to_monitor = SharedRide.objects.filter(debug=settings.DEV, depart_time__gte=default_tz_now() - START_MONITORING_TIME, depart_time__lte=default_tz_now() + STOP_MONITORING_TIME, status__in=[RideStatus.PROCESSING, RideStatus.ACCEPTED, RideStatus.PENDING, RideStatus.ASSIGNED, RideStatus.VIEWED])
    logging.info(u"cron: monitored rides: %s" % rides_to_monitor)
    for ride in rides_to_monitor:
        if default_tz_now() - ride.depart_time >= MUST_ACCEPT_TIME and ride.status != RideStatus.ACCEPTED:
            ride.change_status(new_status=RideStatus.FAILED)
        elif ride.depart_time <= default_tz_now() + SHOULD_ACCEPT_TIME and ride.status != RideStatus.ACCEPTED:
            send_ride_in_risk_notification(u"Ride was not accepted by station", ride.id)
        elif ride.depart_time <= default_tz_now() + SHOULD_VIEW_TIME and ride.status not in [RideStatus.VIEWED, RideStatus.ACCEPTED]:
            send_ride_in_risk_notification(u"Ride was not viewed by dispatcher", ride.id)

    rides_to_complete = SharedRide.objects.filter(debug=settings.DEV, status=RideStatus.ACCEPTED, depart_time__lte=default_tz_now() - MARK_COMPLETE_TIME)
    for ride in rides_to_complete:
        if not ride.change_status(old_status=RideStatus.ACCEPTED, new_status=RideStatus.COMPLETED):
            logging.error(u"ride [%s] was not marked COMPLETED" % ride.id)

    return HttpResponse("OK")
Example #19
0
def sharing_workstation_data(request, work_station):
    logging.info("sharing_workstation_data: %s" % work_station)

    rides_query = SharedRide.objects.filter(
        station=work_station.station,
        depart_time__lt=default_tz_now() + timedelta(hours=24),
        status__in=[
            RideStatus.ASSIGNED, RideStatus.VIEWED, RideStatus.ACCEPTED
        ])
    rides = [
        r.serialize_for_ws()
        for r in sorted(rides_query, key=lambda ride: ride.depart_time)
    ]

    return JSONResponse({'rides': rides})
Example #20
0
def delete_expired_sessions(start_at=0):
    now = default_tz_now()
    expired = Session.objects.filter(expire_date__lte=now)

    logging.info("start_at: %s" % start_at)
    stop_at = start_at
    try:
        for session in expired:
            session.delete()
            stop_at += 1

    except Exception, e:
        logging.info("stop_at: %s (%s deleted this run)" %
                     (stop_at, (stop_at - start_at)))
        deferred.defer(delete_expired_sessions, stop_at, _queue="maintenance")
        return
    def report_conversion(udid):
        url = "http://tracking.taptica.com/aff_u"
        payload = urlencode(
            {
                "tt_adv_id": 612,
                "tt_deviceid": udid,
                "tt_appid": 501682022,
                "tt_time": default_tz_now().strftime("%Y-%m-%d %H:%M:%S.%f"),
            }
        )
        url = "%s?%s" % (url, payload)
        logging.info("report_conversion: %s" % url)
        res = safe_fetch(url, method="GET", deadline=15)
        if res:
            res = simplejson.loads(res.content)["tt_cid"]

        return res
Example #22
0
        def get_query_date_range_by_month_offset(month_offset):
            now = default_tz_now()
            if now.month > month_offset:
                d = now.replace(month=now.month - month_offset)
            else:
                d = now.replace(month=now.month - month_offset + 12,
                                year=now.year - 1)

            start_day, end_day = calendar.monthrange(d.year, d.month)

            start_date = default_tz_now_min().replace(day=1,
                                                      month=d.month,
                                                      year=d.year)
            end_date = default_tz_now_max().replace(day=end_day,
                                                    month=d.month,
                                                    year=d.year)

            return start_date, end_date
Example #23
0
    def report_conversion(udid):
        url = "http://tracking.taptica.com/aff_u"
        payload = urlencode({
            "tt_adv_id":
            612,
            "tt_deviceid":
            udid,
            "tt_appid":
            501682022,
            "tt_time":
            default_tz_now().strftime("%Y-%m-%d %H:%M:%S.%f"),
        })
        url = "%s?%s" % (url, payload)
        logging.info("report_conversion: %s" % url)
        res = safe_fetch(url, method="GET", deadline=15)
        if res:
            res = simplejson.loads(res.content)["tt_cid"]

        return res
def get_ongoing_order(passenger):
    """
    @param passenger:
    @return: ongoing order or None
    """
    ongoing_order = None

    # orders that can still be ongoing
    recently = default_tz_now() - datetime.timedelta(minutes=MAX_RIDE_DURATION)
    possibly_ongoing_orders = passenger.orders.filter(depart_time__gt=recently).order_by("-depart_time")
    for order in possibly_ongoing_orders:
        if all([ order.status in ORDER_SUCCESS_STATUS,
                 order.ride and order.ride.status == RideStatus.ACCEPTED,
                 order.dropoff_point and not order.dropoff_point.visited ]):

            ongoing_order = order
            break

    return ongoing_order
Example #25
0
def dispatching_cron(request):
    from sharing.station_controller import send_ride_in_risk_notification

    rides_to_dispatch = SharedRide.objects.filter(
        debug=settings.DEV,
        status=RideStatus.PENDING,
        depart_time__lte=default_tz_now() + DISPATCHING_TIME)
    logging.info(u"cron: dispatch rides: %s" % rides_to_dispatch)
    for ride in rides_to_dispatch:
        deferred.defer(dispatch_ride, ride)

    rides_to_monitor = SharedRide.objects.filter(
        debug=settings.DEV,
        depart_time__gte=default_tz_now() - START_MONITORING_TIME,
        depart_time__lte=default_tz_now() + STOP_MONITORING_TIME,
        status__in=[
            RideStatus.PROCESSING, RideStatus.ACCEPTED, RideStatus.PENDING,
            RideStatus.ASSIGNED, RideStatus.VIEWED
        ])
    logging.info(u"cron: monitored rides: %s" % rides_to_monitor)
    for ride in rides_to_monitor:
        if default_tz_now(
        ) - ride.depart_time >= MUST_ACCEPT_TIME and ride.status != RideStatus.ACCEPTED:
            ride.change_status(new_status=RideStatus.FAILED)
        elif ride.depart_time <= default_tz_now(
        ) + SHOULD_ACCEPT_TIME and ride.status != RideStatus.ACCEPTED:
            send_ride_in_risk_notification(u"Ride was not accepted by station",
                                           ride.id)
        elif ride.depart_time <= default_tz_now(
        ) + SHOULD_VIEW_TIME and ride.status not in [
                RideStatus.VIEWED, RideStatus.ACCEPTED
        ]:
            send_ride_in_risk_notification(
                u"Ride was not viewed by dispatcher", ride.id)

    rides_to_complete = SharedRide.objects.filter(
        debug=settings.DEV,
        status=RideStatus.ACCEPTED,
        depart_time__lte=default_tz_now() - MARK_COMPLETE_TIME)
    for ride in rides_to_complete:
        if not ride.change_status(old_status=RideStatus.ACCEPTED,
                                  new_status=RideStatus.COMPLETED):
            logging.error(u"ride [%s] was not marked COMPLETED" % ride.id)

    return HttpResponse("OK")
Example #26
0
    def _create_order_stop(cls, order):
        order_stop = cls._create_ISR_object("Order_Stop")
        order_stop.Address = cls._create_stop_address(order)

        stop_number = 0 # TODO_WB: the pickup order, change when ISR supports more than 1 stop

        key_value_string_passenger = cls._create_array_object("KeyValueOfstringPassanger8pH_SfiQv")
        key_value_string_passenger.Key = stop_number
        key_value_string_passenger.Value = cls._create_passenger(order.passenger)

        array_of_string_passenger = cls._create_array_object("ArrayOfKeyValueOfstringPassanger8pH_SfiQv")
        array_of_string_passenger.KeyValueOfstringPassanger8pH_SfiQv.append(key_value_string_passenger)

        order_stop.Passangers = array_of_string_passenger
        order_stop.Stop_Order = stop_number

        # this field is used as the start time in ISR client UI
        order_stop.Stop_Time = (order.depart_time or (default_tz_now() + DEFAULT_TIMEDELTA)).isoformat()

        return order_stop
Example #27
0
def get_ride_position(ride):
    """
    Get the latest known taxi position for a ride.
    @param ride: ride to track
    @return: A C{TaxiRidePosition} or None
    """
    trp = None
    cached_trp = memcache.get(_get_key(ride.uuid),
                              namespace=FM_MEMCACHE_NAMESPACE)
    if cached_trp:
        trp = pickle.loads(cached_trp)
        logging.info("found position for ride: %s" % ride.uuid)
        logging.info(
            "position.timestamp = %s, stale? = %s" %
            (trp.timestamp,
             (trp.timestamp < default_tz_now() - timedelta(minutes=15))))
    else:
        logging.warning("no position found for ride: %s (%s)" %
                        (ride.uuid, ride.id))

    return trp
Example #28
0
    def _create_external_order(cls, order, isr_station_id):
        ex_order = cls._create_ISR_object("External_Order")
        ex_order.Auto_Order = True  #ISRsays: should be True
        ex_order.Comments = order.comments
        ex_order.Remarks = ""
        ex_order.Visa_ID = "visa_id"
        ex_order.Customer = cls._create_customer_data(order.passenger)
        ex_order.External_Order_ID = order.id
        ex_order.Prefered_Operator_ID = isr_station_id
        # ex_order.Prefered_Vehicle_ID = -1

        # TODO_WB: if passenger.business the business is contact?
        ex_order.Contact_Name = ""
        ex_order.Contact_Phone = ""

        # ISRsays: these fields are required but not reflected in ISR client UI
        start_time = default_tz_now() + DEFAULT_TIMEDELTA
        finish_time = start_time + DEFAULT_TIMEDELTA
        ex_order.Start_Time = (order.depart_time or start_time).isoformat()
        ex_order.Finish_Time = (order.arrive_time or finish_time).isoformat()

        order_stop = cls._create_order_stop(order)
        key_value_string_order_stop = cls._create_array_object(
            "KeyValueOfstringOrder_Stop8pH_SfiQv")
        key_value_string_order_stop.Key = order_stop.Stop_Order
        key_value_string_order_stop.Value = order_stop

        array_of_string_order_stop = cls._create_array_object(
            "ArrayOfKeyValueOfstringOrder_Stop8pH_SfiQv")
        array_of_string_order_stop.KeyValueOfstringOrder_Stop8pH_SfiQv.append(
            key_value_string_order_stop)
        ex_order.Stops = array_of_string_order_stop

        order_type = cls._create_ISR_object("External_Order.Order_Type")
        ex_order.Order_Type.value = order_type.Taxi_Order

        order_status = cls._create_ISR_object("External_Order.Status")
        ex_order.Status.value = getattr(order_status, INITIAL_STATUS)
        return ex_order
Example #29
0
def calc_passenger_ride_freq(offset=0, data=None):
    if not data:
        data = [["id", "orders", "days"]]
    else:
        data = pickle.loads(gzip.zlib.decompress(data))

    batch_size = 500
    logging.info("querying passengers %s->%s" % (offset, offset + batch_size))
    passengers = Passenger.objects.all()[offset:offset + batch_size]

    for p in passengers:
        try:
            bi = p.billing_info
        except BillingInfo.DoesNotExist:
            continue

        days = (default_tz_now() - bi.create_date).days
        if days:
            orders = list(
                Order.objects.filter(
                    passenger=p,
                    type__in=[OrderType.SHARED, OrderType.PRIVATE]))
            orders = filter(lambda o: o.ride, orders)
            data.append([p.id, len(orders), days])

    if passengers:
        data = gzip.zlib.compress(pickle.dumps(data), 9)
        deferred.defer(calc_passenger_ride_freq,
                       offset=offset + batch_size + 1,
                       data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        csv_string = ""
        for line in data:
            csv_string += ",".join([str(i) for i in line]) + "\n"

        send_mail_as_noreply("*****@*****.**",
                             "Passenger ride freq",
                             attachments=[("passenger_freq.csv", csv_string)])
def cancel_order(request, passenger):
    """
    Cancel an order. Current status must be APPROVED meaning J5 was successful.
    The billing backend is responsible for not charging (J4) the order.
    """
    from sharing.sharing_dispatcher import WS_SHOULD_HANDLE_TIME
    response = {'success': False,
                'message': _("This order cannot be cancelled anymore")}

    order = Order.by_id(request.POST.get("order_id"))
    cancel_allowed = False
    if order and order.passenger == passenger:
        cancel_allowed = True
        ride = order.ride
        if ride:
            cancel_allowed = ride.depart_time > default_tz_now() + datetime.timedelta(minutes=WS_SHOULD_HANDLE_TIME)

    if cancel_allowed and order.change_status(APPROVED, CANCELLED):
        response = {'success': True,
                    'message': _("Order cancelled")}

    return JSONResponse(response)
Example #31
0
    def _create_ride(cls, ride, isr_station_id, taxi_number=None):
        from ordering.models import PickMeAppRide, SharedRide
        from fleet.isr_tests import FakeSharedRide

        # ISRsays: these fields are required but not reflected in ISR client UI
        start_time = default_tz_now() + DEFAULT_TIMEDELTA
        finish_time = start_time + DEFAULT_TIMEDELTA

        order = None
        if isinstance(ride, PickMeAppRide):
            order = ride.order
        elif isinstance(ride, SharedRide):
            order = ride.first_pickup.pickup_orders.all()[0]
        elif isinstance(ride, FakeSharedRide):
            order = ride.orders.all()[0]

        stop_number = 0  # TODO_WB: the pickup order, change when ISR supports more than 1 stop
        first_stop = cls._create_order_stop(
            order, stop_number)  #TODO_WB: get from ride
        return {
            'Auto_Order': False,
            'Comments': order.comments,
            'Remarks': '',
            'Visa_ID': 'visa_id',
            'Customer': cls._create_customer_data(order.passenger),
            'External_Order_ID': ride.uuid,
            'Preferred_Operator_ID': int(isr_station_id),
            'Preferred_Vehicle_ID': taxi_number if taxi_number else '',
            # ex_order.Prefered_Vehicle_ID = -1,
            # TODO_WB: if passenger.business the business is contact?
            'Contact_Name': '',
            'Contact_Phone': '',
            'Start_Time': (order.depart_time or start_time).isoformat(),
            'Finish_Time': (order.arrive_time or finish_time).isoformat(),
            'Stops': [first_stop],
            'Order_Type': 'Taxi_Order',
            'Status': INITIAL_STATUS
        }
Example #32
0
    def _create_ride(cls, ride, isr_station_id, taxi_number=None):
        from ordering.models import PickMeAppRide, SharedRide
        from fleet.isr_tests import FakeSharedRide

        # ISRsays: these fields are required but not reflected in ISR client UI
        start_time = default_tz_now() + DEFAULT_TIMEDELTA
        finish_time = start_time + DEFAULT_TIMEDELTA

        order = None
        if isinstance(ride, PickMeAppRide):
            order = ride.order
        elif isinstance(ride, SharedRide):
            order = ride.first_pickup.pickup_orders.all()[0]
        elif isinstance(ride, FakeSharedRide):
            order = ride.orders.all()[0]

        stop_number = 0 # TODO_WB: the pickup order, change when ISR supports more than 1 stop
        first_stop = cls._create_order_stop(order, stop_number)  #TODO_WB: get from ride
        return {
            'Auto_Order': False,
            'Comments': order.comments,
            'Remarks': '',
            'Visa_ID': 'visa_id',
            'Customer': cls._create_customer_data(order.passenger),
            'External_Order_ID': ride.uuid,
            'Preferred_Operator_ID': int(isr_station_id),
            'Preferred_Vehicle_ID': taxi_number if taxi_number else '',
            # ex_order.Prefered_Vehicle_ID = -1,
            # TODO_WB: if passenger.business the business is contact?
            'Contact_Name': '',
            'Contact_Phone': '',
            'Start_Time': (order.depart_time or start_time).isoformat(),
            'Finish_Time': (order.arrive_time or finish_time).isoformat(),
            'Stops': [first_stop],
            'Order_Type': 'Taxi_Order',
            'Status': INITIAL_STATUS
        }
Example #33
0
    def _create_external_order(cls, order, isr_station_id):
        ex_order = cls._create_ISR_object("External_Order")
        ex_order.Auto_Order = True #ISRsays: should be True
        ex_order.Comments = order.comments
        ex_order.Remarks = ""
        ex_order.Visa_ID = "visa_id"
        ex_order.Customer = cls._create_customer_data(order.passenger)
        ex_order.External_Order_ID = order.id
        ex_order.Prefered_Operator_ID = isr_station_id
        # ex_order.Prefered_Vehicle_ID = -1

        # TODO_WB: if passenger.business the business is contact?
        ex_order.Contact_Name = ""
        ex_order.Contact_Phone = ""

        # ISRsays: these fields are required but not reflected in ISR client UI
        start_time = default_tz_now() + DEFAULT_TIMEDELTA
        finish_time = start_time + DEFAULT_TIMEDELTA
        ex_order.Start_Time = (order.depart_time or start_time).isoformat()
        ex_order.Finish_Time = (order.arrive_time or finish_time).isoformat()

        order_stop = cls._create_order_stop(order)
        key_value_string_order_stop = cls._create_array_object("KeyValueOfstringOrder_Stop8pH_SfiQv")
        key_value_string_order_stop.Key = order_stop.Stop_Order
        key_value_string_order_stop.Value = order_stop

        array_of_string_order_stop = cls._create_array_object("ArrayOfKeyValueOfstringOrder_Stop8pH_SfiQv")
        array_of_string_order_stop.KeyValueOfstringOrder_Stop8pH_SfiQv.append(key_value_string_order_stop)
        ex_order.Stops = array_of_string_order_stop

        order_type = cls._create_ISR_object("External_Order.Order_Type")
        ex_order.Order_Type.value = order_type.Taxi_Order

        order_status = cls._create_ISR_object("External_Order.Status")
        ex_order.Status.value = getattr(order_status, INITIAL_STATUS)
        return ex_order
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})
Example #35
0
def send_message(ride, message):
    logging.info(u"send_message '%s' to ride: %s" % (message, ride.id))
    try:
        station = ride.station
        assert station, "ride [%s] is not assigned to a station" % ride.id
        assert station.fleet_station_id, "station %s has no fleet_station_id" % ride.station.name
        assert ride.dn_fleet_manager_id, "ride [%s] is not associated with a fleet manager" % ride.id
        assert ride.taxi_number, "ride [%s] is not associated with a taxi number" % ride.id

        ride_fm = FleetManager.by_id(ride.dn_fleet_manager_id)
        result = ride_fm.send_message(message, ride.station.fleet_station_id, ride.taxi_number)

        # log a RideEvent about his message
        rp = get_ride_position(ride)
        e = RideEvent(pickmeapp_ride=None, shared_ride=ride,
                      status=FleetManagerRideStatus.MESSAGE_SENT, raw_status=message, lat=rp.lat if rp else None, lon=rp.lon if rp else None, taxi_id=ride.taxi_number, timestamp=default_tz_now())
        e.save()

        return result
    except Exception, e:
        logging.error(traceback.format_exc())
        return False
def is_valid_candidate(ride, order_settings):
    return ride.debug == settings.DEV and \
           ride.can_be_joined and \
           ride.depart_time > default_tz_now() + datetime.timedelta(minutes=asap_interval()) and \
           ride.status in [RideStatus.PENDING, RideStatus.ASSIGNED] and \
           sum([order.num_seats for order in ride.orders.all()]) + order_settings.num_seats <= MAX_SEATS
Example #37
0
def sharing_workstation_data(request, work_station):
    logging.info("sharing_workstation_data: %s" % work_station)

    rides_query = SharedRide.objects.filter(station=work_station.station, depart_time__lt=default_tz_now() + timedelta(hours=24), status__in=[RideStatus.ASSIGNED, RideStatus.VIEWED, RideStatus.ACCEPTED])
    rides = [r.serialize_for_ws() for r in sorted(rides_query, key=lambda ride: ride.depart_time)]

    return JSONResponse({
        'rides': rides
    })
def asap_interval():
    # 2012 SYLVESTER
    if datetime.datetime(2012, 12, 31, 20, 00, tzinfo=TZ_JERUSALEM) <= default_tz_now() <= datetime.datetime(2013, 1, 1, 5, 30, tzinfo=TZ_JERUSALEM):
        return 30  # minutes

    return 10 # minutes
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)
Example #40
0
def get_ride_position(ride):
    """
    Get the latest known taxi position for a ride.
    @param ride: ride to track
    @return: A C{TaxiRidePosition} or None
    """
    trp = None
    cached_trp = memcache.get(_get_key(ride.uuid), namespace=FM_MEMCACHE_NAMESPACE)
    if cached_trp:
        trp = pickle.loads(cached_trp)
        logging.info("found position for ride: %s" % ride.uuid)
        logging.info("position.timestamp = %s, stale? = %s" % (trp.timestamp, (trp.timestamp < default_tz_now() - timedelta(minutes=15))))
    else:
        logging.warning("no position found for ride: %s (%s)" % (ride.uuid, ride.id))

    return trp