Files
orderPRO/DOCS/ARCHITECTURE.md

34 KiB

Architecture

Status

  • Projekt po resecie do trybu users-only.
  • UI korzysta z globalnego standardu naglowkow sekcji (h2/h3/h4.section-title) definiowanego centralnie w resources/scss/app.scss i buildowanego do public/assets/css/app.css.
  • Kolory akcji UI (przyciski btn--primary i warianty btn--outline-primary) sa odseparowane od koloru naglowkow (section-title) przez dedykowane tokeny --c-action-primary i --c-action-primary-dark w resources/scss/shared/_ui-components.scss.
  • Import Allegro zapisuje log import z kontekstem triggera (manual_import, orders_sync, status_sync) i deduplikuje powtarzalne wpisy bez realnej zmiany.
  • Automatyzacja obsluguje zdarzenie shipment.status_changed i warunek shipment_status oparty o statusy biznesowe.
  • ShipmentTrackingHandler triggeruje automatyzacje tylko po zmianie delivery_status i przekazuje kontekst (package_id, provider, delivery_status, delivery_status_raw, previous_status).
  • Kolejka wydruku ma akcje usuwania wpisu przez route POST /settings/printing/jobs/delete (CSRF + OrderProAlerts.confirm).

Moduly aktywne

  • App\Modules\Auth
  • App\Modules\Orders
  • App\Modules\Users
  • App\Modules\Settings
  • App\Modules\Accounting (modul paragonow — wystawianie, podglad, druk, PDF, lista, eksport XLSX)
  • App\Modules\Settings\EmailMailbox* (skrzynki pocztowe SMTP — CRUD + test polaczenia)
  • App\Modules\Settings\EmailTemplate* (szablony e-mail — CRUD + Quill.js + zmienne + zalaczniki)
  • App\Modules\Email (wysylka e-mail z zamowien — EmailSendingService, VariableResolver, AttachmentGenerator)
  • App\Modules\Automation (zadania automatyczne — reguly zdarzenie/warunki/akcje, CRUD)

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
  • POST /orders/{id}/send-email (wysylka e-mail z zamowienia, AJAX)
  • POST /orders/{id}/email-preview (podglad szablonu z rozwiazanymi zmiennymi, AJAX)
  • GET /accounting (lista paragonow z filtrami i paginacja)
  • GET /accounting/export (eksport XLSX z aktywnymi filtrami)
  • 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
  • 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
  • POST /settings/integrations/apaczka/test
  • GET /settings/integrations/inpost
  • POST /settings/integrations/inpost/save
  • GET /settings/integrations/shoppro
  • POST /settings/integrations/shoppro/save
  • POST /settings/integrations/shoppro/test
  • POST /settings/integrations/shoppro/statuses/save
  • POST /settings/integrations/shoppro/statuses/sync
  • POST /settings/integrations/shoppro/delivery/save
  • GET /settings/accounting
  • POST /settings/accounting/save
  • POST /settings/accounting/toggle
  • POST /settings/accounting/delete
  • GET /settings/email-mailboxes
  • POST /settings/email-mailboxes/save
  • POST /settings/email-mailboxes/delete
  • POST /settings/email-mailboxes/toggle
  • POST /settings/email-mailboxes/test
  • GET /settings/automation
  • GET /settings/automation/create
  • POST /settings/automation/store
  • GET /settings/automation/edit
  • POST /settings/automation/update
  • POST /settings/automation/delete
  • POST /settings/automation/toggle
  • POST /settings/printing/jobs/delete
  • 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\AllegroTokenManager
  • App\Modules\Settings\AllegroApiClient
  • App\Modules\Settings\AllegroOrderImportService
  • App\Modules\Settings\AllegroStatusMappingRepository
  • App\Modules\Settings\AllegroStatusDiscoveryService
  • App\Modules\Settings\IntegrationsRepository
  • App\Modules\Settings\IntegrationSecretCipher
  • App\Modules\Settings\EmailMailboxController
  • App\Modules\Settings\EmailMailboxRepository
  • 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\Cron\ShopproOrdersImportHandler
  • App\Modules\Cron\ShopproStatusSyncHandler
  • App\Modules\Cron\ShopproPaymentStatusSyncHandler
  • App\Modules\Users\UsersController
  • App\Modules\Users\UserRepository
  • App\Modules\Settings\ApaczkaIntegrationController
  • App\Modules\Settings\ApaczkaIntegrationRepository
  • App\Modules\Settings\ApaczkaApiClient
  • App\Modules\Settings\CarrierDeliveryMethodMappingRepository
  • App\Modules\Settings\InpostIntegrationController
  • App\Modules\Settings\InpostIntegrationRepository
  • App\Modules\Settings\IntegrationsHubController
  • App\Modules\Settings\ShopproIntegrationsController
  • App\Modules\Settings\ShopproIntegrationsRepository
  • App\Modules\Settings\ShopproStatusMappingRepository
  • App\Modules\Settings\ShopproDeliveryMethodMappingRepository
  • App\Modules\Settings\ShopproApiClient
  • App\Modules\Settings\ShopproOrdersSyncService
  • App\Modules\Settings\ShopproStatusSyncService
  • App\Modules\Settings\ShopproPaymentStatusSyncService
  • App\Modules\Settings\AllegroOrdersSyncService
  • App\Modules\Settings\AllegroOrderSyncStateRepository
  • App\Modules\Settings\AllegroStatusSyncService
  • App\Modules\Settings\ReceiptConfigController
  • App\Modules\Settings\ReceiptConfigRepository
  • App\Modules\Accounting\ReceiptRepository (findById, findByOrderId, create, getNextNumber, paginate, exportData)
  • App\Modules\Accounting\ReceiptController (create, store, show, printView, pdf)
  • App\Modules\Accounting\AccountingController (index — lista paragonow, export — XLSX)
  • App\Modules\Automation\AutomationController (index, create, store, edit, update, destroy, toggleStatus)
  • App\Modules\Automation\AutomationRepository (findAll, findById, create, update, delete, toggleActive, findActiveByEvent)
  • App\Modules\Automation\AutomationService (trigger, evaluateConditions, executeActions — watcher/executor regul automatyzacji; flow: ReceiptController::store() -> trigger('receipt.created') oraz ShipmentTrackingHandler::handle() -> trigger('shipment.status_changed', context) -> ewaluacja warunkow -> EmailSendingService::send())
  • App\Modules\Shipments\ShipmentProviderInterface
  • App\Modules\Shipments\ShipmentProviderRegistry
  • App\Modules\Shipments\ApaczkaShipmentService

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.
    • na liscie zamowien nie ma juz akcji bulk print Drukuj etykiety; druk etykiet odbywa sie tylko przez flow pojedynczy (POST /api/print/jobs).
  • 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 (/settings/integrations) - wspolny hub konfiguracji providerow.
    • Ksiegowosc (/settings/accounting) - konfiguracja paragonow.

Przeplyw Ustawienia > Ksiegowosc (konfiguracja paragonow)

  • GET /settings/accounting:
    • ReceiptConfigController::index(Request): Response
    • pobiera liste konfiguracji przez ReceiptConfigRepository::listAll(),
    • opcjonalnie laduje konfiguracje do edycji przez findById() (query param edit),
    • renderuje widok resources/views/settings/accounting.php.
  • POST /settings/accounting/save:
    • ReceiptConfigController::save(Request): Response
    • waliduje CSRF, nazwe (wymagana) i format numeracji (wymagany, musi zawierac %N),
    • zapisuje przez ReceiptConfigRepository::save(...) (INSERT lub UPDATE wg obecnosci id).
  • POST /settings/accounting/toggle:
    • ReceiptConfigController::toggleStatus(Request): Response
    • przelacza is_active przez ReceiptConfigRepository::toggleStatus(...).
  • POST /settings/accounting/delete:
    • ReceiptConfigController::delete(Request): Response
    • usuwa konfiguracje przez ReceiptConfigRepository::delete(...),
    • FK RESTRICT blokuje usuniecie jesli istnieja powiazane paragony.

Przeplyw Wystawianie paragonu z zamowienia

  • GET /orders/{id}/receipt/create:
    • ReceiptController::create(Request): Response
    • pobiera zamowienie (OrdersRepository::findDetails), aktywne konfiguracje, dane sprzedawcy,
    • renderuje formularz resources/views/orders/receipt-create.php.
  • POST /orders/{id}/receipt/store:
    • ReceiptController::store(Request): Response
    • waliduje CSRF, config_id, istnienie zamowienia,
    • buduje snapshoty: seller_data_json (z company_settings), buyer_data_json (z adresow zamowienia), items_json (z pozycji),
    • oblicza total_gross, sale_date (wg sale_date_source z konfiguracji), order_reference_value,
    • generuje numer atomowo przez ReceiptRepository::getNextNumber(...) (INSERT ON DUPLICATE KEY UPDATE na receipt_number_counters),
    • zapisuje paragon przez ReceiptRepository::create(...),
    • redirect na /orders/{id} z flash success.

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),
    • historia (past_jobs) ma stronicowanie po parametrze query past_page (25 rekordow na strone).
  • 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).
    • shoppro_orders_import -> ShopproOrdersImportHandler::handle(...) (automatyczny import zamowien z aktywnych integracji shopPRO z wlaczonym pobieraniem).
    • shoppro_order_status_sync -> ShopproStatusSyncHandler::handle(...) (synchronizacja statusow shopPRO wg kierunku ustawionego per instancja).
    • shoppro_payment_status_sync -> ShopproPaymentStatusSyncHandler::handle(...) (odswiezanie statusu platnosci zamowien shopPRO na podstawie flagi paid).

Przeplyw tworzenia przesylki

  • GET /orders/{id}/shipment/prepare:
    • ShipmentController::prepare(Request): Response,
    • laduje uslugi dostawy providerow z ShipmentProviderRegistry (aktualnie: allegro_wza, apaczka),
    • pobiera automatyczne mapowanie formy dostawy przez CarrierDeliveryMethodMappingRepository (source_system + source_integration_id + order_delivery_method),
    • dla dostaw punktowych (parcel_external_id/parcel_name) prefillem receiver_name sa dane klienta (a nie nazwa punktu/metody dostawy),
    • gdy mapowanie nie zostanie znalezione, buduje komunikat diagnostyczny (brak mapowan dla instancji lub brak mapowania konkretnej metody) i przekazuje go do widoku.
  • POST /orders/{id}/shipment/create:
    • ShipmentController::create(Request): Response,
    • wybiera providera dynamicznie po provider_code i deleguje do ShipmentProviderInterface::createShipment(...),
    • dla apaczka waliduje wymagane punkty odbioru/nadania wg definicji uslugi (service_structure) i przy bledzie wyceny zwraca rozszerzona diagnostyke parametrow,
    • apaczka uzupelnia i wysyla contact_person dla nadawcy (z Ustawienia > Dane firmy) i odbiorcy (fallback z danych zamowienia),
    • apaczka ustawia jawnie pickup.type (SELF/COURIER) na podstawie uslugi i obecnosci sender_point_id; dla COURIER dopelnia tez pickup.date, pickup.hours_from, pickup.hours_to,
    • dla uslug punktowych apaczka payload adresu zawiera aliasy identyfikatora punktu (point, foreign_address_id, point_id) dla nadania i odbioru,
    • ApaczkaShipmentService::buildReceiverAddress(...) sklada dane odbiorcy z fallbackami (formularz -> delivery -> punkt odbioru z parcel_name -> customer), a dla przesylek punktowych dodatkowo probuje uzupelnic adres punktu przez API points; przy dalszych brakach dopelnia minimum techniczne, aby nie blokowac tworzenia.
  • GET /orders/{id}/shipment/{packageId}/status:
    • ShipmentController::checkStatus(Request): Response,
    • wybiera providera po shipment_packages.provider i deleguje checkCreationStatus(...).
  • POST /orders/{id}/shipment/{packageId}/label:
    • ShipmentController::label(Request): Response,
    • wybiera providera po shipment_packages.provider i deleguje downloadLabel(...),
    • dla Apaczka bledy typu Label is not available for this order oznaczaja paczke jako error, aby nie ponawiac nieskutecznych prob pobrania.
  • POST /orders/{id}/shipment/manual:
    • ShipmentController::createManual(Request): Response,
    • tworzy rekord w shipment_packages z provider='manual', status='created' i podanym tracking_number,
    • opcjonalnie zapisuje nazwe przewoznika w carrier_id,
    • loguje zdarzenie shipment_manual w order_activity_log,
    • ShipmentPackageRepository::createManual(int $orderId, string $trackingNumber, ?string $carrierName): int.

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(...).
  • AllegroTokenManager:
    • Shared Allegro OAuth token resolver. Checks expiry and refreshes via AllegroOAuthClient when needed. Injected into all Allegro service classes (AllegroOrderImportService, AllegroOrdersSyncService, AllegroStatusDiscoveryService, AllegroShipmentService).
  • AllegroOrderImportService:
    • pilnuje waznosci tokenu przez AllegroTokenManager::resolveToken() (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 (z integration_id aktywnej instancji Allegro),
    • zapisuje aggregate przez OrderImportRepository::upsertOrderAggregate(...).
  • AllegroOrdersSyncService:
    • uruchamiany z crona (allegro_orders_import),
    • korzysta z dynamicznego integration_id aktywnego srodowiska Allegro (zamiast stalej),
    • 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(...) do tabeli bazowej integrations (type=apaczka).

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 przez InpostIntegrationRepository::saveSettings(...):
      • token API w integrations.api_key_encrypted (type=inpost),
      • parametry specyficzne przewoznika w inpost_integration_settings.

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.

Przeplyw Ustawienia > Integracje (hub)

  • GET /settings/integrations:
    • IntegrationsHubController::index(Request): Response
    • buduje liste instancji providerow (Allegro sandbox/production, Apaczka, InPost, shopPRO),
    • pokazuje tabele podsumowania i przycisk Ustawienia w kazdym wierszu,
    • przycisk Ustawienia prowadzi do dedykowanego ekranu providera (/settings/integrations/allegro|apaczka|inpost|shoppro),
    • renderuje resources/views/settings/integrations.php.

Przeplyw Ustawienia > Integracje > shopPRO

  • GET /settings/integrations/shoppro:
    • ShopproIntegrationsController::index(Request): Response
    • pobiera liste instancji przez ShopproIntegrationsRepository::listIntegrations(),
    • opcjonalnie laduje wskazana instancje (?id=) przez findIntegration(...),
    • renderuje resources/views/settings/shoppro.php z zakladkami: Integracja, Statusy, Ustawienia, Formy dostawy.
  • POST /settings/integrations/shoppro/save:
    • ShopproIntegrationsController::save(Request): Response
    • waliduje CSRF, nazwe, URL (http|https), klucz API (wymagany przy nowej konfiguracji) oraz format daty orders_fetch_start_date (Y-m-d),
    • zapisuje konfiguracje przez ShopproIntegrationsRepository::saveIntegration(...) do tabeli bazowej integrations (type=shoppro),
    • zapisuje interwal joba shoppro_orders_import (minuty) do cron_schedules.interval_seconds,
    • zapisuje kierunek synchronizacji statusow per instancja (integrations.order_status_sync_direction),
    • zapisuje interwal joba shoppro_order_status_sync (minuty) do cron_schedules.interval_seconds,
    • zapisuje interwal joba shoppro_payment_status_sync (minuty) do cron_schedules.interval_seconds,
    • zapisuje liste statusow orderPRO (per instancja) dla kontroli platnosci (integrations.payment_sync_status_codes_json).
  • POST /settings/integrations/shoppro/test:
    • ShopproIntegrationsController::test(Request): Response
    • waliduje CSRF i integration_id,
    • wykonuje test API przez ShopproIntegrationsRepository::testConnection(...),
    • zapisuje wynik testu w integrations.last_test_* i integration_test_logs.
  • POST /settings/integrations/shoppro/statuses/sync:
    • ShopproIntegrationsController::syncStatuses(Request): Response
    • pobiera slownik statusow z API (dictionaries/statuses) przez ShopproIntegrationsRepository::fetchOrderStatuses(...),
    • przekazuje odkryte statusy do widoku zakladki Statusy (flash/sesja).
  • POST /settings/integrations/shoppro/statuses/save:
    • ShopproIntegrationsController::saveStatusMappings(Request): Response
    • waliduje CSRF, integration_id i kody statusow orderPRO,
    • zapisuje mapowania per instancja shopPRO przez ShopproStatusMappingRepository::replaceForIntegration(...) do order_status_mappings.
  • POST /settings/integrations/shoppro/delivery/save:
    • ShopproIntegrationsController::saveDeliveryMappings(Request): Response
    • waliduje CSRF i integration_id,
    • zapisuje mapowania form dostawy przez ShopproDeliveryMethodMappingRepository::saveMappings(...) (per instancja).
  • ShopproOrdersSyncService:
    • uruchamiany z crona (shoppro_orders_import),
    • pobiera liste zamowien i (opcjonalnie) szczegoly zamowienia z API shopPRO,
    • mapuje kwoty z fallbackami (summary, paid, transport_cost) oraz ceny pozycji (price_brutto),
    • uzupelnia order_items.media_url przez pobranie products/get po product_id, gdy zamowienie nie zawiera obrazu.
    • wykrywa zadanie faktury takze po obecnosci danych firmowych (firm_*) i ustawia orders.is_invoice,
    • mapuje adres faktury do order_addresses.address_type=invoice (firma/NIP/adres) na podstawie pol invoice/billing*/firm_*,
    • mapuje punkty odbioru (inpost_paczkomat / orlen_point) do adresu delivery (parcel_external_id, parcel_name, ulica/kod/miasto),
    • uzupelnia delivery o telefon/e-mail klienta i etykiete metody dostawy z kosztem (transport_cost).
  • ShopproStatusSyncService:
    • uruchamiany z crona (shoppro_order_status_sync),
    • filtruje aktywne instancje shopPRO po kierunku synchronizacji statusow (shoppro_to_orderpro),
    • dla wspieranego kierunku wykorzystuje ShopproOrdersSyncService do odswiezenia statusow/importu danych,
    • dla kierunku orderpro_to_shoppro pomija instancje i zwraca wynik informacyjny (tryb przygotowany pod kolejny etap).
  • ShopproPaymentStatusSyncService:
    • uruchamiany z crona (shoppro_payment_status_sync),
    • pobiera zamowienia shopPRO nieoznaczone jako oplacone (orders.payment_status != 2) i nie-finalne,
    • dla kazdego zamowienia odpytuje API orders/get|details i odczytuje flage paid,
    • aktualizuje orders.payment_status, orders.total_paid i order_payments,
    • zapisuje log payment do order_activity_log,
    • respektuje liste statusow z integrations.payment_sync_status_codes_json (gdy pusta: fallback na pomijanie statusow finalnych).
  • Zakladka Formy dostawy (shopPRO):
    • laduje formy dostawy wykryte w zamowieniach danej instancji (orders.source=shoppro + orders.integration_id),
    • laduje uslugi dostawy z Allegro API (delivery-services) z fallbackiem na odswiezenie tokenu OAuth,
    • zapisuje mapowanie: forma dostawy shopPRO -> usluga Allegro/InPost WZA.