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)
 | 
					    brand = db.Column(db.Text(), nullable=False)
 | 
				
			||||||
    lat = db.Column(db.Numeric(2, 5), nullable=False)
 | 
					    lat = db.Column(db.Numeric(2, 5), nullable=False)
 | 
				
			||||||
    lng = 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):
 | 
					    def as_dict(self):
 | 
				
			||||||
        res = {}
 | 
					        res = {}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,3 +3,4 @@ from .admin import *
 | 
				
			|||||||
from .misc import *
 | 
					from .misc import *
 | 
				
			||||||
from .pitstop import *
 | 
					from .pitstop import *
 | 
				
			||||||
from .service import *
 | 
					from .service import *
 | 
				
			||||||
 | 
					from .filling_stations import *
 | 
				
			||||||
@ -6,9 +6,8 @@ from datetime import date
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from ..entities import Vehicle, Consumable, Pitstop
 | 
					from ..entities import Vehicle, Consumable, Pitstop
 | 
				
			||||||
from ..forms import SelectVehicleForm, SelectConsumableForm, CreatePitstopForm, EditPitstopForm, DeletePitStopForm
 | 
					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, \
 | 
					from ..tools import db_log_update, db_log_delete, db_log_add, pitstop_service_key, \
 | 
				
			||||||
    get_latest_pitstop_for_vehicle_and_consumable, compute_lower_limits_for_new_pitstop, pitstop_service_key, \
 | 
					    get_event_line_for_vehicle, update_filling_station_prices
 | 
				
			||||||
    get_event_line_for_vehicle
 | 
					 | 
				
			||||||
from .. import app, db
 | 
					from .. import app, db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,6 +49,27 @@ def select_consumable_for_new_pitstop(vid):
 | 
				
			|||||||
    return render_template('selectConsumableForVehicle.html', vehicle=vehicle, form=form)
 | 
					    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'])
 | 
					@app.route('/pitstops/vehicle/<int:vid>/consumable/<int:cid>/create', methods=['GET', 'POST'])
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
def create_pit_stop_form(vid, cid):
 | 
					def create_pit_stop_form(vid, cid):
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										50
									
								
								app/templates/planPitStopForm.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								app/templates/planPitStopForm.html
									
									
									
									
									
										Normal 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 %}
 | 
				
			||||||
							
								
								
									
										65
									
								
								app/tools.py
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								app/tools.py
									
									
									
									
									
								
							@ -1,7 +1,10 @@
 | 
				
			|||||||
 | 
					from sqlalchemy import or_
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
import logging
 | 
					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:
 | 
					class ConsumableStats:
 | 
				
			||||||
@ -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)
 | 
					    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):
 | 
					def pitstop_service_key(x):
 | 
				
			||||||
    return x.odometer, x.date
 | 
					    return x.odometer, x.date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -189,3 +165,34 @@ def get_event_line_for_vehicle(vehicle):
 | 
				
			|||||||
        data.append(service)
 | 
					        data.append(service)
 | 
				
			||||||
    data.sort(key=pitstop_service_key)
 | 
					    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
	
	Block a user