add page to plan a pitstop
This commit is contained in:
parent
28990f27fa
commit
9427ed50ad
|
@ -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 = {}
|
||||
|
|
|
@ -3,3 +3,4 @@ from .admin import *
|
|||
from .misc import *
|
||||
from .pitstop import *
|
||||
from .service import *
|
||||
from .filling_stations import *
|
|
@ -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):
|
||||
|
|
|
@ -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 %}
|
83
app/tools.py
83
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
|
||||
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()
|
||||
|
|
Loading…
Reference in New Issue