add page to plan a pitstop

This commit is contained in:
Joachim Lusiardi 2017-11-12 15:38:32 +01:00
parent 28990f27fa
commit 9427ed50ad
5 changed files with 124 additions and 41 deletions

View File

@ -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 = {}

View File

@ -3,3 +3,4 @@ from .admin import *
from .misc import *
from .pitstop import *
from .service import *
from .filling_stations import *

View File

@ -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/<int:vid>/consumable/<int:cid>/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/<int:vid>/consumable/<int:cid>/create', methods=['GET', 'POST'])
@login_required
def create_pit_stop_form(vid, cid):

View File

@ -0,0 +1,50 @@
{% extends "layout.html" %}
{% block body %}
<div class="col-md-2" ></div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-body">
<h3>Plan Pitstop for '{{ vehicle.name }}'</h3>
Price comparision for {{ consumable.name }}:
<div class="table-responsive">
<table id="compare" class="table table-striped table-bordered table-condensed tablesorter">
<thead>
<tr>
<th>Filling Station</th>
<th>Price/{{ consumable.unit }}</th>
</tr>
</thead>
<tbody>
{% for offer in offers %}
<tr>
<td>
<div class="row filling_station_info" style="border: 0px">
<div class="col-md-8">
<div>{{ offer[0].name }}</div>
<div>{{ offer[0].street }} {{ offer[0].houseNumber }}</div>
<div>{{ offer[0].postCode }} {{ offer[0].place }}</div>
</div>
<div class="col-md-4" style="height: 60px;">
<img src="/static/logos/{{ offer[0].brand|lower }}.png">
</div>
</div>
</td>
<td>
{{ offer[1] }} €/{{ consumable.unit }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$("#compare").tablesorter({sortList: [[1,0]]});
});
</script>
<div class="col-md-2" ></div>
{% endblock %}

View File

@ -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
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()