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))
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))
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 _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
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)
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")
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
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
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
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
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")
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 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
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 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
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")
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 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
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 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)
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 }
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 }
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})
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
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)
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