from flask import url_for, redirect, render_template, flash from flask_security import login_required from flask_security.core import current_user from sqlalchemy.exc import IntegrityError 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, pitstop_service_key, \ get_event_line_for_vehicle, update_filling_station_prices from .. import app, db @app.route('/pitstops/vehicle/select', methods=['GET', 'POST']) @login_required def select_vehicle_for_new_pitstop(): if len(current_user.vehicles) == 1: return redirect(url_for('select_consumable_for_new_pitstop', vid=current_user.vehicles[0].id)) form = SelectVehicleForm() form.vehicle.choices = [(g.id, g.name) for g in current_user.vehicles] if form.validate_on_submit(): return redirect(url_for('select_consumable_for_new_pitstop', vid=form.vehicle.data)) return render_template('selectVehicle.html', form=form) @app.route('/pitstops/vehicle//consumable/select', methods=['GET', 'POST']) @login_required def select_consumable_for_new_pitstop(vid): 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')) if len(vehicle.consumables) == 0: flash('Please choose at least one consumable!', 'warning') return redirect(url_for('edit_vehicle', vid=vid)) if len(vehicle.consumables) == 1: return redirect(url_for('create_pit_stop_form', vid=vid, cid=vehicle.consumables[0].id)) form = SelectConsumableForm() form.consumable.choices = [(g.id, g.name) for g in vehicle.consumables] if form.validate_on_submit(): return redirect(url_for('create_pit_stop_form', vid=vid, cid=form.consumable.data)) return render_template('selectConsumableForVehicle.html', vehicle=vehicle, form=form) @app.route('/pitstops/vehicle//consumable//create', methods=['GET', 'POST']) @login_required def create_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)) form = CreatePitstopForm() data = get_event_line_for_vehicle(vehicle) if len(data) > 0: form.set_pitstops(vehicle.pitstops) form.same_odometer_allowed = (type(data[-1]) != Pitstop) or (data[-1].consumable.id != cid) else: form.set_pitstops([]) form.same_odometer_allowed = True # set the label of the litres field to make the user comfortable form.set_consumable(consumable) # preinitialize the defaults with potentially existing values from a try before form.preinit_with_data() # # Validate should accept same odometer on different consumables # if form.validate_on_submit(): new_stop = Pitstop(form.odometer.data, form.litres.data, form.date.data, form.costs.data, cid) db.session.add(new_stop) vehicle.pitstops.append(new_stop) try: db.session.commit() db_log_add(new_stop) except IntegrityError: db.session.rollback() form.odometer.errors.append('Pitstop already present for %s at odometer %s km!' % (consumable.name, form.odometer.data)) return render_template('createPitStopForm.html', form=form, vehicle=vehicle, messages=form.get_hint_messages()) return redirect(url_for('get_pit_stops', _anchor= 'v' + str(vehicle.id))) form.process() return render_template('createPitStopForm.html', form=form, vehicle=vehicle, messages=form.get_hint_messages()) @app.route('/pitstops/delete/', methods=['GET', 'POST']) @login_required def delete_pit_stop_form(pid): pitstop = Pitstop.query.filter(Pitstop.id == pid).first() if pitstop is None: return redirect(url_for('get_pit_stops')) vehicle = Vehicle.query.filter(Vehicle.id == pitstop.vehicle_id).first() if vehicle not in current_user.vehicles: return redirect(url_for('get_pit_stops')) form = DeletePitStopForm() if form.validate_on_submit(): db.session.delete(pitstop) db.session.commit() db_log_delete(pitstop) return redirect(url_for('get_pit_stops', _anchor='v' + str(vehicle.id))) return render_template('deletePitstopForm.html', form=form, pitstop=pitstop ) @app.route('/pitstops/edit/', methods=['GET', 'POST']) @login_required def edit_pit_stop_form(pid): edit_pitstop = Pitstop.query.get(pid) if edit_pitstop is None: return redirect(url_for('get_pit_stops')) vehicle = Vehicle.query.filter(Vehicle.id == edit_pitstop.vehicle_id).first() if vehicle not in current_user.vehicles: return redirect(url_for('get_pit_stops')) last_pitstop_pos = vehicle.pitstops.index(edit_pitstop) - 1 if last_pitstop_pos > 0: last_pitstop = vehicle.pitstops[last_pitstop_pos] else: last_pitstop = Pitstop(0, 0, date(1970, 1, 1), 0, 0) form = EditPitstopForm() form.set_pitstop(last_pitstop) if form.validate_on_submit(): edit_pitstop.costs = form.costs.data edit_pitstop.date = form.date.data edit_pitstop.amount = form.litres.data edit_pitstop.odometer = form.odometer.data db.session.commit() db_log_update(edit_pitstop) return redirect(url_for('get_pit_stops', _anchor='v' + str(vehicle.id))) form.odometer.default = edit_pitstop.odometer form.litres.default = edit_pitstop.amount form.date.default = edit_pitstop.date form.costs.default = edit_pitstop.costs form.process() messages = { 'date': 'Date must be between %s and %s (including).' % (str(last_pitstop.date), str(date.today())), 'odometer': 'Odometer must be greater than %s km.' % (str(last_pitstop.odometer)) } if edit_pitstop.costs is not None and edit_pitstop.costs > 0: messages['costs'] = 'Costs must be higher than 0.01 €.' return render_template('editPitStopForm.html', form=form, vehicle=vehicle, messages=messages) @app.route('/pitstops', methods=['GET']) @login_required def get_pit_stops(): user = { 'vehicles': [] } for vehicle in current_user.vehicles: data = [] for pitstop in vehicle.pitstops: data.append(pitstop) for service in vehicle.services: data.append(service) data.sort(key=pitstop_service_key) v = { 'id': vehicle.id, 'name': vehicle.name, 'data': data } user['vehicles'].append(v) return render_template('pitstops.html', user=user) @app.route('/pitstops/plan/vehicle/select', methods=['GET', 'POST']) @login_required def select_vehicle_for_plan_pitstop(): if len(current_user.vehicles) == 1: return redirect(url_for('select_consumable_for_plan_pitstop', vid=current_user.vehicles[0].id)) form = SelectVehicleForm() form.vehicle.choices = [(g.id, g.name) for g in current_user.vehicles] if form.validate_on_submit(): return redirect(url_for('select_consumable_for_plan_pitstop', vid=form.vehicle.data)) return render_template('selectVehicle.html', form=form) @app.route('/pitstops/plan/vehicle//consumable/select', methods=['GET', 'POST']) @login_required def select_consumable_for_plan_pitstop(vid): vehicle = Vehicle.query.get(vid) if vehicle is None or vehicle not in current_user.vehicles: return redirect(url_for('select_consumable_for_plan_pitstop')) if len(vehicle.consumables) == 0: flash('Please choose at least one consumable!', 'warning') return redirect(url_for('edit_vehicle', vid=vid)) if len(vehicle.consumables) == 1: return redirect(url_for('plan_pit_stop_form', vid=vid, cid=vehicle.consumables[0].id)) form = SelectConsumableForm() form.consumable.choices = [(g.id, g.name) for g in vehicle.consumables] if form.validate_on_submit(): return redirect(url_for('plan_pit_stop_form', vid=vid, cid=form.consumable.data)) return render_template('selectConsumableForVehicle.html', vehicle=vehicle, form=form) @app.route('/pitstops/plan/vehicle//consumable/', 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: offers.append((fs, getattr(fs, consumable.ext_id),)) return render_template('planPitStopForm.html', vehicle=vehicle, consumable=consumable, offers=offers)