update
This commit is contained in:
@@ -1,3 +1,177 @@
|
||||
# API
|
||||
# API
|
||||
|
||||
> Endpointy, kontrakty request/response, autentykacja.
|
||||
## Zakres
|
||||
- Dokument opisuje aktualne endpointy z `routes/web.php` (stan repo: 2026-04-18).
|
||||
- Runtime API jest oparte o sesje (`AuthMiddleware`) i CSRF dla formularzy.
|
||||
- Publiczny endpoint bez sesji: `GET /cron` (token w query lub segmencie sciezki).
|
||||
- API dla klienta drukowania uzywa `X-Api-Key` (`ApiKeyMiddleware`).
|
||||
|
||||
## Uwierzytelnianie
|
||||
- Session auth: wszystkie trasy panelowe i wiekszosc tras `/api/*`.
|
||||
- API key auth: tylko zdalne kolejki druku.
|
||||
- CSRF: wszystkie trasy `POST` w panelu (`_token` w body).
|
||||
|
||||
## Endpointy publiczne
|
||||
- `GET /health` - status aplikacji JSON.
|
||||
- `GET /info` - strona info.
|
||||
- `GET /cron?token=...` - uruchomienie crona przez HTTPS.
|
||||
- `GET /cron/{tokenValue}` - alternatywny wariant tokenu w sciezce.
|
||||
|
||||
## Auth
|
||||
- `GET /login` - formularz logowania.
|
||||
- `POST /login` - logowanie.
|
||||
- `POST /logout` - wylogowanie.
|
||||
|
||||
## Nawigacja i dashboard
|
||||
- `GET /` - redirect do `/settings/users` (zalogowany) albo `/login`.
|
||||
- `GET /users` - redirect do `/settings/users`.
|
||||
- `GET /orders` - redirect do `/orders/list`.
|
||||
- `GET /settings` - redirect do `/settings/users`.
|
||||
|
||||
## Orders
|
||||
- `GET /orders/list` - lista zamowien; AJAX zwraca fragmenty HTML tabeli/panelu statusow.
|
||||
- `GET /orders/{id}` - szczegoly zamowienia.
|
||||
- `POST /orders/{id}/status` - zmiana statusu; obsluguje HTML i AJAX JSON.
|
||||
- `POST /orders/{id}/details/update` - update formy dostawy/platnosci.
|
||||
- `POST /orders/{id}/send-email` - wysylka e-mail z szablonu (JSON).
|
||||
- `POST /orders/{id}/email-preview` - preview e-maila (JSON: subject/body/attachments).
|
||||
- `POST /orders/{id}/payment/add` - reczne dodanie platnosci (JSON).
|
||||
- `GET /api/orders/search` - quick search (JSON).
|
||||
- `GET /api/orders/{id}/preview` - podglad mini karty zamowienia (HTML fragment).
|
||||
|
||||
## Receipts i accounting
|
||||
- `GET /orders/{id}/receipt/create`
|
||||
- `POST /orders/{id}/receipt/store`
|
||||
- `GET /orders/{id}/receipt/{receiptId}`
|
||||
- `GET /orders/{id}/receipt/{receiptId}/print`
|
||||
- `GET /orders/{id}/receipt/{receiptId}/pdf`
|
||||
- `GET /accounting` - lista paragonow.
|
||||
- `POST /accounting/export` - eksport danych ksiegowych.
|
||||
|
||||
## Shipments
|
||||
- `GET /orders/{id}/shipment/prepare`
|
||||
- `POST /orders/{id}/shipment/create`
|
||||
- `GET /orders/{id}/shipment/{packageId}/status`
|
||||
- `POST /orders/{id}/shipment/{packageId}/label`
|
||||
- `POST /orders/{id}/shipment/manual`
|
||||
- `POST /orders/{id}/shipment/{packageId}/delete`
|
||||
|
||||
## Printing API
|
||||
- Session auth:
|
||||
- `POST /api/print/jobs` - dodanie zlecenia druku.
|
||||
- `GET /api/print/jobs/status` - statusy kolejek.
|
||||
- API key auth (`X-Api-Key`):
|
||||
- `GET /api/print/jobs/pending` - lista zadan `pending`.
|
||||
- `GET /api/print/jobs/{id}/download` - pobranie etykiety.
|
||||
- `POST /api/print/jobs/{id}/complete` - finalizacja zadania.
|
||||
|
||||
## Settings: users i baza
|
||||
- `GET /settings/users`
|
||||
- `POST /settings/users`
|
||||
- `GET /settings/database`
|
||||
- `POST /settings/database/migrate`
|
||||
|
||||
## Settings: statusy
|
||||
- `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`
|
||||
|
||||
## Settings: cron i integracje
|
||||
- `GET /settings/cron`
|
||||
- `POST /settings/cron`
|
||||
- `GET /settings/integrations`
|
||||
|
||||
## Settings: Allegro
|
||||
- `GET /settings/integrations/allegro`
|
||||
- `POST /settings/integrations/allegro/save`
|
||||
- `POST /settings/integrations/allegro/settings/save`
|
||||
- `POST /settings/integrations/allegro/oauth/start`
|
||||
- `GET /settings/integrations/allegro/oauth/callback`
|
||||
- `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/save-pull`
|
||||
- `POST /settings/integrations/allegro/statuses/sync`
|
||||
- `POST /settings/integrations/allegro/delivery/save`
|
||||
|
||||
## Settings: Apaczka / Inpost / shopPRO
|
||||
- `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/save-pull`
|
||||
- `POST /settings/integrations/shoppro/statuses/sync`
|
||||
- `POST /settings/integrations/shoppro/delivery/save`
|
||||
|
||||
## Settings: firma, e-mail, automatyzacja, delivery mapping
|
||||
- `GET /settings/company`
|
||||
- `POST /settings/company/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/email-templates`
|
||||
- `GET /settings/email-templates/create`
|
||||
- `GET /settings/email-templates/edit`
|
||||
- `POST /settings/email-templates/save`
|
||||
- `POST /settings/email-templates/delete`
|
||||
- `POST /settings/email-templates/duplicate`
|
||||
- `POST /settings/email-templates/toggle`
|
||||
- `POST /settings/email-templates/preview`
|
||||
- `GET /settings/email-templates/variables`
|
||||
- `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/duplicate`
|
||||
- `POST /settings/automation/toggle`
|
||||
- `GET /settings/delivery-status-mappings`
|
||||
- `POST /settings/delivery-status-mappings/save`
|
||||
- `POST /settings/delivery-status-mappings/save-bulk`
|
||||
- `POST /settings/delivery-status-mappings/reset`
|
||||
- `POST /settings/delivery-status-mappings/reset-all`
|
||||
|
||||
## Settings: druk i mapowania projektow
|
||||
- `GET /settings/printing`
|
||||
- `POST /settings/printing/keys/create`
|
||||
- `POST /settings/printing/keys/{id}/delete`
|
||||
- `POST /settings/printing/jobs/delete`
|
||||
- `GET /settings/project-mappings`
|
||||
- `POST /settings/project-mappings`
|
||||
- `POST /settings/project-mappings/{id}/update`
|
||||
- `POST /settings/project-mappings/{id}/delete`
|
||||
- `POST /settings/project-mappings/{id}/toggle`
|
||||
|
||||
## API shipment presets
|
||||
- `GET /api/shipment-presets`
|
||||
- `POST /api/shipment-presets`
|
||||
- `POST /api/shipment-presets/update`
|
||||
- `POST /api/shipment-presets/delete`
|
||||
|
||||
## Kontrakty JSON (najwazniejsze)
|
||||
- `GET /health`: `{status, app, timestamp}`.
|
||||
- `GET /cron*`: `{ok, message, limit, timestamp}` albo blad `{ok:false, message, error?}`.
|
||||
- `POST /api/print/jobs`: tworzy rekord kolejki dla `package_id`; zwraca JSON statusu.
|
||||
- `GET /api/print/jobs/pending`: lista pending dla klienta desktop.
|
||||
- `POST /api/print/jobs/{id}/complete`: potwierdza wydruk, ustawia `completed`.
|
||||
- `GET /api/orders/search`: `{results:[...]}`.
|
||||
- `POST /orders/{id}/payment/add`: `{ok, payment_id, payment_status, total_paid}` lub blad.
|
||||
|
||||
@@ -1,3 +1,94 @@
|
||||
# ARCHITECTURE
|
||||
# ARCHITECTURE
|
||||
|
||||
> Struktura klas, modulow, przeplywow i zaleznosci w projekcie.
|
||||
## Zakres
|
||||
- Dokument opisuje aktualna architekture kodu (stan repo: 2026-04-18).
|
||||
- Zrodlem prawdy sa: `src/`, `routes/web.php`, `database/migrations/`.
|
||||
|
||||
## Warstwy systemu
|
||||
- `Core`: bootstrap aplikacji, router, request/response, sesja, template, migrator, logger.
|
||||
- `Modules/*Controller`: obsluga requestow HTTP i walidacja wejscia.
|
||||
- `Modules/*Repository`: dostep do danych przez PDO/Medoo (prepared statements).
|
||||
- `Modules/*Service`: logika domenowa i integracje zewnetrzne.
|
||||
- `Cron`: runner, schedulery i handlery jobow okresowych.
|
||||
|
||||
## Moduly domenowe
|
||||
- `Auth`: logowanie, wylogowanie, middleware sesyjne.
|
||||
- `Users`: zarzadzanie uzytkownikami panelu.
|
||||
- `Orders`: lista, szczegoly, statusy, platnosci reczne, preview, quick search.
|
||||
- `Shipments`: przygotowanie, tworzenie, status trackingu, etykiety, usuwanie, paczki reczne.
|
||||
- `Accounting`: paragony i eksport ksiegowy.
|
||||
- `Email`: wysylka i preview wiadomosci z resolverem zmiennych i zalacznikow.
|
||||
- `Automation`: reguly event-condition-action, historia wykonan.
|
||||
- `Settings`: konfiguracja statusow, integracji, cron, skrzynek, szablonow, drukowania, mapowan projektow.
|
||||
- `Printing`: API kolejkowania wydruku i klucze API dla klienta desktop.
|
||||
- `Cron`: synchronizacje integracji i zadania utrzymaniowe.
|
||||
- `Info`: endpoint diagnostyczny `/info`.
|
||||
|
||||
## Kluczowe klasy i odpowiedzialnosci
|
||||
- `App\Core\Application`: bootstrap, dispatch requestu, opcjonalny web-cron z lockiem DB.
|
||||
- `App\Modules\Cron\CronRunner`: pobiera kolejke jobow z `cron_schedules/cron_jobs` i wykonuje handlery.
|
||||
- `App\Modules\Cron\CronHandlerFactory`: sklada zaleznosci i mapuje `job_type -> handler`.
|
||||
- `App\Modules\Orders\OrdersController`: flow UI zamowien + endpointy AJAX.
|
||||
- `App\Modules\Orders\OrdersRepository`: query listy/szczegolow zamowien, update statusow, activity log.
|
||||
- `App\Modules\Shipments\ShipmentController`: flow przesylek i etykiet.
|
||||
- `App\Modules\Shipments\ShipmentProviderRegistry`: wybor providera wysylki po `provider_code`.
|
||||
- `App\Modules\Printing\PrintApiController`: endpointy kolejki wydruku (session/api-key).
|
||||
- `App\Modules\Automation\AutomationService`: trigger eventow, ewaluacja warunkow, wykonanie akcji.
|
||||
- `App\Modules\Settings\ProjectMappingController`: CRUD mapowania produkt -> skrypt generacji projektu.
|
||||
|
||||
## Integracje zewnetrzne
|
||||
- Allegro: OAuth, import zamowien, sync statusow push/pull, mapowania statusow i dostaw.
|
||||
- shopPRO: import zamowien, sync statusow push/pull, sync platnosci, mapowania statusow i dostaw.
|
||||
- Apaczka: konfiguracja API, tworzenie i tracking przesylek.
|
||||
- InPost: konfiguracja API, tworzenie i tracking przesylek.
|
||||
|
||||
## Glowny przeplyw HTTP
|
||||
- Request -> `Router` -> middleware (`AuthMiddleware` lub `ApiKeyMiddleware`) -> Controller.
|
||||
- Controller waliduje dane i CSRF, wywoluje Repository/Service.
|
||||
- Response: HTML (widoki) albo JSON (endpointy AJAX/API).
|
||||
|
||||
## Glowny przeplyw Cron
|
||||
- Trigger:
|
||||
- `GET /cron` (public token) lub web-cron w `Application::maybeRunCronOnWeb`.
|
||||
- `CronRunner::run(limit)` przetwarza aktywne zadania.
|
||||
- Obslugiwane joby:
|
||||
- `allegro_token_refresh`
|
||||
- `allegro_orders_import`
|
||||
- `allegro_status_sync`
|
||||
- `shoppro_orders_import`
|
||||
- `shoppro_order_status_sync`
|
||||
- `shoppro_payment_status_sync`
|
||||
- `shipment_tracking_sync`
|
||||
- `automation_history_cleanup`
|
||||
- `order_status_aged`
|
||||
|
||||
## Automatyzacja
|
||||
- Triggerowana z wielu miejsc (m.in. zmiana statusu, przesylki, platnosci, wystawienie paragonu, cron age).
|
||||
- `AutomationService`:
|
||||
- wyszukuje aktywne reguly po `event_type`,
|
||||
- sprawdza warunki,
|
||||
- wykonuje akcje (`send_email`, `issue_receipt`, `update_shipment_status`, `update_order_status`),
|
||||
- zapisuje wynik do `automation_execution_logs`.
|
||||
|
||||
## Printing
|
||||
- Panel tworzy job `print_jobs` przez `/api/print/jobs`.
|
||||
- Klient desktop pobiera pending joby przez API key.
|
||||
- Klient pobiera etykiete i zamyka job przez `/complete`.
|
||||
- Konfiguracja i zarzadzanie kluczami: `PrintSettingsController` + `print_api_keys`.
|
||||
|
||||
## Projekt generation
|
||||
- `project_mappings` mapuje wzorzec nazwy produktu na `script_name` i `output_dir`.
|
||||
- `order_items.project_generated` i `project_generated_at` trzymaja status wygenerowania artefaktu.
|
||||
- UI konfiguracji: `/settings/project-mappings`.
|
||||
|
||||
## Bezpieczenstwo
|
||||
- Session auth dla panelu.
|
||||
- API key auth dla zdalnego klienta druku.
|
||||
- CSRF dla POST w panelu.
|
||||
- Sekrety integracji szyfrowane przez `IntegrationSecretCipher`.
|
||||
|
||||
## Zaleznosci miedzy modulami
|
||||
- `Orders` korzysta z `Automation`, `Email`, `Printing`, `Shipments`, `Settings`.
|
||||
- `Shipments` korzysta z `Orders`, `CompanySettings`, `Automation`.
|
||||
- `Cron` spina `Settings`, `Orders`, `Shipments`, `Automation`, `Email`.
|
||||
- `Automation` korzysta z `Orders`, `Email`, `Accounting`, `Shipments`.
|
||||
|
||||
@@ -1,3 +1,178 @@
|
||||
# DB_SCHEMA
|
||||
# DB_SCHEMA
|
||||
|
||||
> Schemat bazy danych — tabele, kolumny, FK, indeksy.
|
||||
## Zakres i zrodlo prawdy
|
||||
- Schemat wynika z migracji SQL w `database/migrations`.
|
||||
- Dokument odzwierciedla stan repo na 2026-04-18 (migracje do `20260413_000100`).
|
||||
|
||||
## Ostatnie istotne migracje
|
||||
- `20260413_000100_ensure_orders_delivery_payment_columns.sql`
|
||||
- `20260412_000099_add_requires_photo_to_project_mappings.sql`
|
||||
- `20260412_000098_rename_external_status_id_to_status_code.sql`
|
||||
- `20260412_000097_add_project_generation.sql`
|
||||
- `20260410_000081_add_remember_token_to_users.sql`
|
||||
- `20260408_000090_backfill_delivery_price.sql`
|
||||
- `20260407_000083_allegro_pull_status_mappings.sql`
|
||||
- `20260407_000080_backfill_personalization_message.sql`
|
||||
- `20260407_000079_pull_status_mappings.sql`
|
||||
- `20260407_000078_reverse_status_mapping_keys.sql`
|
||||
|
||||
## Kompensacyjne migracje ensure_
|
||||
- `000038` - naprawa brakujacej tabeli `order_status_mappings`.
|
||||
- `000039` - uzupelnienie brakujacych kolumn fetch w `integrations`.
|
||||
- `000040` - seed/naprawa harmonogramu `shoppro_orders_import`.
|
||||
- `000041` - seed/naprawa harmonogramu `shoppro_order_status_sync` + direction.
|
||||
- `000042` - seed/naprawa `shoppro_payment_status_sync` + kolumny payment sync.
|
||||
- `000100` - kompensacja brakujacych kolumn `orders.payment_method` i `orders.delivery_method`.
|
||||
|
||||
## Kluczowe tabele
|
||||
|
||||
### users
|
||||
- Uzytkownicy panelu.
|
||||
- Wazne kolumny:
|
||||
- `id`, `email` (UNIQUE), `password_hash`, `remember_token` (od `000081`), `is_active`, `created_at`, `updated_at`.
|
||||
|
||||
### orders
|
||||
- Glowna tabela zamowien (model neutralny wzgledem zrodla).
|
||||
- Wazne kolumny:
|
||||
- `id`, `source`, `integration_id`, `source_order_id`, `internal_order_number` (UNIQUE),
|
||||
- `status_code` (rename z `external_status_id` w `000098`),
|
||||
- `payment_status`, `total_paid`, `payment_method`,
|
||||
- `delivery_method`, `delivery_price` (dodane/backfill `000090`),
|
||||
- daty zrodlowe i techniczne, `payload_json`, `preferences_json`.
|
||||
- Wydajnosc:
|
||||
- indeksy na `source`, `status_code`, `ordered_at`, `(source, status_code)`.
|
||||
|
||||
### order_items
|
||||
- Pozycje zamowienia.
|
||||
- Wazne kolumny:
|
||||
- `order_id`, `source_item_id`, `name`, `quantity`, `price_gross`, `media_url`, `payload_json`,
|
||||
- `personalization` (`000075`, backfill `000080`),
|
||||
- `project_generated`, `project_generated_at` (`000097`).
|
||||
|
||||
### order_payments
|
||||
- Platnosci zamowien (import i reczne).
|
||||
- Wazne kolumny:
|
||||
- `order_id`, `source_payment_id`, `payment_type_id`, `payment_date`, `amount`, `currency`, `payload_json`.
|
||||
- Klucz unikalny:
|
||||
- `(order_id, source_payment_id)`.
|
||||
|
||||
### order_status_history
|
||||
- Historia zmian statusow zamowienia.
|
||||
- Wazne kolumny:
|
||||
- `order_id`, `from_status_id`, `to_status_id`, `change_source`, `changed_by`, `changed_at`.
|
||||
|
||||
### order_activity_log
|
||||
- Uniwersalny log aktywnosci (`status_change`, `payment`, `shipment`, `import`, itd.).
|
||||
- Wazne kolumny:
|
||||
- `order_id`, `event_type`, `summary`, `details_json`, `actor_type`, `actor_name`, `created_at`.
|
||||
|
||||
### order_status_groups i order_statuses
|
||||
- Slownik statusow biznesowych i grup statusow.
|
||||
- Relacja:
|
||||
- `order_statuses.group_id -> order_status_groups.id` (`ON DELETE CASCADE`).
|
||||
|
||||
### integrations
|
||||
- Bazowa tabela instancji integracji.
|
||||
- Wazne kolumny:
|
||||
- `type`, `name`, `base_url`, `api_key_encrypted`, `is_active`,
|
||||
- `orders_fetch_enabled`, `orders_fetch_start_date`,
|
||||
- `order_status_sync_direction`, `payment_sync_status_codes_json`,
|
||||
- pola diagnostyczne testu polaczenia.
|
||||
|
||||
### integration_order_sync_state
|
||||
- Kursor synchronizacji per integracja.
|
||||
- Wazne kolumny:
|
||||
- `integration_id` (PK), `last_synced_order_updated_at`, `last_synced_source_order_id`,
|
||||
- `last_success_at`, `last_status_pushed_at`, `last_error`.
|
||||
|
||||
### order_status_mappings
|
||||
- Mapowania push statusow dla shopPRO.
|
||||
- Po `000078` klucz unikalny:
|
||||
- `(integration_id, orderpro_status_code)`.
|
||||
- Dodatkowe indeksy:
|
||||
- `(integration_id, shoppro_status_code)`.
|
||||
|
||||
### order_status_pull_mappings
|
||||
- Dedykowane mapowanie pull shopPRO -> orderPRO (`000079`).
|
||||
- Klucz unikalny:
|
||||
- `(integration_id, shoppro_status_code)`.
|
||||
|
||||
### allegro_order_status_mappings
|
||||
- Mapowania statusow Allegro dla kierunku push.
|
||||
- Po `000078` klucz unikalny:
|
||||
- `orderpro_status_code`.
|
||||
- Indeks lookup:
|
||||
- `allegro_status_code`.
|
||||
|
||||
### allegro_order_status_pull_mappings
|
||||
- Dedykowane mapowanie pull Allegro -> orderPRO (`000083`).
|
||||
- Klucz unikalny:
|
||||
- `allegro_status_code`.
|
||||
|
||||
### allegro_integration_settings
|
||||
- OAuth i tokeny Allegro per srodowisko/integracja.
|
||||
- Wazne kolumny:
|
||||
- `integration_id` (UNIQUE FK), `environment`, `client_id`, `client_secret_encrypted`,
|
||||
- `redirect_uri`, `access_token_encrypted`, `refresh_token_encrypted`, `token_expires_at`,
|
||||
- `orders_fetch_enabled`, `orders_fetch_start_date`.
|
||||
|
||||
### apaczka_integration_settings i inpost_integration_settings
|
||||
- Ustawienia providerow wysylek, powiazane 1:1 z `integrations` przez `integration_id`.
|
||||
|
||||
### company_settings
|
||||
- Dane firmy/nadawcy, parametry domyslnych paczek i pola ksiegowe.
|
||||
|
||||
### receipt_configs, receipts, receipt_number_counters
|
||||
- Konfiguracja numeracji, wystawione paragony i liczniki numerow.
|
||||
|
||||
### email_mailboxes, email_templates, email_logs
|
||||
- Skrzynki SMTP, szablony i log wysylki.
|
||||
|
||||
### automation_rules, automation_conditions, automation_actions, automation_execution_logs
|
||||
- Definicje regul i historia ich wykonan.
|
||||
|
||||
### shipment_packages
|
||||
- Rekordy przesylek i etykiet.
|
||||
- Wazne kolumny trackingowe (od `000060`):
|
||||
- `delivery_status`, `delivery_status_raw`, `delivery_status_updated_at`.
|
||||
|
||||
### delivery_status_mappings
|
||||
- Mapowanie statusow przewoznikow na status biznesowy (`provider + raw_status` UNIQUE).
|
||||
|
||||
### carrier_delivery_method_mappings
|
||||
- Wspolne mapowanie form dostawy na providerow wysylki.
|
||||
|
||||
### shipment_presets
|
||||
- Presety nadania wykorzystywane przez API presetow przesylek.
|
||||
|
||||
### print_api_keys
|
||||
- Klucze API dla klienta desktop druku.
|
||||
- Kolumny:
|
||||
- `key_hash` (UNIQUE), `key_prefix`, `is_active`, `last_used_at`.
|
||||
|
||||
### print_jobs
|
||||
- Kolejka wydruku etykiet.
|
||||
- Kolumny:
|
||||
- `order_id`, `package_id`, `label_path`, `status`, `created_by`, `created_at`, `completed_at`.
|
||||
|
||||
### project_mappings
|
||||
- Mapowanie produktu na skrypt generujacy projekt (`000097`).
|
||||
- Wazne kolumny:
|
||||
- `product_name_pattern`, `script_name`, `output_dir`, `requires_photo` (`000099`), `is_active`.
|
||||
|
||||
## Harmonogram cron (cron_schedules)
|
||||
- Wykorzystywane typy jobow:
|
||||
- `allegro_token_refresh`
|
||||
- `allegro_orders_import`
|
||||
- `allegro_status_sync`
|
||||
- `shoppro_orders_import`
|
||||
- `shoppro_order_status_sync`
|
||||
- `shoppro_payment_status_sync`
|
||||
- `shipment_tracking_sync`
|
||||
- `automation_history_cleanup`
|
||||
- `order_status_aged`
|
||||
|
||||
## Notatki kompatybilnosci
|
||||
- Migracje `ensure_` i `000100` sa idempotentne i kompensuja roznice miedzy srodowiskami.
|
||||
- Rename `orders.external_status_id -> status_code` wymaga, aby nowe query i dokumentacja uzywaly tylko `status_code`.
|
||||
- `delivery_price` jest backfillowane z JSON payloadow importu (Allegro/shopPRO).
|
||||
|
||||
@@ -1,629 +0,0 @@
|
||||
# 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 zdarzenia `shipment.created` (natychmiast po utworzeniu paczki), `shipment.status_changed` (po realnej zmianie statusu dostawy), `payment.status_changed` (po zmianie statusu platnosci — reczne dodanie lub cron sync shopPRO), `order.status_changed` (po zmianie statusu zamowienia — reczna zmiana lub chain z akcji automatyzacji), oraz `order.status_aged` (cron co 1h — zamowienie w danym statusie od X dni).
|
||||
- Automatyzacja obsluguje warunek `shipment_status` oparty o statusy biznesowe, warunek `payment_status` (0=nieoplacone, 1=czesciowo oplacone, 2=oplacone), warunek `order_status` (kody aktywnych statusow zamowien z `order_statuses`), oraz warunek `days_in_status` (pole numeryczne, ewaluacja >=).
|
||||
- Automatyzacja obsluguje akcje `issue_receipt` (Wystaw paragon) z parametrami: `receipt_config_id`, `issue_date_mode`, `duplicate_policy`.
|
||||
- Automatyzacja obsluguje akcje `update_shipment_status` (Zmiana statusu przesylki) z parametrem `status_key` mapowanym na techniczny `delivery_status`.
|
||||
- Automatyzacja obsluguje akcje `update_order_status` (Zmiana statusu zamowienia) z parametrem `status_code` (aktywny kod z `order_statuses`).
|
||||
- Orkiestracja automatyzacji obsluguje chain events: akcja moze emitowac kolejne zdarzenie (`emitEvent`), a engine propaguje wspolny kontekst lancucha.
|
||||
- Zabezpieczenia chain automation (dla obecnych i przyszlych eventow):
|
||||
- limit glebokosci lancucha (`MAX_CHAIN_DEPTH`),
|
||||
- deduplikacja wykonania tej samej pary `event_type + rule_id` w obrebie jednego lancucha,
|
||||
- limit historii wykonan w kontekście (`MAX_CHAIN_EXECUTIONS`).
|
||||
- `ShipmentTrackingHandler` triggeruje automatyzacje tylko po zmianie `delivery_status` i przekazuje kontekst (`package_id`, `provider`, `delivery_status`, `delivery_status_raw`, `previous_status`).
|
||||
- `DeliveryStatus` normalizuje statusy Allegro edge zarowno z opisow PL, jak i EN (mapa slugow + fallback keyword matching), dzieki czemu opisy typu `Parcel is awaiting pick-up` i `Parcel has been delivered` sa mapowane na statusy biznesowe zamiast `unknown`.
|
||||
- Kolejka wydruku ma akcje usuwania wpisu przez route `POST /settings/printing/jobs/delete` (CSRF + `OrderProAlerts.confirm`).
|
||||
- Szablony e-mail obsluguja zmienne przesylki:
|
||||
- `{{przesylka.numer}}` -> `shipment_packages.tracking_number` (najnowsza paczka zamowienia),
|
||||
- `{{przesylka.link_sledzenia}}` -> `DeliveryStatus::trackingUrl(provider, tracking_number, carrier_id)`,
|
||||
- fallback: gdy brak paczki lub tracking number, wartosci sa puste.
|
||||
|
||||
## 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 - lista + osobna podstrona formularza create/edit + Quill.js + zmienne + zalaczniki)
|
||||
- `App\Modules\Email` (wysylka e-mail z zamowien — EmailSendingService, VariableResolver, AttachmentGenerator; kompozycja: header (mailbox) + body (template) + footer (mailbox))
|
||||
- `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)
|
||||
- `POST /orders/{id}/payment/add` (dodanie platnosci recznej, AJAX + push set_paid do shopPRO)
|
||||
- `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 /cron` (publiczny trigger crona HTTPS, autoryzacja tokenem)
|
||||
- `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/save-pull`
|
||||
- `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/email-templates`
|
||||
- `GET /settings/email-templates/create`
|
||||
- `GET /settings/email-templates/edit`
|
||||
- `POST /settings/email-templates/save`
|
||||
- `POST /settings/email-templates/delete`
|
||||
- `POST /settings/email-templates/duplicate`
|
||||
- `POST /settings/email-templates/toggle`
|
||||
- `POST /settings/email-templates/preview`
|
||||
- `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'), ShipmentController::create()/createManual() -> trigger('shipment.created', context), ShipmentTrackingHandler::handle() -> trigger('shipment.status_changed', context) -> ewaluacja warunkow -> akcje: EmailSendingService::send() / auto issue_receipt / update_shipment_status / update_order_status)
|
||||
- `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)`.
|
||||
- `GET /cron?token=...`:
|
||||
- publiczny trigger uruchamiany z zewnetrznego crona HTTPS,
|
||||
- waliduje token `CRON_PUBLIC_TOKEN`,
|
||||
- uruchamia `CronRunner::run($limit)` z limitem opartym o `cron_web_limit`.
|
||||
- `App\Core\Application::maybeRunCronOnWeb(Request): void`:
|
||||
- przy wlaczonej opcji `cron_run_on_web=1` uruchamia `CronRunner` podczas requestu HTTP,
|
||||
- pomija endpointy `/cron` i `/cron/*` (dedykowany trigger uruchamia cron recznie, bez podwojenia),
|
||||
- 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`),
|
||||
- `buildReceiverAddress` laczy delivery + customer z fallbackami: jezeli delivery nie ma ulicy (`street_name`), wszystkie brakujace pola adresowe (name, street, city, zip, country, phone, email) sa uzupelniane z customer,
|
||||
- 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(...)`,
|
||||
- po sukcesie tworzenia paczki triggeruje automatyzacje `shipment.created` z kontekstem paczki (`package_id`, `provider`, `tracking_number`, `package_status`, `delivery_status`),
|
||||
- dla `apaczka` waliduje wymagane punkty odbioru/nadania wg definicji uslugi (`service_structure`) i przy bledzie wyceny zwraca rozszerzona diagnostyke parametrow,
|
||||
- dla `apaczka` przy bledzie API niedostepnego dnia nadania (np. `Pickup not available for selected day` lub `you can't place an order today`) w trybie `COURIER` serwis automatycznie ponawia `order_send` z `pickup.date` przesunieta na kolejny dzien roboczy (max 7 przesuniec),
|
||||
- `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.
|
||||
- `ApaczkaShipmentService::buildOptionsPayload(array $formData): array` mapuje pola formularza (`weekend_delivery`) na klucze `option[]` w payloadzie API Apaczki (`order_send`). Klucz `19` = dostawa w sobote (InPost Paczka w Weekend); stala `OPTION_KEYS` trzyma mape pole_formularza -> id_opcji, walidacja boolean przez `filter_var(..., FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE)`.
|
||||
- `GET /orders/{id}/shipment/{packageId}/status`:
|
||||
- `ShipmentController::checkStatus(Request): Response`,
|
||||
- wybiera providera po `shipment_packages.provider` i deleguje `checkCreationStatus(...)`.
|
||||
- dla providera `allegro_wza` po uzyskaniu `tracking_number` serwis probuje przekazac waybill do Allegro przez `POST /order/checkout-forms/{id}/shipments` (`AllegroApiClient::addShipmentToOrder(...)`),
|
||||
- push waybilla jest wykonywany tylko dla zamowien `orders.source='allegro'` i niepustego `orders.source_order_id`,
|
||||
- blad pushu waybilla do Allegro nie przerywa lokalnego flow tworzenia paczki (fallback niekrytyczny, paczka zostaje zapisana w orderPRO).
|
||||
- `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`,
|
||||
- po sukcesie triggeruje automatyzacje `shipment.created` dla recznie dodanej paczki,
|
||||
- `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`
|
||||
- redirect stub — logika przeniesiona do `saveStatusMappingsBulk()`.
|
||||
- `POST /settings/integrations/allegro/statuses/save-bulk`:
|
||||
- `AllegroIntegrationController::saveStatusMappingsBulk(Request): Response`
|
||||
- zapisuje mapowania zbiorczo z kluczem `orderpro_status_code` przez `AllegroStatusMappingRepository::replaceAllMappings(...)`.
|
||||
- `AllegroStatusMappingRepository::listExternalStatuses()` — zwraca liste zewnetrznych statusow Allegro.
|
||||
- `AllegroStatusMappingRepository::buildAllegroToOrderproMap()` — buduje mape allegro_status -> orderpro_status.
|
||||
- `AllegroStatusMappingRepository::replaceAllMappings(array)` — atomowy zapis wszystkich mapowan.
|
||||
- `AllegroStatusMappingRepository::upsertMapping(...)` — teraz klucz na `orderpro_status_code`.
|
||||
- `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` pushuje reczne zmiany statusow (`order_status_history.change_source=manual`) do API Allegro,
|
||||
- push buduje mapping `orderpro_status_code -> allegro_status_code` z `allegro_order_status_mappings` (po odwroceniu kluczy mapowanie jest bezposrednie),
|
||||
- push aktualizuje kursor `integration_order_sync_state.last_status_pushed_at` po sukcesie.
|
||||
- `AllegroApiClient::updateCheckoutFormFulfillment()`:
|
||||
- PUT `/order/checkout-forms/{id}/fulfillment`,
|
||||
- body JSON: `{"status":"<ALLEGRO_STATUS>"}`,
|
||||
- uzywane przez `AllegroStatusSyncService` w kierunku `orderpro_to_allegro`.
|
||||
|
||||
## 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.status_code`, 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.status_code`, 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.
|
||||
|
||||
## Przeplyw Ustawienia > Szablony e-mail
|
||||
- `GET /settings/email-templates`:
|
||||
- `EmailTemplateController::index(Request): Response`
|
||||
- renderuje liste szablonow (`resources/views/settings/email-templates.php`) i akcje tabeli.
|
||||
- `GET /settings/email-templates/create`:
|
||||
- `EmailTemplateController::create(Request): Response`
|
||||
- renderuje osobna podstrone formularza tworzenia (`resources/views/settings/email-templates-form.php`).
|
||||
- `GET /settings/email-templates/edit?id={id}`:
|
||||
- `EmailTemplateController::edit(Request): Response`
|
||||
- laduje wskazany szablon i renderuje osobna podstrone formularza edycji.
|
||||
- `POST /settings/email-templates/save`:
|
||||
- `EmailTemplateController::save(Request): Response`
|
||||
- waliduje CSRF i wymagane pola,
|
||||
- przy bledzie wraca na odpowiednia podstrone formularza (`create` lub `edit`),
|
||||
- po sukcesie zapisuje szablon i wraca do listy.
|
||||
|
||||
## 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` (klucz: `orderpro_status_code`).
|
||||
- `ShopproStatusMappingRepository::listExternalStatuses(int)` — zwraca liste zewnetrznych statusow shopPRO dla danej integracji.
|
||||
- `ShopproIntegrationsController` uzywa `buildMappingIndex()` + `buildExternalStatusOptions()` zamiast poprzedniego `buildStatusRows()`.
|
||||
- `POST /settings/integrations/shoppro/statuses/save-pull`:
|
||||
- `ShopproIntegrationsController::savePullStatusMappings(Request): Response`
|
||||
- waliduje CSRF, `integration_id` i kody statusow,
|
||||
- zapisuje mapowania pull (shopPRO → orderPRO) przez `ShopproPullStatusMappingRepository::replaceForIntegration(...)` do `order_status_pull_mappings` (klucz: `shoppro_status_code`).
|
||||
- `ShopproIntegrationsController` uzywa `buildPullMappingIndex()` do zaladowania pull mappings do widoku.
|
||||
- `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`).
|
||||
- `ShopproOrderMapper::extractPersonalization()` buduje personalizacje z pol: `attributes`, `custom_fields` i `message` (wiadomosc klienta z prefiksem "Wiadomosc:").
|
||||
- `ShopproStatusSyncService`:
|
||||
- uruchamiany z crona (`shoppro_order_status_sync`),
|
||||
- obsluguje oba kierunki synchronizacji statusow:
|
||||
- `shoppro_to_orderpro` (pull): wykorzystuje `ShopproOrdersSyncService` do odswiezenia statusow/importu danych,
|
||||
- `orderpro_to_shoppro` (push): `syncPushDirection()` buduje reverse mapping (orderpro -> shoppro), query `order_status_history` po zmianach `change_source=manual`, wywoluje `ShopproApiClient::updateOrderStatus()` (PUT) dla kazdego zamowienia z mapowaniem, aktualizuje kursor `last_status_pushed_at`.
|
||||
- push nie wysyla zmian z `change_source=import/sync` (zapobieganie petli).
|
||||
- `ShopproApiClient::updateOrderStatus()`:
|
||||
- PUT `/api.php?endpoint=orders&action=change_status&id={orderId}`,
|
||||
- body JSON: `{"status_id": <int>, "send_email": <bool>}`,
|
||||
- zwraca `{ok, http_code, message, changed}`.
|
||||
- `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.
|
||||
|
||||
## Przeplyw Ustawienia > Zadania automatyczne (aktualizacja 2026-03-28)
|
||||
- `GET /settings/automation`:
|
||||
- `AutomationController::index(Request): Response` renderuje taby `Ustawienia` i `Historia`.
|
||||
- tab `Ustawienia` zawiera istniejacy CRUD regul automatyzacji.
|
||||
- tab `Historia` pokazuje wpisy z `automation_execution_logs` z filtrami (`event_type`, `execution_status`, `rule_id`, `order_id`, `date_from`, `date_to`) i paginacja (`history_page`, 25/strona).
|
||||
- `AutomationService::trigger(...)` zapisuje historie wykonania reguly:
|
||||
- status `success` po wykonaniu akcji,
|
||||
- status `failed` przy wyjatku podczas wykonania reguly,
|
||||
- zapisywany kontrakt: `event_type`, `rule_id`, `rule_name`, `order_id`, `execution_status`, `result_message`, `executed_at`, `context_json`.
|
||||
- Akcja `update_order_status`:
|
||||
- konfiguracja reguly przechowuje `status_code`,
|
||||
- wykonanie delegowane do `OrdersRepository::updateOrderStatus(...)` (wspolny flow historii statusow i activity logu),
|
||||
- aktor zmiany: `system` / `Automatyzacja: <nazwa reguly>`.
|
||||
- Retencja historii:
|
||||
- cron job `automation_history_cleanup` wywoluje `AutomationHistoryCleanupHandler::handle(...)`,
|
||||
- handler usuwa wpisy starsze niz N dni (domyslnie 30) przez `AutomationExecutionLogRepository::purgeOlderThanDays(...)`.
|
||||
|
||||
## Klasy (aktualizacja 2026-03-28)
|
||||
- `App\Modules\Automation\AutomationExecutionLogRepository` (create, paginate, count, listEventTypes, purgeOlderThanDays).
|
||||
- `App\Modules\Cron\AutomationHistoryCleanupHandler` (cleanup retencji historii automatyzacji).
|
||||
|
||||
@@ -1,556 +0,0 @@
|
||||
# DB Schema
|
||||
|
||||
## Compensating Migrations
|
||||
|
||||
Migracje z prefiksem `ensure_` to migracje kompensujące — zostały dodane
|
||||
2026-03-08 aby naprawić rozbieżności schematu między środowiskami.
|
||||
Środowisko jest zsynchronizowane od 2026-03-08. Migracje są idempotentne.
|
||||
|
||||
| Plik migracji | Kompensuje | Powód |
|
||||
|---------------|------------|-------|
|
||||
| 000038_ensure_order_status_mappings_table | 000020_create_order_status_mappings_table | Tabela nie dotarła do środowiska produkcyjnego |
|
||||
| 000039_ensure_integrations_fetch_columns | 000017_add_shoppro_orders_fetch_settings | ALTER TABLE w 000017 nie-idempotentny; kolumny już istniały |
|
||||
| 000040_ensure_shoppro_orders_import_schedule | 000018_create_orders_tables_and_schedule (cron seed) | Koryguje interval z 60s na 300s; używa IFNULL zamiast nadpisywania |
|
||||
| 000041_ensure_shoppro_status_sync_schedule_and_direction | 000021_add_order_status_sync_direction_and_schedule | ALTER TABLE nie-idempotentny; koryguje interval z 3600s na 900s |
|
||||
| 000042_ensure_shoppro_payment_sync_schedule_and_columns | brak (pierwsza migracja payment sync) | Prefiks ensure_ użyty defensywnie — brak wcześniejszej migracji dla payment sync |
|
||||
|
||||
## Status
|
||||
- Projekt po resecie do trybu `users-only`.
|
||||
- Aktualizuj ten plik przy kazdej zmianie migracji/schematu.
|
||||
- 2026-03-02: Przywrocenie UI `Ustawienia > Baza danych` nie wprowadza zmian w schemacie.
|
||||
- 2026-03-02: Dodano tabele statusow (grupy + statusy) dla nowej zakladki `Ustawienia > Statusy`.
|
||||
- 2026-03-02: Przygotowano draft generycznego schematu zamowien (bez aktywnej migracji) w `database/drafts/20260302_orders_schema_v1.sql`.
|
||||
- 2026-03-03: Wdrozono generyczne tabele zamowien na bazie docelowej skryptem `bin/deploy_and_seed_orders.php` (bez migratora SQL).
|
||||
- 2026-03-03: Dodano UI `Zamowienia > Lista zamowien` - bez zmian schematu (wykorzystuje istniejace tabele domeny zamowien).
|
||||
- 2026-03-03: Dodano UI `Zamowienia > Szczegoly zamowienia` (`GET /orders/{id}`) - bez zmian schematu.
|
||||
- 2026-03-04: Dodano tabele `allegro_integration_settings` pod konfiguracje OAuth2 Allegro i tokeny dostepowe.
|
||||
- 2026-03-04: Dodano harmonogram crona `allegro_token_refresh` (co 3600s, priorytet 10, max 3 proby).
|
||||
- 2026-03-04: Dodano reczny import pojedynczego zamowienia Allegro - bez zmian schematu (wykorzystuje istniejace tabele domeny zamowien).
|
||||
- 2026-03-04: Dodano tabele `allegro_order_status_mappings` do mapowania statusow Allegro na statusy orderPRO.
|
||||
- 2026-03-04: Zmieniono `allegro_order_status_mappings.orderpro_status_code` na nullable, aby zapisac statusy pobrane z Allegro przed przypisaniem mapowania.
|
||||
- 2026-03-04: Dodano rozwiazywanie miniatur pozycji zamowien z mapowania produktu orderPRO (`product_channel_map` + `product_images`) - bez zmian schematu.
|
||||
- 2026-03-04: Dodano diagnostyke importu miniatur Allegro (alerty przyczyn brakow) - bez zmian schematu.
|
||||
- 2026-03-04: Dodano harmonogram `allegro_orders_import` (auto-import zamowien Allegro) oraz rozszerzono `integration_order_sync_state` o kolumny kursora sync (`last_synced_order_updated_at`, `last_synced_source_order_id`, `last_success_at`) - migracja `20260304_000027_add_allegro_orders_import_schedule.sql`.
|
||||
- 2026-03-04: Dodano zakladke `Ustawienia` w integracji Allegro z konfiguracja interwalu importu zamowien; zapis aktualizuje istniejacy rekord `cron_schedules` (`job_type=allegro_orders_import`) - bez zmian schematu.
|
||||
- 2026-03-04: Rozszerzono zakladke `Ustawienia` integracji Allegro o kierunek synchronizacji statusow i interwal synchronizacji statusow; zapis do `app_settings` (`allegro_status_sync_direction`, `allegro_status_sync_interval_minutes`) - bez zmian schematu.
|
||||
- 2026-03-04: Dodano harmonogram `allegro_status_sync` (cron synchronizacji statusow) + defaulty `app_settings` dla kierunku i interwalu status sync - migracja `20260304_000028_add_allegro_status_sync_schedule.sql`.
|
||||
- 2026-03-04: Import Allegro mapuje forme wysylki do `orders.external_carrier_id` i `orders.external_carrier_account_id` - bez zmian schematu.
|
||||
- 2026-03-05: Dodano tabele `order_activity_log` — uniwersalny log aktywnosci zamowien (zmiany statusow, platnosci, przesylki, faktury, wiadomosci itp.).
|
||||
- 2026-03-05: Dodano tabele `apaczka_integration_settings` pod konfiguracje klucza API Apaczka.
|
||||
- 2026-03-05: Dodano tabele `inpost_integration_settings` pod konfiguracje integracji InPost ShipX.
|
||||
- 2026-03-06: Dodano kolumne `carrier` do tabeli `allegro_delivery_method_mappings` (default 'allegro') - umozliwia mapowanie na roznych przewoznikow (Allegro, InPost).
|
||||
- 2026-03-06: Wdrozono migracje `20260302_000019_add_internal_order_number_to_orders.sql` - kolumna `internal_order_number` VARCHAR(11) UNIQUE w tabeli `orders`, format `OPXXXXXXXXX` (np. `OP000000001`); backfill istniejacych rekordow; UI: lista i szczegoly zamowien wyswietlaja numer wewnetrzny jako glowny identyfikator.
|
||||
- 2026-03-04: Poprawiono prezentacje daty zamowienia na liscie (`fallback ordered_at -> source_created_at -> source_updated_at -> fetched_at`) - bez zmian schematu.
|
||||
- 2026-03-08: Rozpoczeto ujednolicanie integracji - migracja `20260308_000037_unify_integrations_base_links.sql`:
|
||||
- dodano `integration_id` do tabel `allegro_integration_settings`, `apaczka_integration_settings`, `inpost_integration_settings`,
|
||||
- dodano FK/UNIQUE 1:1 z tabela `integrations`,
|
||||
- dodano/uzupelniono rekordy bazowe providerow (`allegro`, `apaczka`, `inpost`) w `integrations`.
|
||||
- 2026-03-08: Dodano UI i endpointy konfiguracji `shopPRO` (wieloinstancyjnie) w oparciu o istniejaca tabele `integrations` (`type=shoppro`) - bez zmian schematu.
|
||||
- 2026-03-08: Dodano mapowanie statusow dla `shopPRO` (zakladka `Statusy`) z zapisem do istniejacej tabeli `order_status_mappings` per `integration_id` - bez zmian schematu.
|
||||
- 2026-03-08: Dodano migracje naprawcza `20260308_000038_ensure_order_status_mappings_table.sql` (uzupelnia brakujaca tabele `order_status_mappings` w srodowiskach z niepelna historia migracji).
|
||||
- 2026-03-08: Dodano migracje naprawcza `20260308_000039_ensure_integrations_fetch_columns.sql` (uzupelnia brakujace kolumny `orders_fetch_enabled` i `orders_fetch_start_date` w `integrations`).
|
||||
- 2026-03-08: Dodano migracje `20260308_000040_ensure_shoppro_orders_import_schedule.sql` (seed/naprawa harmonogramu `cron_schedules` dla joba `shoppro_orders_import`) - bez zmian schematu tabel.
|
||||
- 2026-03-08: Dodano migracje `20260308_000041_ensure_shoppro_status_sync_schedule_and_direction.sql` (seed/naprawa harmonogramu `cron_schedules` dla joba `shoppro_order_status_sync` oraz uzupelnienie kolumny `integrations.order_status_sync_direction` w srodowiskach niezgodnych).
|
||||
- 2026-03-08: Dodano migracje `20260308_000042_ensure_shoppro_payment_sync_schedule_and_columns.sql`:
|
||||
- uzupelnienie kolumny `integrations.payment_sync_status_codes_json` (JSON) dla konfiguracji statusow objetych kontrola platnosci,
|
||||
- seed/naprawa harmonogramu `cron_schedules` dla joba `shoppro_payment_status_sync` (domyslnie 600s, priorytet 105).
|
||||
- 2026-03-08: Dodano migracje `20260308_000043_create_shoppro_delivery_method_mappings_table.sql`:
|
||||
- nowa tabela `shoppro_delivery_method_mappings` (mapowanie form dostawy per `integration_id`),
|
||||
- tabela przechowuje mapowanie formy shopPRO na usluge Allegro WZA/InPost (`allegro_delivery_method_id`, `allegro_credentials_id`, `allegro_carrier_id`, `allegro_service_name`, `carrier`).
|
||||
- 2026-03-08: Poprawiono mapowanie importu zamowien shopPRO (kwoty i miniatury pozycji) - bez zmian schematu bazy.
|
||||
- 2026-03-08: Poprawiono mapowanie danych wysylki shopPRO (paczkomat/punkt odbioru + kontakt klienta + koszt transportu) - bez zmian schematu bazy.
|
||||
- 2026-03-08: Dodano migracje `20260308_000044_create_carrier_delivery_method_mappings_table.sql`:
|
||||
- nowa tabela `carrier_delivery_method_mappings` (wspolne mapowanie form dostawy dla roznych zrodel zamowien i providerow wysylek),
|
||||
- migracja backfilluje dane z `allegro_delivery_method_mappings` i `shoppro_delivery_method_mappings`.
|
||||
- 2026-03-08: Dodano migracje `20260308_000045_extend_apaczka_credentials.sql`:
|
||||
- rozszerzenie `apaczka_integration_settings` o `app_id` i `app_secret_encrypted`,
|
||||
- migracja przenosi legacy sekret z `api_key_encrypted` do `app_secret_encrypted`.
|
||||
- 2026-03-08: Poprawiono mapowanie danych faktury w imporcie shopPRO - bez zmian schematu:
|
||||
- `orders.is_invoice` jest wykrywany takze po polach firmowych (`firm_*`),
|
||||
- adres faktury jest zapisywany do istniejacej tabeli `order_addresses` (`address_type=invoice`, `company_name`, `company_tax_number`).
|
||||
- 2026-03-08: Poprawiono diagnostyke tworzenia przesylek Apaczka - bez zmian schematu:
|
||||
- payload tworzenia przesylki przekazuje punkty odbioru/nadania (`receiver.point`, `sender.point`) z danych formularza,
|
||||
- komunikaty bledow tworzenia zawieraja rozszerzona diagnostyke parametrow wyceny.
|
||||
- 2026-03-08: Poprawiono obsluge bledow etykiet Apaczka - bez zmian schematu:
|
||||
- przy odpowiedzi API `Label is not available for this order` rekord `shipment_packages` jest oznaczany statusem `error` i zachowuje tresc bledu.
|
||||
- 2026-03-08: Poprawiono fallback danych odbiorcy dla przesylek punktowych Apaczka (Orlen/InPost) - bez zmian schematu:
|
||||
- brakujace dane adresowe odbiorcy sa uzupelniane na etapie budowania payloadu z danych zamowienia (`delivery`, `customer`) oraz metadanych punktu (`parcel_name`).
|
||||
- 2026-03-08: Rozszerzono fallback adresu odbiorcy dla przesylek punktowych Apaczka - bez zmian schematu:
|
||||
- serwis probuje uzupelnic adres punktu przez API `points` po `receiver_point_id`,
|
||||
- przy dalszych brakach danych dla przesylki punktowej dopelniane jest minimum techniczne wymagane przez lokalna walidacje payloadu.
|
||||
- 2026-03-08: Poprawiono przekazywanie punktow w payloadzie Apaczka (nadanie/odbior) - bez zmian schematu:
|
||||
- payload wysyla aliasy identyfikatora punktu (`point`, `foreign_address_id`, `point_id`) dla zgodnosci z wariantami API.
|
||||
- 2026-03-08: Uzupelniono payload odbioru kurierem Apaczka (`pickup.date`, `pickup.hours_from`, `pickup.hours_to`) - bez zmian schematu.
|
||||
- 2026-03-08: Dodano migracje `20260308_000046_extend_company_settings_contact_person.sql`:
|
||||
- rozszerzenie `company_settings` o `sender_contact_person` (osoba kontaktowa nadawcy),
|
||||
- wykorzystywane w payloadzie Apaczka jako `address.sender.contact_person`.
|
||||
- 2026-03-08: Ujednolicono styl naglowkow sekcji UI (`section-title`) - bez zmian schematu bazy.
|
||||
- 2026-03-14: Dodano migracje `20260314_000048_add_orders_performance_indexes.sql` — indeksy wydajnosciowe na tabeli `orders`: `source`, `status_code`, `ordered_at`, composite `(source, status_code)`.
|
||||
- 2026-03-14: Dodano migracje `20260314_000049_add_cron_last_run_at_setting.sql` — seed klucza `cron_web_last_run_at` w `app_settings` (cron throttle przeniesiony z sesji do DB).
|
||||
- 2026-03-14: Przemianowano migracje `20260301_000014_add_products_sku_format_setting.sql` na `20260301_000014b_add_products_sku_format_setting.sql` — deduplikacja numeru sekwencji (kolizja z `000014_create_product_integration_translations`).
|
||||
- 2026-03-15: Dodano migracje `20260315_000050_create_receipt_configs_table.sql` — tabela konfiguracji paragonow (szablony numeracji, ustawienia imiennosci, zrodlo daty sprzedazy).
|
||||
- 2026-03-15: Dodano migracje `20260315_000051_create_receipts_table.sql` — tabela wystawionych paragonow ze snapshotem danych (JSON seller/buyer/items), FK do orders i receipt_configs.
|
||||
- 2026-03-15: Dodano migracje `20260315_000052_create_receipt_number_counters_table.sql` — liczniki numeracji paragonow per konfiguracja i okres (miesiac/rok).
|
||||
- 2026-03-15: Dodano migracje `20260315_000053_extend_company_settings_extra_fields.sql` — rozszerzenie company_settings o bdo_number, regon, court_register, logo_path.
|
||||
- 2026-03-15: Dodano migracje `20260315_000054_create_email_mailboxes_table.sql` — tabela skrzynek pocztowych SMTP (credentials szyfrowane IntegrationSecretCipher).
|
||||
- 2026-03-15: Dodano migracje `20260315_000055_create_email_templates_table.sql` — tabela szablonow wiadomosci email z FK do email_mailboxes.
|
||||
- 2026-03-15: Dodano migracje `20260315_000056_create_email_logs_table.sql` — tabela logow wyslanych wiadomosci z FK do email_templates, email_mailboxes i indeksami na order_id, status, sent_at.
|
||||
- 2026-03-16: Dodano migracje `20260316_000001_add_attachment1_to_email_templates.sql` — kolumna attachment_1 VARCHAR(50) w email_templates (typ zalacznika, np. 'receipt').
|
||||
- 2026-03-17: Nowa zaleznosc `phpmailer/phpmailer` v7.0.2. Modul `App\Modules\Email` — wysylka e-mail z zamowien, resolwer zmiennych, generowanie zalacznikow PDF. Tabela `email_logs` wykorzystywana do logowania wysylek (bez nowych migracji).
|
||||
- 2026-03-28: Rozszerzono automatyzacje o akcje `update_order_status` (zmiana statusu zamowienia) - bez zmian schematu (wykorzystuje istniejace `order_statuses`, `orders`, `order_status_history`, `order_activity_log`).
|
||||
- 2026-03-28: Hotfix Apaczka bledow niedostepnego dnia nadania (`Pickup not available for selected day` oraz `you can't place an order today`) - bez zmian schematu (retry `order_send` z automatycznym przesuwaniem `pickup.date` dla `pickup.type=COURIER`).
|
||||
- 2026-03-28: Dodano publiczny endpoint triggera crona HTTPS (`/cron`) z tokenem `CRON_PUBLIC_TOKEN` - bez zmian schematu bazy.
|
||||
- 2026-03-28: Dodano migracje `20260328_000072_create_automation_execution_logs_table.sql`:
|
||||
- nowa tabela `automation_execution_logs` (historia wykonan regul automatyzacji: co, kiedy, na jakim zamowieniu, wynik),
|
||||
- indeksy pod filtrowanie po czasie/zdarzeniu/statusie/regule/zamowieniu,
|
||||
- seed harmonogramu `cron_schedules` dla joba `automation_history_cleanup` (retencja historii starszej niz 30 dni).
|
||||
- 2026-04-04: Hotfix trackingu Allegro Delivery (edge API) - rozszerzono mapowanie statusow EN i fallback keyword matching (`Parcel is awaiting pick-up`, `Parcel has been delivered`, itp.) w warstwie aplikacyjnej; bez zmian schematu bazy.
|
||||
- 2026-04-07: Dodano tabele `order_status_pull_mappings` — dedykowane mapowanie pull (shopPRO → orderPRO) z UNIQUE na `(integration_id, shoppro_status_code)`. Migracja `20260407_000079_pull_status_mappings.sql` tworzy tabele i pre-populuje z istniejacych danych push mappings.
|
||||
|
||||
## Tabele
|
||||
|
||||
### `users`
|
||||
- Uzytkownicy panelu.
|
||||
- Klucz unikalny: `email`.
|
||||
|
||||
### `order_status_groups`
|
||||
- Grupy statusow zamowien zarzadzane z UI.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `name` (varchar 120),
|
||||
- `code` (varchar 64, UNIQUE),
|
||||
- `color_hex` (char 7, domyslnie `#64748b`),
|
||||
- `sort_order` (int, domyslnie `0`),
|
||||
- `is_active` (tinyint(1), domyslnie `1`),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `order_status_groups_code_unique` (UNIQUE: `code`),
|
||||
- `order_status_groups_sort_order_idx` (`sort_order`).
|
||||
|
||||
### `order_statuses`
|
||||
- Statusy przypisane do grup statusow.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `group_id` (FK -> `order_status_groups.id`),
|
||||
- `name` (varchar 120),
|
||||
- `code` (varchar 64, UNIQUE),
|
||||
- `sort_order` (int, domyslnie `0`),
|
||||
- `is_active` (tinyint(1), domyslnie `1`),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `order_statuses_code_unique` (UNIQUE: `code`),
|
||||
- `order_statuses_group_sort_idx` (`group_id`, `sort_order`, `id`).
|
||||
- Klucze obce:
|
||||
- `order_statuses_group_fk`: `group_id` -> `order_status_groups.id` (`ON DELETE CASCADE`, `ON UPDATE CASCADE`).
|
||||
|
||||
### Domena zamowien (generyczna)
|
||||
- Wdrozone tabele:
|
||||
- `orders`
|
||||
- `order_addresses`
|
||||
- `order_items`
|
||||
- `order_payments`
|
||||
- `order_shipments`
|
||||
- `order_documents`
|
||||
- `order_notes`
|
||||
- `order_status_history`
|
||||
- `order_tags_dict`
|
||||
- `order_tag_links`
|
||||
- `integration_order_sync_state`
|
||||
- Charakterystyka:
|
||||
- schema neutralna wzgledem dostawcy API (pola `source_*`, `external_*`),
|
||||
- kolekcje zamowienia rozdzielone na osobne tabele 1:N,
|
||||
- `payload_json` dostepne dla diagnostyki/replay,
|
||||
- `personalization` (TEXT, nullable) w `order_items` — dane personalizacji produktu z shopPRO (custom_fields), przechowywane jako czysty tekst,
|
||||
- historia zmian statusow utrzymywana w `order_status_history`.
|
||||
|
||||
### `integration_order_sync_state`
|
||||
- Kursor synchronizacji importu zamowien dla integracji (uzywany przez cron auto-importu Allegro i push statusow shopPRO).
|
||||
- Kolumny:
|
||||
- `integration_id` (PK),
|
||||
- `last_synced_order_updated_at` (datetime, nullable) lub historycznie `last_synced_external_updated_at`,
|
||||
- `last_synced_source_order_id` (varchar, nullable) lub historycznie `last_synced_external_order_id`,
|
||||
- `last_run_at` (datetime),
|
||||
- `last_success_at` (datetime),
|
||||
- `last_status_pushed_at` (datetime, nullable) — kursor synchronizacji push statusow orderPRO -> shopPRO,
|
||||
- `last_error` (varchar 500),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `order_status_mappings`
|
||||
- Mapowanie statusow zamowien shopPRO na statusy orderPRO per instancja integracji.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `integration_id` (int unsigned, FK -> `integrations.id`),
|
||||
- `shoppro_status_code` (varchar 64),
|
||||
- `shoppro_status_name` (varchar 128, nullable),
|
||||
- `orderpro_status_code` (varchar 64),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `order_status_mappings_integration_orderpro_unique` (UNIQUE: `integration_id`, `orderpro_status_code`),
|
||||
- `order_status_mappings_integration_idx` (`integration_id`),
|
||||
- `order_status_mappings_integration_shoppro_idx` (`integration_id`, `shoppro_status_code`).
|
||||
- Klucze obce:
|
||||
- `order_status_mappings_integration_fk`: `integration_id` -> `integrations.id` (`ON DELETE CASCADE`, `ON UPDATE CASCADE`).
|
||||
|
||||
### `order_status_pull_mappings`
|
||||
- Mapowanie pull statusow shopPRO na statusy orderPRO (kierunek import/pull). UNIQUE na shoppro_status_code per integracja.
|
||||
- Kolumny:
|
||||
- `id` (PK, int, AI),
|
||||
- `integration_id` (int, NOT NULL),
|
||||
- `shoppro_status_code` (varchar 100, NOT NULL),
|
||||
- `shoppro_status_name` (varchar 255, nullable),
|
||||
- `orderpro_status_code` (varchar 100, NOT NULL),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `order_status_pull_mappings_integration_shoppro_unique` (UNIQUE: `integration_id`, `shoppro_status_code`),
|
||||
- `order_status_pull_mappings_integration_idx` (`integration_id`).
|
||||
|
||||
### `allegro_integration_settings`
|
||||
- Konfiguracja OAuth i sync dla integracji Allegro per srodowisko (`sandbox|production`) zarzadzana z `Ustawienia > Integracje > Allegro`.
|
||||
- Kolumny:
|
||||
- `id` (PK, tinyint unsigned),
|
||||
- `integration_id` (int unsigned, UNIQUE, FK -> `integrations.id`),
|
||||
- `environment` (varchar 16, `sandbox|production`),
|
||||
- `client_id` (varchar 128),
|
||||
- `client_secret_encrypted` (text),
|
||||
- `redirect_uri` (varchar 255),
|
||||
- `orders_fetch_enabled` (tinyint(1), domyslnie `0`),
|
||||
- `orders_fetch_start_date` (date),
|
||||
- `access_token_encrypted` (mediumtext),
|
||||
- `refresh_token_encrypted` (mediumtext),
|
||||
- `token_type` (varchar 32),
|
||||
- `token_scope` (varchar 255),
|
||||
- `token_expires_at` (datetime),
|
||||
- `connected_at` (datetime),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `allegro_integration_settings_environment_idx` (`environment`),
|
||||
- `allegro_integration_settings_token_expires_at_idx` (`token_expires_at`),
|
||||
- `allegro_integration_settings_integration_unique` (`integration_id`, UNIQUE).
|
||||
|
||||
### `allegro_order_status_mappings`
|
||||
- Mapowanie kodow statusow Allegro na kody statusow orderPRO.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `allegro_status_code` (varchar 64, UNIQUE),
|
||||
- `allegro_status_name` (varchar 120),
|
||||
- `orderpro_status_code` (varchar 64),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `allegro_order_status_mappings_orderpro_unique` (UNIQUE: `orderpro_status_code`),
|
||||
- `allegro_order_status_mappings_allegro_code_idx` (`allegro_status_code`).
|
||||
|
||||
### `order_payments`
|
||||
- Platnosci zamowien (z importu API lub reczne).
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `order_id` (int unsigned, FK -> `orders.id`, CASCADE),
|
||||
- `source_payment_id` (varchar 64, nullable),
|
||||
- `external_payment_id` (varchar 64, nullable),
|
||||
- `payment_type_id` (varchar 64, NOT NULL) — typ: ONLINE, TRANSFER, CASH_ON_DELIVERY,
|
||||
- `payment_date` (datetime, nullable),
|
||||
- `amount` (decimal 12,2, nullable),
|
||||
- `currency` (char 3, nullable),
|
||||
- `comment` (varchar 255, nullable),
|
||||
- `payload_json` (json, nullable),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `order_payments_order_source_payment_unique` (UNIQUE: `order_id`, `source_payment_id`),
|
||||
- `order_payments_order_idx` (`order_id`),
|
||||
- `order_payments_date_idx` (`payment_date`).
|
||||
- Migracja: `20260330_000073_create_order_payments_table.sql`
|
||||
|
||||
### `order_activity_log`
|
||||
- Uniwersalny log aktywnosci zamowienia (zmiany statusow, platnosci, przesylki, faktury, wiadomosci itp.).
|
||||
- Kolumny:
|
||||
- `id` (PK, bigint unsigned, AI),
|
||||
- `order_id` (FK -> `orders.id`, CASCADE),
|
||||
- `event_type` (varchar 32) — typ zdarzenia: `status_change`, `payment`, `invoice`, `shipment`, `message`, `document`, `import`, `note`,
|
||||
- `summary` (varchar 255) — czytelny opis zdarzenia,
|
||||
- `details_json` (json, nullable) — dodatkowe dane strukturalne,
|
||||
- `actor_type` (varchar 16, domyslnie `system`) — `system`, `user`, `import`, `api`, `sync`,
|
||||
- `actor_name` (varchar 128, nullable) — nazwa uzytkownika lub identyfikator systemu,
|
||||
- `created_at`.
|
||||
- Indeksy:
|
||||
- `order_activity_log_order_created_idx` (`order_id`, `created_at`),
|
||||
- `order_activity_log_event_type_idx` (`event_type`).
|
||||
|
||||
### `integrations`
|
||||
- Bazowa tabela wszystkich instancji integracji (model docelowy pod wielu providerow i wiele kont per provider).
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `type` (varchar 32, np. `allegro`, `apaczka`, `inpost`, `shoppro`),
|
||||
- `name` (varchar 128, unikalne w obrebie `type`),
|
||||
- `base_url` (varchar 255),
|
||||
- `api_key_encrypted` (text, nullable),
|
||||
- `timeout_seconds` (smallint unsigned),
|
||||
- `is_active` (tinyint(1)),
|
||||
- `orders_fetch_enabled` (tinyint(1)),
|
||||
- `orders_fetch_start_date` (date, nullable),
|
||||
- `order_status_sync_direction` (varchar 32),
|
||||
- `payment_sync_status_codes_json` (json, nullable; lista kodow statusow orderPRO, dla ktorych cron ma sprawdzac oplacenie zamowien),
|
||||
- pola diagnostyki testu (`last_test_status`, `last_test_http_code`, `last_test_message`, `last_test_at`),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `shoppro_delivery_method_mappings`
|
||||
- Mapowanie form dostawy shopPRO na uslugi dostawy Allegro WZA/InPost per instancja integracji.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `integration_id` (int unsigned, FK -> `integrations.id`),
|
||||
- `order_delivery_method` (varchar 200),
|
||||
- `carrier` (varchar 50; np. `allegro`, `inpost`),
|
||||
- `allegro_delivery_method_id` (varchar 128),
|
||||
- `allegro_credentials_id` (varchar 128, nullable),
|
||||
- `allegro_carrier_id` (varchar 128, nullable),
|
||||
- `allegro_service_name` (varchar 255, nullable),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `shoppro_dm_mapping_unique` (UNIQUE: `integration_id`, `order_delivery_method`),
|
||||
- `shoppro_dm_mapping_integration_idx` (`integration_id`).
|
||||
- Klucze obce:
|
||||
- `shoppro_dm_mapping_integration_fk`: `integration_id` -> `integrations.id` (`ON DELETE CASCADE`, `ON UPDATE CASCADE`).
|
||||
|
||||
### `apaczka_integration_settings`
|
||||
- Tabela kompatybilnosci dla integracji Apaczka (`id = 1`); sekret API jest utrzymywany bazowo w `integrations.api_key_encrypted`.
|
||||
- Kolumny:
|
||||
- `id` (PK, tinyint unsigned),
|
||||
- `integration_id` (int unsigned, UNIQUE, FK -> `integrations.id`),
|
||||
- `app_id` (varchar 128, nullable),
|
||||
- `app_secret_encrypted` (text, nullable),
|
||||
- `api_key_encrypted` (text, nullable),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `carrier_delivery_method_mappings`
|
||||
- Wspolne mapowanie form dostawy zamowien na providerow wysylek (model docelowy pod wielu kurierow: `allegro_wza`, `apaczka`, kolejne).
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `source_system` (varchar 32; np. `allegro`, `shoppro`),
|
||||
- `source_integration_id` (int unsigned; `0` dla mapowan globalnych, np. Allegro),
|
||||
- `order_delivery_method` (varchar 200),
|
||||
- `provider` (varchar 50; np. `allegro_wza`, `apaczka`),
|
||||
- `provider_service_id` (varchar 128),
|
||||
- `provider_account_id` (varchar 128, nullable),
|
||||
- `provider_carrier_id` (varchar 128, nullable),
|
||||
- `provider_service_name` (varchar 255, nullable),
|
||||
- `created_at`, `updated_at`.
|
||||
- Indeksy:
|
||||
- `carrier_dm_mapping_unique` (UNIQUE: `source_system`, `source_integration_id`, `order_delivery_method`),
|
||||
- `carrier_dm_mapping_provider_idx` (`provider`),
|
||||
- `carrier_dm_mapping_source_idx` (`source_system`, `source_integration_id`).
|
||||
|
||||
### `inpost_integration_settings`
|
||||
- Tabela ustawien specyficznych InPost ShipX (`id = 1`); token API utrzymywany bazowo w `integrations.api_key_encrypted`.
|
||||
- Kolumny:
|
||||
- `id` (PK, tinyint unsigned),
|
||||
- `integration_id` (int unsigned, UNIQUE, FK -> `integrations.id`),
|
||||
- `api_token_encrypted` (text, nullable),
|
||||
- `organization_id` (varchar 50, nullable),
|
||||
- `environment` (enum: sandbox, production),
|
||||
- `default_dispatch_method` (enum: pop, parcel_locker, courier),
|
||||
- `default_dispatch_point` (varchar 50, nullable),
|
||||
- `default_insurance` (decimal 10,2, nullable),
|
||||
- `default_locker_size` (enum: small, medium, large),
|
||||
- `default_courier_length`, `default_courier_width`, `default_courier_height` (smallint unsigned),
|
||||
- `label_format` (enum: Pdf, Zpl, Epl),
|
||||
- `weekend_delivery`, `auto_insurance_value`, `multi_parcel` (tinyint 0/1),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `company_settings`
|
||||
- Ustawienia firmy/nadawcy wykorzystywane m.in. przy tworzeniu przesylek.
|
||||
- Kolumny:
|
||||
- `id` (PK, tinyint unsigned),
|
||||
- `company_name` (varchar 200, nullable),
|
||||
- `person_name` (varchar 200, nullable),
|
||||
- `sender_contact_person` (varchar 200, nullable),
|
||||
- `street` (varchar 200, nullable),
|
||||
- `city` (varchar 128, nullable),
|
||||
- `postal_code` (varchar 16, nullable),
|
||||
- `country_code` (char 2, default `PL`),
|
||||
- `phone` (varchar 64, nullable),
|
||||
- `email` (varchar 128, nullable),
|
||||
- `tax_number` (varchar 64, nullable),
|
||||
- `bank_account` (varchar 64, nullable),
|
||||
- `bank_owner_name` (varchar 200, nullable),
|
||||
- `bdo_number` (varchar 20, nullable),
|
||||
- `regon` (varchar 14, nullable),
|
||||
- `court_register` (varchar 128, nullable),
|
||||
- `logo_path` (varchar 255, nullable),
|
||||
- `default_package_length_cm` (decimal 8,1),
|
||||
- `default_package_width_cm` (decimal 8,1),
|
||||
- `default_package_height_cm` (decimal 8,1),
|
||||
- `default_package_weight_kg` (decimal 8,3),
|
||||
- `default_label_format` (varchar 8),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `receipt_configs`
|
||||
- Konfiguracje paragonow (szablony numeracji, ustawienia).
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `name` (varchar 128),
|
||||
- `is_active` (tinyint(1), default 1),
|
||||
- `number_format` (varchar 64, default `PAR/%N/%M/%Y`),
|
||||
- `numbering_type` (enum: monthly, yearly; default monthly),
|
||||
- `is_named` (tinyint(1), default 0) — czy paragon imienny (dane klienta),
|
||||
- `sale_date_source` (enum: order_date, payment_date, issue_date; default issue_date),
|
||||
- `order_reference` (enum: none, orderpro, integration; default none),
|
||||
- `created_at`, `updated_at`.
|
||||
|
||||
### `receipts`
|
||||
- Wystawione paragony ze snapshotem danych.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `order_id` (bigint unsigned, FK -> `orders.id` CASCADE),
|
||||
- `config_id` (int unsigned, FK -> `receipt_configs.id` RESTRICT),
|
||||
- `receipt_number` (varchar 64, UNIQUE),
|
||||
- `issue_date` (datetime),
|
||||
- `sale_date` (date),
|
||||
- `seller_data_json` (json) — snapshot danych sprzedawcy,
|
||||
- `buyer_data_json` (json, nullable) — snapshot danych klienta (jesli imienny),
|
||||
- `items_json` (json) — snapshot pozycji zamowienia,
|
||||
- `total_net` (decimal 12,2),
|
||||
- `total_gross` (decimal 12,2),
|
||||
- `order_reference_value` (varchar 128, nullable),
|
||||
- `created_by` (int unsigned, nullable),
|
||||
- `created_at`.
|
||||
- Indeksy:
|
||||
- `receipts_number_unique` (UNIQUE: `receipt_number`),
|
||||
- `receipts_order_idx` (`order_id`),
|
||||
- `receipts_config_idx` (`config_id`),
|
||||
- `receipts_issue_date_idx` (`issue_date`).
|
||||
- Klucze obce:
|
||||
- `receipts_order_fk`: `order_id` -> `orders.id` (ON DELETE CASCADE),
|
||||
- `receipts_config_fk`: `config_id` -> `receipt_configs.id` (ON DELETE RESTRICT).
|
||||
|
||||
### `receipt_number_counters`
|
||||
- Liczniki numeracji paragonow per konfiguracja i okres.
|
||||
- Kolumny:
|
||||
- `id` (PK, int unsigned, AI),
|
||||
- `config_id` (int unsigned, FK -> `receipt_configs.id` CASCADE),
|
||||
- `year` (smallint unsigned),
|
||||
- `month` (tinyint unsigned, nullable — null dla numeracji rocznej),
|
||||
- `last_number` (int unsigned, default 0).
|
||||
- Indeksy:
|
||||
- `receipt_counters_config_period_unique` (UNIQUE: `config_id`, `year`, `month`).
|
||||
- Klucze obce:
|
||||
- `receipt_counters_config_fk`: `config_id` -> `receipt_configs.id` (ON DELETE CASCADE).
|
||||
|
||||
### `email_mailboxes`
|
||||
- Skrzynki pocztowe SMTP do wysylki wiadomosci e-mail.
|
||||
- Kolumny:
|
||||
- `id` INT UNSIGNED PK AUTO_INCREMENT
|
||||
- `name` VARCHAR(100) NOT NULL — nazwa wyswietlana
|
||||
- `smtp_host` VARCHAR(255) NOT NULL
|
||||
- `smtp_port` SMALLINT UNSIGNED NOT NULL DEFAULT 587
|
||||
- `smtp_encryption` ENUM('tls','ssl','none') NOT NULL DEFAULT 'tls'
|
||||
- `smtp_username` VARCHAR(255) NOT NULL
|
||||
- `smtp_password_encrypted` TEXT NOT NULL — szyfrowane IntegrationSecretCipher (AES-256-CBC+HMAC)
|
||||
- `sender_email` VARCHAR(255) NOT NULL
|
||||
- `sender_name` VARCHAR(200) DEFAULT NULL
|
||||
- `header_html` TEXT DEFAULT NULL — HTML naglowek dolaczany do kazdego e-maila z tej skrzynki
|
||||
- `footer_html` TEXT DEFAULT NULL — HTML stopka dolaczana do kazdego e-maila z tej skrzynki
|
||||
- `is_default` TINYINT(1) NOT NULL DEFAULT 0
|
||||
- `is_active` TINYINT(1) NOT NULL DEFAULT 1
|
||||
- `created_at`, `updated_at` DATETIME
|
||||
|
||||
### `email_templates`
|
||||
- Szablony wiadomosci e-mail z systemem zmiennych.
|
||||
- Kolumny:
|
||||
- `id` INT UNSIGNED PK AUTO_INCREMENT
|
||||
- `name` VARCHAR(200) NOT NULL — nazwa szablonu
|
||||
- `subject` VARCHAR(500) NOT NULL — temat (moze zawierac zmienne)
|
||||
- `body_html` TEXT NOT NULL — tresc HTML (Quill.js output)
|
||||
- `mailbox_id` INT UNSIGNED DEFAULT NULL — FK do email_mailboxes ON DELETE SET NULL
|
||||
- `attachment_1` VARCHAR(50) DEFAULT NULL — typ zalacznika nr 1 (np. 'receipt' = paragon); NULL = brak
|
||||
- `is_active` TINYINT(1) NOT NULL DEFAULT 1
|
||||
- `created_at`, `updated_at` DATETIME
|
||||
- Indeksy: `idx_email_templates_mailbox` (mailbox_id)
|
||||
|
||||
### `email_logs`
|
||||
- Log wyslanych wiadomosci e-mail.
|
||||
- Kolumny:
|
||||
- `id` BIGINT UNSIGNED PK AUTO_INCREMENT
|
||||
- `template_id` INT UNSIGNED DEFAULT NULL — FK do email_templates ON DELETE SET NULL
|
||||
- `mailbox_id` INT UNSIGNED DEFAULT NULL — FK do email_mailboxes ON DELETE SET NULL
|
||||
- `order_id` INT UNSIGNED DEFAULT NULL
|
||||
- `recipient_email` VARCHAR(255) NOT NULL
|
||||
- `recipient_name` VARCHAR(200) DEFAULT NULL
|
||||
- `subject` VARCHAR(500) NOT NULL
|
||||
- `body_html` TEXT NOT NULL — tresc po rozwinieciu zmiennych
|
||||
- `attachments_json` JSON DEFAULT NULL — lista zalacznikow [{name, path, type}]
|
||||
- `status` ENUM('sent','failed','pending') NOT NULL DEFAULT 'pending'
|
||||
- `error_message` TEXT DEFAULT NULL
|
||||
- `sent_at` DATETIME DEFAULT NULL
|
||||
- `created_at` DATETIME
|
||||
- Indeksy: `idx_email_logs_template`, `idx_email_logs_mailbox`, `idx_email_logs_order`, `idx_email_logs_status`, `idx_email_logs_sent_at`
|
||||
|
||||
### `automation_rules`
|
||||
- Reguly automatyzacji (zdarzenie -> warunki -> akcje).
|
||||
- Kolumny:
|
||||
- `id` INT UNSIGNED PK AUTO_INCREMENT
|
||||
- `name` VARCHAR(128) NOT NULL — nazwa reguly
|
||||
- `event_type` VARCHAR(64) NOT NULL — typ zdarzenia (np. 'receipt.created')
|
||||
- `is_active` TINYINT(1) NOT NULL DEFAULT 1
|
||||
- `created_at`, `updated_at` DATETIME
|
||||
- Indeksy:
|
||||
- `auto_rules_event_active_idx` (`event_type`, `is_active`)
|
||||
|
||||
### `automation_conditions`
|
||||
- Warunki reguly automatyzacji (laczenie logiczne AND).
|
||||
- Kolumny:
|
||||
- `id` INT UNSIGNED PK AUTO_INCREMENT
|
||||
- `rule_id` INT UNSIGNED NOT NULL, FK -> `automation_rules.id` ON DELETE CASCADE
|
||||
- `condition_type` VARCHAR(64) NOT NULL — typ warunku (np. 'integration')
|
||||
- `condition_value` JSON NOT NULL — konfiguracja warunku (np. {"integration_ids": [1, 3]})
|
||||
- `sort_order` SMALLINT UNSIGNED NOT NULL DEFAULT 0
|
||||
- Indeksy:
|
||||
- `auto_cond_rule_idx` (`rule_id`)
|
||||
- Klucze obce:
|
||||
- `auto_cond_rule_fk`: `rule_id` -> `automation_rules.id` (ON DELETE CASCADE)
|
||||
|
||||
### `automation_actions`
|
||||
- Akcje do wykonania po spelnieniu warunkow reguly.
|
||||
- Kolumny:
|
||||
- `id` INT UNSIGNED PK AUTO_INCREMENT
|
||||
- `rule_id` INT UNSIGNED NOT NULL, FK -> `automation_rules.id` ON DELETE CASCADE
|
||||
- `action_type` VARCHAR(64) NOT NULL — typ akcji (np. 'send_email')
|
||||
- `action_config` JSON NOT NULL — konfiguracja akcji (np. {"template_id": 5, "recipient": "client"})
|
||||
- `sort_order` SMALLINT UNSIGNED NOT NULL DEFAULT 0
|
||||
- Indeksy:
|
||||
- `auto_act_rule_idx` (`rule_id`)
|
||||
- Klucze obce:
|
||||
- `auto_act_rule_fk`: `rule_id` -> `automation_rules.id` (ON DELETE CASCADE)
|
||||
|
||||
### `automation_execution_logs`
|
||||
- Historia wykonan automatyzacji pokazywana w `Ustawienia > Zadania automatyczne > Historia`.
|
||||
- Kolumny:
|
||||
- `id` BIGINT UNSIGNED PK AUTO_INCREMENT
|
||||
- `event_type` VARCHAR(64) NOT NULL — typ triggera (np. `receipt.created`, `shipment.created`)
|
||||
- `rule_id` INT UNSIGNED NULL — FK do `automation_rules.id` (NULL gdy regula zostala usunieta)
|
||||
- `rule_name` VARCHAR(128) NOT NULL — snapshot nazwy reguly w momencie wykonania
|
||||
- `order_id` INT UNSIGNED NOT NULL — FK do `orders.id`
|
||||
- `execution_status` VARCHAR(16) NOT NULL — wynik (`success`/`failed`)
|
||||
- `result_message` VARCHAR(500) NULL — komunikat wykonania lub bledu
|
||||
- `context_json` JSON NULL — zrzut kontekstu triggera (sanityzowany)
|
||||
- `executed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
- `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
- Indeksy:
|
||||
- `auto_exec_logs_executed_idx` (`executed_at`)
|
||||
- `auto_exec_logs_event_idx` (`event_type`)
|
||||
- `auto_exec_logs_status_idx` (`execution_status`)
|
||||
- `auto_exec_logs_rule_idx` (`rule_id`)
|
||||
- `auto_exec_logs_order_idx` (`order_id`)
|
||||
- Klucze obce:
|
||||
- `auto_exec_logs_rule_fk`: `rule_id` -> `automation_rules.id` (`ON DELETE SET NULL`, `ON UPDATE CASCADE`)
|
||||
- `auto_exec_logs_order_fk`: `order_id` -> `orders.id` (`ON DELETE CASCADE`, `ON UPDATE CASCADE`)
|
||||
|
||||
## Zasady aktualizacji
|
||||
- Po kazdej migracji dopisz:
|
||||
- nowe/zmienione tabele i kolumny,
|
||||
- indeksy i klucze obce,
|
||||
- wplyw na dane i kompatybilnosc wsteczna.
|
||||
|
||||
## Drafty (nieaktywne)
|
||||
- `database/drafts/20260302_orders_schema_v1.sql`:
|
||||
- propozycja normalizacji domeny zamowien pod integracje zewnetrzne (`orders`, `order_items`, `order_status_history`, platnosci, wysylki, dokumenty, notatki, tagi, sync-state),
|
||||
- plik nie jest odpalany przez obecny migrator (`database/migrations/*.sql`).
|
||||
- `bin/deploy_and_seed_orders.php`:
|
||||
- techniczny skrypt wdrozeniowy, ktory aplikuje schema z draftu i opcjonalnie seeduje dane testowe.
|
||||
@@ -1,44 +0,0 @@
|
||||
# Orders Schema Draft (Generic)
|
||||
|
||||
## Context
|
||||
- This is a generic schema proposal for external orders import/sync.
|
||||
- API docs from Apilo were used only as an example of a rich order payload shape.
|
||||
- Target is integration-agnostic storage (no vendor lock in table/column names).
|
||||
|
||||
## Proposed tables
|
||||
- `orders`
|
||||
- `order_addresses`
|
||||
- `order_items`
|
||||
- `order_payments`
|
||||
- `order_shipments`
|
||||
- `order_documents`
|
||||
- `order_notes`
|
||||
- `order_status_history`
|
||||
- `order_tags_dict`
|
||||
- `order_tag_links`
|
||||
- `integration_order_sync_state`
|
||||
|
||||
SQL draft:
|
||||
- [20260302_orders_schema_v1.sql](/C:/visual%20studio%20code/projekty/orderPRO/database/drafts/20260302_orders_schema_v1.sql)
|
||||
|
||||
## Design principles
|
||||
- Keep one row per imported source order in `orders`.
|
||||
- Store child collections in dedicated tables (1:N).
|
||||
- Keep source IDs and selected business scalars as first-class columns.
|
||||
- Keep raw payload snapshots (`payload_json`) for diagnostics and replay safety.
|
||||
- Keep import idempotent:
|
||||
- unique `(integration_id, source_order_id)` in `orders`,
|
||||
- unique child keys per order and source child ID.
|
||||
- Keep event timeline in separate `order_status_history`.
|
||||
|
||||
## Why these extra tables
|
||||
- `order_status_history`: audit + timeline reconstruction + sync debugging.
|
||||
- `integration_order_sync_state`: robust incremental fetch cursor.
|
||||
- `order_tags_*`: proper many-to-many, easy filtering and deduplication.
|
||||
|
||||
## Notes before implementation
|
||||
- Draft is intentionally in `database/drafts` (not auto-run by Migrator).
|
||||
- Before production migration:
|
||||
- confirm source-specific mapping in service layer,
|
||||
- confirm retention policy for `payload_json`,
|
||||
- decide merge strategy for child rows (upsert by source IDs vs hard refresh per sync).
|
||||
@@ -1,207 +0,0 @@
|
||||
# Statusy śledzenia przesyłek — dokumentacja API przewoźników
|
||||
|
||||
## Spis treści
|
||||
- [InPost ShipX API v1](#inpost-shipx-api-v1)
|
||||
- [Apaczka API v2](#apaczka-api-v2)
|
||||
- [Allegro Shipment Management API](#allegro-shipment-management-api)
|
||||
- [Mapowanie na statusy znormalizowane](#mapowanie-na-statusy-znormalizowane)
|
||||
|
||||
---
|
||||
|
||||
## InPost ShipX API v1
|
||||
|
||||
Endpoint: `GET /v1/organizations/{orgId}/shipments/{shipmentId}`
|
||||
Pole statusu: `status` (string)
|
||||
Historia: tablica `tracking_details[]` z polami `status`, `origin_status`, `datetime`, `agency`
|
||||
|
||||
### Tworzenie i przygotowanie
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `created` | Przesyłka utworzona |
|
||||
| `offers_prepared` | Oferty cenowe przygotowane |
|
||||
| `offer_selected` | Oferta wybrana |
|
||||
| `confirmed` | Przesyłka potwierdzona / opłacona |
|
||||
| `dispatched` | Przesyłka nadana (etykieta wygenerowana) |
|
||||
|
||||
### Odbiór od nadawcy
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `collected` | Przesyłka odebrana od nadawcy / wrzucona do paczkomatu |
|
||||
| `taken_by_courier` | Przesyłka odebrana przez kuriera |
|
||||
| `adopted_at_source_branch` | Przyjęta w oddziale źródłowym |
|
||||
|
||||
### Sortowanie i transport
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `adopted_at_sorting_center` | Przyjęta w centrum sortowania |
|
||||
| `sent_from_sorting_center` | Wysłana z centrum sortowania |
|
||||
| `adopted_at_target_sorting_center` | Przyjęta w docelowym centrum sortowania |
|
||||
| `sent_from_target_sorting_center` | Wysłana z docelowego centrum sortowania |
|
||||
| `adopted_at_target_branch` | Przyjęta w oddziale docelowym |
|
||||
|
||||
### Dostarczanie
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `out_for_delivery` | W drodze do odbiorcy / paczkomatu |
|
||||
| `ready_to_pickup` | Gotowa do odbioru w paczkomacie |
|
||||
| `pickup_reminder_sent` | Wysłano przypomnienie o odbiorze |
|
||||
| `delivered` | Dostarczona / odebrana |
|
||||
| `pickup_time_expired` | Czas odbioru z paczkomatu upłynął |
|
||||
|
||||
### Awizo i ponowne doręczenie
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `avizo` | Awizowana (pierwsza próba doręczenia nieudana) |
|
||||
| `claimed` | Odebrana po awizo |
|
||||
| `readdressed` | Przekierowana na inny adres |
|
||||
| `stack_in_box_machine` | Umieszczona w paczkomacie (overflow) |
|
||||
| `stack_parcel_pickup_time_expired` | Czas odbioru ze stack upłynął |
|
||||
|
||||
### Zwrot do nadawcy
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `returned_to_sender` | Zwrócona do nadawcy |
|
||||
| `undelivered` | Niedoręczona |
|
||||
| `undelivered_wrong_address` | Niedoręczona — błędny adres |
|
||||
| `undelivered_incomplete_address` | Niedoręczona — niepełny adres |
|
||||
| `undelivered_unknown_recipient` | Niedoręczona — nieznany odbiorca |
|
||||
| `undelivered_cod_cash_receiver` | Niedoręczona — problem z pobraniem |
|
||||
|
||||
### Anulowanie i wygaśnięcie
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `cancelled` | Anulowana |
|
||||
| `expired` | Wygasła |
|
||||
|
||||
### Inne / specjalne
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `ready_to_pickup_from_branch` | Gotowa do odbioru z oddziału |
|
||||
| `ready_to_pickup_from_pok` | Gotowa do odbioru z POK |
|
||||
| `oversized` | Przesyłka ponadgabarytowa |
|
||||
| `missing` | Przesyłka zagubiona |
|
||||
| `delay_in_delivery` | Opóźnienie w dostawie |
|
||||
| `redirect_to_box` | Przekierowana do paczkomatu |
|
||||
| `stack_in_customer_service_point` | Umieszczona w punkcie obsługi |
|
||||
| `pickup_reminder_sent_address` | Przypomnienie wysłane na adres |
|
||||
|
||||
### Uwagi
|
||||
- InPost okresowo dodaje nowe statusy — warto sprawdzać `tracking_details` zamiast polegać na zamkniętej liście
|
||||
- W `tracking_details` każdy wpis zawiera: `status`, `origin_status`, `datetime`, `agency`
|
||||
- Dokładna lista może się różnić w zależności od typu usługi (paczkomat vs kurier vs POP)
|
||||
|
||||
---
|
||||
|
||||
## Apaczka API v2
|
||||
|
||||
Endpoint: `GET /api/v2/order/{orderId}/`
|
||||
Pole statusu: `status` (integer)
|
||||
Autentykacja: `app_id` + podpis HMAC-SHA256 z `app_secret`
|
||||
|
||||
### Statusy zamówienia
|
||||
|
||||
| Wartość | Nazwa | Opis PL |
|
||||
|---------|-------|---------|
|
||||
| `0` | PENDING | Zamówienie utworzone, oczekuje na przetworzenie |
|
||||
| `1` | CONFIRMED | Zamówienie potwierdzone |
|
||||
| `2` | PICKED_UP | Przesyłka odebrana przez kuriera |
|
||||
| `3` | IN_TRANSIT | Przesyłka w transporcie |
|
||||
| `4` | OUT_FOR_DELIVERY | Przesyłka w doręczeniu |
|
||||
| `5` | DELIVERED | Przesyłka doręczona |
|
||||
| `6` | RETURNED | Przesyłka zwrócona do nadawcy |
|
||||
| `7` | CANCELLED | Zamówienie anulowane |
|
||||
| `8` | ERROR | Błąd zamówienia |
|
||||
| `9` | WAITING_FOR_PICKUP | Oczekuje na odbiór w punkcie |
|
||||
| `10` | REDIRECT | Przesyłka przekierowana |
|
||||
|
||||
### Dodatkowe pola w odpowiedzi
|
||||
|
||||
- `tracking_number` — numer śledzenia
|
||||
- `tracking_status` — szczegółowy status śledzenia (może różnić się od `status`)
|
||||
- `service_id` — identyfikator usługi kurierskiej
|
||||
|
||||
### Uwagi
|
||||
- Apaczka nie publikuje pełnej dokumentacji API publicznie — dostęp wymaga konta
|
||||
- Powyższa lista wymaga weryfikacji z oficjalną dokumentacją (panel.apaczka.pl)
|
||||
- Endpoint trackingu: `GET /api/v2/order/{orderId}/tracking/` (jeśli dostępny)
|
||||
|
||||
---
|
||||
|
||||
## Allegro Shipment Management API
|
||||
|
||||
Endpoint: `GET /shipment-management/shipments/{shipmentId}`
|
||||
Pole statusu: `status` (string)
|
||||
|
||||
### Statusy przesyłki (Shipment Management)
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `NEW` | Przesyłka utworzona, nie przekazana przewoźnikowi |
|
||||
| `READY_TO_SHIP` | Etykieta wygenerowana, oczekuje na odbiór/nadanie |
|
||||
| `IN_TRANSIT` | Przesyłka odebrana przez przewoźnika |
|
||||
| `DELIVERED` | Przesyłka doręczona |
|
||||
| `CANCELLED` | Przesyłka anulowana |
|
||||
| `ERROR` | Błąd przetwarzania |
|
||||
| `RETURNED` | Przesyłka zwrócona do nadawcy |
|
||||
|
||||
### Statusy realizacji zamówienia (Order Fulfillment)
|
||||
|
||||
Endpoint: `GET /order/checkout-forms/{checkoutFormId}`
|
||||
Pole: `fulfillment.status`
|
||||
|
||||
| Status | Opis PL |
|
||||
|--------|---------|
|
||||
| `NEW` | Zamówienie złożone, nie przetworzone |
|
||||
| `PROCESSING` | Sprzedawca przetwarza zamówienie |
|
||||
| `READY_FOR_SHIPMENT` | Spakowane, oczekuje na wysyłkę |
|
||||
| `SENT` | Wysłane (numer śledzenia podany) |
|
||||
| `DELIVERED` | Potwierdzone doręczenie |
|
||||
| `CANCELLED` | Zamówienie anulowane |
|
||||
|
||||
### Ważne ograniczenia
|
||||
- **Allegro NIE ma dedykowanego API śledzenia przesyłek** (brak endpointu typu `/tracking/{trackingNumber}`)
|
||||
- Shipment Management API daje statusy TYLKO dla przesyłek utworzonych przez zintegrowanych przewoźników Allegro
|
||||
- Dla szczegółowego śledzenia trzeba odpytywać **API przewoźnika bezpośrednio** (InPost, DPD, DHL, etc.)
|
||||
- Dla ręcznie wpisanych numerów śledzenia — brak automatycznego trackingu przez Allegro
|
||||
|
||||
---
|
||||
|
||||
## Mapowanie na statusy znormalizowane
|
||||
|
||||
System orderPRO używa dwupoziomowego systemu statusów:
|
||||
1. **`delivery_status`** — znormalizowany status (dla UI, filtrów, logiki)
|
||||
2. **`delivery_status_raw`** — surowy status z API przewoźnika
|
||||
|
||||
### Tabela mapowania
|
||||
|
||||
| Znormalizowany | InPost ShipX | Apaczka | Allegro SM |
|
||||
|----------------|-------------|---------|------------|
|
||||
| `unknown` | *(brak danych)* | *(brak danych)* | *(brak danych)* |
|
||||
| `created` | `created`, `offers_prepared`, `offer_selected` | `0` (PENDING) | `NEW` |
|
||||
| `confirmed` | `confirmed`, `dispatched` | `1` (CONFIRMED) | `READY_TO_SHIP` |
|
||||
| `in_transit` | `collected`, `taken_by_courier`, `adopted_at_sorting_center`, `sent_from_sorting_center`, `adopted_at_target_sorting_center`, `sent_from_target_sorting_center`, `adopted_at_target_branch`, `adopted_at_source_branch` | `2` (PICKED_UP), `3` (IN_TRANSIT) | `IN_TRANSIT` |
|
||||
| `out_for_delivery` | `out_for_delivery` | `4` (OUT_FOR_DELIVERY) | — |
|
||||
| `ready_for_pickup` | `ready_to_pickup`, `ready_to_pickup_from_branch`, `ready_to_pickup_from_pok`, `stack_in_box_machine`, `stack_in_customer_service_point` | `9` (WAITING_FOR_PICKUP) | — |
|
||||
| `delivered` | `delivered`, `claimed` | `5` (DELIVERED) | `DELIVERED` |
|
||||
| `returned` | `returned_to_sender`, `undelivered`, `undelivered_wrong_address`, `undelivered_incomplete_address`, `undelivered_unknown_recipient`, `undelivered_cod_cash_receiver` | `6` (RETURNED) | `RETURNED` |
|
||||
| `cancelled` | `cancelled`, `expired` | `7` (CANCELLED) | `CANCELLED` |
|
||||
| `problem` | `avizo`, `pickup_time_expired`, `stack_parcel_pickup_time_expired`, `missing`, `delay_in_delivery`, `oversized` | `8` (ERROR), `10` (REDIRECT) | `ERROR` |
|
||||
|
||||
### Uwagi do mapowania
|
||||
- Status `problem` zbiera wszystkie nietypowe sytuacje wymagające uwagi (awizo, zagubienie, opóźnienie)
|
||||
- Surowy status (`delivery_status_raw`) zawsze zachowuje oryginalną wartość z API
|
||||
- Dla przesyłek `manual` — `delivery_status` zawsze `unknown` (brak automatycznego trackingu)
|
||||
- Mapowanie powinno być zaimplementowane jako stałe w klasie per provider (łatwe do rozszerzenia)
|
||||
|
||||
---
|
||||
|
||||
*Dokument utworzony: 2026-03-23*
|
||||
*Źródła: InPost ShipX API docs, Apaczka API v2 docs (ograniczony dostęp), Allegro REST API docs*
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user