from flask import url_for, redirect, render_template, request, jsonify from flask_security import login_required from flask_security.core import current_user from sqlalchemy.exc import IntegrityError import requests import json from ..entities import Vehicle, Consumable, FillingStation from ..forms import EditVehicleForm, DeleteVehicleForm, DeleteAccountForm from ..tools import db_log_update, db_log_delete, db_log_add from .. import app, db, user_datastore, limiter @app.route('/account', methods=['GET']) @login_required def get_account_page(): stations = [x.as_dict() for x in current_user.favourite_filling_stations] for station in stations: station['state'] = 'favourite' return render_template('account.html', map_pos=(current_user.home_lat, current_user.home_long, current_user.home_zoom), fs=json.dumps(stations)) @app.route('/account/vehicle/edit/', methods=['GET', 'POST']) @login_required def edit_vehicle(vid): vehicle = Vehicle.query.filter(Vehicle.id == vid).first() # prevent edit of foreign vehicles if vehicle not in current_user.vehicles: return redirect(url_for('get_account_page')) form = EditVehicleForm() form.consumables.choices = [(g.id, g.name) for g in Consumable.query.all()] if not form.consumables.data: form.consumables.default = [g.id for g in vehicle.consumables] if form.name.data is not None: form.name.default = form.name.data if form.validate_on_submit(): vehicle.name = form.name.data # we cannot delete consumables where there are pitstops for => report error vehicle.consumables = [] for consumable_id in form.consumables.data: consumable = Consumable.query.get(consumable_id) if consumable is not None: vehicle.consumables.append(consumable) try: db.session.commit() db_log_update(vehicle) except IntegrityError: db.session.rollback() form.name.errors.append('"%s" is not unique.' % (form.name.data)) return render_template('editVehicleForm.html', form=form) return redirect(url_for('get_account_page')) form.name.default = vehicle.name form.process() return render_template('editVehicleForm.html', form=form, vehicle=vehicle) @app.route('/account/vehicle/delete/', methods=['GET', 'POST']) @login_required def delete_vehicle(vid): vehicle = Vehicle.query.filter(Vehicle.id == vid).first() # prevent deletion of foreign vehicles if vehicle not in current_user.vehicles: return redirect(url_for('get_account_page')) if len(current_user.vehicles) == 1: return redirect(url_for('get_account_page')) form = DeleteVehicleForm() if form.validate_on_submit(): db.session.delete(vehicle) db.session.commit() db_log_delete(vehicle) return redirect(url_for('get_account_page')) return render_template('deleteVehicleForm.html', form=form, vehicle=vehicle) @app.route('/account/vehicle/create', methods=['GET', 'POST']) @login_required def create_vehicle(): form = EditVehicleForm() form.consumables.choices = [(g.id, g.name) for g in Consumable.query.all()] if form.name.data is not None: form.name.default = form.name.data if form.consumables.data: form.consumables.default = form.consumables.data else: form.consumables.default = [] if form.validate_on_submit(): if len(form.consumables.data) == 0: form.consumables.errors.append('At least one consumable must be selected.') return render_template('createVehicleForm.html', form=form) vehicle_name = form.name.data new_vehicle = Vehicle(vehicle_name) for consumable_id in form.consumables.data: consumable = Consumable.query.get(consumable_id) if consumable is not None: new_vehicle.consumables.append(consumable) db.session.add(new_vehicle) current_user.vehicles.append(new_vehicle) try: db.session.commit() db_log_add(new_vehicle) except IntegrityError: db.session.rollback() form.name.errors.append('"%s" is not unique.' % (form.name.data)) return render_template('createVehicleForm.html', form=form) return redirect(url_for('get_account_page')) return render_template('createVehicleForm.html', form=form) @app.route('/account/delete', methods=['GET', 'POST']) @login_required def delete_account(): form = DeleteAccountForm() if form.validate_on_submit(): user_datastore.delete_user(current_user) db.session.commit() return redirect(url_for('index')) return render_template('deleteAccountForm.html', form=form) @app.route('/account/home', methods=['GET']) @login_required def get_users_home(): return jsonify( {'lat': float(current_user.home_lat), 'long': float(current_user.home_long), 'zoom': current_user.home_zoom}) @app.route('/account/home', methods=['POST']) @login_required def set_users_home(): current_user.home_lat = request.json['lat'] current_user.home_long = request.json['long'] current_user.home_zoom = request.json['zoom'] db.session.commit() return jsonify({}) @app.route('/filling_stations/update') def update_filling_stations(): print(FillingStation.query.all()) return jsonify({}) @app.route('/filling_stations/favourites/toggle/') def add_favourite_filling_stations(fsid): favourite_ids = {x.id:x for x in current_user.favourite_filling_stations} print(favourite_ids) if fsid in favourite_ids: current_user.favourite_filling_stations.remove(favourite_ids[fsid]) state = 'normal' else: fs = FillingStation.query.filter(FillingStation.id == fsid).first() current_user.favourite_filling_stations.append(fs) state = 'favourite' db.session.commit() return jsonify({'state':state}) @app.route('/filling_stations', methods=['GET']) @login_required @limiter.limit('1 per second') def query_filling_stations(): api_key = app.config['TANKERKOENIG_API_KEY'] latitude = request.args.get('latitude') longitude = request.args.get('longitude') radius = request.args.get('radius', default=1.5) type = request.args.get('type', default='all') sort = request.args.get('sort', default='dist') url = 'https://creativecommons.tankerkoenig.de/json/list.php' params = { 'lat': latitude, 'lng': longitude, 'rad': radius, 'apikey': api_key, 'type': type, 'sort': sort } response = requests.get(url, params=params) data = response.json() for station in data['stations']: fs = FillingStation.query.filter(FillingStation.id == station['id']).first() if not fs: fs = FillingStation() fs.id = station['id'] fs.brand = station['brand'] fs.lat = station['lat'] fs.lng = station['lng'] fs.name = station['name'] fs.street = station['street'] fs.place = station['place'] fs.houseNumber = station['houseNumber'] fs.postCode = station['postCode'] db.session.add(fs) if fs in current_user.favourite_filling_stations: station['state'] = 'favourite' else: station['state'] = 'normal' db.session.commit() return jsonify(data) @app.route('/filling_stations/', methods=['GET']) @login_required @limiter.limit('1 per second') def query_filling_station_details(fsid): api_key = app.config['TANKERKOENIG_API_KEY'] if ',' in fsid: # more than one id, redirect to method 2 (preisabfrage) url = 'https://creativecommons.tankerkoenig.de/json/prices.php' params = { 'apikey': api_key, 'ids': fsid } else: url = 'https://creativecommons.tankerkoenig.de/json/detail.php' params = { 'apikey': api_key, 'id': fsid } response = requests.get(url, params=params) return jsonify(response.json())