first commit
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
# FuelTrack
|
||||
|
||||
Aplikacja Flask do monitorowania paliwa, kosztów, VAT i firmowych kart paliwowych.
|
||||
|
||||
## Start w Dockerze
|
||||
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
Aplikacja: `http://localhost:8000`
|
||||
|
||||
Pierwsze konto:
|
||||
|
||||
- e-mail: `admin@example.com`
|
||||
- hasło: `admin123!`
|
||||
|
||||
Zmień hasło i `SECRET_KEY` przed wdrożeniem.
|
||||
|
||||
## WebSocket i Gunicorn
|
||||
|
||||
Projekt uruchamia jeden worker `gthread`, 8 wątków i wyłączony timeout dla długich połączeń Socket.IO:
|
||||
|
||||
```bash
|
||||
gunicorn --worker-class gthread --workers 1 --threads 8 --timeout 0 --bind 0.0.0.0:8000 wsgi:app
|
||||
```
|
||||
|
||||
Nie uruchamiaj aplikacji przez samo `gunicorn wsgi:app`, ponieważ domyślny worker `sync` i timeout 30 sekund mogą przerywać WebSocket błędem `SystemExit: 1`.
|
||||
|
||||
## Ceny Orlen
|
||||
|
||||
Zakładka **Ceny Orlen** pozwala:
|
||||
|
||||
- wybrać Pb95, Pb98, diesel lub LPG,
|
||||
- pobrać dane za wskazany rok,
|
||||
- zapisać lub zaktualizować dane w SQLite,
|
||||
- wyświetlić wykres trendu i tabelę historyczną.
|
||||
|
||||
Dla Pb95, Pb98 i diesla wartość API za m³ jest dzielona przez 1000. Endpoint LPG zwraca regionalny zestaw dostępny w chwili pobrania.
|
||||
|
||||
## Motyw
|
||||
|
||||
Motyw jest ustawiany globalnie przez szefa lub administratora w zakładce **Administracja**. Darkly ustawia także `data-bs-theme="dark"`, dzięki czemu tło, formularze, tabele, listy i wykresy używają ciemnej palety.
|
||||
|
||||
## Testy
|
||||
|
||||
```bash
|
||||
python -m pytest -q
|
||||
```
|
||||
|
||||
|
||||
## Wersja v5
|
||||
|
||||
- jawny endpoint zapisu ustawień administracyjnych,
|
||||
- opcjonalny podział faktur kartowych po dniu miesiąca,
|
||||
- lista udostępnień pojazdu i odbieranie dostępu,
|
||||
- reguły cennika karty: Orlen last price, rabat procentowy i dopłata za litr,
|
||||
- porównanie ceny detalicznej z kwotą do zapłaty na wykresie i w tabeli.
|
||||
|
||||
## REST API i Swagger
|
||||
|
||||
Interfejs zapisuje i modyfikuje dane wyłącznie przez endpointy `/api/...`. Widoki HTML odpowiadają za prezentację, natomiast operacje biznesowe przechodzą przez REST API i zwracają JSON.
|
||||
|
||||
Dokumentacja po uruchomieniu:
|
||||
|
||||
- Swagger UI: `http://localhost:8000/docs`
|
||||
- OpenAPI JSON: `http://localhost:8000/openapi.json`
|
||||
|
||||
Autoryzacja API korzysta z tej samej bezpiecznej sesji cookie co interfejs. Najważniejsze grupy endpointów:
|
||||
|
||||
- `/api/auth/*`
|
||||
- `/api/users`
|
||||
- `/api/settings`
|
||||
- `/api/vehicles`
|
||||
- `/api/fuel-entries`
|
||||
- `/api/orlen/*`
|
||||
- `/api/stations/*`
|
||||
|
||||
Stare endpointy formularzy pozostają chwilowo jako warstwa zgodności dla zakładek HTML, ale interfejs nie wysyła już do nich operacji zapisu.
|
||||
|
||||
|
||||
## Wersja v8
|
||||
|
||||
- odnośnik do Swagger UI znajduje się w stopce,
|
||||
- specyfikacja OpenAPI nie deklaruje zbędnej sekcji `servers`,
|
||||
- województwo firmy wybierane jest z listy 16 województw,
|
||||
- wybór wielu województw LPG jest domyślnie ukryty; każda wybrana pozycja tworzy osobną serię,
|
||||
- wyszukiwanie stacji działa na żywo przez AJAX i obejmuje firmę, marki, NIP oraz REGON,
|
||||
- sortowanie katalogu po nazwie, liczbie punktów, NIP, REGON i województwie,
|
||||
- last price działa wyłącznie według wybranej stacji i użycia karty paliwowej,
|
||||
- maksymalnie 10 ulubionych sieci użytkownika; domyślnie wybierane są największe sieci,
|
||||
- lista sieci dozwolonych przez firmę jest egzekwowana również przez API,
|
||||
- konfiguracja portów, bazy, timeoutów i Gunicorna znajduje się w `.env`,
|
||||
- dodane `.gitignore` oraz `.dockerignore`.
|
||||
|
||||
Skopiuj i dostosuj konfigurację:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
## Wersja 9
|
||||
|
||||
- motyw przeniesiony do ustawień aplikacji,
|
||||
- firmowy katalog kart paliwowych,
|
||||
- karta przypisywana użytkownikowi lub pojazdowi,
|
||||
- warunki rozliczenia definiowane per karta i stacja,
|
||||
- blokada stacji, Orlen last price, rabat netto i dopłata netto za litr,
|
||||
- wyszukiwanie stacji po nazwie firmy lub marki stacji.
|
||||
|
||||
## Administracja v10
|
||||
|
||||
Panel jest podzielony na:
|
||||
|
||||
- `/admin/companies` — firmy, ustawienia podatkowe, karty paliwowe i firmowe ulubione stacje,
|
||||
- `/admin/application` — globalny motyw aplikacji,
|
||||
- `/admin/users` — użytkownicy, firma, rola, karta i hasło.
|
||||
|
||||
Ulubione stacje są rozstrzygane kolejno: lista użytkownika, lista firmy, a następnie 10 największych sieci z katalogu URE.
|
||||
|
||||
## Ograniczenie historii LPG Orlen
|
||||
|
||||
Endpoint `https://tool.orlen.pl/api/autogasprices` zwraca wyłącznie bieżący snapshot cen dla 16 województw. Nie obsługuje parametrów daty. FuelTrack zapisuje każdy pobrany snapshot w bazie, dzięki czemu historia LPG narasta od momentu uruchomienia synchronizacji. Nie jest możliwe pobranie pełnej historii LPG wstecz z tego endpointu.
|
||||
|
||||
## Konfiguracja integracji
|
||||
|
||||
Adresy API Orlen/URE, timeouty, adresy bibliotek frontendowych i mapowanie nazw marek są konfigurowane w `.env`. Domyślne wartości znajdują się w `.env.example`.
|
||||
|
||||
Kod integracji został rozdzielony na:
|
||||
|
||||
- `app/integrations/orlen.py` – ceny Orlen,
|
||||
- `app/integrations/ure.py` – pobieranie i agregacja rejestru URE,
|
||||
- `app/integrations/http.py` – wspólna obsługa HTTP,
|
||||
- `app/domain/costs.py` – obliczenia kosztów,
|
||||
- `app/domain/invoices.py` – okresy faktur.
|
||||
|
||||
Frontend jest podzielony funkcjonalnie w `app/static/js/` i `app/static/css/`.
|
||||
|
||||
|
||||
## Punkty stacji URE
|
||||
Po imporcie katalogu URE kliknięcie nazwy firmy mającej więcej niż jeden punkt otwiera modal z listą placówek, adresami, województwem i dostępnymi paliwami.
|
||||
|
||||
## Poprawka importu punktów URE
|
||||
|
||||
Importer scala powtarzające się rekordy tego samego punktu po numerze DKN, aktualizuje istniejące punkty zamiast usuwać i dodawać je ponownie oraz usuwa punkty, których nie ma już w aktualnym imporcie. Zapobiega to błędowi unikalności `fuel_station_point.station_company_id, fuel_station_point.ure_dkn`.
|
||||
|
||||
## v12.2
|
||||
- poprawione agregowanie sieci stacji po marce i adresie punktu
|
||||
- poprawione wyszukiwanie live i sortowanie
|
||||
- DKN traktowany jako identyfikator źródłowy, nie unikalny punkt
|
||||
|
||||
|
||||
## Reset hasła administratora w Docker Compose
|
||||
|
||||
Bezpieczny wariant interaktywny (hasło nie jest wyświetlane):
|
||||
|
||||
```bash
|
||||
docker compose exec web flask reset-admin-password --email admin@example.com
|
||||
```
|
||||
|
||||
Polecenie poprosi dwukrotnie o nowe hasło. Konto musi już istnieć i mieć rolę `admin`.
|
||||
|
||||
Wariant nieinteraktywny, przydatny w skryptach (hasło może zostać zapisane w historii powłoki):
|
||||
|
||||
```bash
|
||||
docker compose exec web flask reset-admin-password \
|
||||
--email admin@example.com \
|
||||
--password 'NoweBezpieczneHaslo123!'
|
||||
```
|
||||
|
||||
Usunięcie użytkownika jest dostępne w panelu administracyjnym. System nie pozwala usunąć własnego konta, ostatniego aktywnego administratora ani użytkownika posiadającego pojazdy lub historię tankowań. Takie konto można dezaktywować po edycji.
|
||||
|
||||
## Zarządzanie wieloma firmami
|
||||
|
||||
Panel **Administracja → Firmy i karty** używa listy firm z wyszukiwaniem i paginacją. Po wybraniu firmy po prawej stronie wyświetlane są tylko jej ustawienia, karty paliwowe i ulubione stacje. Dzięki temu liczba formularzy w DOM nie rośnie wraz z liczbą firm.
|
||||
|
||||
W **Predefiniowanych stacjach paliw** administrator może wskazać firmę bezpośrednio w ustawieniach każdej pozycji. Zmiana firmy przeładowuje kontekst tabeli i pokazuje właściwe ulubione, dozwolone stacje oraz warunki kart.
|
||||
Reference in New Issue
Block a user