Beispiel #1
0
def calc_passenger_rides(offset=0, data=None):
    if not data: data = {"active":0, "non-active": 0}
    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

        orders = list(Order.objects.filter(passenger=p, type__in=[OrderType.SHARED, OrderType.PRIVATE]))
        if not orders:
            continue

        active = False
        for o in orders:
            if o.ride:
                active = True
                break

        if active:
            data["active"] += 1
        else:
            data["non-active"] += 1


    if passengers:
        deferred.defer(calc_passenger_rides, offset=offset + batch_size + 1, data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**", "passenger rides", msg="%s" % data)
Beispiel #2
0
def calc_kpi3(start_index=0, two_address=0, single_address=0, order_count=0):
    logging.info("calc_kpi3: starting at: %d" % start_index)

    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[start_index:]
    first = False
    order = None
    try:
        for o in orders:
            order = o
            if not first:
                logging.info("First order = %s" % o)
                first = True

            order_count += 1

            if o.from_raw and o.to_raw:
                two_address += 1
            else:
                single_address +=1
    except :
        logging.info("DB timeout raised after %d\nlast order = %s" % (order_count, order))
        deferred.defer(calc_kpi3, start_index=order_count, two_address=two_address, single_address=single_address, order_count=order_count)

    if orders:
        deferred.defer(calc_kpi3, start_index=order_count, two_address=two_address, single_address=single_address, order_count=order_count)
    else:
#    send_mail_as_noreply("*****@*****.**", "KPIs", attachments=[("kpis.csv", csv_file)])
        send_mail_as_noreply("*****@*****.**", "KPIs - Order Addresses", msg="count=%d, single=%d, double=%d" % (order_count, single_address, two_address))
Beispiel #3
0
def create_user(username,
                password="",
                email="",
                first_name="",
                last_name="",
                save=True):
    user = User.objects.create_user(username, email, password)
    user.first_name = (first_name or "").strip()
    user.last_name = (last_name or "").strip()

    if email and not user.first_name:
        user.first_name = email.split("@")[0]

    if save:
        user.save()

    # welcome the new user
    if user.email:
        t = get_template("welcome_email.html")
        context = Context({'passenger_name': user.first_name or ''})

        send_mail_as_noreply(user.email,
                             u"WAYbetter - %s" % ugettext("Shared Taxi Rides"),
                             html=t.render(context))

    logging.info("welcome new user: %s" % user)
    return user
Beispiel #4
0
def feb_statistics():
    sharing_launched = set_default_tz_time(
        datetime.datetime(2011, 10, 1, 0, 0, 0))
    feb_start = datetime.date(2012, 2, 1)
    feb_end = datetime.date(2012, 3, 1) - datetime.timedelta(days=1)

    rides = filter(
        lambda ride: ride.debug == False,
        SharedRide.objects.filter(create_date__gte=sharing_launched))
    orders = [order for ride in rides for order in ride.orders.all()]
    sharing_passengers = set([order.passenger for order in orders])

    feb_rides = []
    pre_feb_sharing_passengers = set()

    for ride in rides:
        if feb_start <= ride.create_date.date() <= feb_end:
            feb_rides.append(ride)

    feb_orders = [order for ride in feb_rides for order in ride.orders.all()]
    for order in feb_orders:
        if order.passenger.create_date.date() < feb_start:
            pre_feb_sharing_passengers.add(order.passenger)

    msg = """
    total sharing passengers: %s
    total orders: %s
    orders in february: %s
    passengers registered before feb 1st and ordered in feb: %s
    """ % (len(sharing_passengers), len(orders), len(feb_orders),
           len(pre_feb_sharing_passengers))
    send_mail_as_noreply("*****@*****.**", "feb stats", msg)
Beispiel #5
0
def calc_passenger_order_freq(offset=0, data=None):
    if not data: data = {"7": 0, "14":0, "30": 0, "longer": 0, "avg": 0, "count": 0}
    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:
        orders = list(Order.objects.filter(passenger=p, type__in=[OrderType.SHARED, OrderType.PRIVATE]))
        orders = sorted(orders, key=lambda o: o.create_date)
        orders = filter(lambda o: o.ride, orders)
        for i, o in enumerate(orders):
            if len(orders) > i + 1:
                td = orders[i + 1].create_date - o.create_date
                days = td.days
                if not days:
                    days = td.seconds / 60.0 / 60.0 / 24.0

                data["avg"] = (data["avg"] * data["count"] + days) / float(data["count"] + 1)
                data["count"] += 1

                if days <= 7:
                    data["7"] += 1
                elif days <= 14:
                    data["14"] += 1
                elif days <= 30:
                    data["30"] += 1
                else:
                    data["longer"] += 1

    if passengers:
        deferred.defer(calc_passenger_order_freq, offset=offset + batch_size + 1, data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**", "Order freq", msg="%s" % data)
Beispiel #6
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)])
Beispiel #7
0
def calc_order_timing(offset=0, hours=None):
    if not hours: hours = {}
    batch_size = 500
    logging.info("querying shared rides %s->%s" %
                 (offset, offset + batch_size))
    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[offset:offset +
                                                            batch_size]
    for o in orders:
        hour = str(o.create_date.hour)
        if hour in hours:
            hours[hour] += 1
        else:
            hours[hour] = 1

    if orders:
        deferred.defer(calc_order_timing,
                       offset=offset + batch_size + 1,
                       hours=hours)
    else:
        logging.info("all done, sending report\n%s" % hours)
        csv = ",".join(hours.keys()) + "\n" + ",".join(
            [str(v) for v in hours.values()])
        send_mail_as_noreply("*****@*****.**",
                             "Shared rides data for NY",
                             attachments=[("order_timing.csv", csv)])
Beispiel #8
0
def calc_station_rating(offset=0, data=None):
    if not data: data = {}

    batch_size = 500
    logging.info("querying orders %s->%s" % (offset, offset + batch_size))
    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[offset: offset + batch_size]
    for o in orders:
        if not o.station: continue
        if not o.passenger_rating: continue

        station_name = o.station.name
        if station_name in data:
            count, avg = data[station_name]
            avg = (count*avg + o.passenger_rating) / float(count+1)
            count += 1
            data[station_name] = (count, avg)
        else:
            data[station_name] = (1, o.passenger_rating)

    if orders:
        deferred.defer(calc_station_rating, offset=offset + batch_size + 1, data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        csv = [["Station Name", "Ratings", "Avg"]]
        for s in data.keys():
            csv.append([s, data[s][0], data[s][1]])
        csv_string = ""
        logging.info("csv = %s" % csv)
        for line in csv:
            csv_string += ",".join(line) + "\n"

        send_mail_as_noreply("*****@*****.**", "Shared rides data for NY", attachments=[("stations_ratings.csv", csv_string)])
def calc_orders_data_csv(recipient, batch_size, offset=0, csv_bytestring=u"", calc_cost=False):
    link_domain = "www.waybetter.com"

    logging.info("querying computations %s->%s" % (offset, offset + batch_size))

    start_dt = set_default_tz_time(datetime(2012, 1, 1))
    end_dt = set_default_tz_time(datetime.now())
    station, station_cost_rules = None, []

    computations = [] #TODO_WB: no computations any more... fix if needed
    for computation in computations:
        if computation.debug:
            continue

        rides = computation.rides.all()
        total_interval_orders = sum([ride.orders.count() for ride in rides])

        for ride in rides:
            orders = ride.orders.all()
            count_orders = len(orders)
            for order in orders:
                depart_day = order.depart_time.date().isoformat() if order.depart_time else ""
                depart_time = order.depart_time.time().strftime("%H:%M") if order.depart_time else ""
                arrive_day = order.arrive_time.date().isoformat() if order.arrive_time else ""
                arrive_time = order.arrive_time.time().strftime("%H:%M") if order.arrive_time else ""
                hotspot_type = computation.get_hotspot_type_display()

                ordering_td = (order.depart_time or order.arrive_time) - order.create_date
                ordering_td_format = str(ordering_td).split(".")[0] # trim microseconds

                passenger_name = order.passenger.full_name
                shared = "yes" if count_orders > 1 else ""
                price = order.get_billing_amount()
                cost = 0

                if calc_cost:
                    if ride.station and ride.station != station: # store the rules in memory to reduce queries
                        station = ride.station
                        station_cost_rules = list(ride.station.fixed_prices.all())
                        logging.info("got new prices from station %s (was %s)" % (ride.station, station))
                    for rule in station_cost_rules:
                        if rule.is_active(order.from_lat, order.from_lon, order.to_lat, order.to_lon, ride.depart_time):
                            cost = rule.price

                link = "http://%s/%s" % (link_domain , reverse(ride_page, args=[ride.id]))

                order_data = [depart_day, depart_time, arrive_day, arrive_time, ordering_td_format, passenger_name,
                              order.from_raw, order.from_lat, order.from_lon, order.to_raw, order.to_lat, order.to_lon,
                              hotspot_type, shared, order.computation_id, total_interval_orders, price, cost, link]
                csv_bytestring += u";".join([unicode(i).replace(";", "").replace('"', '') for i in order_data])
                csv_bytestring += u"\n"

    if computations:
        deferred.defer(calc_orders_data_csv, recipient, batch_size, offset=offset + batch_size + 1, csv_bytestring=csv_bytestring, calc_cost=calc_cost)
    else:
        logging.info("all done, sending data...")
        timestamp = date.today()
        send_mail_as_noreply(recipient, "Orders data %s" % timestamp, attachments=[("orders_data_%s.csv" % timestamp, csv_bytestring)])
Beispiel #10
0
def calc_users_data_csv(recipient ,offset=0, csv_bytestring=u""):
    batch_size = 500
    datetime_format = "%d/%m/%y"
    link_domain = "www.waybetter.com"

    logging.info("querying users %s->%s" % (offset, offset + batch_size))
    users = User.objects.order_by("-last_login")[offset: offset + batch_size]
    for user in users:
        link = ""
        last_login = user.last_login.strftime(datetime_format)
        date_joined = user.date_joined.strftime(datetime_format)
        first_name = user.first_name
        last_name = user.last_name
        email = user.email
        phone = ""
        billing_info = ""
        first_order_date = ""
        last_order_date = ""
        num_orders_mobile = ""
        num_orders_website = ""
        num_rides = ""
        total_payment = ""
        try:
            passenger = user.passenger
            link = "http://%s/%s" % (link_domain , reverse(view_passenger_orders, args=[passenger.id]))
            phone = passenger.phone
            if hasattr(passenger, "billing_info"):
                billing_info = "yes"
            orders = sorted(passenger.orders.filter(type=OrderType.SHARED, debug=False), key=lambda order: order.create_date)

            num_orders = len(orders)
            if num_orders:
                first_order_date = orders[0].create_date.strftime(datetime_format)
                last_order_date = orders[-1].create_date.strftime(datetime_format)
                dispatched_orders = filter(lambda o: o.ride, orders)
                total_payment = sum([order.get_billing_amount() for order in dispatched_orders])
                num_rides = len(dispatched_orders)
                num_orders_mobile = len(filter(lambda o: o.mobile, orders))
                num_orders_website = num_orders - num_orders_mobile
        except Passenger.DoesNotExist:
            pass
        except Passenger.MultipleObjectsReturned:
            pass

        user_data = [last_login, first_order_date, last_order_date, date_joined, first_name, last_name, email, phone, num_orders_mobile, num_orders_website, num_rides, billing_info, total_payment, link]
        csv_bytestring += u",".join([unicode(i).replace(",", "") for i in user_data])
        csv_bytestring += u"\n"

    if users:
        deferred.defer(calc_users_data_csv, recipient, offset=offset + batch_size + 1, csv_bytestring=csv_bytestring)
    else:
        logging.info("all done, sending data...")
        timestamp = date.today()
        logging.info(csv_bytestring)
        send_mail_as_noreply(recipient, "Users data %s" % timestamp, attachments=[("users_data_%s.csv" % timestamp, csv_bytestring)])
Beispiel #11
0
def calc_ny_sharing(offset=0, count=0, value=0):
    batch_size = 500
    logging.info("querying shared rides %s->%s" % (offset, offset + batch_size))
    s = Station.by_id(1529226)
    shared_rides = SharedRide.objects.filter(station=s)[offset: offset + batch_size]
    for sr in shared_rides:
        count += 1
        value += sr.cost

    if shared_rides:
        deferred.defer(calc_ny_sharing, offset=offset + batch_size + 1, count=count, value=value)
    else:
        logging.info("all done, sending report")
        send_mail_as_noreply("*****@*****.**", "Shared rides data for NY", msg="count=%d, value=%f" % (count, value))
Beispiel #12
0
def handle_approved_orders(sender, signal_type, order, status, **kwargs):
    from common.util import notify_by_email, send_mail_as_noreply
    from common.langsupport.util import translate_to_lang
    from ordering.models import APPROVED
    from sharing.passenger_controller import get_passenger_ride_email

    logging.info("handle_approved_orders: %s" % status)
    if status == APPROVED:

        # send confirmation email
        passenger = order.passenger
        if passenger.user and passenger.user.email:
            msg = get_passenger_ride_email(order)
            send_mail_as_noreply(passenger.user.email, translate_to_lang("WAYbetter Order Confirmation", order.language_code), html=msg)
            notify_by_email("Order Confirmation [%s]%s" % (order.id, " (DEBUG)" if order.debug else ""), html=msg)
Beispiel #13
0
def calc_pickmeapp_passenger_count(offset=0, count=0):
    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:
        pickemapp_orders = p.orders.filter(type=OrderType.PICKMEAPP)
        if pickemapp_orders:
            count +=1

    if passengers:
        logging.info("continue to next batch: %s" % count)
        deferred.defer(calc_pickmeapp_passenger_count, offset=offset + batch_size + 1, count=count)
    else:
        logging.info("all done, sending report\n%s" % count)
        send_mail_as_noreply("*****@*****.**", "Passenger count - pickmeapp", msg="count = %s" % count)
Beispiel #14
0
def calc_order_timing(offset=0, hours=None):
    if not hours: hours = {}
    batch_size = 500
    logging.info("querying shared rides %s->%s" % (offset, offset + batch_size))
    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[offset: offset + batch_size]
    for o in orders:
        hour = str(o.create_date.hour)
        if hour in hours:
            hours[hour] += 1
        else:
            hours[hour] = 1

    if orders:
        deferred.defer(calc_order_timing, offset=offset + batch_size + 1, hours=hours)
    else:
        logging.info("all done, sending report\n%s" % hours)
        csv = ",".join(hours.keys()) + "\n" + ",".join([str(v) for v in hours.values()])
        send_mail_as_noreply("*****@*****.**", "Shared rides data for NY", attachments=[("order_timing.csv", csv)])
Beispiel #15
0
def calc_pickmeapp_passenger_count(offset=0, count=0):
    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:
        pickemapp_orders = p.orders.filter(type=OrderType.PICKMEAPP)
        if pickemapp_orders:
            count += 1

    if passengers:
        logging.info("continue to next batch: %s" % count)
        deferred.defer(calc_pickmeapp_passenger_count,
                       offset=offset + batch_size + 1,
                       count=count)
    else:
        logging.info("all done, sending report\n%s" % count)
        send_mail_as_noreply("*****@*****.**",
                             "Passenger count - pickmeapp",
                             msg="count = %s" % count)
Beispiel #16
0
def calc_passenger_order_freq(offset=0, data=None):
    if not data:
        data = {"7": 0, "14": 0, "30": 0, "longer": 0, "avg": 0, "count": 0}
    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:
        orders = list(
            Order.objects.filter(
                passenger=p, type__in=[OrderType.SHARED, OrderType.PRIVATE]))
        orders = sorted(orders, key=lambda o: o.create_date)
        orders = filter(lambda o: o.ride, orders)
        for i, o in enumerate(orders):
            if len(orders) > i + 1:
                td = orders[i + 1].create_date - o.create_date
                days = td.days
                if not days:
                    days = td.seconds / 60.0 / 60.0 / 24.0

                data["avg"] = (data["avg"] * data["count"] +
                               days) / float(data["count"] + 1)
                data["count"] += 1

                if days <= 7:
                    data["7"] += 1
                elif days <= 14:
                    data["14"] += 1
                elif days <= 30:
                    data["30"] += 1
                else:
                    data["longer"] += 1

    if passengers:
        deferred.defer(calc_passenger_order_freq,
                       offset=offset + batch_size + 1,
                       data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**",
                             "Order freq",
                             msg="%s" % data)
Beispiel #17
0
def create_user(username, password="", email="", first_name="", last_name="", save=True):
    user = User.objects.create_user(username, email, password)
    user.first_name = (first_name or "").strip()
    user.last_name = (last_name or "").strip()

    if email and not user.first_name:
        user.first_name = email.split("@")[0]

    if save:
        user.save()

    # welcome the new user
    if user.email:
        t = get_template("welcome_email.html")
        context = Context({'passenger_name': user.first_name or ''})

        send_mail_as_noreply(user.email, u"WAYbetter - %s" % ugettext("Shared Taxi Rides"), html=t.render(context))

    logging.info("welcome new user: %s" % user)
    return user
Beispiel #18
0
def calc_ny_sharing(offset=0, count=0, value=0):
    batch_size = 500
    logging.info("querying shared rides %s->%s" %
                 (offset, offset + batch_size))
    s = Station.by_id(1529226)
    shared_rides = SharedRide.objects.filter(station=s)[offset:offset +
                                                        batch_size]
    for sr in shared_rides:
        count += 1
        value += sr.cost

    if shared_rides:
        deferred.defer(calc_ny_sharing,
                       offset=offset + batch_size + 1,
                       count=count,
                       value=value)
    else:
        logging.info("all done, sending report")
        send_mail_as_noreply("*****@*****.**",
                             "Shared rides data for NY",
                             msg="count=%d, value=%f" % (count, value))
Beispiel #19
0
def handle_approved_orders(sender, signal_type, order, status, **kwargs):
    from common.util import notify_by_email, send_mail_as_noreply
    from common.langsupport.util import translate_to_lang
    from ordering.models import APPROVED
    from sharing.passenger_controller import get_passenger_ride_email

    logging.info("handle_approved_orders: %s" % status)
    if status == APPROVED:

        # send confirmation email
        passenger = order.passenger
        if passenger.user and passenger.user.email:
            msg = get_passenger_ride_email(order)
            send_mail_as_noreply(passenger.user.email,
                                 translate_to_lang(
                                     "WAYbetter Order Confirmation",
                                     order.language_code),
                                 html=msg)
            notify_by_email("Order Confirmation [%s]%s" %
                            (order.id, " (DEBUG)" if order.debug else ""),
                            html=msg)
Beispiel #20
0
def calc_kpi3(start_index=0, two_address=0, single_address=0, order_count=0):
    logging.info("calc_kpi3: starting at: %d" % start_index)

    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[start_index:]
    first = False
    order = None
    try:
        for o in orders:
            order = o
            if not first:
                logging.info("First order = %s" % o)
                first = True

            order_count += 1

            if o.from_raw and o.to_raw:
                two_address += 1
            else:
                single_address += 1
    except:
        logging.info("DB timeout raised after %d\nlast order = %s" %
                     (order_count, order))
        deferred.defer(calc_kpi3,
                       start_index=order_count,
                       two_address=two_address,
                       single_address=single_address,
                       order_count=order_count)

    if orders:
        deferred.defer(calc_kpi3,
                       start_index=order_count,
                       two_address=two_address,
                       single_address=single_address,
                       order_count=order_count)
    else:
        #    send_mail_as_noreply("*****@*****.**", "KPIs", attachments=[("kpis.csv", csv_file)])
        send_mail_as_noreply("*****@*****.**",
                             "KPIs - Order Addresses",
                             msg="count=%d, single=%d, double=%d" %
                             (order_count, single_address, two_address))
Beispiel #21
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)])
Beispiel #22
0
def calc_passenger_rides(offset=0, data=None):
    if not data: data = {"active": 0, "non-active": 0}
    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

        orders = list(
            Order.objects.filter(
                passenger=p, type__in=[OrderType.SHARED, OrderType.PRIVATE]))
        if not orders:
            continue

        active = False
        for o in orders:
            if o.ride:
                active = True
                break

        if active:
            data["active"] += 1
        else:
            data["non-active"] += 1

    if passengers:
        deferred.defer(calc_passenger_rides,
                       offset=offset + batch_size + 1,
                       data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**",
                             "passenger rides",
                             msg="%s" % data)
Beispiel #23
0
def calc_station_rating(offset=0, data=None):
    if not data: data = {}

    batch_size = 500
    logging.info("querying orders %s->%s" % (offset, offset + batch_size))
    orders = Order.objects.filter(type=OrderType.PICKMEAPP)[offset:offset +
                                                            batch_size]
    for o in orders:
        if not o.station: continue
        if not o.passenger_rating: continue

        station_name = o.station.name
        if station_name in data:
            count, avg = data[station_name]
            avg = (count * avg + o.passenger_rating) / float(count + 1)
            count += 1
            data[station_name] = (count, avg)
        else:
            data[station_name] = (1, o.passenger_rating)

    if orders:
        deferred.defer(calc_station_rating,
                       offset=offset + batch_size + 1,
                       data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        csv = [["Station Name", "Ratings", "Avg"]]
        for s in data.keys():
            csv.append([s, data[s][0], data[s][1]])
        csv_string = ""
        logging.info("csv = %s" % csv)
        for line in csv:
            csv_string += ",".join(line) + "\n"

        send_mail_as_noreply("*****@*****.**",
                             "Shared rides data for NY",
                             attachments=[("stations_ratings.csv", csv_string)
                                          ])
Beispiel #24
0
def generate_passengers_list():
    jan_first = datetime.datetime.combine(datetime.date(2012, 1, 1),
                                          default_tz_time_min())
    rides = SharedRide.objects.filter(depart_time__gte=jan_first)

    passengers = []
    for ride in rides:
        if ride.debug:
            continue
        for o in ride.orders.all():
            if o.passenger.create_date > jan_first:
                passengers.append(o.passenger)

    passengers = set(passengers)

    csv = u""
    for p in passengers:
        user = p.user
        csv += u",".join([user.email, user.get_full_name()])
        csv += u"\n"

    send_mail_as_noreply("*****@*****.**",
                         "passengers list",
                         attachments=[("passengers.csv", csv.encode("utf-8"))])
Beispiel #25
0
 def notify(self):
     subject = u"WAYbetter - מהפכה בתחבורה, מוניות ספיישל לכולם!"
     t = get_template("pilot_interest_email.html")
     html = t.render(Context({}))
     send_mail_as_noreply(self.email, subject, html=html)
Beispiel #26
0
        my_orders = filter(lambda o: o.passenger == passenger, orders)
        if my_orders:
            my_first_order = sorted(my_orders, key=lambda o: o.create_date)[0]
            try:
                csv += u",".join([
                    unicode(v) for v in [
                        my_first_order.depart_time.date().isoformat(),
                        passenger.full_name, passenger.phone
                    ]
                ])
                csv += u"\n"
            except Exception, e:
                logging.error("order[%s]: %s" % (my_first_order.id, e.message))

    send_mail_as_noreply("*****@*****.**",
                         "first rides data",
                         attachments=[("first_ride_stats.csv", csv)])


def feb_statistics():
    sharing_launched = set_default_tz_time(
        datetime.datetime(2011, 10, 1, 0, 0, 0))
    feb_start = datetime.date(2012, 2, 1)
    feb_end = datetime.date(2012, 3, 1) - datetime.timedelta(days=1)

    rides = filter(
        lambda ride: ride.debug == False,
        SharedRide.objects.filter(create_date__gte=sharing_launched))
    orders = [order for ride in rides for order in ride.orders.all()]
    sharing_passengers = set([order.passenger for order in orders])
Beispiel #27
0
def calc_users_data_csv(recipient, offset=0, csv_bytestring=u""):
    batch_size = 500
    datetime_format = "%d/%m/%y"
    link_domain = "www.waybetter.com"

    logging.info("querying users %s->%s" % (offset, offset + batch_size))
    users = User.objects.order_by("-last_login")[offset:offset + batch_size]
    for user in users:
        link = ""
        last_login = user.last_login.strftime(datetime_format)
        date_joined = user.date_joined.strftime(datetime_format)
        first_name = user.first_name
        last_name = user.last_name
        email = user.email
        phone = ""
        billing_info = ""
        first_order_date = ""
        last_order_date = ""
        num_orders_mobile = ""
        num_orders_website = ""
        num_rides = ""
        total_payment = ""
        try:
            passenger = user.passenger
            link = "http://%s/%s" % (link_domain,
                                     reverse(view_passenger_orders,
                                             args=[passenger.id]))
            phone = passenger.phone
            if hasattr(passenger, "billing_info"):
                billing_info = "yes"
            orders = sorted(passenger.orders.filter(type=OrderType.SHARED,
                                                    debug=False),
                            key=lambda order: order.create_date)

            num_orders = len(orders)
            if num_orders:
                first_order_date = orders[0].create_date.strftime(
                    datetime_format)
                last_order_date = orders[-1].create_date.strftime(
                    datetime_format)
                dispatched_orders = filter(lambda o: o.ride, orders)
                total_payment = sum([
                    order.get_billing_amount() for order in dispatched_orders
                ])
                num_rides = len(dispatched_orders)
                num_orders_mobile = len(filter(lambda o: o.mobile, orders))
                num_orders_website = num_orders - num_orders_mobile
        except Passenger.DoesNotExist:
            pass
        except Passenger.MultipleObjectsReturned:
            pass

        user_data = [
            last_login, first_order_date, last_order_date, date_joined,
            first_name, last_name, email, phone, num_orders_mobile,
            num_orders_website, num_rides, billing_info, total_payment, link
        ]
        csv_bytestring += u",".join(
            [unicode(i).replace(",", "") for i in user_data])
        csv_bytestring += u"\n"

    if users:
        deferred.defer(calc_users_data_csv,
                       recipient,
                       offset=offset + batch_size + 1,
                       csv_bytestring=csv_bytestring)
    else:
        logging.info("all done, sending data...")
        timestamp = date.today()
        logging.info(csv_bytestring)
        send_mail_as_noreply(recipient,
                             "Users data %s" % timestamp,
                             attachments=[("users_data_%s.csv" % timestamp,
                                           csv_bytestring)])
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)
Beispiel #29
0
def calc_kpi2(r):
    data = [[
        "Month", "New Users", "Active Users", "Avg. Rides per User",
        "Avg. Occupancy", "Stickiness", "Income"
    ]]
    for month_offset in xrange(0, r):
        logging.info("kpi for %s" % month_offset)

        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

        start_date, end_date = get_query_date_range_by_month_offset(
            month_offset)

        rides = SharedRide.objects.filter(create_date__gte=start_date,
                                          create_date__lte=end_date,
                                          debug=False)
        all_bi = BillingInfo.objects.filter(create_date__gte=start_date,
                                            create_date__lte=end_date)
        new_passengers = set()
        income = 0

        for bi in all_bi:
            try:
                p = bi.passenger
                new_passengers.add(p)
            except Passenger.DoesNotExist:
                pass

        active_passengers = set()
        number_of_people_in_rides = 0
        for ride in rides:
            orders = ride.orders.all()
            for o in orders:
                try:
                    p = o.passenger
                    active_passengers.add(p)
                except Passenger.DoesNotExist:
                    pass

                number_of_people_in_rides += o.num_seats

                income += sum(
                    [bt.amount for bt in o.billing_transactions.all()])

        sticky_passengers = set()
        for a_p in active_passengers:
            prev_orders = Order.objects.filter(
                passenger=a_p,
                depart_time__lte=start_date,
                type=OrderType.SHARED,
                status__in=[APPROVED, ACCEPTED, CHARGED]).order_by(
                    "-depart_time")  # sorting to re-use existing index
            if prev_orders:
                sticky_passengers.add(a_p)

        line = [
            end_date.strftime(
                "%m/%d/%Y"),  # prepared for google docs trend chart
            len(new_passengers),
            len(active_passengers),
            len(rides) /
            float(len(active_passengers)) if len(active_passengers) else "NA",
            number_of_people_in_rides /
            float(len(rides)) if len(rides) else "NA",
            len(sticky_passengers) / float(len(active_passengers)) *
            100 if len(active_passengers) else "NA",
            income / float(1000)
        ]
        data.append(line)

    csv_file = ""
    for line in data:
        logging.info("line = %s" % line)

        line = [round(i, 2) if isinstance(i, float) else i for i in line]
        csv_file += u",".join([unicode(i) for i in line])
        csv_file += "\n"

    send_mail_as_noreply("*****@*****.**",
                         "KPIs",
                         attachments=[("kpis.csv", csv_file)])
Beispiel #30
0
 def notify(self):
     subject = u"WAYbetter - מהפכה בתחבורה, מוניות ספיישל לכולם!"
     t = get_template("pilot_interest_email.html")
     html = t.render(Context({}))
     send_mail_as_noreply(self.email, subject, html=html)
Beispiel #31
0
def calc_orders_data_csv(recipient,
                         batch_size,
                         offset=0,
                         csv_bytestring=u"",
                         calc_cost=False):
    link_domain = "www.waybetter.com"

    logging.info("querying computations %s->%s" %
                 (offset, offset + batch_size))

    start_dt = set_default_tz_time(datetime(2012, 1, 1))
    end_dt = set_default_tz_time(datetime.now())
    station, station_cost_rules = None, []

    computations = []  #TODO_WB: no computations any more... fix if needed
    for computation in computations:
        if computation.debug:
            continue

        rides = computation.rides.all()
        total_interval_orders = sum([ride.orders.count() for ride in rides])

        for ride in rides:
            orders = ride.orders.all()
            count_orders = len(orders)
            for order in orders:
                depart_day = order.depart_time.date().isoformat(
                ) if order.depart_time else ""
                depart_time = order.depart_time.time().strftime(
                    "%H:%M") if order.depart_time else ""
                arrive_day = order.arrive_time.date().isoformat(
                ) if order.arrive_time else ""
                arrive_time = order.arrive_time.time().strftime(
                    "%H:%M") if order.arrive_time else ""
                hotspot_type = computation.get_hotspot_type_display()

                ordering_td = (order.depart_time
                               or order.arrive_time) - order.create_date
                ordering_td_format = str(ordering_td).split(".")[
                    0]  # trim microseconds

                passenger_name = order.passenger.full_name
                shared = "yes" if count_orders > 1 else ""
                price = order.get_billing_amount()
                cost = 0

                if calc_cost:
                    if ride.station and ride.station != station:  # store the rules in memory to reduce queries
                        station = ride.station
                        station_cost_rules = list(
                            ride.station.fixed_prices.all())
                        logging.info(
                            "got new prices from station %s (was %s)" %
                            (ride.station, station))
                    for rule in station_cost_rules:
                        if rule.is_active(order.from_lat, order.from_lon,
                                          order.to_lat, order.to_lon,
                                          ride.depart_time):
                            cost = rule.price

                link = "http://%s/%s" % (link_domain,
                                         reverse(ride_page, args=[ride.id]))

                order_data = [
                    depart_day, depart_time, arrive_day, arrive_time,
                    ordering_td_format, passenger_name, order.from_raw,
                    order.from_lat, order.from_lon, order.to_raw, order.to_lat,
                    order.to_lon, hotspot_type, shared, order.computation_id,
                    total_interval_orders, price, cost, link
                ]
                csv_bytestring += u";".join([
                    unicode(i).replace(";", "").replace('"', '')
                    for i in order_data
                ])
                csv_bytestring += u"\n"

    if computations:
        deferred.defer(calc_orders_data_csv,
                       recipient,
                       batch_size,
                       offset=offset + batch_size + 1,
                       csv_bytestring=csv_bytestring,
                       calc_cost=calc_cost)
    else:
        logging.info("all done, sending data...")
        timestamp = date.today()
        send_mail_as_noreply(recipient,
                             "Orders data %s" % timestamp,
                             attachments=[("orders_data_%s.csv" % timestamp,
                                           csv_bytestring)])
Beispiel #32
0
def calc_order_per_day_pickmeapp(offset=0, data=None):
    if not data: data = {"avg": 0, "count": 0}
    batch_size = 500
    days_threshold = 3
    logging.info("querying passengers %s->%s" % (offset, offset + batch_size))
    passengers = Passenger.objects.all()[offset:offset + batch_size]

    for p in passengers:
        skip_passenger = False
        orders = list(
            Order.objects.filter(passenger=p, type=OrderType.PICKMEAPP))
        orders = filter(lambda o: not o.debug, orders)
        orders = sorted(orders, key=lambda o: o.create_date)
        if len(p.phone) != 10 or (not p.phone.startswith("05")):
            skip_passenger = True

        if len(orders) < 2:
            #            logging.info("skipping passenger[%s]: not enough orders (%d)" % (p.id, len(orders)))
            skip_passenger = True

        if not skip_passenger:
            used_days = {}
            for o in orders:
                day = o.create_date.strftime("%Y/%m/%d")
                if day in used_days:
                    if used_days[day] >= days_threshold:
                        logging.info(
                            "skipping passenger[%s]: too many orders per day: %s"
                            % (p.id, day))
                        skip_passenger = True
                        break
                    else:
                        used_days[day] += 1
                else:
                    used_days[day] = 1

        if skip_passenger:
            continue

        first_order = orders[0]
        last_order = orders[-1]

        td = (last_order.create_date - first_order.create_date)
        interval = td.days
        if interval < 3: continue

        #        if not interval:
        #            if td.seconds >= 60 * 15:
        #                interval += td.seconds / 60.0 / 60.0 / 24.0

        if interval:
            avg = len(orders) / float(interval)
            data["avg"] = (data["avg"] * data["count"] +
                           avg) / float(data["count"] + 1)
            data["count"] += 1
            logging.info(
                "avg for passenger: %s is %f (orders=%d, interval=%f)\ndata=%s"
                % (p, avg, len(orders), interval, data))
        else:
            logging.info(
                "skipping passenger[%s]: interval=0 for orders[%s, %s]" %
                (p.id, first_order, last_order))

    if passengers:
        logging.info("continue to next batch: %s" % data)
        deferred.defer(calc_order_per_day_pickmeapp,
                       offset=offset + batch_size + 1,
                       data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**",
                             "Order freq - pickmeapp",
                             msg="%s" % data)
Beispiel #33
0
    def notify(self):
        subject = u"תודה על התעניינותך ב WAYbetter"
        t = get_template("m2m_interest_email.html")
        html = t.render(Context({}))

        send_mail_as_noreply(self.email, subject, html=html)
Beispiel #34
0
def calc_order_per_day_pickmeapp(offset=0, data=None):
    if not data: data = {"avg": 0, "count": 0}
    batch_size = 500
    days_threshold = 3
    logging.info("querying passengers %s->%s" % (offset, offset + batch_size))
    passengers = Passenger.objects.all()[offset: offset + batch_size]

    for p in passengers:
        skip_passenger = False
        orders = list(Order.objects.filter(passenger=p, type=OrderType.PICKMEAPP))
        orders = filter(lambda o: not o.debug, orders)
        orders = sorted(orders, key=lambda o: o.create_date)
        if len(p.phone) != 10 or (not p.phone.startswith("05")):
            skip_passenger = True

        if len(orders) < 2:
#            logging.info("skipping passenger[%s]: not enough orders (%d)" % (p.id, len(orders)))
            skip_passenger = True

        if not skip_passenger:
            used_days = {}
            for o in orders:
                day = o.create_date.strftime("%Y/%m/%d")
                if day in used_days:
                    if used_days[day] >= days_threshold:
                        logging.info("skipping passenger[%s]: too many orders per day: %s" % (p.id, day))
                        skip_passenger = True
                        break
                    else:
                        used_days[day] += 1
                else:
                    used_days[day] = 1


        if skip_passenger:
            continue

        first_order = orders[0]
        last_order = orders[-1]

        td = (last_order.create_date - first_order.create_date)
        interval = td.days
        if interval < 3: continue


#        if not interval:
#            if td.seconds >= 60 * 15:
#                interval += td.seconds / 60.0 / 60.0 / 24.0

        if interval:
            avg = len(orders) / float(interval)
            data["avg"] = (data["avg"] * data["count"] + avg) / float(data["count"] + 1)
            data["count"] += 1
            logging.info("avg for passenger: %s is %f (orders=%d, interval=%f)\ndata=%s" % (p, avg, len(orders), interval, data))
        else:
            logging.info("skipping passenger[%s]: interval=0 for orders[%s, %s]" % (p.id, first_order, last_order))

    if passengers:
        logging.info("continue to next batch: %s" % data)
        deferred.defer(calc_order_per_day_pickmeapp, offset=offset + batch_size + 1, data=data)
    else:
        logging.info("all done, sending report\n%s" % data)
        send_mail_as_noreply("*****@*****.**", "Order freq - pickmeapp", msg="%s" % data)
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)
Beispiel #36
0
    def notify(self):
        subject = u"תודה על התעניינותך ב WAYbetter"
        t = get_template("m2m_interest_email.html")
        html = t.render(Context({}))

        send_mail_as_noreply(self.email, subject, html=html)
Beispiel #37
0
def calc_kpi2(r):
    data = [["Month", "New Users", "Active Users", "Avg. Rides per User", "Avg. Occupancy", "Stickiness", "Income"]]
    for month_offset in xrange(0,r):
        logging.info("kpi for %s" % month_offset)
        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

        start_date, end_date = get_query_date_range_by_month_offset(month_offset)

        rides = SharedRide.objects.filter(create_date__gte=start_date, create_date__lte=end_date, debug=False)
        all_bi = BillingInfo.objects.filter(create_date__gte=start_date, create_date__lte=end_date)
        new_passengers = set()
        income  = 0

        for bi in all_bi:
            try:
                p = bi.passenger
                new_passengers.add(p)
            except Passenger.DoesNotExist:
                pass

        active_passengers = set()
        number_of_people_in_rides = 0
        for ride in rides:
            orders = ride.orders.all()
            for o in orders:
                try:
                    p = o.passenger
                    active_passengers.add(p)
                except Passenger.DoesNotExist:
                    pass

                number_of_people_in_rides += o.num_seats

                income += sum([bt.amount for bt in o.billing_transactions.all()])

        sticky_passengers = set()
        for a_p in active_passengers:
            prev_orders = Order.objects.filter(passenger=a_p, depart_time__lte=start_date, type=OrderType.SHARED, status__in=[APPROVED, ACCEPTED, CHARGED]).order_by("-depart_time") # sorting to re-use existing index
            if prev_orders:
                sticky_passengers.add(a_p)

        line = [
            end_date.strftime("%m/%d/%Y"), # prepared for google docs trend chart
            len(new_passengers),
            len(active_passengers),
            len(rides) / float(len(active_passengers)) if len(active_passengers) else "NA",
            number_of_people_in_rides / float(len(rides)) if len(rides) else "NA",
            len(sticky_passengers) / float(len(active_passengers)) * 100 if len(active_passengers) else "NA",
            income / float(1000)
        ]
        data.append(line)

    csv_file = ""
    for line in data:
        logging.info("line = %s" % line)

        line = [round(i, 2) if isinstance(i, float) else i for i in line]
        csv_file += u",".join([unicode(i) for i in line])
        csv_file += "\n"

    send_mail_as_noreply("*****@*****.**", "KPIs", attachments=[("kpis.csv", csv_file)])