Files
Mateusz Gruszczyński cf4398a2a0 split api pythons
2026-07-14 14:55:46 +02:00

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}')