97 lines
6.2 KiB
Python
97 lines
6.2 KiB
Python
from collections import defaultdict
|
|
from datetime import date, datetime
|
|
from decimal import Decimal
|
|
|
|
from flask import current_app, jsonify, request, url_for
|
|
from flask_login import current_user, login_required, login_user
|
|
from sqlalchemy import extract
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
from . import api
|
|
from .common import accessible_vehicles, boolv, fail, payload, response, role_required, station_dict, user_dict, vehicle_dict
|
|
from .. import THEMES
|
|
from ..api_tokens import create_access_token
|
|
from ..extensions import db
|
|
from ..models import AppSetting, CompanySettings, FuelCard, FuelCardPolicy, FuelCardStationRule, FuelEntry, FuelStationCompany, FuelStationPoint, OrlenPrice, User, Vehicle
|
|
from ..services import POLISH_REGIONS, aggregate_ure_companies, calculate_costs, fetch_orlen_price, fetch_orlen_range, fetch_ure_stations, invoice_period
|
|
from ..station_catalog import sync_station_catalog
|
|
|
|
FUEL_TYPES = ("PB95", "PB98", "DIESEL", "LPG")
|
|
|
|
@api.get('/stations')
|
|
@login_required
|
|
def stations():
|
|
q=request.args.get('q','').strip();page=request.args.get('page',1,type=int);per=min(request.args.get('per_page',30,type=int),100);query=FuelStationCompany.query.filter_by(active=True)
|
|
if q:
|
|
for term in [x for x in q.split() if x]:
|
|
needle=f'%{term}%'
|
|
query=query.filter(db.or_(FuelStationCompany.brand_name.ilike(needle),FuelStationCompany.company_name.ilike(needle),FuelStationCompany.nip.ilike(needle),FuelStationCompany.regon.ilike(needle),FuelStationCompany.station_names.ilike(needle)))
|
|
sort=request.args.get('sort','company_name');direction=request.args.get('direction','asc')
|
|
allowed={'company_name':FuelStationCompany.brand_name,'station_count':FuelStationCompany.station_count,'nip':FuelStationCompany.nip,'regon':FuelStationCompany.regon,'selected_region':FuelStationCompany.selected_region}
|
|
col=allowed.get(sort,FuelStationCompany.company_name);query=query.order_by(col.desc() if direction=='desc' else col.asc(),FuelStationCompany.brand_name.asc())
|
|
p=query.paginate(page=page,per_page=per,error_out=False);return response({'items':[station_dict(x) for x in p.items],'page':p.page,'pages':p.pages,'total':p.total,'sort':sort,'direction':direction})
|
|
|
|
@api.get('/stations/<int:station_id>/points')
|
|
@login_required
|
|
def station_points(station_id):
|
|
station=FuelStationCompany.query.get_or_404(station_id)
|
|
page=max(request.args.get('page',1,type=int),1)
|
|
per_page=min(max(request.args.get('per_page',50,type=int),1),100)
|
|
q=(request.args.get('q') or '').strip()
|
|
query=FuelStationPoint.query.filter_by(station_company_id=station.id)
|
|
if q:
|
|
needle=f'%{q}%'
|
|
query=query.filter(db.or_(FuelStationPoint.station_name.ilike(needle),FuelStationPoint.street.ilike(needle),FuelStationPoint.city.ilike(needle),FuelStationPoint.postal_code.ilike(needle)))
|
|
query=query.order_by(FuelStationPoint.city.asc(),FuelStationPoint.street.asc(),FuelStationPoint.street_number.asc())
|
|
result=query.paginate(page=page,per_page=per_page,error_out=False)
|
|
items=[{'id':x.id,'dkn':x.ure_dkn.split(':',1)[0] if x.ure_dkn else '','name':x.station_name,'address':x.address,'city':x.city,'region':x.region,'coordinates':x.coordinates,'has_petrol':x.has_petrol,'has_diesel':x.has_diesel,'has_lpg':x.has_lpg} for x in result.items]
|
|
return response({'station':station_dict(station),'items':items,'page':result.page,'pages':result.pages,'total':result.total})
|
|
|
|
@api.put('/me/favorite-stations')
|
|
@login_required
|
|
def favorite_stations():
|
|
d=payload();ids=request.form.getlist('station_ids') if request.form else d.get('station_ids',[]);ids=[ids] if isinstance(ids,(str,int)) else ids
|
|
try: ids=[int(x) for x in ids]
|
|
except Exception: return fail('Nieprawidłowa lista stacji')
|
|
if len(ids)>10:return fail('Użytkownik może mieć maksymalnie 10 ulubionych stacji')
|
|
current_user.favorite_stations=FuelStationCompany.query.filter(FuelStationCompany.id.in_(ids),FuelStationCompany.active.is_(True)).all() if ids else []
|
|
db.session.commit();return response([station_dict(x) for x in current_user.favorite_stations],'Zapisano ulubione stacje')
|
|
|
|
@api.put('/settings/allowed-stations')
|
|
@role_required('boss','admin')
|
|
def allowed_stations():
|
|
d=payload();ids=request.form.getlist('station_ids') if request.form else d.get('station_ids',[]);ids=[ids] if isinstance(ids,(str,int)) else ids
|
|
try: ids=[int(x) for x in ids]
|
|
except Exception: return fail('Nieprawidłowa lista stacji')
|
|
settings=CompanySettings.query.first();settings.allowed_stations=FuelStationCompany.query.filter(FuelStationCompany.id.in_(ids),FuelStationCompany.active.is_(True)).all() if ids else []
|
|
db.session.commit();return response([station_dict(x) for x in settings.allowed_stations],'Zapisano dozwolone stacje')
|
|
|
|
@api.post('/stations/sync')
|
|
@role_required('boss','admin')
|
|
def stations_sync():
|
|
try:
|
|
companies=aggregate_ure_companies(fetch_ure_stations())
|
|
added,updated=sync_station_catalog(companies)
|
|
db.session.commit();return response({'added':added,'updated':updated},f'Katalog URE: dodano {added}, zaktualizowano {updated}')
|
|
except Exception as exc:db.session.rollback();return fail(f'Nie udało się pobrać danych URE: {exc}',502)
|
|
|
|
@api.put('/stations/<int:station_id>')
|
|
@role_required('boss','admin')
|
|
def update_station(station_id):
|
|
s=FuelStationCompany.query.get_or_404(station_id);d=payload()
|
|
region=None
|
|
if 'selected_region' in d:
|
|
region=(d.get('selected_region') or '').strip().lower()
|
|
if region and region not in s.region_list:return fail('Wybrane województwo nie występuje w danych tej firmy')
|
|
try:
|
|
company_id=int(d.get('company_id') or current_user.company_id or 0)
|
|
except (TypeError,ValueError):
|
|
return fail('Nieprawidłowa firma')
|
|
settings=CompanySettings.query.get_or_404(company_id)
|
|
if current_user.role=='boss' and current_user.company_id!=settings.id:return fail('Brak uprawnień',403)
|
|
if region is not None: s.selected_region=region
|
|
s.active=boolv(d,'active');allowed=boolv(d,'allowed')
|
|
if allowed and s not in settings.allowed_stations: settings.allowed_stations.append(s)
|
|
if not allowed and s in settings.allowed_stations: settings.allowed_stations.remove(s)
|
|
db.session.commit();return response(station_dict(s),f'Zapisano ustawienia stacji dla firmy {settings.name}')
|