From 9427ed50adb361b177d9ee822a951e29b33fd1b7 Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Sun, 12 Nov 2017 15:38:32 +0100 Subject: [PATCH] add page to plan a pitstop --- app/entities.py | 5 ++ app/routes/__init__.py | 1 + app/routes/pitstop.py | 26 ++++++++-- app/templates/planPitStopForm.html | 50 ++++++++++++++++++ app/tools.py | 83 ++++++++++++++++-------------- 5 files changed, 124 insertions(+), 41 deletions(-) create mode 100644 app/templates/planPitStopForm.html diff --git a/app/entities.py b/app/entities.py index fe86c52..275692f 100644 --- a/app/entities.py +++ b/app/entities.py @@ -190,6 +190,11 @@ class FillingStation(db.Model): brand = db.Column(db.Text(), nullable=False) lat = db.Column(db.Numeric(2, 5), nullable=False) lng = db.Column(db.Numeric(2, 5), nullable=False) + last_update = db.Column(db.DateTime) + diesel = db.Column(db.Numeric(10, 3), default=0) + e5 = db.Column(db.Numeric(10, 3), default=0) + e10 = db.Column(db.Numeric(10, 3), default=0) + open = db.Column(db.Boolean()) def as_dict(self): res = {} diff --git a/app/routes/__init__.py b/app/routes/__init__.py index f5a1dc4..c169592 100644 --- a/app/routes/__init__.py +++ b/app/routes/__init__.py @@ -3,3 +3,4 @@ from .admin import * from .misc import * from .pitstop import * from .service import * +from .filling_stations import * \ No newline at end of file diff --git a/app/routes/pitstop.py b/app/routes/pitstop.py index cb54f3b..46a8dc1 100644 --- a/app/routes/pitstop.py +++ b/app/routes/pitstop.py @@ -6,9 +6,8 @@ from datetime import date from ..entities import Vehicle, Consumable, Pitstop from ..forms import SelectVehicleForm, SelectConsumableForm, CreatePitstopForm, EditPitstopForm, DeletePitStopForm -from ..tools import db_log_update, db_log_delete, db_log_add, get_latest_pitstop_for_vehicle, \ - get_latest_pitstop_for_vehicle_and_consumable, compute_lower_limits_for_new_pitstop, pitstop_service_key, \ - get_event_line_for_vehicle +from ..tools import db_log_update, db_log_delete, db_log_add, pitstop_service_key, \ + get_event_line_for_vehicle, update_filling_station_prices from .. import app, db @@ -50,6 +49,27 @@ def select_consumable_for_new_pitstop(vid): return render_template('selectConsumableForVehicle.html', vehicle=vehicle, form=form) +@app.route('/pitstops/vehicle//consumable//plan', methods=['GET', 'POST']) +@login_required +def plan_pit_stop_form(vid, cid): + vehicle = Vehicle.query.get(vid) + if vehicle is None or vehicle not in current_user.vehicles: + return redirect(url_for('select_vehicle_for_new_pitstop')) + + consumable = Consumable.query.get(cid) + if consumable not in vehicle.consumables: + return redirect(url_for('select_consumable_for_new_pitstop', vid=vid)) + + update_filling_station_prices([x.id for x in current_user.favourite_filling_stations]) + + offers = [] + for fs in current_user.favourite_filling_stations: + if fs.open: + offers.append((fs, getattr(fs, consumable.ext_id),)) + + return render_template('planPitStopForm.html', vehicle=vehicle, consumable=consumable, offers=offers) + + @app.route('/pitstops/vehicle//consumable//create', methods=['GET', 'POST']) @login_required def create_pit_stop_form(vid, cid): diff --git a/app/templates/planPitStopForm.html b/app/templates/planPitStopForm.html new file mode 100644 index 0000000..0911681 --- /dev/null +++ b/app/templates/planPitStopForm.html @@ -0,0 +1,50 @@ +{% extends "layout.html" %} + +{% block body %} +
+
+
+
+

Plan Pitstop for '{{ vehicle.name }}'

+ Price comparision for {{ consumable.name }}: +
+ + + + + + + + + {% for offer in offers %} + + + + + {% endfor %} + +
Filling StationPrice/{{ consumable.unit }}
+
+
+
{{ offer[0].name }}
+
{{ offer[0].street }} {{ offer[0].houseNumber }}
+
{{ offer[0].postCode }} {{ offer[0].place }}
+
+
+ +
+
+
+ {{ offer[1] }} €/{{ consumable.unit }} +
+
+
+
+
+ +
+{% endblock %} diff --git a/app/tools.py b/app/tools.py index ee56ae7..09d233f 100644 --- a/app/tools.py +++ b/app/tools.py @@ -1,7 +1,10 @@ +from sqlalchemy import or_ +import requests import logging -from datetime import date +from datetime import date, datetime, timedelta -from .entities import Pitstop +from .entities import Pitstop, FillingStation +from . import db, app class ConsumableStats: @@ -34,7 +37,7 @@ class ConsumableStats: self.average_amount.append( StatsEvent( current_ps.date, - round(100 * current_ps.amount/(current_ps.odometer - last_ps.odometer), 2))) + round(100 * current_ps.amount / (current_ps.odometer - last_ps.odometer), 2))) class VehicleStats: @@ -104,9 +107,9 @@ def get_latest_pitstop_for_vehicle(vehicle_id): :param vehicle_id: the id of the vehicle :return: the latest pitstop or None if no pitstop exists """ - latest_pitstop = Pitstop.query\ - .filter(Pitstop.vehicle_id == vehicle_id)\ - .order_by(Pitstop.id.desc())\ + latest_pitstop = Pitstop.query \ + .filter(Pitstop.vehicle_id == vehicle_id) \ + .order_by(Pitstop.id.desc()) \ .first() return latest_pitstop @@ -118,10 +121,10 @@ def get_latest_pitstop_for_vehicle_and_consumable(vehicle_id, consumable_id): :param consumable_id: the id of the consumable :return: the latest pitstop or None if no pitstop exists """ - latest_pitstop_consumable = Pitstop.query\ - .filter(Pitstop.vehicle_id == vehicle_id)\ - .filter(Pitstop.consumable_id == consumable_id)\ - .order_by(Pitstop.id.desc())\ + latest_pitstop_consumable = Pitstop.query \ + .filter(Pitstop.vehicle_id == vehicle_id) \ + .filter(Pitstop.consumable_id == consumable_id) \ + .order_by(Pitstop.id.desc()) \ .first() return latest_pitstop_consumable @@ -150,33 +153,6 @@ def compute_lower_limits_for_new_pitstop(latest_pitstop, last_pitstop_consumable return Pitstop(odometer, amount, date_of_pitstop, costs, consumable_id) - # if latest_pitstop is not None: - # if last_pitstop_consumable is not None and last_pitstop_consumable != latest_pitstop: - # if latest_pitstop.id > last_pitstop_consumable.id: - # return Pitstop(latest_pitstop.odometer, - # last_pitstop_consumable.overall_amount, - # latest_pitstop.date, - # last_pitstop_consumable.costs, - # consumable_id) - # else: - # return Pitstop(last_pitstop_consumable.odometer, - # last_pitstop_consumable.overall_amount, - # last_pitstop_consumable.date, - # last_pitstop_consumable.costs, - # consumable_id) - # else: - # # either only one pitstop exists or both are the same - # litres = 0 - # costs = 0 - # if latest_pitstop.consumable_id == last_pitstop_consumable.consumable_id: - # litres = latest_pitstop.overall_amount - # costs = latest_pitstop.costs - # return Pitstop(latest_pitstop.odometer, litres, latest_pitstop.date, costs, consumable_id) - # else: - # # No existing pitstop at all: insert fake data - # return Pitstop(0, 0, date(1970, 1, 1), 0, None) - - def pitstop_service_key(x): return x.odometer, x.date @@ -188,4 +164,35 @@ def get_event_line_for_vehicle(vehicle): for service in vehicle.services: data.append(service) data.sort(key=pitstop_service_key) - return data \ No newline at end of file + return data + + +def update_filling_station_prices(ids): + max_age = (datetime.now() - timedelta(minutes=15)).strftime('%Y-%m-%d %H:%M') + + res = db.session. \ + query(FillingStation). \ + filter(FillingStation.id.in_(ids)). \ + filter(or_(FillingStation.last_update==None, FillingStation.last_update < max_age)).\ + all() + + if len(res) > 0: + map = {x.id:x for x in res} + query_ids = [x.id for x in res] + api_key = app.config['TANKERKOENIG_API_KEY'] + url = 'https://creativecommons.tankerkoenig.de/json/prices.php' + params = { + 'apikey': api_key, 'ids': ','.join(query_ids) + } + response = requests.get(url, params=params) + prices = response.json()['prices'] + for price in prices: + id = price + station_status = prices[id] + print(id, station_status) + map[id].diesel = station_status['diesel'] + map[id].e10 = station_status['e10'] + map[id].e5 = station_status['e5'] + map[id].open = station_status['status'] == 'open' + map[id].last_update = datetime.now() + db.session.commit()