def choose_station(ride): tariff = RuleSet.get_active_set(ride.depart_time) pricing_model_names = ride.cost_data.model_names_for_tariff(tariff) logging.info( u"found pricing models: %s" % u",".join([unicode(model_name) for model_name in pricing_model_names])) stations = Station.objects.filter( pricing_model_name__in=pricing_model_names) logging.info(u"found stations: %s" % u",".join([unicode(station.name) for station in stations])) # make sure debug and real orders don't mix stations = filter(lambda station: station.debug == ride.debug, stations) logging.info(u"stations list: %s" % u",".join([unicode(station.name) for station in stations])) if stations: return stations[0] else: logging.error(u"No sharing stations found %s" % ride.get_log()) return None
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 choose_station(ride): tariff = RuleSet.get_active_set(ride.depart_time) pricing_model_names = ride.cost_data.model_names_for_tariff(tariff) logging.info(u"found pricing models: %s" % u",".join([unicode(model_name) for model_name in pricing_model_names])) stations = Station.objects.filter(pricing_model_name__in=pricing_model_names) logging.info(u"found stations: %s" % u",".join([unicode(station.name) for station in stations])) # make sure debug and real orders don't mix stations = filter(lambda station: station.debug == ride.debug, stations) logging.info(u"stations list: %s" % u",".join([unicode(station.name) for station in stations])) if stations: return stations[0] else: logging.error(u"No sharing stations found %s" % ride.get_log()) return None
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 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)
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)