- O projekcie
- Zespół
- Stos Technologiczny
- Struktura Projektu
- Modele Danych
- Logika Działania Aplikacji
- Komunikacja, Autoryzacja i API
- Zadania Asynchroniczne
- Konteneryzacja
- Testy i CI/CD
- Instalacja i Uruchomienie
- Funkcjonalności
- Przegląd Widoków (Galeria)
- Dodatkowa Konfiguracja
FasterPost to kompleksowy system logistyczny obsługujący proces dostarczania przesyłek w modelu dwuwarstwowym:
- Logistyka Krajowa (Hub-to-Hub): Transport międzygrodowy pomiędzy głównymi magazynami.
- Logistyka Lokalna (Last Mile): Dostarczanie przesyłek z magazynów lokalnych do paczkomatów.
Celem aplikacji jest optymalizacja tras kurierskich, zarządzanie flotą pojazdów oraz automatyzacja procesu alokacji przesyłek do skrytek paczkomatowych.
| Profil GitHub | Rola w projekcie |
|---|---|
| Oleksii Nawrocki | Lider zespołu / Logistics |
| Tomasz Nowak | Auth / Backend |
Aplikacja została zbudowana w architekturze klient-serwer (rozdzielony frontend i backend).
- Język: Python 3.x
- Framework: Django (z Django REST Framework)
- Baza danych: PostgreSQL (relacyjna)
- Biblioteki algorytmiczne: NumPy, Scikit-learn (do K-Means), GeoPy (do obliczeń geograficznych).
- Framework: Next.js (React)
- Język: TypeScript / JavaScript
- UI: Tailwind CSS / Lucide React (ikony)
- Komunikacja: Axios / Fetch API
Projekt podzielony jest na dwa główne katalogi:
fasterpost/
├── backend/ # Logika biznesowa i API (Django)
│ ├── accounts/ # Zarządzanie użytkownikami i autoryzacją
│ ├── packages/ # Logika przesyłek i śledzenia
│ ├── logistics/ # Aplikacja: Logistyka Krajowa
│ │ ├── services/ # Algorytmy routingu (VRP)
│ │ └── models.py # Modele Hubów i Tras krajowych
│ ├── postmats/ # Aplikacja: Logistyka Lokalna
│ │ ├── management/ # Komendy (np. seed_zones - K-Means)
│ │ ├── services/ # Algorytmy TSP i alokacji skrytek
│ │ └── models.py # Modele Paczkomatów i Przesyłek
│ ├── core/ # Ustawienia globalne, konfiguracja Celery
│ ├── tests/ # Testy jednostkowe i integracyjne
│ ├── Dockerfile # Obraz dla backendu
│ └── requirements.txt # Zależności Python
├── frontend/ # Interfejs użytkownika (Next.js)
│ ├── src/
│ │ ├── components/ # Komponenty React
│ │ ├── pages/ # Widoki aplikacji
│ │ └── services/ # Klient API (połączenie z backendem)
│ └── Dockerfile # Obraz dla frontendu
├── .github/ # Konfiguracja CI/CD (GitHub Actions)
│ └── workflows/
│ └── tests.yml # Automatyczne uruchamianie testów
├── docker-compose.yml # Orkiestracja kontenerów
└── docs/ # Dokumentacja projektowa
System opiera się na relacyjnej bazie danych. Kluczowe encje to:
- User: Rozszerzony model użytkownika Django.
email(Primary Key),first_name,last_name.role: Enum (client,courier,admin,warehouse_manager).warehouse: FK doWarehouse(tylko dla kurierów i magazynierów - przypisanie do bazy).
- Hub (Magazyn): Reprezentuje węzeł w sieci krajowej.
name,city,address.latitude,longitude(Decimal).connections: Many-to-Many (graf połączeń między magazynami).
- Vehicle (Pojazd):
registration_number,capacity(domyślnie 50).max_work_minutes(720),current_hub(FK).
- Route (Trasa Krajowa):
courier(FK User),scheduled_date.status(planned,in_progress,completed).total_distance,estimated_duration.
- RouteStop (Przystanek):
route(FK),order(int),warehouse(FK) lubpostmat(FK).arrival_time,departure_time.
- Zone (Strefa):
name,warehouse(FK),color(do wizualizacji na mapie).
- Postmat (Paczkomat):
name,address,latitude,longitude.zone(FK Zone - wynik algorytmu K-Means).is_active(bool).
- Stash (Skrytka):
postmat(FK),size(small,medium,large).is_empty(bool),reserved_until(DateTime, nullable).
- Package (Paczka):
tracking_number(UUID/String).sender(FK User),receiver_email.size,weight.status(created,paid,in_warehouse,in_transit,delivered).origin_postmat(FK),destination_postmat(FK).
- Actualization (Historia statusów):
package(FK),status,timestamp,location_description.
Schemat relacji encji (ERD):
!ERD Diagram
Logika zaimplementowana w backend/logistics/services/routing_service.py.
- Problem: CVRP (Capacitated Vehicle Routing Problem) z oknami czasowymi.
- Algorytm: Heurystyka zachłanna (Greedy Construction).
- Przebieg:
- System grupuje paczki według Huba startowego.
- Dla każdego pojazdu wybierany jest cel metodą Nearest Neighbor (Najbliższy Sąsiad).
- Sprawdzane są ograniczenia: czas pracy (12h) i pojemność.
- Backhauling: W drodze powrotnej pojazd zabiera paczki zmierzające do jego bazy macierzystej, aby uniknąć "pustych przebiegów".
Logika zaimplementowana w backend/postmats/services/routing_service.py.
- Zoning (K-Means): Miasto dzielone jest na strefy (klastry) w oparciu o lokalizację paczkomatów. Kurierzy są przypisani do stref.
- Alokacja: Przed wyjazdem system sprawdza dostępność skrytek (
is_empty=True) w paczkomacie docelowym. Jeśli brak miejsca -> status DELAYED. - Routing (TSP): Wewnątrz strefy trasa wyznaczana jest algorytmem Nearest Neighbor z użyciem formuły Haversine do obliczania odległości sferycznej.
- Nadawanie i Wybór Paczkomatu:
- Użytkownik wybiera paczkomat nadawczy i odbiorczy z interaktywnej mapy (Frontend).
- System filtruje paczkomaty dostępne w bazie danych, umożliwiając wybór tylko aktywnych punktów.
- Płatności:
- Koszt przesyłki obliczany jest dynamicznie na podstawie wybranego gabarytu (S/M/L) oraz wagi.
- System przewiduje integrację z bramką płatności Stripe. Po pomyślnej transakcji paczka zmienia status na
PAIDi staje się widoczna dla algorytmów logistycznych oraz niemozliwa jest jej pozniejsza edycja.
- Edycja Danych:
- Edycja przesyłki (np. zmiana odbiorcy, rozmiaru, paczkomatu docelowego) jest możliwa wyłącznie przed dokonaniem płatności (status
CREATED). - Po opłaceniu (
PAID) dane są "zamrożone", ponieważ system mógł już rozpocząć proces rezerwacji skrytki lub planowania logistyki.
- Edycja przesyłki (np. zmiana odbiorcy, rozmiaru, paczkomatu docelowego) jest możliwa wyłącznie przed dokonaniem płatności (status
Mechanizm ten zapobiega przepełnieniu paczkomatów (logika w backend/postmats/services/routing_service.py).
- Weryfikacja przed trasą: Podczas generowania trasy lokalnej, system sprawdza dostępność skrytek w paczkomacie docelowym dla każdej paczki.
- Kryteria dostępności: Skrytka jest uznana za wolną tylko wtedy, gdy spełnia łącznie dwa warunki:
- Jest fizycznie pusta (
is_empty=True). - Nie posiada aktywnej rezerwacji (
reserved_until IS NULL).
- Jest fizycznie pusta (
- Dopasowanie: Algorytm dobiera skrytkę odpowiednią do rozmiaru paczki (S do S, M do M itd.).
- Rezerwacja (Lock):
- W momencie utworzenia paczki, system rezerwuje skrytkę na 24 godziny.
- Po opłaceniu przesyłki, rezerwacja jest odnawiana na kolejne 24 godziny od momentu płatności.
- Status skrytki zmienia się na zajęty (
is_empty=False), co blokuje możliwość przypisania tam innej paczki przez ten czas.
- Brak miejsca: Jeśli paczkomat jest pełny, paczka otrzymuje status
DELAYEDi zostaje w magazynie do następnego cyklu dostaw.
Aplikacja wykorzystuje architekturę REST API. Frontend komunikuje się z backendem za pomocą zapytań HTTP (JSON).
Role w systemie: - Użytkownik: Może tworzyć przesyłki i śledzić tylko swoje paczki. - Kurier: Ma dostęp do przypisanych mu tras oraz możliwość zmiany statusu paczek (np. przy odbiorze/dostarczeniu). - Magazynier/Admin: Pełny dostęp do zarządzania flotą i generowania tras.
Pełna lista endpointów, wraz z wymaganymi parametrami i strukturą odpowiedzi, jest generowana automatycznie i dostępna pod adresem:
- Swagger UI:
/api/schema/swagger-ui/ - Redoc:
/api/schema/redoc/
System wykorzystuje standardowy mechanizm tokenów autoryzacyjnych, jednak ze względów bezpieczeństwa token jest przechowywany wyłącznie w ciasteczkach HttpOnly Cookie. Dzięki temu kod JavaScript (Frontend) nie ma do niego dostępu, co zabezpiecza aplikację przed atakami typu XSS.
- Logowanie: Użytkownik wysyła
emailipasswordna endpoint logowania. - Generacja Tokena: Serwer weryfikuje dane i ustawia token w odpowiedzi jako ciasteczko z flagą
HttpOnly.- Przechowywanie: Ciasteczko jest niewidoczne dla skryptów JS.
- Bezpieczeństwo:
SameSite=LaxorazSecure=True(na produkcji).
- Komunikacja: Przeglądarka automatycznie dołącza ciasteczko do każdego zapytania do API. Backend odczytuje token z ciasteczka, a nie z nagłówka
Authorization. - Wylogowanie: Serwer wysyła polecenie usunięcia ciasteczka (set-cookie z datą w przeszłości).
System wykorzystuje niestandardowe klasy uprawnień (Custom Permissions) w Django:
IsCourier: Sprawdza, czyuser.role == 'courier'.IsWarehouseManager: Dostęp do panelu generowania tras.IsOwnerOrReadOnly: Użytkownik widzi tylko swoje paczki, chyba że jest pracownikiem.
- Frontend: Użytkownik wchodzi na stronę mapy. Komponent React (np.
MapComponent) w hookuuseEffectwywołuje funkcję serwisu. - Request:
GET /api/postmats/ - Backend:
- Django Viewset odbiera zapytanie.
- Pobiera listę obiektów
Postmatz bazy danych. - Serializer zamienia obiekty Pythonowe na JSON (zawierający
lat,lng,status).
- Response: JSON z listą paczkomatów.
- Frontend: Otrzymuje dane i renderuje markery na mapie (np. używając Leaflet lub Google Maps).
- Frontend: Administrator klika przycisk "Generuj Trasy".
- Request:
POST /api/logistics/generate-routes/ - Backend:
- Uruchamia
RoutingService. - Algorytm pobiera nieobsłużone paczki.
- Wylicza trasy (zgodnie z logiką opisaną w pkt 5).
- Zapisuje nowe obiekty
Routew bazie danych. - Zwraca status operacji.
- Uruchamia
- Response:
200 OK+ podsumowanie (np. "Wygenerowano 5 tras"). - Frontend: Wyświetla powiadomienie o sukcesie i odświeża listę tras.
- Frontend: Klient wpisuje numer paczki.
- Request:
GET /api/packages/{id}/track/ - Backend: Sprawdza status paczki i jej ostatnią lokalizację (Hub lub Paczkomat).
- Response: JSON
{ "status": "IN_TRANSIT", "location": "Hub Warszawa", "estimated_delivery": "2024-05-20" }.
Ze względu na złożoność obliczeniową algorytmów oraz konieczność wysyłania powiadomień, projekt wykorzystuje Celery z brokerem wiadomości Redis.
send_status_email_task:- Wyzwalane sygnałem (Django Signals) przy zmianie statusu paczki (np. na
DELIVERED). - Wysyła e-mail do klienta z informacją o zmianie statusu.
- Wyzwalane sygnałem (Django Signals) przy zmianie statusu paczki (np. na
release_expired_reservations:- Zadanie okresowe (Celery Beat).
- Sprawdza skrytki, których
reserved_untilminął, i zwalnia je (is_empty=True), jeśli paczka nie dotarła.
Całe środowisko jest skonteneryzowane, co zapewnia spójność między środowiskiem deweloperskim a produkcyjnym. Plik docker-compose.yml definiuje następujące usługi:
db: Baza danych PostgreSQL (Alpine Linux). Dane są persystowane w wolumeniepostgres_data.backend: Kontener Django (Gunicorn/Uvicorn).- Zależy od
dbiredis. - Uruchamia migracje przy starcie.
- Zależy od
frontend: Kontener Next.js (Node.js).- Budowany wieloetapowo (Multi-stage build) dla optymalizacji rozmiaru obrazu.
redis: Broker wiadomości dla Celery oraz cache.worker: Instancja Celery przetwarzająca zadania w tle.beat: Harmonogram zadań okresowych Celery.
Uruchomienie całego środowiska:
docker-compose up --buildProjekt kładzie duży nacisk na jakość kodu, wykorzystując testy automatyczne uruchamiane w potoku CI (GitHub Actions).
- Testy Jednostkowe (Unit Tests): Testowanie pojedynczych funkcji algorytmicznych (np. czy funkcja Haversine poprawnie liczy odległość).
- Testy Integracyjne (Integration Tests): Testowanie endpointów API (np. czy próba rezerwacji zajętej skrytki zwraca błąd). Używamy
APITestCasez Django REST Framework.
Plik .github/workflows/tests.yml definiuje proces, który uruchamia się przy każdym push do repozytorium:
- Postawienie kontenera z bazą danych PostgreSQL (Service Container).
- Instalacja zależności (
pip install -r requirements.txt). - Uruchomienie lintera (np.
flake8) w celu sprawdzenia stylu kodu. - Wykonanie testów:
python manage.py test.
- Docker
- Docker Compose
-
Konfiguracja środowiska: Skopiuj plik przykładowy
.env.cd src cp .env.example .env -
Uruchomienie kontenerów:
docker-compose -f backend/docker-compose.yml build --no-cache docker-compose -f backend/docker-compose.yml up
-
Inicjalizacja aplikacji:
docker-compose run web sh -c "python manage.py makemigrations" docker-compose run web sh -c "python manage.py migrate"
-
Seedowanie
docker-compose run web sh -c "python manage.py seed_warehouses" docker-compose run web sh -c "python manage.py seed_logistics" docker-compose run web sh -c "python manage.py seed_accounts" docker-compose run web sh -c "python manage.py seed_zones" docker-compose run web sh -c "python manage.py seed_local_delivery" -
Testowanie
docker-compose -f test.yml run web sh -c "DJANGO_SETTINGS_MODULE=proj.settings_test python manage.py test"
Aplikacja frontendowa jest dostępna pod adresem: http://localhost:80
Aplikacja backendowa jest dostępnia pod adresem: http://localhost:8000
- Zatrzymanie kontenerów:
docker-compose down - Ponowne uruchomienie:
docker-compose up -d - Logi:
docker-compose logs -f
cd backend
pip install -r requirements.txt
python manage.py migrate
python manage.py seed_zones # Inicjalizacja stref K-Means
python manage.py runservercd frontend
npm install
npm run devSystem oferuje następujące możliwości w podziale na role:
- Zakładanie konta i logowanie.
- Nadawanie paczek i wybór paczkomatu.
- Śledzenie statusu przesyłki.
- Odbieranie paczek.
- Przegląd paczek do odebrania i dostarczenia.
- Obsługa procesu umieszczania paczki w paczkomacie.
- Transport między magazynami a paczkomatami.
- Zarządzanie użytkownikami (CRUD).
- Zarządzanie paczkomatami i magazynami.
- Podgląd logistyki.
| Strona Główna | Logowanie |
|---|---|
![]() |
![]() |
Rejestracja i Weryfikacja:
| Rejestracja | Walidacja Błędów |
|---|---|
![]() |
![]() |
| Poprawne Dane | Weryfikacja Email |
|---|---|
![]() |
![]() |
Dashboard i Ustawienia:
| Kokpit Użytkownika | Nadchodzące Paczki |
|---|---|
![]() |
![]() |
Proces Nadawania Paczki:
Dedykowany panel dla klientów biznesowych z obsługą masowych wysyłek.
| Strona Biznesowa | Dashboard Biznesowy |
|---|---|
![]() |
![]() |
Zarządzanie Zasobami:
| Twoje Paczki | Płatności i Faktury |
|---|---|
![]() |
![]() |
| Masowe Płatności | Zarządzanie Magazynami |
|---|---|
![]() |
![]() |
Operacje:
- Wysyłanie paczek:
docs/screenshots/6_business_sending_packages.png - Zgłoszenia/Wnioski:
docs/screenshots/6_business_request.png
| Śledzenie Przesyłki | Odbiór Paczki |
|---|---|
![]() |
Zarządzanie całym systemem logistycznym.
| Dashboard Admina | Logistyka |
|---|---|
![]() |
![]() |
Zarządzanie Infrastrukturą:
| Paczkomaty i Skrytki | Magazyny |
|---|---|
![]() |
![]() |
Lista wszystkich paczek w systemie
Sekcja Najczęściej Zadawanych Pytań
https://myaccount.google.com/apppasswords
Aby otrzymać klucze stripe nalezy wejść pod link (z wcześniej załozonym kontem): https://dashboard.stripe.com/
























