Files
orderPRO/DOCS/TECH_CHANGELOG.md
2026-04-04 18:20:13 +02:00

906 lines
73 KiB
Markdown

# Tech Changelog
## 2026-04-04 (Email templates - split list/form view)
- `EmailTemplateController`:
- dodano osobne endpointy widokowe `create()` i `edit()` dla formularza szablonu,
- wydzielono render formularza do `renderForm(...)`,
- `save()` przy bledzie walidacji/CSRF wraca na odpowiednia podstrone formularza (`/create` albo `/edit?id=`), zamiast do listy.
- Routing:
- dodano trasy `GET /settings/email-templates/create` oraz `GET /settings/email-templates/edit`.
- Widoki:
- `resources/views/settings/email-templates.php` zawiera tylko liste szablonow i akcje tabeli,
- dodano `resources/views/settings/email-templates-form.php` jako osobna podstrone create/edit (Quill, zmienne, preview).
- Brak zmian schematu bazy danych.
## 2026-04-04 (Phase 69 - Allegro Tracking English Statuses, Plan 01)
- `DeliveryStatus::slugifyAllegroDescription()`:
- dodano obsluge prefiksow EN (`Parcel has been ...`, `Parcel is ...`, `Courier has ...`) przed slugifikacja.
- `DeliveryStatus`:
- rozszerzono `ALLEGRO_EDGE_MAP` o slugi EN i ich mapowanie na statusy biznesowe (m.in. `awaiting_pick_up`, `delivered`, `dispatched`, `released_for_delivery`),
- rozszerzono `ALLEGRO_EDGE_DESCRIPTIONS` o opisy EN/PL dla nowych slugow,
- rozszerzono `guessStatusFromDescription()` o keyword fallback dla statusow EN (delivery/return/cancel/pickup/transit/confirmed/created/problem).
- Dodano test jednostkowy `tests/Unit/DeliveryStatusTest.php` pokrywajacy:
- mapowanie EN (`Parcel is awaiting pick-up`, `Parcel has been delivered`),
- fallback EN (`released for delivery`),
- regresje mapowania PL (`Przesylka zostala dostarczona`).
- Brak zmian schematu bazy danych.
## 2026-04-03 (Phase 64 - Receipt Datetime Precision, Plan 01)
- Migracja `20260403_000076_alter_receipts_issue_date_to_datetime.sql`: ALTER TABLE receipts MODIFY issue_date DATETIME NOT NULL.
- `ReceiptController::store()`: zapis issue_date jako Y-m-d H:i:s, konwersja z formatu datetime-local (T separator).
- `AccountingController::toTableRow()` i `export()`: formatowanie issue_date do YYYY-MM-DD HH:MM (substr 0-16).
- `receipt-create.php`: input type=datetime-local z domyslna biezaca data+czas.
- `receipts/show.php`, `receipts/print.php`, `orders/show.php`: wyswietlanie issue_date z godzina (substr 0-16).
## 2026-04-01 (Phase 63 - Order Item Personalization, Plan 01)
- Migracja `20260401_000075_add_personalization_to_order_items.sql`: kolumna `personalization TEXT NULL` w `order_items`.
- `ShopproOrderMapper::extractPersonalization()`: ekstrakcja `custom_fields` z odpowiedzi shopPRO API, konwersja HTML na czysty tekst (strip_tags, html_entity_decode, br->newline).
- `ShopproOrderMapper::mapItems()`: dodanie klucza `personalization` do mapowanego itemu.
- `OrderImportRepository::replaceItems()`: zapis `personalization` do INSERT query.
- `resources/views/orders/show.php`: warunkowe wyswietlanie personalizacji pod nazwa produktu (div.item-personalization z etykieta i liniami tekstu, escape via `e()`).
- `resources/scss/app.scss`: style `.item-personalization` (kompaktowy blok, border-left, muted colors).
## 2026-03-31 (Phase 60 - Order Status Aged Event, Plan 01)
- Migracja `20260331_000074_seed_order_status_aged_cron.sql`: seed cron schedule `order_status_aged` co 3600s.
- `OrderStatusAgedService`: skanuje zamowienia w danym statusie od X dni (query HAVING MAX(changed_at) na `order_status_history`), limit 100/regule, trigger `order.status_aged`.
- `OrderStatusAgedHandler`: cron handler delegujacy do `OrderStatusAgedService::scan()`.
- `CronHandlerFactory`: rejestracja handlera `order_status_aged`.
- `AutomationController`: dodano `order.status_aged` do `ALLOWED_EVENTS`, `days_in_status` do `ALLOWED_CONDITION_TYPES`, `parseConditionValue` + branch `days_in_status`.
- `AutomationService::evaluateDaysInStatusCondition()`: ewaluacja `context.days_in_status >= value.days`.
- `resources/views/automation/form.php`: opcja "Minelo X dni od zmiany statusu" w zdarzeniach, "Liczba dni w statusie" w warunkach z polem numerycznym.
- `public/assets/js/modules/automation-form.js`: `buildDaysInStatusInput()`, opcja `days_in_status` w `addCondition()` i `onConditionTypeChange()`.
## 2026-03-31 (Phase 59 - Order Status Automation Event, Plan 01)
- `AutomationController`: dodano `order.status_changed` do `ALLOWED_EVENTS`, `order_status` do `ALLOWED_CONDITION_TYPES`, `parseConditionValue` + branch `order_status` (walidacja kodow vs DB), `buildRuleFromRequest` + branch `order_status`.
- `AutomationService::evaluateOrderStatusCondition()`: ewaluacja warunku order_status — porownanie `new_status` z context vs dozwolone `order_status_codes`.
- `AutomationService::handleUpdateOrderStatus()`: pobiera old_status przed zmiana, emituje chain event `order.status_changed` przez `emitEvent()` (tylko przy realnej zmianie statusu).
- `OrdersController::changeStatus()`: pobiera old_status przed `updateOrderStatus()`, emisja `order.status_changed` po udanej zmianie (try/catch, non-blocking).
- `resources/views/automation/form.php`: opcja "Zmiana statusu zamowienia" w zdarzeniach, "Status zamowienia" w warunkach z checkboxami aktywnych statusow.
- `resources/views/automation/index.php`: dodano etykiety `payment.status_changed` i `order.status_changed` do `$eventLabels`.
- `public/assets/js/modules/automation-form.js`: `buildOrderStatusCheckboxes()`, opcja `order_status` w `addCondition()` i `onConditionTypeChange()`.
## 2026-03-30 (Phase 58 - Automation Form Preserve, Plan 01)
- `AutomationController::store()` i `update()`: re-render formularza z danymi z request zamiast redirect przy bledzie walidacji.
- `AutomationController::buildRuleFromRequest()`: buduje tablice `$rule` z POST data w formacie oczekiwanym przez `form.php`.
- `AutomationController::renderForm()`: nowy parametr `$errorMessage` — priorytet nad Flash.
- `resources/views/automation/form.php`: `$isEdit` sprawdza `isset($rule['id'])` (nie `$rule !== null`), conditions/actions wyciagane z `$rule` niezaleznie od `$isEdit`.
## 2026-03-30 (Phase 57 - Payment Automation Event, Plan 01)
- `AutomationController`: dodano `payment.status_changed` do `ALLOWED_EVENTS`, `payment_status` do `ALLOWED_CONDITION_TYPES`, stala `PAYMENT_STATUS_OPTIONS` (0/1/2), parseConditions dla `payment_status_keys`.
- `AutomationService::evaluatePaymentStatusCondition()`: ewaluacja warunku payment_status — porownanie `new_payment_status` z context vs dozwolone status_keys.
- `OrdersController::addPayment()`: emisja `payment.status_changed` po zapisie platnosci (try/catch, non-blocking).
- `ShopproPaymentStatusSyncService::syncSingleOrderPayment()`: emisja `payment.status_changed` po zmianie payment_status w cron sync (tylko przy realnej zmianie).
- `CronHandlerFactory`: przeniesiono tworzenie `$automationService` przed `$shopproPaymentSyncService`, przekazano jako zależność.
- `resources/views/automation/form.php`: opcja "Zmiana statusu platnosci" w zdarzeniach, "Status platnosci" w warunkach z checkboxami (Nieoplacone/Czesciowo oplacone/Oplacone).
- `public/assets/js/modules/automation-form.js`: `buildPaymentStatusCheckboxes()`, opcja w `addCondition()` i `onConditionTypeChange()`.
## 2026-03-30 (Phase 56 - Order Payments, Plan 01)
- Migracja `20260330_000073_create_order_payments_table.sql`: tabela `order_payments` (id, order_id, source_payment_id, external_payment_id, payment_type_id, payment_date, amount, currency, comment, payload_json) + idempotentne dodanie kolumn `total_with_tax`, `total_paid`, `external_payment_type_id` do `orders`.
- `OrdersRepository::addPayment()`: INSERT do `order_payments`, przeliczenie `total_paid` i `payment_status` na `orders`.
- `OrdersRepository::findOrderSourceInfo()`: pobiera `source`, `integration_id`, `source_order_id` dla push do shopPRO.
- `OrdersController::addPayment()`: POST `/orders/{id}/payment/add` — walidacja, zapis platnosci, activity log, push do shopPRO.
- `OrdersController::pushPaymentToShoppro()`: po dodaniu platnosci pokrywajacej calosc — PUT `set_paid` do shopPRO API.
- `ShopproApiClient::setOrderPaid()`: PUT `/api.php?endpoint=orders&action=set_paid&id={sourceOrderId}`.
- `resources/views/orders/show.php`: przycisk "Dodaj platnosc", formularz inline (kwota, typ, data, komentarz), AJAX submit z reload.
- Style: `.payment-add-form` w `resources/scss/app.scss`.
## 2026-03-28 (Phase 51 - Email HTML Layout, Plan 01)
- Migracja `20260328_000001_add_html_layout_to_email_mailboxes.sql`: kolumny `header_html` TEXT NULL i `footer_html` TEXT NULL w `email_mailboxes`.
- `EmailMailboxRepository::save()`: zapis `header_html`/`footer_html` w INSERT i UPDATE.
- `EmailMailboxController::save()`: pobiera `header_html`/`footer_html` z POST i przekazuje do repozytorium.
- `resources/views/settings/email-mailboxes.php`: sekcja "Szablon wiadomosci" z dwoma edytorami Quill.js (email-safe toolbar: bold, italic, underline, kolor, wyrownanie, listy, link, image, naglowki h1-h3). Sync innerHTML do hidden inputs przy submit.
- `EmailSendingService`: nowa metoda `composeBody()` — sklada header + body + footer. Uzywa variableResolver na header/footer. Uzyta w `send()` i `preview()`. NULL/pusty header/footer = pomijany.
## 2026-03-28 (Phase 50 - Allegro Shipment Waybill Push, Plan 01)
- `AllegroShipmentService`:
- po sukcesie `checkCreationStatus(...)` (gdy jest `tracking_number`) probuje dopiac przesylke do checkout form Allegro,
- wykorzystuje `AllegroApiClient::addShipmentToOrder(...)` (`POST /order/checkout-forms/{id}/shipments`),
- push wykonywany tylko dla zamowien `orders.source='allegro'` i niepustego `source_order_id`,
- retry pushu po `ALLEGRO_HTTP_401` z ponownym `tokenManager->resolveToken()`,
- bledy pushu traktowane jako niekrytyczne (lokalna paczka pozostaje utworzona).
- `AllegroShipmentService::downloadLabel(...)`:
- przy fallbackowym dopelnieniu trackingu (gdy brak numeru w rekordzie paczki) wykonuje ten sam warunkowy push waybilla do Allegro.
- Testy:
- dodano `tests/Unit/AllegroShipmentServiceTest.php` (scenariusze: push dla Allegro, brak pushu dla nie-Allegro, fallback przy bledzie API, retry po 401).
## 2026-03-28 (Public HTTPS cron endpoint)
- Dodano publiczny endpoint triggera crona:
- `GET /cron?token=<CRON_PUBLIC_TOKEN>`
- dodatkowo kompatybilny wariant sciezki: `GET /cron/token=<CRON_PUBLIC_TOKEN>`.
- Token jest walidowany przez `hash_equals` i pochodzi z nowej zmiennej srodowiskowej `CRON_PUBLIC_TOKEN`.
- Endpoint uruchamia `CronRunner` z limitem z ustawienia `cron_web_limit`.
- `Application::maybeRunCronOnWeb(...)` ignoruje teraz sciezki `/cron` i `/cron/*`, aby uniknac podwojnego triggera.
- Zaktualizowano `.env.example` o `CRON_PUBLIC_TOKEN`.
## 2026-03-28 (Hotfix - Apaczka pickup day fallback)
- `ApaczkaShipmentService`:
- dodano automatyczny retry `order_send` dla bledu API `Pickup not available for selected day`,
- rozszerzono detekcje bledu o wariant komunikatu: `We're sorry, you can't place an order today. Change its date to another working day.`,
- fallback dotyczy tylko `pickup.type=COURIER`,
- kazdy retry przesuwa `pickup.date` na kolejny dzien roboczy (`normalizeCourierPickupDate`) i ponawia wysylke,
- limit fallbacku: do 7 kolejnych dni, potem zwracany jest oryginalny blad API.
## 2026-03-28 (Phase 49 - Automation History Tab, Plan 01 - rozszerzenie akcji)
- Rozszerzono automatyzacje o nowy typ akcji `update_order_status` (UI: `Zmiana statusu zamowienia`).
- `AutomationController`:
- `ALLOWED_ACTION_TYPES` zawiera `update_order_status`,
- waliduje i parsuje `order_status_code` tylko do aktywnych statusow z `order_statuses`.
- `AutomationRepository`:
- nowa metoda `listActiveOrderStatuses()` zwracajaca aktywne statusy (`code`, `name`) sortowane rosnaco po nazwie.
- `resources/views/automation/form.php` i `public/assets/js/modules/automation-form.js`:
- nowa opcja akcji z wyborem docelowego statusu zamowienia.
- `AutomationService`:
- nowy handler `handleUpdateOrderStatus(...)`,
- wykonanie zmiany przez `OrdersRepository::updateOrderStatus(...)` z aktorem systemowym `Automatyzacja: <nazwa reguly>`,
- fallback log aktywnosci `automation_order_status_failed` gdy zmiana nie powiedzie sie.
## 2026-03-28 (Phase 49 - Automation History Tab, Plan 01)
- `Ustawienia > Zadania automatyczne` (`/settings/automation`) rozdzielone na 2 taby:
- `Ustawienia` - obecne zarzadzanie regulami,
- `Historia` - log wykonan automatyzacji z filtrowaniem i paginacja.
- Dodano migracje `20260328_000072_create_automation_execution_logs_table.sql`:
- nowa tabela `automation_execution_logs` (event, regula, order, status, wynik, context, timestamp),
- indeksy pod filtry historii,
- seed harmonogramu crona `automation_history_cleanup` (co 24h).
- Nowe klasy backend:
- `AutomationExecutionLogRepository` - zapis/listowanie/paginacja/licznik historii + purge retencji,
- `AutomationHistoryCleanupHandler` - usuwanie wpisow starszych niz konfigurowalna liczba dni (domyslnie 30).
- `AutomationService::trigger(...)` zapisuje wpis historii per wykonana regula:
- `success` po poprawnym wykonaniu akcji,
- `failed` przy wyjatku w wykonaniu reguly.
- `AutomationController::index(...)` obsluguje filtry historii (`history_*`) i paginacje (`history_page`), zachowujac kompatybilnosc listy regul.
- UI historii wykorzystuje kompaktowy formularz filtrow i paginacje z zachowaniem aktywnych parametrow.
## 2026-03-28 (Phase 48 - Email Template Shipment Variables, Plan 01)
- Email templates (`/settings/email-templates`):
- dodano zmienne `{{przesylka.numer}}` i `{{przesylka.link_sledzenia}}` w `EmailTemplateController::VARIABLE_GROUPS`,
- rozszerzono `SAMPLE_DATA` do preview o przykladowy numer i URL sledzenia.
- `VariableResolver`:
- otrzymuje zaleznosc `ShipmentPackageRepository`,
- pobiera najnowsza paczke (`findLatestByOrderId(order_id)`),
- mapuje `przesylka.numer` i `przesylka.link_sledzenia`,
- link jest liczony przez `DeliveryStatus::trackingUrl(provider, tracking_number, carrier_id)`.
- DI:
- `routes/web.php` i `CronHandlerFactory` przekazuja `ShipmentPackageRepository` do `VariableResolver`.
- Zachowanie brzegowe:
- brak paczki lub brak numeru trackingowego nie psuje renderu - zmienne przesylki zwracaja pusty string.
## 2026-03-28 (Phase 47 - Shipment Creation Automation, Plan 01)
- Automatyzacja:
- dodano nowe zdarzenie `shipment.created` (UI: `Utworzenie przesylki`),
- trigger jest uruchamiany natychmiast po sukcesie `ShipmentController::create()` oraz `ShipmentController::createManual()`,
- kontekst triggera zawiera m.in. `package_id`, `provider`, `tracking_number`, `package_status`, `delivery_status`.
- Dodano nowy typ akcji automatyzacji `update_shipment_status` (UI: `Zmiana statusu przesylki`):
- walidacja konfiguracji przez `AutomationController` (`shipment_status_key` -> `status_key`),
- wykonanie przez `AutomationService::handleUpdateShipmentStatus(...)`,
- aktualizacja `delivery_status` tylko przy realnej zmianie (bez falszywych triggerow),
- po zmianie statusu emitowane jest `shipment.status_changed` z kontekstem zmiany.
- Rozszerzono `AutomationService` o zaleznosc `ShipmentPackageRepository`:
- nowa metoda pomocnicza `ShipmentPackageRepository::findLatestByOrderId(int): ?array` (fallback wyboru paczki dla akcji).
- UI automatyzacji (`resources/views/automation/form.php`, `resources/views/automation/index.php`, `public/assets/js/modules/automation-form.js`) rozszerzono o:
- event `Utworzenie przesylki`,
- akcje `Zmiana statusu przesylki` z wyborem docelowego statusu biznesowego.
- Aktualizacja DI:
- `routes/web.php` i `src/Modules/Cron/CronHandlerFactory.php` przekazuja `ShipmentPackageRepository` do `AutomationService`,
- `ShipmentController` otrzymuje `AutomationService` jako zaleznosc konstruktora.
## 2026-03-28 (Allegro Status Push - orderPRO -> Allegro)
- Zaimplementowano kierunek synchronizacji statusow `orderpro_to_allegro` w `AllegroStatusSyncService`.
- `AllegroStatusSyncService`:
- pobiera reczne zmiany statusow (`order_status_history.change_source=manual`) dla zamowien Allegro,
- buduje reverse mapping (`orderpro_status_code -> allegro_status_code`) na podstawie `allegro_order_status_mappings`,
- pushuje statusy do API Allegro i raportuje `pushed/skipped/failed`,
- aktualizuje kursor `integration_order_sync_state.last_status_pushed_at`.
- Nowa metoda `AllegroApiClient::updateCheckoutFormFulfillment()`:
- PUT `/order/checkout-forms/{id}/fulfillment`,
- body JSON: `{"status":"<ALLEGRO_STATUS>"}`.
- `AllegroOrderSyncStateRepository`: dodano obsluge kursora push (`getLastStatusPushedAt`, `updateLastStatusPushedAt`).
- `AllegroStatusMappingRepository`: dodano reverse map builder `buildOrderproToAllegroMap()`.
- UI `Ustawienia > Integracje > Allegro > Ustawienia`:
- odblokowano wybor opcji `orderPRO -> Allegro` (usunieto `disabled` i dopisek `(wkrotce)`),
- zaktualizowano opis hintu kierunku synchronizacji.
- Dodano testy jednostkowe `tests/Unit/AllegroStatusSyncServiceTest.php` dla scenariuszy push/skip/fail/retry-401.
## 2026-03-27 (ShopPRO Status Push — orderPRO -> shopPRO)
- Zaimplementowano kierunek synchronizacji statusow `orderpro_to_shoppro` w `ShopproStatusSyncService`.
- Nowa metoda `ShopproApiClient::updateOrderStatus()` — PUT `/api.php?endpoint=orders&action=change_status&id={id}`.
- Wydzielono wspolna metode `executeRequest()` w `ShopproApiClient` (reuse GET/PUT).
- `ShopproStatusSyncService::syncPushDirection()`:
- buduje reverse mapping (orderpro_status_code -> shoppro_status_code),
- query `order_status_history` po zmianach `change_source=manual` po kursore,
- pushuje status do shopPRO API, aktualizuje kursor `last_status_pushed_at`.
- Migracja: `20260327_000071_add_last_status_pushed_at_to_sync_state.sql` — kolumna `last_status_pushed_at` w `integration_order_sync_state`.
- `ShopproOrderSyncStateRepository`: nowe metody `getLastStatusPushedAt()`, `updateLastStatusPushedAt()`.
- `CronHandlerFactory`: zaktualizowana kompozycja `ShopproStatusSyncService` z nowymi zaleznosciami.
## 2026-03-25 (Automation - new action "Wystaw paragon")
- Dodano nowy typ akcji automatyzacji: `issue_receipt` (Wystaw paragon).
- Konfiguracja akcji wymaga kompletu parametrow:
- `receipt_config_id` (aktywna konfiguracja paragonu),
- `issue_date_mode` (`today` / `order_date` / `payment_date`),
- `duplicate_policy` (`skip_if_exists` / `allow_duplicates`).
- `AutomationController`:
- rozszerzono `ALLOWED_ACTION_TYPES`,
- dodano walidacje i parsowanie configu akcji `issue_receipt`,
- formularz dostaje aktywne konfiguracje paragonow i slowniki opcji.
- `resources/views/automation/form.php` i `public/assets/js/modules/automation-form.js`:
- nowa pozycja akcji `Wystaw paragon`,
- dynamiczne pola dla parametrow akcji.
- `AutomationService`:
- wykonuje automatyczne wystawienie paragonu przez `ReceiptRepository`,
- zapisuje activity log sukcesu/pominiecia/bledu,
- ma ochrone przed petla dla eventu `receipt.created` (akcja `issue_receipt` jest pomijana i logowana),
- obsluguje polityke duplikatow.
- Aktualizacja DI:
- `routes/web.php` i `CronHandlerFactory` przekazuja do `AutomationService` zaleznosci `ReceiptRepository` i `ReceiptConfigRepository`.
- Dodano systemowy mechanizm chain automation dla obecnych i przyszlych zdarzen:
- wspolny kontekst lancucha (`__automation_chain`) propagowany miedzy kolejnymi triggerami,
- `emitEvent(...)` jako bezpieczny mechanizm emitowania kolejnych eventow z akcji,
- ochrona anty-petla przez deduplikacje wykonania `event_type + rule_id` w jednym lancuchu,
- limit glebokosci lancucha (`MAX_CHAIN_DEPTH`) i limit historii wykonan (`MAX_CHAIN_EXECUTIONS`).
## 2026-03-25 (Phase 43 - Print Queue Entry Removal, Plan 01)
- Dodano usuwanie wpisu kolejki wydruku:
- `PrintJobRepository::deleteById(int): bool`,
- `PrintSettingsController::deleteJob(Request): Response`,
- route `POST /settings/printing/jobs/delete` w `routes/web.php`.
- Widok `resources/views/settings/printing.php` ma przycisk `Usun` dla wpisu kolejki z potwierdzeniem `window.OrderProAlerts.confirm(...)`.
- Dodano style `print-queue-actions` i `print-queue-delete-form` w `resources/scss/modules/_printing.scss` + rebuild `public/assets/css/app.css`.
## 2026-03-25 (Phase 42 - Automation Shipment Status Event, Plan 01)
- Rozszerzono automatyzacje o event `shipment.status_changed` i condition type `shipment_status`:
- `AutomationController` dopuszcza nowe event/condition i waliduje `status_keys`,
- `AutomationService::trigger()` przyjmuje kontekst triggera i ocenia warunki statusowe.
- UI automatyzacji (`resources/views/automation/form.php`, `index.php`, `public/assets/js/modules/automation-form.js`) obsluguje:
- wybor eventu `Zmiana statusu przesylki`,
- nowy warunek biznesowy statusu przesylki:
- zarejestrowana -> `created|confirmed`,
- do odbioru -> `ready_for_pickup`,
- nadana w punkcie -> `confirmed|in_transit`,
- odebrana -> `delivered`,
- anulowana -> `cancelled`,
- nieodebrana -> `problem`,
- odebrana (zwrot) -> `returned`.
- `ShipmentTrackingHandler` triggeruje `AutomationService->trigger('shipment.status_changed', orderId, context)` tylko gdy `delivery_status` realnie sie zmieni.
- `CronHandlerFactory` buduje `AutomationService` dla procesu cron i przekazuje go do `ShipmentTrackingHandler`; konstruktor dostaje teraz dodatkowo `basePath` (zmiany w `bin/cron.php` i `Application::maybeRunCronOnWeb`).
## 2026-03-25 (Phase 41 - Allegro Import Log Rationalization, Plan 01)
- `AllegroOrderImportService::importSingleOrder(...)` przyjmuje trigger (`manual_import`, `orders_sync`, `status_sync`) i zapisuje go w `details_json` logu `import` (`trigger`, `trigger_label`, `source_updated_at`).
- `AllegroOrdersSyncService` i `AllegroStatusSyncService` przekazuja jawny trigger do importu.
- `OrdersRepository::shouldSkipDuplicateImportActivity(...)` deduplikuje kolejne wpisy `import`, gdy ostatni wpis ma ten sam `source_order_id`, `source_updated_at` i `trigger` (z wyjatkiem nowo utworzonego zamowienia).
- Widok historii zamowienia (`resources/views/orders/show.php`) pokazuje przy wpisie `import` skondensowany kontekst triggera i `source_updated_at`.
## 2026-03-25 (Phase 40 - Remove Order List Bulk Print, Plan 01)
- Usunieto akcje bulk print z listy zamowien:
- OrdersController::index() nie wystawia juz przycisku Drukuj etykiety w header_actions.
- resources/views/orders/list.php nie zawiera juz skryptu wysylajacego bulk request do drukarki.
- Wycofano endpoint i logike backendowa bulk print:
- usunieto trase POST /api/print/jobs/bulk z routes/web.php,
- usunieto metode PrintApiController::bulkCreateJobs(...),
- usunieto nieuzywana metode PrintJobRepository::findPackagesWithLabelsByOrderIds(...).
- Pozostawiono bez zmian druk pojedynczej etykiety przez POST /api/print/jobs oraz API klienta Windows (pending/download/complete).
## 2026-03-25 (Phase 30 - Button Primary Color Distinction, Plan 01)
- Rozdzielono palete kolorow naglowkow i przyciskow akcji w warstwie SCSS:
- `resources/scss/shared/_ui-components.scss` ma nowe tokeny `--c-action-primary`, `--c-action-primary-dark`, `--focus-ring-action`,
- `btn--primary` i `btn:focus-visible` korzystaja z tokenow akcji, bez zmiany koloru `section-title` opartego o `--c-primary`.
- `resources/scss/modules/_printing.scss`: `btn--outline-primary` zostal przepiety z twardego niebieskiego (`#4a90d9`) na token `--c-action-primary`.
- Przebudowano assety frontendowe komenda `npm run build:css`, co zaktualizowalo `public/assets/css/app.css`.
## 2026-03-23 (Phase 26 — Manual Tracking Number, Plan 01)
- Nowa metoda `ShipmentPackageRepository::createManual(int, string, ?string): int` — INSERT do `shipment_packages` z `provider='manual'`, `status='created'`.
- Nowa metoda `ShipmentController::createManual(Request): Response` — endpoint `POST /orders/{id}/shipment/manual`, walidacja CSRF + tracking_number, activity log `shipment_manual`.
- Nowa route w `routes/web.php`: `POST /orders/{id}/shipment/manual`.
- `resources/views/orders/show.php` — formularz inline do dodawania recznego numeru przesylki w zakladce Przesylki; zmienione wyswietlanie przesylek manualnych (status "Dodana recznie", przewoznik z carrier_id, brak etykiety).
- `resources/scss/app.scss` — nowa klasa `.manual-tracking-form` (flex, gap 8px).
## 2026-03-22 (Phase 21 — Order Source Display, Plan 01)
- `OrdersRepository::buildListSql()` — LEFT JOIN `integrations ig ON ig.id = o.integration_id`, nowa kolumna `ig.name AS integration_name`.
- `OrdersRepository::findDetails()` — analogiczny LEFT JOIN dla strony szczegolow zamowienia.
- `OrdersRepository::transformOrderRow()` — nowe pole `integration_name`.
- `OrdersController::toTableRow()` — wyswietla `integration_name` gdy niepuste, fallback na `sourceLabel()` (Allegro/Erli/default).
- `resources/views/orders/show.php` — naglowek zamowienia: dwa osobne spany (nazwa integracji + "ID: identyfikator") zamiast jednego.
## 2026-03-18 (Phase 16 — Zadania automatyczne, Plan 02: Watcher/Executor)
- Nowa klasa `App\Modules\Automation\AutomationService` — trigger + ewaluacja warunkow (AND) + wykonanie akcji.
- Flow: `ReceiptController::store()` -> `AutomationService::trigger('receipt.created', orderId)` -> sprawdzenie warunkow (integration_id) -> `EmailSendingService::send()`.
- Rozszerzenie `EmailSendingService::send()` o opcjonalne parametry `$recipientEmailOverride` i `$recipientNameOverride` (kompatybilnosc wsteczna).
- 3 tryby odbiorcy: 'client' (kupujacy), 'company' (e-mail firmy z company_settings), 'client_and_company' (oba).
- Trigger w try/catch — blad automatyzacji nie blokuje sukcesu tworzenia paragonu.
- Activity log: automation_email_sent / automation_email_failed z actor_type='system'.
## 2026-03-18 (Phase 16 — Zadania automatyczne, Plan 01: DB + CRUD)
- Nowe tabele: `automation_rules`, `automation_conditions`, `automation_actions` (migracja 000057).
- Nowy modul `App\Modules\Automation` z 2 klasami:
- `AutomationController` — CRUD regul automatyzacji (index, create, store, edit, update, destroy, toggleStatus).
- `AutomationRepository` — operacje DB z transakcjami (create/update atomowe z conditions+actions), findActiveByEvent dla watchera.
- 7 nowych route'ow: `/settings/automation/*`.
- Widoki: `resources/views/automation/index.php` (lista regul), `resources/views/automation/form.php` (formularz z dynamicznymi warunkami/akcjami).
- Nowy JS: `public/assets/js/modules/automation-form.js` (dodawanie/usuwanie wierszy warunkow i akcji).
- Nowy SCSS: `resources/scss/modules/_automation.scss` (style formularza dynamicznego).
- Menu nawigacji: dodany link "Zadania automatyczne" w sekcji Ustawienia.
## 2026-03-17 (Phase 15 — Wysylka e-mail z zamowien)
- Nowa zaleznosc: `phpmailer/phpmailer` v7.0.2 (SMTP transport).
- Nowy modul `App\Modules\Email` z 3 klasami:
- `EmailSendingService` — wysylka e-mail (send, preview), logowanie do email_logs, resolwer skrzynki (mailboxId → template → default).
- `VariableResolver` — zamiana `{{grupa.zmienna}}` na dane zamowienia/kupujacego/adresu/firmy.
- `AttachmentGenerator` — generowanie PDF paragonu (dompdf) jako zalacznik in-memory (addStringAttachment).
- `OrdersController`: nowe metody `sendEmail()`, `emailPreview()`, `loadEmailLogs()`.
- Nowe route'y: `POST /orders/{id}/send-email`, `POST /orders/{id}/email-preview`.
- Widok `orders/show.php`: przycisk "Wyslij e-mail" + modal (wybor szablonu/skrzynki, podglad, wysylka AJAX).
- Zakladka Dokumenty: sekcja "Wysylki e-mail" z historia wyslanych maili (status, podglad body).
- Nowy partial: `resources/views/orders/partials/email-send-modal.php`.
- Nowy SCSS: `resources/scss/modules/_email-send.scss` (modal overlay, podglad, style).
## 2026-03-15 (Phase 13 — DB + Skrzynki pocztowe)
- Dodano 3 migracje email: `000054_create_email_mailboxes_table`, `000055_create_email_templates_table`, `000056_create_email_logs_table`.
- Nowe klasy: `EmailMailboxController` (index, save, delete, toggleStatus, testConnection), `EmailMailboxRepository` (listAll, findById, save, delete, toggleStatus, listActive).
- Test polaczenia SMTP przez natywny `stream_socket_client` z pelnym handshake (EHLO → STARTTLS → AUTH LOGIN) — bez zewnetrznych bibliotek.
- Hasla SMTP szyfrowane przez `IntegrationSecretCipher` (AES-256-CBC + HMAC-SHA256).
- Widok `settings/email-mailboxes.php` — lista skrzynek + formularz CRUD + AJAX test polaczenia.
- Nawigacja: link "Skrzynki pocztowe" w sidebar Settings.
- 5 nowych route'ow: GET/POST `/settings/email-mailboxes/*`.
## 2026-03-14
- Zoptymalizowano zapytanie listy zamowien (`OrdersRepository::buildListSql()`):
- 4 correlated subqueries (items_count, items_qty, shipments_count, documents_count) zastapiono aggregating LEFT JOINami — eliminuje N+1 na kazdym wierszu listy.
- `OrdersRepository::canResolveMappedMedia()` — zamiana instance property na `static``information_schema` odpytywany co najwyzej raz na cykl PHP zamiast raz per instancja.
- Dodano migracje `20260314_000048_add_orders_performance_indexes.sql` — indeksy na `orders`: `source`, `external_status_id`, `ordered_at`, composite `(source, external_status_id)`.
- Dodano SSL verification (`CURLOPT_SSL_VERIFYPEER => true`, `CURLOPT_SSL_VERIFYHOST => 2`, `CURLOPT_CAINFO`) do 4 klas ApiClient: AllegroApiClient (3 metody), AllegroOAuthClient, ShopproApiClient, ApaczkaApiClient. Fallback: `$_ENV['CURL_CA_BUNDLE_PATH']` → XAMPP cacert.pem → system CA bundle.
- Cron web throttle (`isWebCronThrottled()`) przeniesiony z `$_SESSION` do `app_settings` (klucz `cron_web_last_run_at`) — eliminuje wielokrotne uruchamianie crona przy wielu aktywnych sesjach.
- Deduplikacja migracji `000014``000014b` (kolizja z `create_product_integration_translations`).
- `AllegroStatusSyncService::sync()` zwraca `ok:false` dla kierunku `orderpro_to_allegro` (wczesniej false-positive `ok:true`). Opcja UI oznaczona jako `disabled` z `(wkrotce)`.
- Lista zamowien: source wyswietlany przed ID z prefixem `ID:`; `sourceLabel()` mapuje shoppro→shopPRO, allegro→Allegro.
- Statusy zamowien na liscie kolorowane kolorem grupy z konfiguracji (`statusColorMap()` → inline `background-color`).
- Ciemniejsze obramowanie pol formularzy: `--c-border` zmieniony z `#e2e8f0` na `#b0bec5`.
- Hotfix SSL: `getCaBundlePath()` zwraca `null` gdy zaden CA bundle nie znaleziony — `CURLOPT_CAINFO` ustawiany warunkowo, cURL uzywa systemowego CA na serwerze.
## 2026-03-08
- Poprawiono date podjazdu kuriera w payloadzie Apaczka:
- `pickup.date` dla trybu `COURIER` jest normalizowane tak, aby nie wypadal w niedziele (niedziela -> poniedzialek),
- `pickup.hours_to` jest ograniczane do `16:00` (wg limitu API), a okno godzinowe jest korygowane do poprawnej relacji `hours_from < hours_to`,
- eliminuje blad API `Field PickupLocation->MaxPickupDate cannot be set to Sunday`.
- Dodano pole firmy `sender_contact_person` (osoba kontaktowa nadawcy):
- nowa migracja `20260308_000046_extend_company_settings_contact_person.sql`,
- UI `Ustawienia > Dane firmy` ma nowe pole `Osoba kontaktowa nadawcy`,
- `ApaczkaShipmentService` wysyla `contact_person` dla nadawcy z ustawien firmy.
- Uzupelniono kontakt odbiorcy w payloadzie Apaczka:
- `ApaczkaShipmentService` wysyla `receiver.contact_person` (fallback na dane odbiorcy/klienta z zamowienia),
- eliminuje blad API: `Osoba kontaktowa nadawcy/odbiorcy: Pole jest wymagane`.
- Dla tworzenia przesylek Apaczka dodano jawne pole `pickup.type` w payloadzie `order_send`:
- gdy podano `sender_point_id` ustawiane jest `SELF`,
- gdy brak punktu nadania i usluga dopuszcza odbior kurierem ustawiane jest `COURIER`.
- Poprawiono obsluge punktow nadania/odbioru w payloadzie Apaczka:
- adres `sender` i `receiver` wysyla teraz komplet aliasow punktu (`point`, `foreign_address_id`, `point_id`),
- rozszerzono diagnostyke dla bledu API `Niepoprawny sposob nadania przesylki` o wskazowke dot. `sender_point_id` / doboru uslugi.
- Wzmocniono fallback adresu odbiorcy dla przesylek punktowych Apaczka (Orlen/InPost):
- `ApaczkaShipmentService` probuje teraz dodatkowo uzupelnic adres punktu (`street`, `postal_code`, `city`) przez API `points` na podstawie `receiver_point_id`,
- jezeli zamowienie punktowe dalej nie ma kompletu danych adresowych, serwis uzupelnia techniczne minimum (`line1`, `city`, `postal_code`) zamiast blokowac tworzenie przesylki bledem walidacji lokalnej.
- Ujednolicono i wzmocniono naglowki sekcji UI (`h2/h3/h4.section-title`) w widokach:
- naglowki sekcyjne maja teraz wyrazniejszy styl (akcent lewy, delikatne tlo, obramowanie),
- zmiana jest globalna (SCSS), obejmuje m.in. `Zamowienia > Przygotuj przesylke` oraz pozostale ekrany korzystajace z `section-title`.
- Poprawiono fallback danych odbiorcy dla przesylek punktowych Apaczka (w tym Orlen Paczka):
- `ApaczkaShipmentService::buildReceiverAddress(...)` uzupelnia brakujace pola z wielu zrodel w kolejnosci:
- dane z formularza,
- adres `delivery` z zamowienia,
- dane punktu z `parcel_name` (`ulica`, `kod`, `miasto`),
- dane klienta (`name`, `phone`, `email`, `country`),
- adres ulicy sklada teraz `street_name + street_number`,
- naprawiono fallback `receiver_point_id` (uzywa `delivery.parcel_external_id`, usunieto bledne odwolanie do niezdefiniowanej zmiennej).
- Poprawiono obsluge usunietych/nieosiagalnych etykiet Apaczka:
- gdy API zwraca `Label is not available for this order`, rekord paczki jest oznaczany jako `error` i zapisywany jest `error_message`,
- dzieki temu przycisk etykiety nie jest ponownie pokazywany dla tego rekordu.
- Ujednolicono flow etykiet w `Zamowienia > Przygotuj przesylke` (dla wszystkich providerow):
- po statusie `created` etykieta jest generowana automatycznie przez cykliczne sprawdzanie statusu (backend probuje `downloadLabel`),
- UI nie pokazuje juz przycisku `Generuj etykiete`; do czasu gotowosci widoczny jest stan `Generowanie etykiety...`,
- przycisk `Pobierz` pojawia sie dopiero po zapisaniu pliku etykiety (`label_path`).
- Uzgodniono payload `order_send` Apaczka z dokumentacja API v2:
- `ApaczkaShipmentService` wysyla teraz strukture `address.sender/receiver` + `shipment[]` (`dimension1/2/3`, `weight` w kg),
- `cod` jest przekazywany jako obiekt (`amount`, `currency`), a wartosc ubezpieczenia przez `shipment_value` + `shipment_currency`,
- punkty sa przekazywane jako `foreign_address_id` (z aliasami diagnostycznymi),
- naprawilo to blad wyceny dla zamowienia testowego `#21` (utworzenie przesylki zakonczone sukcesem).
- Dodano techniczny skrypt diagnostyczny `tools/apaczka_probe_order.php`:
- wykonuje automatyczne proby `order_send` dla wskazanego zamowienia (bez klikania w UI),
- testuje kombinacje uslug i wariantow pol punktu, raportujac sukces/blad per proba.
- Rozszerzono payload punktow w tworzeniu przesylki Apaczka:
- oprocz `point` przekazywane sa teraz aliasy `foreign_address_id` i `point_id` (dla odbiorcy i nadawcy),
- cel: kompatybilnosc z wariantami API wymagajacymi innej nazwy pola punktu.
- Korekta walidacji punktu odbioru Apaczka:
- usunieto twarde blokowanie tworzenia przesylki na podstawie prefiksu punktu (`POP-`),
- informacja o prefiksie punktu pozostaje tylko jako sugestia diagnostyczna.
- Poprawiono prefill danych odbiorcy na ekranie `Zamowienia > Przygotuj przesylke`:
- `ShipmentController` dla dostaw do punktu (`parcel_external_id`/`parcel_name`) ustawia `receiver_name` na dane klienta (`address_type=customer`),
- eliminuje przypadek podstawiania nazwy punktu/metody dostawy w polu `Imie i nazwisko`.
- Poprawiono diagnostyke bledow tworzenia przesylki Apaczka:
- `ApaczkaShipmentService` przekazuje teraz `receiver_point_id` do payloadu `receiver.point` (oraz `sender_point_id` do `sender.point`),
- dodano walidacje wymagan uslugi na podstawie `service_structure` (np. wymagany punkt odbioru/nadania),
- dla bledu API `Brak wyceny dla podanych parametrów zamówienia` komunikat zawiera rozszerzona diagnostyke (service_id/nazwa/supplier, punkt odbioru/nadania, gabaryt/waga) i hint o niedopasowaniu uslugi do typu punktu.
- Poprawiono import danych faktury z shopPRO:
- `ShopproOrdersSyncService` wykrywa fakture nie tylko po `is_invoice`/`invoice.required`, ale takze po danych firmowych (`firm_name`/`firm_nip`),
- `ShopproOrdersSyncService::mapAddresses(...)` zapisuje adres `invoice` (firma, NIP, adres) na podstawie pol `invoice`/`billing*`/`firm_*`,
- widok `orders/show` wyswietla teraz `company_name` i `company_tax_number` dla adresu faktury.
- Fix prewyboru uslugi Apaczka na ekranie `Zamowienia > Przygotuj przesylke`:
- widok `resources/views/shipments/prepare.php` odczytuje ID uslugi Apaczka z fallbackiem `service_id -> id`,
- naprawia przypadek, gdy przewoznik (`Apaczka`) byl wybierany poprawnie, ale usluga dostawy pozostawala pusta mimo mapowania.
- Poprawiono diagnostyke mapowania form dostawy na ekranie `Zamowienia > Przygotuj przesylke`:
- `ShipmentController` zwraca teraz komunikat diagnostyczny, gdy brak mapowania metody dostawy,
- komunikat rozroznia brak mapowan dla instancji `shopPRO` (`source_integration_id`) od braku mapowania konkretnej metody,
- widok `resources/views/shipments/prepare.php` wyswietla ten komunikat bezposrednio pod informacja o metodzie z zamowienia.
- Poprawiono UX wyszukiwania w selectach mapowania form dostawy (zakladki `Formy dostawy`):
- `resources/views/settings/allegro.php` przeszlo z przebudowy opcji `<select>` na tryb bezpieczny (`focus first match` bez modyfikacji listy opcji),
- eliminuje przypadki „znikajacych” opcji i problem z wyborem uslugi po zmianie przewoznika na `Apaczka`,
- ujednolicono zachowanie z `resources/views/settings/shoppro.php`.
- Poprawiono inicjalizacje stanu mapowania przewoznika (`allegro.php`, `shoppro.php`):
- dla niezamapowanych form domyslny przewoznik to teraz pusty wybor (zamiast `allegro`),
- panel uslugi (`Allegro/InPost/Apaczka/pusty`) jest synchronizowany na starcie z realna wartoscia selecta przewoznika (`showPanel(carrierSelect.value)`),
- usunieto pozostaly po refaktorze odwolanie do nieistniejacej zmiennej `$currentAllegroId` (zastapione `$currentMethodId`).
- Dodano architekture provider-agnostic dla wysylek:
- nowy kontrakt `ShipmentProviderInterface`,
- nowy rejestr `ShipmentProviderRegistry`,
- `ShipmentController` wybiera providera dynamicznie (`allegro_wza` / `apaczka`) przy tworzeniu przesylki, sprawdzaniu statusu i pobieraniu etykiety.
- Dodano integracje API Apaczka v2:
- nowy klient `App\Modules\Settings\ApaczkaApiClient` (`service_structure`, `order_send`, `order_details`, `waybill`, `points`),
- nowy serwis wysylkowy `App\Modules\Shipments\ApaczkaShipmentService`,
- rozszerzone `Ustawienia > Integracje > Apaczka` o pola `App ID`, `App Secret` oraz test polaczenia (`POST /settings/integrations/apaczka/test`).
- poprawiono format podpisu/requestu zgodnie z API v2 (`app_id:route:request_json:expires`, endpointy URL zamiast pola `method`), co naprawia blad testu polaczenia (`brak JSON`).
- Dodano wspolny model mapowania form dostawy dla wielu providerow:
- nowa tabela `carrier_delivery_method_mappings` (migracja `20260308_000044_create_carrier_delivery_method_mappings_table.sql`),
- nowy repo `CarrierDeliveryMethodMappingRepository`,
- backfill danych z tabel legacy (`allegro_delivery_method_mappings`, `shoppro_delivery_method_mappings`),
- zakladki `Formy dostawy` w Allegro i shopPRO obsluguja mapowanie na `allegro_wza` i `apaczka`.
- Dodano migracje `20260308_000045_extend_apaczka_credentials.sql`:
- rozszerzenie `apaczka_integration_settings` o `app_id` i `app_secret_encrypted`,
- migracja danych legacy sekretu z `api_key_encrypted`.
- Dodano zakladke `Formy dostawy` dla integracji `shopPRO` (analogicznie do Allegro):
- nowy endpoint `POST /settings/integrations/shoppro/delivery/save`,
- mapowanie per instancja: forma dostawy shopPRO -> usluga dostawy Allegro/InPost WZA,
- UI z wyborem przewoznika (`allegro`/`inpost`) i wyszukiwaniem uslug Allegro.
- Dodano `ShopproDeliveryMethodMappingRepository` i tabele mapowan per `integration_id`.
- Dodano migracje `20260308_000043_create_shoppro_delivery_method_mappings_table.sql`.
- Dodano synchronizacje platnosci shopPRO oparta o flage `paid`:
- nowy job cron `shoppro_payment_status_sync`,
- nowy handler `App\Modules\Cron\ShopproPaymentStatusSyncHandler`,
- nowy serwis `App\Modules\Settings\ShopproPaymentStatusSyncService`,
- runner podlaczony w `App\Core\Application::maybeRunCronOnWeb(...)` oraz `bin/cron.php`.
- Rozszerzono `Ustawienia > Integracje > shopPRO > Ustawienia`:
- dodano interwal sprawdzania platnosci (minuty) dla joba `shoppro_payment_status_sync`,
- dodano wybor statusow orderPRO, dla ktorych cron ma sprawdzac oplacenie zamowien,
- zapis konfiguracji listy statusow per instancja trafia do `integrations.payment_sync_status_codes_json`.
- Import zamowien shopPRO zapisuje status platnosci numerycznie (`orders.payment_status`) na podstawie flagi `paid`, co unifikuje filtry/statystyki platnosci z Allegro.
- Dodano migracje `20260308_000042_ensure_shoppro_payment_sync_schedule_and_columns.sql`:
- uzupelnienie kolumny `integrations.payment_sync_status_codes_json`,
- seed/naprawa harmonogramu `shoppro_payment_status_sync` (domyslnie 600s, priorytet 105).
- Fix danych wysylki dla zamowien shopPRO (np. `OP000000016`):
- `ShopproOrdersSyncService` mapuje `inpost_paczkomat`/`orlen_point` do adresu `delivery` (punkt, ulica, kod, miasto),
- zapisuje `parcel_external_id` i `parcel_name` dla punktu odbioru,
- `delivery` dziedziczy telefon i e-mail klienta, gdy API nie zwraca osobnych danych odbiorcy,
- etykieta metody dostawy (`external_carrier_id`) zawiera koszt transportu (`transport_cost`), np. `Paczkomaty InPost - przedpłata: 13.5 zł`.
- Fix importu shopPRO dla listy zamowien (`Kwoty` + miniatury):
- `ShopproOrdersSyncService` mapuje kwoty zamowienia z `summary` i `paid` (fallback), ceny pozycji z `price_brutto`,
- poprawiono laczenie payloadow `orders/list` i `orders/get|details` (zachowanie kluczowych pol z listy),
- dodano fallback miniatur pozycji przez API `products/get` po `product_id`,
- dodano dodatkowy fallback miniatur po `parent_product_id` (warianty), gdy obraz nie istnieje na produkcie potomnym.
- `OrdersRepository`:
- resolver miniatur pozycji uwzglednia kod kanalu zgodny ze zrodlem zamowienia (`o.source`) zamiast stalego `allegro`.
- Korekta layoutu sekcji `Ustawienia` dla integracji `shopPRO`:
- wyrownano pola w siatce (`integration-settings-group__grid`) przez `align-items: start`,
- wymuszono spojna wysokosc kontrolek (`.form-control`), w tym pola `date`,
- przebudowano CSS (`public/assets/css/app.css`) dla rownego przebiegu linii i pol w obu kolumnach.
- Fix UX przycisku `Nowa integracja` w `Ustawienia > Integracje > shopPRO`:
- przycisk otwiera teraz tryb wymuszonego tworzenia (`?new=1`),
- `ShopproIntegrationsController::index(...)` nie auto-wybiera wtedy pierwszej istniejacej integracji,
- formularz tworzenia otwiera sie zawsze jako pusty.
- Poprawiono prezentacje dostawy na szczegolach zamowienia (`orders/show`):
- `Platnosc i wysylka` sanitizuje nazwe przewoznika (usuwa tagi HTML typu `<b>...</b>`),
- `Dane wysylki` pokazuja `parcel_name` i `parcel_external_id` (np. punkt/paczkomat Allegro),
- gdy brak adresu `delivery`, sekcja `Dane wysylki` pokazuje fallback z metody dostawy (`external_carrier_id`).
- Poprawiono import shopPRO dla formy dostawy:
- `ShopproOrdersSyncService` sanitizuje `external_carrier_id` i `order_shipments.carrier_provider_id` (usuwanie HTML + dekodowanie encji),
- rozszerzono fallbacki mapowania przewoznika (`transport`, `transport_description`, `transport_id`).
- Fix mapowania formy dostawy z shopPRO:
- `ShopproOrdersSyncService` mapuje teraz `orders.external_carrier_id` z fallbackiem na pola `transport` i `transport_description`,
- `orders.external_carrier_account_id` mapowane z `transport_id`,
- `order_shipments.carrier_provider_id` rozszerzone o fallback `transport`/`transport_description`.
- Fix importu adresow shopPRO na realnym payloadzie zamowien (`client_name`, `client_surname`, `client_email`, `client_phone`):
- `ShopproOrdersSyncService::mapAddresses(...)` mapuje teraz pola klienta w formacie flat (bez zagniezdzenia),
- usunieto przypadek tworzenia pustego adresu `delivery` tylko na bazie fallbacku e-mail,
- po wymuszonym re-sync zamowienia #13 dane zamawiajacego zapisaly sie jako `Jacek Pyziak`, `pyziak84@gmail.com`, `530755774`.
- Poprawiono mapowanie danych adresowych w imporcie zamowien `shopPRO`:
- `ShopproOrdersSyncService::mapAddresses(...)` obsluguje rozszerzony zestaw aliasow pol klienta i dostawy (`buyer/customer/client`, `billing_address`, `shipping_address`, `delivery_address`, `receiver`, warianty `first_name/last_name`, `postcode` itd.),
- adres dostawy jest zapisywany takze wtedy, gdy brak pelnej nazwy, ale istnieja inne dane adresowe,
- rozszerzono mapowanie `orders.customer_login` i `orders.external_carrier_id` o dodatkowe fallbacki z payloadu shopPRO.
- Poprawiono UX zakladki `Ustawienia` integracji `shopPRO`:
- ustawienia sa pogrupowane w sekcje `Pobieranie zamowien` oraz `Synchronizacja statusow`,
- dodano naglowki sekcji i opisy kontekstu, aby pola nie zlewaly sie wizualnie,
- dodano dedykowane style SCSS (`integration-settings-group*`) i przebudowano `public/assets/css/app.css`.
- Dodano cron synchronizacji statusow `shopPRO`:
- nowy handler `App\Modules\Cron\ShopproStatusSyncHandler`,
- nowy serwis `App\Modules\Settings\ShopproStatusSyncService`,
- nowy job `shoppro_order_status_sync` podlaczony do runnera w `App\Core\Application::maybeRunCronOnWeb(...)` i `bin/cron.php`.
- Rozszerzono `Ustawienia > Integracje > shopPRO > Ustawienia`:
- dodano wybor kierunku synchronizacji statusow (`shopPRO -> orderPRO`, `orderPRO -> shopPRO`),
- dodano pole interwalu synchronizacji statusow (minuty),
- zapis aktualizuje `integrations.order_status_sync_direction` i harmonogram `cron_schedules` dla `shoppro_order_status_sync`.
- Dodano migracje `20260308_000041_ensure_shoppro_status_sync_schedule_and_direction.sql`:
- seed/naprawa harmonogramu `shoppro_order_status_sync` (domyslnie 900s, priorytet 100),
- uzupelnienie kolumny `integrations.order_status_sync_direction` jesli brak.
- Rozszerzono `ShopproOrdersSyncService` o opcje uruchomienia filtrowanego po `integration_id` i z pominięciem flagi `orders_fetch_enabled` (wykorzystane przez cron synchronizacji statusow).
- Dodano cron importu zamowien z `shopPRO`:
- nowy handler `App\Modules\Cron\ShopproOrdersImportHandler`,
- nowy serwis `App\Modules\Settings\ShopproOrdersSyncService`,
- nowy klient API `App\Modules\Settings\ShopproApiClient`,
- job `shoppro_orders_import` jest podlaczony do wykonania zarowno w `App\Core\Application::maybeRunCronOnWeb(...)`, jak i w `bin/cron.php`.
- Rozszerzono `Ustawienia > Integracje > shopPRO > Ustawienia`:
- dodano pole interwalu pobierania zamowien (minuty),
- zapis aktualizuje harmonogram `cron_schedules` dla joba `shoppro_orders_import`.
- Dodano migracje `20260308_000040_ensure_shoppro_orders_import_schedule.sql`:
- seed/naprawa harmonogramu `shoppro_orders_import` (domyslnie 300s, priorytet 90).
- Zadanie #13 z `DOCS/todo.md`: dodano stronicowanie historii w `Ustawienia > Cron`:
- `CronSettingsController` pobiera `past_page` z query i przekazuje metadane paginacji do widoku,
- `CronRepository` rozszerzono o `countPastJobs()` oraz `listPastJobs(limit, offset)`,
- widok `settings/cron.php` renderuje kontrolki paginacji dla sekcji `Historia jobow (przeszle)`.
- Rozpoczeto ujednolicanie modelu integracji na baze `integrations`:
- dodano klasy wspolne `App\Modules\Settings\IntegrationsRepository` oraz `App\Modules\Settings\IntegrationSecretCipher`,
- ograniczono duplikacje szyfrowania sekretow integracji (wspolny cipher dla repozytoriow integracji).
- Migracja `20260308_000037_unify_integrations_base_links.sql`:
- dodaje `integration_id` do `allegro_integration_settings`, `apaczka_integration_settings`, `inpost_integration_settings`,
- podpina relacje 1:1 FK do `integrations`,
- seeduje bazowe rekordy providerow (`allegro`, `apaczka`, `inpost`) i backfilluje powiazania.
- `ApaczkaIntegrationRepository`:
- klucz API zapisuje/odczytuje z `integrations.api_key_encrypted` (`type=apaczka`).
- `InpostIntegrationRepository`:
- token API zapisuje/odczytuje z `integrations.api_key_encrypted` (`type=inpost`),
- ustawienia specyficzne przewoznika pozostaja w `inpost_integration_settings`.
- `AllegroIntegrationRepository`:
- zapewnia powiazanie aktywnego srodowiska OAuth z rekordem bazowym `integrations`,
- dodana metoda `getActiveIntegrationId()` pod spojnosc domeny zamowien/sync.
- `AllegroOrderImportService` i `AllegroOrdersSyncService`:
- przestaly uzywac stalej/`null` dla `integration_id`,
- korzystaja z aktywnego `integration_id` Allegro, co eliminuje sztywne zalozenie `integration_id=1`.
- Dodano wspolny ekran `Ustawienia > Integracje`:
- nowa route `GET /settings/integrations`,
- nowa klasa `App\Modules\Settings\IntegrationsHubController`,
- nawigacja boczna prowadzi do jednego huba integracji.
- Hub integracji zawiera tabele podsumowania oraz akcje per instancja:
- przycisk `Ustawienia` w kazdym wierszu prowadzi do dedykowanego ekranu zaawansowanego providera.
- Fix UI: rozciaganie przyciskow w formularzach (`.form-actions`) przy ukladzie grid:
- ustawiono `align-items: flex-start` oraz `align-self: flex-start` dla `.form-actions .btn`,
- eliminuje pionowe rozciaganie przyciskow do wysokosci sasiednich pol formularza.
- Dodano wieloinstancyjna konfiguracje integracji `shopPRO`:
- nowe endpointy: `GET /settings/integrations/shoppro`, `POST /settings/integrations/shoppro/save`, `POST /settings/integrations/shoppro/test`,
- nowa klasa `App\Modules\Settings\ShopproIntegrationsController`,
- nowy widok `resources/views/settings/shoppro.php` (lista instancji, formularz dodawania/edycji, test polaczenia),
- hub integracji (`/settings/integrations`) zawiera wiersz `shopPRO` z przejsciem do ekranu ustawien,
- dodano pomocnicze style `.table-row-actions` dla kompaktowych akcji w tabelach.
- Ekran `shopPRO` rozbudowano o zakladki analogiczne do Allegro:
- `Integracja`, `Statusy`, `Ustawienia`, `Formy dostawy`,
- `Ustawienia` zawiera pola `Pobieraj zamowienia` i `Data startu pobierania`,
- zapis/odczyt tych pol jest realizowany przez tabele bazowa `integrations` (`orders_fetch_enabled`, `orders_fetch_start_date`).
- Wdrozone mapowanie statusow shopPRO (zakladka `Statusy`):
- nowe endpointy: `POST /settings/integrations/shoppro/statuses/sync` oraz `POST /settings/integrations/shoppro/statuses/save`,
- dodana klasa `App\Modules\Settings\ShopproStatusMappingRepository`,
- synchronizacja statusow pobiera slownik `dictionaries/statuses` z API shopPRO,
- zapis mapowan trafia do `order_status_mappings` per `integration_id` (wieloinstancyjnie).
- Poprawiono parser statusow shopPRO:
- obsluguje odpowiedzi zagniezdzone w `data`,
- obsluguje rowniez format mapy `kod => nazwa` oraz dodatkowe aliasy pol (`status_code`, `status_name`, `symbol`, `slug`).
- Dodano migracje naprawcza `20260308_000038_ensure_order_status_mappings_table.sql`:
- tworzy `order_status_mappings` jesli tabela nie istnieje (scenariusz niepelnej historii migracji na srodowisku).
- Dodano migracje naprawcza `20260308_000039_ensure_integrations_fetch_columns.sql`:
- uzupelnia w `integrations` brakujace kolumny `orders_fetch_enabled` i `orders_fetch_start_date`
dla srodowisk, gdzie tabela `integrations` zostala odtworzona pozniej niz pierwotne migracje shopPRO.
- Poprawiono UX ekranu `shopPRO`:
- przy istniejacych instancjach automatycznie wybierana jest pierwsza integracja (bez koniecznosci wracania do zakladki `Integracja`),
- dodano przełącznik instancji nad zakladkami (`Wybrana integracja`) dostepny globalnie dla `Statusy/Ustawienia/Formy dostawy`.
## 2026-03-06
- Fix: synchronizacja statusow Allegro nie aktualizowala zamowien.
- Przyczyna: Allegro API nie zmienia `updatedAt` przy zmianie `fulfillment.status`.
Cursor-based sync (`AllegroOrdersSyncService`) pomijal takie zamowienia.
- Rozwiazanie: `AllegroStatusSyncService` przepisany na podejscie direct-query:
odpytuje baze o zamowienia Allegro w nie-finalnych statusach i re-importuje je
przez `AllegroOrderImportService::importSingleOrder()`.
- `AllegroStatusSyncService` nie zalezy juz od `AllegroOrdersSyncService`.
- Dodano `ensureDefaultSchedulesExist()` w `AllegroIntegrationController`,
aby harmonogramy cron byly tworzone automatycznie.
- Rozszerzono zakladke `Formy dostawy` o wybor przewoznika (Allegro / InPost) per wiersz:
- nowa kolumna `carrier` w tabeli `allegro_delivery_method_mappings`,
- select przewoznika determinuje dostepne uslugi (Allegro z API, InPost statyczna lista),
- JS przelacza panele uslug w zaleznosci od wybranego przewoznika.
- Migracja `20260306_000036_add_carrier_to_delivery_method_mappings.sql`.
## 2026-03-05
- Dodano nowa zakladke `Ustawienia > Integracja InPost`:
- route `GET /settings/integrations/inpost` i `POST /settings/integrations/inpost/save`,
- widok konfiguracji z polami: token API (szyfrowany), ID organizacji, srodowisko (sandbox/production),
- domyslny sposob nadania (POP/paczkomat/kurier), punkt nadania,
- domyslny rozmiar paczki (A/B/C), wymiary przesylek kurierskich,
- typ etykiety (PDF/ZPL/EPL), paczka weekendowa, auto-ubezpieczenie, multi-paczki.
- Dodano klasy:
- `App\Modules\Settings\InpostIntegrationController`,
- `App\Modules\Settings\InpostIntegrationRepository` (szyfrowanie AES-256-CBC + deszyfrowanie tokenu).
- Dodano migracje `20260305_000035_create_inpost_integration_settings_table.sql`.
- Rozszerzono nawigacje `Ustawienia` o link `Integracja InPost`.
- Import Allegro pobiera przesylki z dedykowanego endpointu `GET /order/checkout-forms/{id}/shipments` zamiast szukac ich w payloadzie checkout form (naprawa zerowej liczby przesylek).
- Dodano metode `AllegroApiClient::getCheckoutFormShipments(...)`.
- Usunieto duplikat ID zamowienia Allegro w naglowku szczegolow zamowienia (wyswietlane bylo `source_order_id` i `external_order_id` z ta sama wartoscia).
- Dodano nazwe integracji (np. "Allegro") przed ID zamowienia w naglowku szczegolow.
- Dodano nowa zakladke `Ustawienia > Integracja Apaczka`:
- route `GET /settings/integrations/apaczka` i `POST /settings/integrations/apaczka/save`,
- widok konfiguracji z polem klucza API (szyfrowany AES-256-CBC jak w integracji Allegro).
- Dodano klasy:
- `App\Modules\Settings\ApaczkaIntegrationController`,
- `App\Modules\Settings\ApaczkaIntegrationRepository`.
- Dodano migracje `20260305_000029_create_apaczka_integration_settings_table.sql`:
- tabela `apaczka_integration_settings` na konfiguracje klucza API (zaszyfrowany).
- Rozszerzono nawigacje `Ustawienia` o link `Integracja Apaczka`.
- Dodano reczna zmiane statusu zamowienia z widoku szczegolow:
- nowa route `POST /orders/{id}/status`,
- nowa metoda `OrdersController::updateStatus(...)`,
- dropdown ze wszystkimi aktywnymi statusami (pogrupowane wg grup) w naglowku szczegolow zamowienia,
- zmiana rejestrowana w `order_status_history` i `order_activity_log` (actor_type: `user`),
- flash messages (sukces/blad) po redirect,
- bez zmian schematu.
- Import zamowienia z Allegro (reczny i auto-sync) rejestruje zdarzenie `import` w `order_activity_log`:
- `AllegroOrderImportService` rozszerzony o zaleznosc `OrdersRepository`,
- po kazdym upsert zamowienia wpisywany jest log z informacja o nowym imporcie lub re-imporcie,
- actor_type: `import`, actor_name: `Allegro`,
- bez zmian schematu.
- Dodano uniwersalny log aktywnosci zamowien:
- nowa tabela `order_activity_log` (migracja `20260305_000030_create_order_activity_log_table.sql`),
- nowe metody w `OrdersRepository`: `recordActivity()`, `recordStatusChange()`, `updateOrderStatus()`,
- zakladka `Historia zmian` w szczegolow zamowienia wyswietla tabele z logiem aktywnosci (data, typ, opis, wykonawca),
- typy zdarzen: zmiana statusu, platnosc, faktura, przesylka, wiadomosc, dokument, import, notatka,
- kolorowe badge'e typow zdarzen,
- historia statusow w zakladce `Szczegoly` pokazuje teraz nazwy statusow zamiast surowych kodow.
## 2026-03-04
- Poprawiono kolumne `Data zamowienia` na liscie zamowien:
- wartosc jest liczona fallbackiem `orders.ordered_at -> orders.source_created_at -> orders.source_updated_at -> orders.fetched_at`,
- domyslne sortowanie listy i filtry zakresu dat korzystaja z tej samej daty efektywnej, co eliminuje puste wartosci przy rekordach bez `ordered_at`.
- Import zamowienia Allegro zapisuje teraz forme wysylki:
- `delivery.method.name` (fallback `delivery.method.id`) trafia do `orders.external_carrier_id`,
- techniczne `delivery.method.id` trafia do `orders.external_carrier_account_id`.
- Dopracowano mapowanie dostawy dla zamowien Allegro:
- dla dostawy do punktu odbioru adres `Dane wysylki` jest budowany z `delivery.pickupPoint` (nazwa punktu + adres punktu),
- terminy z `delivery.time.dispatch` sa zapisywane do `orders.send_date_min` / `orders.send_date_max`.
- Rozszerzono UI `Ustawienia > Integracje > Allegro` o zakladke `Ustawienia`:
- dodano opcje konfiguracji interwalu pobierania zamowien (minuty),
- nowy endpoint zapisu `POST /settings/integrations/allegro/settings/save`,
- zapis aktualizuje harmonogram joba `allegro_orders_import` w `cron_schedules`.
- Rozszerzono zakladke `Ustawienia` integracji Allegro:
- dodano `kierunek synchronizacji statusow` (`Allegro -> orderPRO`, `orderPRO -> Allegro`),
- dodano `interwal synchronizacji statusow` (minuty),
- zapis do `app_settings` (`allegro_status_sync_direction`, `allegro_status_sync_interval_minutes`) pod przyszly cron synchronizacji statusow.
- Dodano cron synchronizacji statusow Allegro:
- nowy job type `allegro_status_sync` z harmonogramem domyslnym co 900s,
- nowy handler `App\Modules\Cron\AllegroStatusSyncHandler`,
- nowy serwis `App\Modules\Settings\AllegroStatusSyncService` (obsluga kierunku sync z ustawien integracji).
- Dodano migracje `20260304_000028_add_allegro_status_sync_schedule.sql`:
- seed `cron_schedules` dla `allegro_status_sync`,
- seed domyslnych ustawien `app_settings` dla kierunku i interwalu synchronizacji statusow.
- Dodano automatyczny import zamowien Allegro przez cron:
- nowy job type `allegro_orders_import` z harmonogramem co 300s (priorytet 20, max_attempts 3),
- nowy handler `App\Modules\Cron\AllegroOrdersImportHandler`,
- nowy serwis `App\Modules\Settings\AllegroOrdersSyncService` (stronicowanie checkout forms, deduplikacja/idempotentny import, limity batcha),
- nowy repo `App\Modules\Settings\AllegroOrderSyncStateRepository` utrzymujacy kursor i status wykonania w `integration_order_sync_state`.
- Podlaczono handler `allegro_orders_import` do runnera crona:
- `bin/cron.php` (CLI worker),
- `App\Core\Application::maybeRunCronOnWeb` (tryb cron-on-web).
- Dodano migracje `20260304_000027_add_allegro_orders_import_schedule.sql`:
- seed harmonogramu `allegro_orders_import`,
- uzupelnienie kompatybilnosci tabeli `integration_order_sync_state` o kolumny kursora sync.
- Dodano obsluge miniatur produktow dla importu Allegro i widokow zamowien:
- import pojedynczego zamowienia Allegro zapisuje URL obrazka pozycji (`lineItems.offer.image*`) do `order_items.media_url`,
- lista i szczegoly zamowienia rozwiazuja miniature priorytetowo: `order_items.media_url` -> glowny obraz powiazanego produktu orderPRO (`product_channel_map` + `sales_channels=allegro` + `product_images`).
- dodano bezpieczny fallback zgodnosci: jesli wymagane tabele/kolumny mapowania produktu nie istnieja w aktualnym schemacie DB, UI korzysta tylko z `order_items.media_url` (bez bledu 404 na szczegolach zamowienia).
- Rozszerzono import pojedynczego zamowienia Allegro o fallback pobrania obrazka po `offerId`:
- gdy `checkout-form lineItem` nie zawiera obrazka, importer pobiera dane oferty przez `GET /sale/product-offers/{offerId}` i zapisuje URL miniatury do `order_items.media_url`,
- obslugiwane sa rowniez URL w formacie `//...` (normalizacja do `https://...`).
- Dodano diagnostyke importu obrazkow Allegro:
- po imporcie pojedynczego zamowienia UI pokazuje podsumowanie `obrazki: X/Y` i ostrzezenie z przyczynami brakow,
- diagnostyka rozroznia m.in. brak obrazka w checkout-form, brak obrazka w API oferty, brak `offerId` oraz bledy HTTP API ofert (np. `403`).
- Rozszerzono zakres scope zadany w OAuth Allegro:
- autoryzacja prosi teraz o `allegro:api:orders:read` oraz `allegro:api:sale:offers:read`,
- po zmianie scope wymagane jest ponowne polaczenie OAuth (`Polacz ponownie`), aby nowe tokeny mialy dostep do API ofert.
- Poprawiono odczyt statusow zamowien w UI listy/szczegolow:
- status efektywny jest liczony dynamicznie z mapowaniem `allegro_order_status_mappings` (nie tylko przy imporcie),
- panel statusow, filtr statusu i etykieta statusu w tabeli korzystaja z tego samego statusu po mapowaniu.
- UI mapowania statusow Allegro zmieniono na zapis zbiorczy:
- jeden przycisk `Zapisz mapowania` dla wszystkich selectow w tabeli,
- nowy endpoint `POST /settings/integrations/allegro/statuses/save-bulk`.
- Dodano automatyczne pobieranie statusow Allegro do mapowania:
- endpoint `POST /settings/integrations/allegro/statuses/sync`,
- przycisk `Pobierz statusy z Allegro` w zakladce `Ustawienia > Integracje > Allegro > Statusy`,
- nowa klasa `App\Modules\Settings\AllegroStatusDiscoveryService` (statusy z API `checkout-forms`).
- Dodano migracje `20260304_000026_make_allegro_status_mapping_nullable.sql`:
- `allegro_order_status_mappings.orderpro_status_code` jest teraz nullable (statusy moga byc najpierw odkryte, potem mapowane).
- Zmieniono podejscie do statusow Allegro:
- usunieto fallbackowe tlumaczenia statusow z kodu listy zamowien,
- dodano zakladke `Statusy` w `Ustawienia > Integracje > Allegro` z recznym mapowaniem `status Allegro -> status orderPRO`.
- Dodano migracje `20260304_000025_create_allegro_order_status_mappings_table.sql`.
- Dodano `App\Modules\Settings\AllegroStatusMappingRepository`.
- Import pojedynczego zamowienia Allegro mapuje teraz status przez `allegro_order_status_mappings` (jesli istnieje wpis), zamiast fallbackowej translacji.
- Poprawiono prezentacje statusow na liscie zamowien:
- filtr statusu pokazuje etykiety biznesowe zamiast surowych kodow (`external_status_id`),
- kody bez mapowania sa tylko formatowane technicznie do czytelnej postaci (`do_odbioru` -> `Do odbioru`).
- Dodano reczny import pojedynczego zamowienia Allegro z poziomu `Ustawienia > Integracje > Allegro`:
- endpoint `POST /settings/integrations/allegro/import-single`,
- formularz z polem `checkout_form_id` w widoku integracji Allegro.
- Dodano klasy importu Allegro:
- `App\Modules\Settings\AllegroApiClient` (request `GET /order/checkout-forms/{id}`),
- `App\Modules\Settings\AllegroOrderImportService` (refresh tokenu + mapowanie payloadu),
- `App\Modules\Orders\OrderImportRepository` (upsert aggregate do tabel zamowien).
- Import pojedynczego zamowienia dziala idempotentnie po kluczu biznesowym (`source=allegro`, `source_order_id`) i nadpisuje kolekcje 1:N (adresy/pozycje/platnosci/wysylki/notatki/historia) aktualnym snapshotem z API.
- Dodano nowy modul crona oparty o tabele `cron_schedules` + `cron_jobs`:
- `App\Modules\Cron\CronRepository`,
- `App\Modules\Cron\CronRunner`.
- Dodano pierwszy handler crona:
- `App\Modules\Cron\AllegroTokenRefreshHandler` dla joba `allegro_token_refresh`.
- Dodano odswiezanie tokenu OAuth w `App\Modules\Settings\AllegroOAuthClient::refreshAccessToken(...)`.
- Rozszerzono `App\Modules\Settings\AllegroIntegrationRepository` o odczyt danych refresh tokenu.
- Odtworzono CLI worker `bin/cron.php` (uruchomienie jobow wg harmonogramu i priorytetu).
- Dodano migracje `20260304_000024_add_allegro_token_refresh_schedule.sql`:
- harmonogram `allegro_token_refresh` (`interval_seconds=3600`, `priority=10`, `max_attempts=3`, `enabled=1`).
- Dodano zakladke `Ustawienia > Cron`:
- `GET /settings/cron`,
- `POST /settings/cron`,
- kontrola opcji `cron_run_on_web` i `cron_web_limit`,
- podglad harmonogramow i kolejki/historii jobow.
- Podlaczono wykonanie crona podczas requestow HTTP:
- `App\Core\Application::maybeRunCronOnWeb(Request)` jest uruchamiane w `Application::run()`,
- aktywowane ustawieniem `cron_run_on_web` i ograniczane lockiem DB + throttlingiem sesyjnym.
- Dodano nowa zakladke `Ustawienia > Integracje > Allegro`:
- route i widok konfiguracji,
- sekcja z gotowym `redirect_uri` do rejestracji aplikacji Allegro.
- Dodano endpointy Allegro OAuth:
- `GET /settings/integrations/allegro`,
- `POST /settings/integrations/allegro/save`,
- `POST /settings/integrations/allegro/oauth/start`,
- `GET /settings/integrations/allegro/oauth/callback`.
- Dodano klasy:
- `App\Modules\Settings\AllegroIntegrationController`,
- `App\Modules\Settings\AllegroIntegrationRepository`,
- `App\Modules\Settings\AllegroOAuthClient`.
- Dodano migracje `20260304_000023_create_allegro_integration_settings_table.sql`:
- tabela `allegro_integration_settings` na konfiguracje OAuth2 i tokeny (`client_secret`, `access_token`, `refresh_token` trzymane jako zaszyfrowane).
- Dodano walidacje i obsluge flow Authorization Code:
- generowanie `state` i walidacja callbacku,
- wymiana `code` na tokeny przez endpoint tokenowy Allegro (sandbox/production).
- Rozszerzono nawigacje `Ustawienia` o link `Integracje Allegro`.
- Dodano style SCSS dla bloku prezentacji callback URL i przebudowano asset CSS (`public/assets/css/app.css`).
## 2026-03-02
- Dodano zakladke `Ustawienia > Statusy` do zarzadzania:
- grupami statusow (z kolorem na poziomie grupy),
- statusami przypisanymi do grup.
- Dodano migracje `20260302_000022_create_order_status_groups_and_statuses_tables.sql`:
- tabela `order_status_groups`,
- tabela `order_statuses` z FK `order_statuses_group_fk` i kasowaniem kaskadowym.
- Dodano `App\Modules\Settings\OrderStatusRepository` (CRUD grup/statusow i walidacja unikalnosci kodow).
- Rozszerzono `App\Modules\Settings\SettingsController` o endpointy:
- `statuses`,
- `createStatusGroup`, `updateStatusGroup`, `deleteStatusGroup`,
- `createStatus`, `updateStatus`, `deleteStatus`.
- Rozszerzono routing o trasy `/settings/statuses*` i `/settings/status-groups*`.
- Sidebar ustawien ma nowy link `Statusy`.
- Dodano widok `resources/views/settings/statuses.php` oraz style SCSS dla formularzy/akcji tego widoku.
- Potwierdzenia usuwania w nowym widoku realizowane sa przez `window.OrderProAlerts.confirm(...)`.
- Przebudowano UI `Ustawienia > Statusy`:
- 2 taby (`Statusy`, `Grupy statusow`),
- sortowanie realizowane przez drag-and-drop z automatycznym zapisem kolejnosci po upuszczeniu.
- Skondensowano UI zakladki `Ustawienia > Statusy`:
- elementy listy statusow i grup maja bardziej kompaktowy, jednoliniowy uklad,
- zmniejszono paddingi/gapy i wysokosci kontrolek, aby zwiekszyc ilosc danych widocznych bez scrolla.
- Wprowadzono globalna preferencje kompaktowego UI w `AGENTS.md`.
- Poprawiono generowanie `code` dla statusow/grup: polskie znaki sa transliterowane do ASCII
(np. `Nieopłacone` -> `nieoplacone`), zamiast zamiany na `_`.
- Dodano skrypt serwisowy `bin/fix_status_codes.php`:
- przelicza kody grup/statusow na podstawie aktualnych nazw z transliteracja PL->ASCII,
- zapewnia unikalnosc kodow (`_2`, `_3` przy konfliktach),
- wspiera `--dry-run` i `--use-remote`.
- Wykonano naprawe kodow na bazie zdalnej (`--use-remote`): zaktualizowano 2 grupy i 1 status.
- Przygotowano draft generycznego schematu tabel zamowien (Apilo tylko jako przyklad pol API):
- dokumentacja: `DOCS/ORDERS_SCHEMA_DRAFT.md`,
- draft SQL (nieuruchamiany automatycznie): `database/drafts/20260302_orders_schema_v1.sql`.
- Wdrozono generyczny schema zamowien na bazie docelowej przez `bin/deploy_and_seed_orders.php`.
- Zasiano dane testowe:
- `orders`: 30,
- `order_items`: 90,
- `order_status_history`: 123,
- pozostale kolekcje (adresy/platnosci/wysylki/dokumenty/notatki/tagi) proporcjonalnie.
- Dodano endpointy zapisu kolejnosci:
- `POST /settings/status-groups/reorder`,
- `POST /settings/statuses/reorder`.
- Zmieniono obsluge pola `code`:
- `code` jest automatycznie generowany przy tworzeniu z nazwy,
- po utworzeniu jest tylko do odczytu i nie podlega edycji z formularza.
- Reset projektu do trybu `users-only`.
- Zarchiwizowano moduly poza `Auth` i `Users` do `archive/2026-03-02_users-only-reset/`.
- Uproszczono routing i layout do obslugi logowania i zarzadzania uzytkownikami.
- Ustalono nowy standard dokumentacji technicznej w plikach root:
- `DB_SCHEMA.md`
- `ARCHITECTURE.md`
- `TECH_CHANGELOG.md`
- Przywrocono sekcje `Ustawienia` w nawigacji jako grupe z podkategoriami:
- `Uzytkownicy` (`/users`)
- `Baza danych` (`/settings/database`)
- Dodano modul `App\Modules\Settings` z kontrolerem `SettingsController` (metody `database`, `migrate`).
- Przywrocono reczne uruchamianie migracji z UI:
- `GET /settings/database` (status migracji + lista pending plikow),
- `POST /settings/database/migrate` (wykonanie pending migracji + log ostatniego uruchomienia).
- Zmieniono tlumaczenie `settings.database.title` na `Baza danych` oraz dodano `navigation.database`.
- Poprawiono redirect po logowaniu (`AuthController`): `/dashboard` -> `/settings/users`.
- Usunieto wewnetrzny pasek zakladek (`settings-nav`) z podstron ustawien.
- Podstrona uzytkownikow jest adresowana jako `GET/POST /settings/users` (z zachowaniem tras kompatybilnosci `/users`).
- Usunieto z podstron ustawien blok naglowkowy `Ustawienia` + opis, aby zwiekszyc obszar roboczy.
- Rozszerzono `bin/deploy_and_seed_orders.php` o parametr `--profile=default|realistic`.
- Dodano realistyczny profil seedowania:
- wazone losowanie statusow i metod platnosci,
- spojne mapowanie `external_status_id` -> `payment_status` i `total_paid`,
- bardziej realne reguly tworzenia wpisow `order_payments`, `order_shipments`, `order_documents`,
- historia statusow oparta na logicznych sciezkach przejsc (zamiast losowych skokow).
- Wykonano ponowne wdrozenie draftu i seed z profilem realistycznym:
- komenda: `C:\xampp\php\php.exe bin/deploy_and_seed_orders.php --use-remote --count=30 --profile=realistic`,
- wynik: `orders=30`, `order_items=94`, `order_status_history=81`.
- Dodano glowna sekcje panelu `Zamowienia` z podzakladka `Lista zamowien`.
- Wdrozone endpointy:
- `GET /orders` (redirect do `/orders/list`),
- `GET /orders/list` (widok listy).
- Dodano modul aplikacyjny:
- `App\Modules\Orders\OrdersController`,
- `App\Modules\Orders\OrdersRepository`.
- Widok listy zamowien opiera sie o aktualna baze (`orders`, `order_addresses`, `order_items`, `order_shipments`, `order_documents`) i udostepnia:
- filtry (fraza, zrodlo, status, status platnosci, zakres dat),
- sortowanie i paginacje,
- kompaktowe komorki (referencje, klient, status+platnosc, pozycje, kwoty, wysylka, daty),
- skrócone statystyki (`wszystkie`, `oplacone`, `wyslane`).
- Rozszerzono liste zamowien o podglad produktow w zamowieniu:
- nazwa produktu,
- miniatura (z `order_items.media_url`, fallback bez obrazu),
- ilosc sztuk per pozycja,
- licznik dodatkowych pozycji poza limitem podgladu.
- Miniatury produktow na liscie zamowien zostaly powiekszone o 100% (uklad bardziej czytelny).
- Dodano modal podgladu zdjecia po kliknieciu miniatury produktu na liscie zamowien.
- Status w kolumnie statusow jest prezentowany jako nazwa biznesowa (np. `Nowe`, `W realizacji`) bez technicznego kodu.
- Dodano skrypt serwisowy `bin/fill_order_item_images.php` do uzupelniania pustych `order_items.media_url`
losowymi URL (`picsum.photos`) i wykonano go na bazie zdalnej (`--use-remote`, zaktualizowano 94 rekordy).
- Rozszerzono sidebar o grupe `Zamowienia` z podlinkiem `Lista zamowien`.
- Dodano widok szczegolow zamowienia:
- endpoint `GET /orders/{id}`,
- link do szczegolow po kliknieciu numeru zamowienia na liscie,
- uklad sekcji inspirowany widokiem Apilo: pozycje, dane zamowienia, platnosc/wysylka, adresy, notatki, historia.
- Dopracowano widok `GET /orders/{id}` do ukladu bardziej zblizonego do Apilo:
- lewy panel statusow z licznikami,
- prawa kolumna szczegolow z paskiem akcji i tabami sekcji,
- aktywne wyroznienie biezacego statusu zamowienia.
- Dodano taki sam lewy panel statusow na `GET /orders/list`:
- grupy statusow z licznikami,
- klikniecie statusu filtruje liste zamowien po `status`,
- kolorowe liczniki per status (info/warn/success/danger).
- Poprawiono zrodlo panelu statusow (lista + szczegoly):
- podzial na grupy i nazwy statusow sa pobierane dynamicznie z `order_status_groups` + `order_statuses`,
- kolory pochodza z `order_status_groups.color_hex`,
- dla statusow nieprzypisanych do konfiguracji dodawana jest sekcja `Pozostale`.
- Ujednolicono render panelu statusow jako jeden widget widoku:
- nowy komponent `resources/views/components/order-status-panel.php`,
- komponent jest wspolnie uzywany przez `orders/list.php` i `orders/show.php`,
- statusy w szczegolach zamowienia sa klikalne (przejscie do listy z odpowiednim filtrem).
- Dodano klikalne taby w `orders/show.php`:
- przelaczanie sekcji bez przeladowania strony (JS),
- aktywny panel `Szczegoly zamowienia`,
- pozostale panele (`Historia zmian`, `Przesylki`, `Platnosci`, `Dokumenty`) zawieraja tymczasowe puste boksy.
- Zmieniono seed zamowien (`bin/deploy_and_seed_orders.php`):
- `external_status_id` jest losowany z aktywnych statusow z tabeli `order_statuses` (zgodnie z konfiguracja w `Ustawienia > Statusy`),
- dodano fallback do listy domyslnej, jesli tabela jest pusta/niedostepna,
- profil `realistic` ma fallback reguly finansowej dla niestandardowych statusow.
- Dodano skrypt serwisowy `bin/randomize_order_statuses.php`:
- losowo podmienia `orders.external_status_id` dla juz istniejacych zamowien na aktywne statusy z `order_statuses`,
- aktualizuje tez `is_canceled_by_buyer` dla statusu `cancelled`,
- wspiera `--use-remote` i `--dry-run`.
- Wykonano podmiane statusow na bazie zdalnej (`--use-remote`): zaktualizowano 30 zamowien.