Files
orderPRO/DOCS/ARCHITECTURE.md
Jacek Pyziak 1b5e403c31 Add Allegro shipment service and related components
- Implement AllegroShipmentService for managing shipment creation and status checks.
- Create ShipmentController to handle shipment preparation and label downloading.
- Introduce ShipmentPackageRepository for database interactions related to shipment packages.
- Add methods for retrieving delivery services, creating shipments, checking creation status, and downloading labels.
- Implement address validation and token management for Allegro API integration.
2026-03-06 01:06:59 +01:00

18 KiB

Architecture

Status

  • Projekt po resecie do trybu users-only.

Moduly aktywne

  • App\Modules\Auth
  • App\Modules\Orders
  • App\Modules\Users
  • App\Modules\Settings

Routing

  • GET /login, POST /login, POST /logout
  • GET /settings/users, POST /settings/users
  • GET /orders (redirect do /orders/list)
  • GET /orders/list
  • GET /orders/{id}
  • POST /orders/{id}/status
  • GET /users (redirect do /settings/users)
  • POST /users (compat route)
  • GET /settings (redirect do /settings/users)
  • GET /settings/database
  • POST /settings/database/migrate
  • GET /settings/statuses
  • POST /settings/status-groups
  • POST /settings/status-groups/update
  • POST /settings/status-groups/delete
  • POST /settings/status-groups/reorder
  • POST /settings/statuses/create
  • POST /settings/statuses/update
  • POST /settings/statuses/delete
  • POST /settings/statuses/reorder
  • GET /settings/cron
  • POST /settings/cron
  • GET /settings/integrations/allegro
  • POST /settings/integrations/allegro/save
  • POST /settings/integrations/allegro/oauth/start
  • POST /settings/integrations/allegro/import-single
  • POST /settings/integrations/allegro/statuses/save
  • POST /settings/integrations/allegro/statuses/save-bulk
  • POST /settings/integrations/allegro/statuses/delete
  • POST /settings/integrations/allegro/statuses/sync
  • GET /settings/integrations/allegro/oauth/callback
  • GET /settings/integrations/apaczka
  • POST /settings/integrations/apaczka/save
  • GET /settings/integrations/inpost
  • POST /settings/integrations/inpost/save
  • GET /health
  • GET / (redirect)

Korekta logowania

  • AuthController::showLogin(Request): Response:
    • dla zalogowanego usera redirect na /settings/users (zamiast nieistniejacego /dashboard).
  • AuthController::login(Request): Response:
    • po poprawnym logowaniu redirect na /settings/users.

Kluczowe klasy

  • App\Core\Application
  • App\Modules\Auth\AuthController
  • App\Modules\Auth\AuthService
  • App\Modules\Orders\OrdersController
  • App\Modules\Orders\OrdersRepository
  • App\Modules\Settings\SettingsController
  • App\Modules\Settings\OrderStatusRepository
  • App\Modules\Settings\AllegroIntegrationController
  • App\Modules\Settings\AllegroIntegrationRepository
  • App\Modules\Settings\AllegroOAuthClient
  • App\Modules\Settings\AllegroApiClient
  • App\Modules\Settings\AllegroOrderImportService
  • App\Modules\Settings\AllegroStatusMappingRepository
  • App\Modules\Settings\AllegroStatusDiscoveryService
  • App\Modules\Orders\OrderImportRepository
  • App\Modules\Settings\CronSettingsController
  • App\Modules\Cron\CronRepository
  • App\Modules\Cron\CronRunner
  • App\Modules\Cron\AllegroTokenRefreshHandler
  • App\Modules\Cron\AllegroOrdersImportHandler
  • App\Modules\Cron\AllegroStatusSyncHandler
  • App\Modules\Users\UsersController
  • App\Modules\Users\UserRepository
  • App\Modules\Settings\ApaczkaIntegrationController
  • App\Modules\Settings\ApaczkaIntegrationRepository
  • App\Modules\Settings\InpostIntegrationController
  • App\Modules\Settings\InpostIntegrationRepository
  • App\Modules\Settings\AllegroOrdersSyncService
  • App\Modules\Settings\AllegroOrderSyncStateRepository
  • App\Modules\Settings\AllegroStatusSyncService

Przeplyw Zamowienia > Lista zamowien

  • GET /orders/list:
    • OrdersController::index(Request): Response
    • pobiera dane listy przez OrdersRepository::paginate(...),
    • data zamowienia na liscie korzysta z fallbacku: orders.ordered_at -> orders.source_created_at -> orders.source_updated_at -> orders.fetched_at,
    • domyslne sortowanie i filtry zakresu dat (date_from, date_to) korzystaja z tej samej daty efektywnej,
    • pobiera slowniki filtrow (sourceOptions(), statusOptions()), statystyki (quickStats()), agregaty statusow (statusCounts()) i konfiguracje grup/statusow (statusPanelConfig()),
    • buduje panel statusow z grupami i licznikami (buildStatusPanel(...)) z linkami filtrujacymi po statusie,
    • panel statusow i etykiety statusow sa zgodne z konfiguracja z Ustawienia > Statusy (z fallbackiem Pozostale),
    • renderuje podglad pozycji zamowienia (nazwa, miniatura, ilosc) na bazie order_items,
    • miniatura pozycji jest rozwiazywana priorytetowo: order_items.media_url -> glowny obraz powiazanego produktu orderPRO (product_channel_map + sales_channels[allegro] + product_images),
    • obsluguje modal podgladu zdjecia pozycji po kliknieciu miniatury,
    • normalizuje status techniczny na etykiete biznesowa (bez kodu statusu),
    • renderuje widok resources/views/orders/list.php i komponent tabeli resources/views/components/table-list.php.
  • GET /orders/{id}:
    • OrdersController::show(Request): Response
    • pobiera szczegoly przez OrdersRepository::findDetails(int $orderId), statystyke statusow przez statusCounts() oraz konfiguracje przez statusPanelConfig(),
    • pozycje zamowienia maja ten sam mechanizm rozwiazywania miniatur co lista (media_url z zamowienia lub obraz z mapowania produktu),
    • buduje panel statusow z grupami i licznikami (buildStatusPanel(...)),
    • renderuje klikalne taby sekcji i przelaczanie paneli po stronie klienta (JS w orders/show.php),
    • renderuje widok resources/views/orders/show.php z sekcjami:
      • pozycje zamowienia,
      • szczegoly zamowienia,
      • platnosc i wysylka,
      • adresy (customer, invoice, delivery),
      • notatki i historia statusow.
  • Sidebar ma oddzielna grupe nawigacyjna:
    • Zamowienia -> Lista zamowien.

Skrypty techniczne (CLI)

  • bin/fix_status_codes.php
    • naprawa kodow grup/statusow (transliteracja PL -> ASCII, tryb --dry-run, opcja --use-remote).
  • bin/deploy_and_seed_orders.php
    • aplikuje generyczny schema zamowien z database/drafts/20260302_orders_schema_v1.sql,
    • seeduje dane testowe (--count, --append, --use-remote, --profile=default|realistic),
    • profil realistic utrzymuje spojne zaleznosci miedzy:
      • statusem zamowienia,
      • statusem i kwota platnosci,
      • obecnoscia wysylek i dokumentow,
      • historia przejsc statusow (deterministyczne sciezki zamiast losowych przeskokow).

Przeplyw Ustawienia > Statusy

  • GET /settings/statuses:
    • SettingsController::statuses(Request): Response
    • pobiera dane przez OrderStatusRepository::listGroups() i OrderStatusRepository::listStatuses(),
    • renderuje widok resources/views/settings/statuses.php.
  • POST /settings/status-groups:
    • SettingsController::createStatusGroup(Request): Response
    • waliduje CSRF i dane (name, color_hex, is_active),
    • code jest generowany automatycznie z name i nie jest edytowany z UI,
    • zapisuje przez OrderStatusRepository::createGroup(...).
  • POST /settings/status-groups/update:
    • SettingsController::updateStatusGroup(Request): Response
    • waliduje istnienie grupy i aktualizuje rekord przez updateGroup(...),
    • code pozostaje bez zmian (read-only po utworzeniu).
  • POST /settings/status-groups/delete:
    • SettingsController::deleteStatusGroup(Request): Response
    • usuwa grupe przez deleteGroup(...); statusy z tej grupy usuwane sa kaskadowo (FK).
  • POST /settings/status-groups/reorder:
    • SettingsController::reorderStatusGroups(Request): Response
    • zapisuje kolejnosc drag-and-drop grup przez OrderStatusRepository::reorderGroups(...),
    • endpoint jest wywolywany automatycznie po upuszczeniu elementu listy (auto-save).
  • POST /settings/statuses/create:
    • SettingsController::createStatus(Request): Response
    • waliduje grupe, pola statusu i zapisuje przez createStatus(...).
  • POST /settings/statuses/update:
    • SettingsController::updateStatus(Request): Response
    • waliduje dane i aktualizuje status przez updateStatus(...),
    • code pozostaje bez zmian (read-only po utworzeniu).
  • POST /settings/statuses/delete:
    • SettingsController::deleteStatus(Request): Response
    • usuwa status przez deleteStatus(...).
  • POST /settings/statuses/reorder:
    • SettingsController::reorderStatuses(Request): Response
    • zapisuje kolejnosc drag-and-drop statusow w ramach grupy przez OrderStatusRepository::reorderStatusesByGroup(...),
    • endpoint jest wywolywany automatycznie po upuszczeniu elementu listy (auto-save).

Nawigacja ustawien

  • Sidebar (resources/views/layouts/app.php) ma nowy podlink:
    • Statusy (/settings/statuses).
    • Cron (/settings/cron).
    • Integracje Allegro (/settings/integrations/allegro).
    • Integracja Apaczka (/settings/integrations/apaczka).
    • Integracja InPost (/settings/integrations/inpost).

Przeplyw Ustawienia > Cron

  • GET /settings/cron:
    • CronSettingsController::index(Request): Response
    • pobiera ustawienia cron_run_on_web, cron_web_limit,
    • renderuje harmonogramy (cron_schedules) oraz kolejke/historie (cron_jobs).
  • POST /settings/cron:
    • CronSettingsController::save(Request): Response
    • waliduje CSRF,
    • zapisuje cron_run_on_web i cron_web_limit do app_settings.

Przeplyw wykonania crona

  • bin/cron.php:
    • laduje aplikacje i uruchamia CronRunner::run($limit).
  • App\Core\Application::maybeRunCronOnWeb(Request): void:
    • przy wlaczonej opcji cron_run_on_web=1 uruchamia CronRunner podczas requestu HTTP,
    • stosuje throttling sesyjny i lock DB (GET_LOCK) zeby uniknac wielu rownoleglych workerow.
  • CronRunner:
    • dispatchuje due schedule z cron_schedules do cron_jobs,
    • pobiera pending joby wg priorytetu i czasu,
    • wykonuje handler po job_type.
  • Pierwszy aktywny handler:
  • allegro_token_refresh -> AllegroTokenRefreshHandler::handle(...) (odswiezenie tokenu OAuth Allegro).
  • Dodatkowy handler:
    • allegro_orders_import -> AllegroOrdersImportHandler::handle(...) (automatyczny import zamowien Allegro).
    • allegro_status_sync -> AllegroStatusSyncHandler::handle(...) (synchronizacja statusow wg kierunku z ustawien integracji Allegro).

Przeplyw Ustawienia > Integracje > Allegro

  • GET /settings/integrations/allegro:
    • AllegroIntegrationController::index(Request): Response
    • odczytuje konfiguracje przez AllegroIntegrationRepository::getSettings(),
    • renderuje resources/views/settings/allegro.php z domyslnym callback URL.
  • POST /settings/integrations/allegro/save:
    • AllegroIntegrationController::save(Request): Response
    • waliduje CSRF, srodowisko, redirect_uri i date startu,
    • zapisuje ustawienia przez AllegroIntegrationRepository::saveSettings(...).
  • POST /settings/integrations/allegro/settings/save:
    • AllegroIntegrationController::saveImportSettings(Request): Response
    • zapisuje interwal harmonogramu allegro_orders_import (w minutach) do cron_schedules.interval_seconds,
    • zapisuje kierunek synchronizacji statusow i interwal synchronizacji statusow do app_settings,
    • zapisuje interwal joba allegro_status_sync do cron_schedules.interval_seconds.
  • POST /settings/integrations/allegro/oauth/start:
    • AllegroIntegrationController::startOAuth(Request): Response
    • waliduje CSRF i komplet danych OAuth (client_id, client_secret, redirect_uri),
    • buduje URL autoryzacji przez AllegroOAuthClient::buildAuthorizeUrl(...) (scope: orders:read + sale:offers:read),
    • zapisuje state w sesji i przekierowuje do Allegro.
  • POST /settings/integrations/allegro/import-single:
    • AllegroIntegrationController::importSingleOrder(Request): Response
    • waliduje CSRF i checkout_form_id,
    • uruchamia AllegroOrderImportService::importSingleOrder(...),
    • po imporcie pokazuje diagnostyke miniatur pozycji (ile pozycji ma obrazek i przyczyny brakow).
  • POST /settings/integrations/allegro/statuses/save:
    • AllegroIntegrationController::saveStatusMapping(Request): Response
    • zapisuje mapowanie allegro_status_code -> orderpro_status_code.
  • POST /settings/integrations/allegro/statuses/save-bulk:
    • AllegroIntegrationController::saveStatusMappingsBulk(Request): Response
    • zapisuje mapowania zbiorczo dla wszystkich wierszy tabeli mapowan.
  • POST /settings/integrations/allegro/statuses/delete:
    • AllegroIntegrationController::deleteStatusMapping(Request): Response
    • usuwa mapowanie po mapping_id.
  • POST /settings/integrations/allegro/statuses/sync:
    • AllegroIntegrationController::syncStatusesFromAllegro(Request): Response
    • pobiera statusy z API Allegro (checkout-forms) i dopisuje je do tabeli mapowan.
  • GET /settings/integrations/allegro/oauth/callback:
    • AllegroIntegrationController::oauthCallback(Request): Response
    • waliduje state i code,
    • wymienia code na tokeny przez AllegroOAuthClient::exchangeAuthorizationCode(...),
    • zapisuje tokeny przez AllegroIntegrationRepository::saveTokens(...).
  • AllegroOrderImportService:
    • pilnuje waznosci tokenu (refresh przed requestem lub retry po 401),
    • pobiera zamowienie GET /order/checkout-forms/{id} przez AllegroApiClient,
    • pobiera przesylki zamowienia GET /order/checkout-forms/{id}/shipments przez AllegroApiClient::getCheckoutFormShipments(...),
    • dla pozycji bez obrazka w checkout-form pobiera szczegoly oferty GET /sale/product-offers/{offerId} i uzupelnia order_items.media_url,
    • mapuje forme wysylki Allegro (delivery.method.name/delivery.method.id) do pol zamowienia (external_carrier_id, external_carrier_account_id),
    • dla dostawy do punktu odbioru mapuje adres delivery.pickupPoint.address i nazwe punktu do adresu typu delivery,
    • mapuje terminy wysylki z delivery.time.dispatch do send_date_min / send_date_max,
    • buduje diagnostyke importu miniatur (statystyki + przyczyny brakow),
    • mapuje status Allegro na status orderPRO na podstawie allegro_order_status_mappings,
    • mapuje payload Allegro na neutralny model tabel zamowien,
    • zapisuje aggregate przez OrderImportRepository::upsertOrderAggregate(...).
  • AllegroOrdersSyncService:
    • uruchamiany z crona (allegro_orders_import),
    • respektuje ustawienia integracji (orders_fetch_enabled, orders_fetch_start_date),
    • pobiera listy checkout forms (GET /order/checkout-forms?sort=-updatedAt) i importuje nowe/zmienione zamowienia,
    • utrzymuje kursor sync i status ostatniego wykonania w integration_order_sync_state.
  • AllegroStatusSyncService:
    • uruchamiany z crona (allegro_status_sync),
    • respektuje ustawienie kierunku allegro_status_sync_direction,
    • dla kierunku allegro_to_orderpro wykorzystuje mechanizm importu zamowien do aktualizacji statusow,
    • dla kierunku orderpro_to_allegro zwraca wynik informacyjny (tryb przygotowany pod kolejny etap).

Log aktywnosci zamowien

  • Tabela order_activity_log rejestruje wszystkie zdarzenia dotyczace zamowienia.
  • Typy zdarzen: status_change, payment, invoice, shipment, message, document, import, note.
  • Rejestracja zdarzen: OrdersRepository::recordActivity(...).
  • Zmiana statusu: OrdersRepository::updateOrderStatus(...) — aktualizuje orders.external_status_id, wpisuje do order_status_history i order_activity_log.
  • Import zamowienia: AllegroOrderImportService::importSingleOrder(...) — po upsert zamowienia rejestruje zdarzenie import w order_activity_log (nowy import lub re-import/aktualizacja), actor_type import, actor_name Allegro.
  • Widok szczegolow zamowienia (GET /orders/{id}) wyswietla log aktywnosci w zakladce Historia zmian.

Zmiana statusu zamowienia z widoku szczegolow

  • POST /orders/{id}/status:
    • OrdersController::updateStatus(Request): Response
    • waliduje CSRF i wybrany status,
    • wywoluje OrdersRepository::updateOrderStatus(...) (aktualizuje orders.external_status_id, wpisuje do order_status_history i order_activity_log),
    • actor_type: user, actor_name: nazwa zalogowanego uzytkownika,
    • po zapisie redirect do GET /orders/{id} z flash message (sukces/blad).
  • Widok szczegolow zamowienia wyswietla dropdown ze wszystkimi aktywnymi statusami (pogrupowanymi wg grup statusow) obok aktualnego statusu.

Przeplyw Ustawienia > Integracja Apaczka

  • GET /settings/integrations/apaczka:
    • ApaczkaIntegrationController::index(Request): Response
    • odczytuje konfiguracje przez ApaczkaIntegrationRepository::getSettings(),
    • renderuje resources/views/settings/apaczka.php.
  • POST /settings/integrations/apaczka/save:
    • ApaczkaIntegrationController::save(Request): Response
    • waliduje CSRF i klucz API,
    • zapisuje zaszyfrowany klucz API przez ApaczkaIntegrationRepository::saveSettings(...).

Przeplyw Ustawienia > Integracja InPost

  • GET /settings/integrations/inpost:
    • InpostIntegrationController::index(Request): Response
    • odczytuje konfiguracje przez InpostIntegrationRepository::getSettings(),
    • renderuje resources/views/settings/inpost.php.
  • POST /settings/integrations/inpost/save:
    • InpostIntegrationController::save(Request): Response
    • waliduje CSRF,
    • zapisuje ustawienia (token API szyfrowany AES-256-CBC, parametry domyslne przesylek) przez InpostIntegrationRepository::saveSettings(...).

Przeplyw Ustawienia > Baza danych

  • GET /settings/database:
    • SettingsController::database(Request): Response
    • pobiera Migrator::status(), przekazuje statystyki i liste pending migracji do widoku resources/views/settings/database.php.
  • POST /settings/database/migrate:
    • SettingsController::migrate(Request): Response
    • waliduje CSRF,
    • uruchamia Migrator::runPending(),
    • zapisuje wynik do flash (settings_success / settings_error, settings_migrate_logs),
    • wykonuje redirect do GET /settings/database.

Zmiany nawigacji

  • Sidebar ma teraz grupe Ustawienia z podlinkami:
    • Uzytkownicy (/settings/users)
    • Baza danych (/settings/database)
  • UsersController::index(Request): Response ustawia:
    • activeMenu = settings
    • activeSettings = users
  • Usunieto wewnetrzny pasek settings-nav z widokow podstron ustawien.

Zasady aktualizacji

  • Przy kazdej zmianie dopisz:
    • nowe klasy i metody (sygnatury + odpowiedzialnosc),
    • zmiany przeplywu request -> controller -> repository,
    • kontrakty wejscia/wyjscia istotnych metod.