diff --git a/.codebase-memory/.gitattributes b/.codebase-memory/.gitattributes new file mode 100644 index 0000000..7ffe250 --- /dev/null +++ b/.codebase-memory/.gitattributes @@ -0,0 +1,3 @@ +# Auto-generated by codebase-memory-mcp +# Prevent merge conflicts on compressed artifact +graph.db.zst merge=ours binary diff --git a/.codebase-memory/artifact.json b/.codebase-memory/artifact.json new file mode 100644 index 0000000..35b40a7 --- /dev/null +++ b/.codebase-memory/artifact.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "commit": "", + "indexed_at": "2026-05-19T07:44:30Z", + "project": "c-visual studio code-projekty-orderPRO", + "nodes": 3069, + "edges": 9206, + "original_size": 8519680, + "compressed_size": 1679158, + "compression_level": 9 +} \ No newline at end of file diff --git a/.codebase-memory/graph.db.zst b/.codebase-memory/graph.db.zst new file mode 100644 index 0000000..5a290ce Binary files /dev/null and b/.codebase-memory/graph.db.zst differ diff --git a/.paul/MILESTONES.md b/.paul/MILESTONES.md deleted file mode 100644 index 5235329..0000000 --- a/.paul/MILESTONES.md +++ /dev/null @@ -1,153 +0,0 @@ -# Milestones - -Completed milestone log for this project. - -## Active / Planned - -| Milestone | Status | Scope | Stats | -|-----------|--------|-------|-------| -| v3.9 Stabilizacja i splata dlugu technicznego | Ready to plan | Backlog reality check, accounting net correctness, invoice idempotency, delivery status verification, security, Sonar cleanup, performance, god-class refactors, architecture guardrails | 9 phases, plans TBD | -| v3.8 Erli Marketplace Integration | Complete in code | Erli API settings, order import, labels, status sync, tracking, automation hooks, shared-surface parity | 7 phases, 7 plans | - -| Milestone | Completed | Duration | Stats | -|-----------|-----------|----------|-------| -| v0.1 Initial Release | 2026-03-13 | 2 days | 6 phases, 15 plans | -| v0.2 Pre-Expansion Fixes | 2026-03-15 | 2 days | 1 phase, 5 plans | -| v0.3 Moduł Paragonów | 2026-03-15 | 1 day | 5 phases, 5 plans | -| v3.0 Mobile Responsive | 2026-04-19 | ~5 tygodni | 52 phases shipped, 55 plans | - ---- - -## ✅ v3.0 Mobile Responsive - -**Completed:** 2026-04-19 -**Duration:** ~5 tygodni (2026-03-15 → 2026-04-19) - -### Stats - -| Metric | Value | -|--------|-------| -| Phases shipped | 52 (z zakresu 52–105) | -| Phases deferred | 1 (Phase 68 Code Deduplication Refactor) | -| Phases cancelled | 1 (Phase 99 Order Delivery & Payment Edit) | -| Plans completed | 55 | -| Files changed | ~250+ | - -### Key Accomplishments - -- **Mobile UI core:** hamburger menu, slide-in sidebar, status panel toggle, image hover zoom, collapsed sidebar fix (Phase 52–55). -- **Order payments i automation events:** reczne platnosci + push `set_paid` do shopPRO; `payment.status_changed`, `order.status_changed`, `order.status_aged`, `order.imported`, `shipment.created/status_changed`, warunki statusowe i `payment_method` (Phase 56–61, 84, 95–96, 98). -- **Import re-import safety + personalizacja:** ochrona pol lokalnych przy re-imporcie shopPRO, activity log rozroznia import/aktualizacje, custom_fields + message jako personalizacja pozycji (Phase 62–63, 75, 79). -- **Receipts:** DATETIME precision, koszt wysylki jako pozycja, bugfix `buildItemsSnapshot`/`delivery_price` (Phase 64, 70, 90). -- **PAUL framework:** Delegated Apply + Codex Executor (Phase 65, 67). -- **Tracking Allegro i shopPRO:** English statuses, pull mapping, push statusow orderPRO→shopPRO/Allegro, Delivery Tracking (Phase 66, 69, 74–75, 83). -- **Przesylki:** preset auto-submit, przekazywanie waybill do Allegro, Apaczka COD bank account, Apaczka long-street truncation, Weekend Delivery (InPost), delete z szczegolow zamowienia, User-Agent header z publiczna /info (Phase 78, 86–89, 102, 104). -- **Listowanie i wyszukiwanie:** per_page w localStorage, search po produkcie, tooltipy, AJAX refresh, status group filter, global search w topbarze, aged highlight, popup preview (Phase 72–73, 80–82, 85, 94–95, 101). -- **Remember Me login, buyer name copy, info page** (Phase 92–93, 89). -- **Print pipeline:** resilient polling 3-layer timeout w OrderPROPrint, preset scope + print UX, auto-click najnowszej etykiety (Phase 91, 100, 103). -- **Project generation (PSD):** polautomatyczne generowanie projektow graficznych z zamowien + `external_status_id` → `status_code` rename + flagi statusu projektu (Phase 97). -- **Statistics (ostatnia faza):** dzienny raport zamowien `/statistics/orders` z filtrami (daty/kanaly/grupy statusow) i stopka `Podsumowanie`; hotfix collation MySQL; fallback netto 23% VAT (Phase 105). - -### Key Decisions - -| Decision | Rationale | -|----------|-----------| -| Event `order.imported` tylko przy pierwszym imporcie + backfill statusow | Unikniecie duplikatow reakcji automatyzacji, poprawa starych zamowien w_realizacji→wyslane | -| Push waybill do Allegro niekrytyczny dla lokalnej paczki | Blad API Allegro nie blokuje utworzenia przesylki; tylko dla `source=allegro` | -| Historia automatyzacji audytowana per rule + retencja 30 dni | Observability bez recznego utrzymania danych | -| Preset przesylek nadpisuje tylko wymiary+wage + auto-submit | Spojnosc z polityka single responsibility preseta | -| `_token` CSRF field standardized | Eliminacja konfliktu nazw z wczesnego `_csrf_token` | -| Statistics channelSql: `CAST(int AS CHAR) COLLATE utf8mb4_unicode_ci` | Unikniecie `1271 Illegal mix of collations`; pattern dla przyszlych raportow per-integration | -| Statistics netto fallback `/ 1.23` | shopPRO nie wysyla netto ani w zamowieniu ani w items — tymczasowy fallback; docelowy fix opisany w `.paul/TODO.md` (STAT-NET) | -| Phase 68 deferred | Refaktor deduplikacyjny wymaga wiekszego kontekstu — przeniesiony na pozniej | - -### Deferred to Next Milestone - -- **STAT-NET:** netto z shopPRO / `order_items.tax_rate` (unikniecie sztywnego 23% VAT). -- **Phase 68 Code Deduplication Refactor** (`0/2`, Planning). -- **Mobile Orders List / Mobile Order Details / Mobile Settings** — TBD z tabeli ROADMAP. - ---- - -## ✅ v0.3 Moduł Paragonów - -**Completed:** 2026-03-15 -**Duration:** 1 day (2026-03-15) - -### Stats - -| Metric | Value | -|--------|-------| -| Phases | 5 (8-12) | -| Plans | 5 | -| Files changed | ~25 | - -### Key Accomplishments - -- **DB Foundation:** 4 migracje (receipts, receipt_configs, receipt_number_counters, company_settings extended) -- **Konfiguracja paragonów:** CRUD w Ustawienia > Księgowość — wielokonfiguracyjne szablony numeracji -- **Wystawianie paragonów:** Formularz z zamówienia, snapshoty JSON (seller/buyer/items), atomowe numerowanie INSERT ON DUPLICATE KEY UPDATE -- **Podgląd i druk:** HTML preview w layoucie, standalone print z auto window.print(), PDF via dompdf v3.1 -- **Sekcja Księgowość:** Lista paragonów z filtrami, paginacją, sortowaniem, zaznaczaniem checkboxami -- **Eksport XLSX:** PhpSpreadsheet v5.5 — eksport zaznaczonych lub wszystkich z filtra (POST + CSRF) -- **Moduł Accounting:** Osobny namespace App\Modules\Accounting z ReceiptController, AccountingController, ReceiptRepository - -### Key Decisions - -| Decision | Rationale | -|----------|-----------| -| Snapshot pattern: seller/buyer/items jako JSON | Dane zamrożone w momencie wystawienia — niezależne od zmian źródła | -| Atomowe numerowanie: INSERT ON DUPLICATE KEY UPDATE | Bezpieczne kolejne numery paragonów bez race conditions | -| Moduł Accounting w osobnym namespace | Separacja od Settings — przyszłe rozszerzenie księgowości | -| dompdf v3.1 server-side PDF | Standard PHP, DejaVu Sans dla polskich znaków | -| PhpSpreadsheet v5.5 dla XLSX | Lepszy od CSV dla księgowości — formatowanie, polskie znaki | -| POST eksport z CSRF + dwa tryby | Bezpieczny; zaznaczone IDs lub wszystkie z filtra | -| ftp-kr vendor/ nie ignorowany | Zmiana z /vendor na /vendor/bin — auto-upload zależności na serwer | - ---- - -## ✅ v0.1 Initial Release - -**Completed:** 2026-03-13 -**Duration:** 2 days (2026-03-12 → 2026-03-13) - -### Stats - -| Metric | Value | -|--------|-------| -| Phases | 6 | -| Plans | 15 | -| Files changed | ~45 | - -### Key Accomplishments - -- **AllegroTokenManager** wydzielony z 4 klas — usunięto ~85 linii duplikatu logiki OAuth -- **StringHelper** centralizuje 19 kopii helperów (nullableString, normalizeDateTime, normalizeColorHex) z 15+ klas -- **CronHandlerFactory** jako jedyne miejsce kompozycji crona — naprawiono rozbieżność Application.php / bin/cron.php + 2 bugi w zależnościach -- **ZPL label page size** naprawiony — martwy warunek `'ZPL' ? 'A6' : 'A6'` → `'ZPL' ? 'A6' : 'A4'` -- **AllegroStatusSyncService** — kursor `last_status_checked_at` eliminuje skanowanie wszystkich zamówień -- **ShopproOrderSyncStateRepository** — poprawna zależność (poprzednio używano Allegro repo) -- **CSRF standardization** — `_csrf_token` → `_token` w całym projekcie -- **5 kompensujących migracji** zaadnotowanych — DB_SCHEMA.md ma sekcję Compensating Migrations -- **Flash::set()/Flash::get()** — 10 bezpośrednich `$_SESSION` writes zastąpiono w kontrolerach -- **Typowane wyjątki** — hierarchia OrderProException (6 klas) eliminuje 95× RuntimeException -- **Stałe IntegrationSources + RedirectPaths** — 40+ powtarzających się literałów zebranych w 2 klasy -- **Złożoność kognitywna** — loadDeliveryServices() w 2 kontrolerach spłaszczone z 5 do 2 poziomów zagnieżdżenia -- **ShopproOrdersSyncService** podzielony 39→9 metod via ShopproOrderMapper + ShopproProductImageResolver -- **AllegroIntegrationController** podzielony 35→25 metod via 2 nowe kontrolery mapowań -- **SonarQube S1448** zredukowane 6x → 2x; S112 z 95x do 0; S1192 z 40x do 0 - -### Key Decisions - -| Decision | Rationale | -|----------|-----------| -| AllegroTokenManager wydzielony z 4 klas | Eliminacja duplikacji logiki odświeżania tokenów | -| StringHelper jako final static class | Centralizacja 19 kopii helperów | -| CronHandlerFactory — jedyne miejsce kompozycji crona | Synchronizacja Application.php i bin/cron.php | -| CSRF pole: `_token` (nie `_csrf_token`) | Standard dla całego projektu | -| Flash::set()/Flash::get() zamiast $_SESSION | Jeden mechanizm flash w całej aplikacji | -| validateXxxInput(): ?string / validateXxxAccess(): ?Response | Wzorzec helperów walidacji — ≤3 return statements | -| God class split via move-method | Czysty podział bez zmiany logiki — ShopproOrdersSyncService 39→9 metod | -| AllegroIntegrationController pozostaje przy 25 metodach | Pełny podział wymaga AllegroImportScheduleService — deferred | - ---- diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md index 1c1af37..c873604 100644 --- a/.paul/PROJECT.md +++ b/.paul/PROJECT.md @@ -1,334 +1,24 @@ -# orderPRO +# PROJECT — orderPRO -## What This Is +**Utworzono:** 2026-05-19 -Aplikacja do zarzÄ…dzania zamĂłwieniami pobieranymi z wielu ĹşrĂłdeĹ‚ sprzedaĹĽy (Allegro, Erli, wĹ‚asne sklepy internetowe). UmoĹĽliwia generowanie etykiet przewozowych u kurierĂłw oraz docelowo zarzÄ…dzanie produktami i stanami magazynowymi w jednym miejscu. +## Nazwa +orderPRO -## Core Value +## Krotki opis +Lekki panel do zarzadzania zamowieniami (PHP 8.4, Medoo, własny mikroframework MVC, SCSS/jQuery na froncie). -Sprzedawca moĹĽe obsĹ‚ugiwać zamĂłwienia ze wszystkich kanałów sprzedaĹĽy i nadawać przesyĹ‚ki bez przełączania siÄ™ miÄ™dzy platformami. - -## Current State - -| Attribute | Value | -|-----------|-------| -| Version | 3.9.0-dev | -| Status | v3.14 Polkurier COD Return Time Hotfix complete - Phase 145 closed | -| Last Updated | 2026-05-18 (Phase 145 unified) | - -## Requirements - -### Validated (Shipped) - -- [x] Integracja z Allegro — pobieranie zamĂłwieĹ„ -- [x] Generowanie etykiet (InPost) -- [x] Performance: N+1 subqueries fix, DB indexes — Phase 7 -- [x] Stability: SSL verification, cron throttle — Phase 7 -- [x] UX: orderpro-to-allegro disable, lista zamĂłwieĹ„ poprawki — Phase 7 -- [x] Unit tests: AllegroTokenManager, AllegroOrderImportService (12 testĂłw) — Phase 7 -- [x] InPost ShipX API: natywny provider niezaleĹĽny od Allegro — Phase 7 -- [x] DB Foundation: tabele receipts, receipt_configs, receipt_number_counters + company_settings extended — Phase 8 -- [x] Konfiguracja paragonĂłw (CRUD w Ustawienia > KsiÄ™gowość) — Phase 9 -- [x] Wystawianie paragonĂłw z zamĂłwienia (formularz, snapshoty, atomowe numerowanie) — Phase 10 -- [x] PodglÄ…d i wydruk paragonu (HTML+PDF, dompdf) — Phase 11 -- [x] Sekcja KsiÄ™gowość — lista paragonĂłw z filtrami, paginacjÄ…, eksportem XLSX — Phase 12 -- [x] DB Foundation: tabele email_mailboxes, email_templates, email_logs — Phase 13 -- [x] Skrzynki pocztowe SMTP (CRUD + test połączenia) — Phase 13 -- [x] Szablony wiadomoĹ›ci e-mail (CRUD + Quill.js + system zmiennych + załączniki) — Phase 14 -- [x] WysyĹ‚ka e-mail z zamĂłwieĹ„ (resolwer zmiennych, załączniki, log) — Phase 15 -- [x] Zadania automatyczne — reguĹ‚y zdarzenie/warunki/akcje (CRUD + watcher/executor) — Phase 16 -- [x] OstrzeĹĽenie i potwierdzenie przy duplikacie paragonu — Phase 17 -- [x] Print Queue Backend: REST API + API key auth + CRUD kluczy — Phase 18 -- [x] UI Integration: przycisk Drukuj, bulk print, kolejka wydruku — Phase 19 -- [x] Windows Client: C# WinForms tray app, polling API, druk etykiet PDF — Phase 20 -- [x] WyĹ›wietlanie nazwy integracji zamiast generycznego "shopPRO" na liĹ›cie i szczegółach zamĂłwienia — Phase 21 -- [x] Naprawa zapisu REGON, BDO, KRS i logo w ustawieniach firmy — Phase 22 -- [x] Presety przesyĹ‚ek — customowe przyciski szybkiego wypeĹ‚niania formularza (CRUD + autofill + zarzÄ…dzanie) — Phase 23-25 -- [x] RÄ™czny numer przesyĹ‚ki — dodawanie tracking number bez API przewoĹşnika — Phase 26 -- [x] Tracking backend — dwupoziomowe statusy dostawy, 3 implementacje providerĂłw, cron handler — Phase 27 -- [x] Tracking UI i ustawienia crona — statusy dostawy i konfiguracja harmonogramu — Phase 28-29 -- [x] UI readability tweak - rozdzielenie koloru przyciskow akcji od naglowkow sekcji (button primary distinction) - Phase 30 -- [x] Usuniecie bulk print "Drukuj etykiety" z listy zamowien (`/orders/list`) wraz z endpointem bulk - Phase 40 -- [x] Ograniczenie szumu logow importu Allegro i deduplikacja wpisow activity log - Phase 41 -- [x] Automatyzacja: event `shipment.status_changed` + warunki statusowe przesylki - Phase 42 -- [x] Usuwanie wpisu z kolejki druku etykiet z panelu ustawien - Phase 43 -- [x] Szybka zmiana statusu zamowienia z listy zamowien (inline dropdown + AJAX) - Phase 44 -- [x] Synchronizacja statusow orderPRO -> shopPRO (cron push, reverse mapping, PUT API) — Phase 45 -- [x] Synchronizacja statusow orderPRO -> Allegro (cron push, reverse mapping, fulfillment status update API) - Phase 46 -- [x] Automatyzacja przesylek: natychmiastowy event `shipment.created` + akcja `update_shipment_status` - Phase 47 -- [x] Szablony e-mail: zmienne `przesylka.numer` i `przesylka.link_sledzenia` z provider-aware linkiem sledzenia - Phase 48 -- [x] Automatyzacja: tab Historia z filtrowaniem/paginacja + retencja 30 dni + akcja update_order_status - Phase 49 -- [x] Allegro: automatyczne przekazywanie numeru przesylki do checkout form po utworzeniu paczki (tylko source=allegro) - Phase 50 -- [x] Email HTML Layout: header/footer HTML per skrzynka pocztowa, dual-mode edytor (Quill + HTML source), kompozycja header+body+footer, podglad — Phase 51 -- [x] Mobile Main Menu: hamburger, slide-in overlay sidebar, backdrop na mobile <=768px — Phase 52 -- [x] Mobile Status Panel Toggle: zwijany/rozwijany panel statusow na /orders/list — Phase 53 -- [x] Order Detail Image Hover: hover zoom na miniaturkach produktow w /orders/{id} — Phase 54 -- [x] Desktop Collapsed Sidebar Fix: ukrycie etykiet, centrowanie ikon w zwiniętym sidebarze — Phase 55 -- [x] Dodawanie płatności ręcznych + push set_paid do shopPRO — Phase 56 -- [x] Automatyzacja: event `payment.status_changed` + warunek `payment_status` (0/1/2) — Phase 57 -- [x] Zachowanie danych formularza automatyzacji po bledzie walidacji — Phase 58 -- [x] Automatyzacja: event `order.status_changed` + warunek `order_status` — Phase 59 -- [x] Automatyzacja: event `order.status_aged` (cron) + warunek `days_in_status` — Phase 60 -- [x] Aktywacja przycisku Platnosc w headerze zamowienia + poprawa odstepu w formularzu platnosci — Phase 61 -- [x] Ochrona danych lokalnych przy re-imporcie + rozroznienie import/aktualizacja w activity log shopPRO — Phase 62 -- [x] Import i wyswietlanie personalizacji produktow z shopPRO (custom_fields) + naprawa daty zamowienia — Phase 63 -- [x] Data wystawienia paragonu z dokladnoscia do godziny i minuty (DATE -> DATETIME) — Phase 64 -- [x] Koszt wysylki jako pozycja paragonu (bugfix buildItemsSnapshot + delivery_price) — Phase 70 -- [x] Import atrybutow produktow z shopPRO (attributes + custom_fields w personalizacji) — Phase 71 -- [x] Zapamiętywanie wybranej liczby wierszy na stronie (per_page) w localStorage — Phase 72 -- [x] Wyszukiwanie zamowien po nazwie produktu (EXISTS subquery) — Phase 73 -- [x] Odwrocenie mapowania statusow: orderPRO po lewej, zewnetrzne po prawej (shopPRO + Allegro) — Phase 74 -- [x] Rozdzielenie mapowania push/pull statusow shopPRO + ochrona statusu przy re-imporcie — Phase 75 -- [x] Fallback danych odbiorcy z customer gdy delivery nie ma adresu (shopPRO) — Phase 76 -- [x] Naprawa auto-fill kwoty pobrania (COD) dla zamowien shopPRO — Phase 77 -- [x] Presety przesylek: auto-submit formularza po autofill — Phase 78 -- [x] Import pola message z shopPRO do personalizacji pozycji i notatek zamowienia — Phase 79 -- [x] Przeladowanie listy zamowien po zmianie statusu inline (location.reload) — Phase 80 -- [x] Globalna wyszukiwarka zamowien w topbarze (AJAX search, dropdown, nawigacja klawiaturowa) — Phase 81 -- [x] Tooltip z pelna nazwa produktu na liscie zamowien (natywny title attribute) — Phase 82 -- [x] Dedykowane pull mapowanie statusow Allegro przy imporcie zamowien — Phase 83 -- [x] Automatyzacja: zdarzenie `order.imported` przy pobraniu zamowienia (Allegro + shopPRO) — Phase 84 -- [x] Filtrowanie zamowien po grupie statusow (klikalna nazwa grupy na panelu) — Phase 85 -- [x] Naprawa tworzenia przesylek COD Apaczka — dodanie numeru konta bankowego do payloadu API — Phase 86 -- [x] Usuwanie przesylek z zakladki Przesylki w szczegolach zamowienia (z potwierdzeniem) — Phase 87 -- [x] Naglowek User-Agent w requestach Allegro API (art. 3.4.c Regulaminu, deadline 30.06.2026) — Phase 88 -- [x] Publiczna strona /info dla Allegro User-Agent URL — Phase 89 -- [x] Naprawa zapisu delivery_price przy imporcie zamowien (Allegro + shopPRO) + backfill — Phase 90 -- [x] Resilient polling w OrderPROPrint — 3 warstwy timeout (HttpClient/CancellationToken/Watchdog) — Phase 91 -- [x] Ikona kopiowania imienia i nazwiska kupujacego w szczegolach zamowienia (clipboard copy) — Phase 92 -- [x] Checkbox "Zapamietaj mnie" z persistent cookie 30 dni + dzialajace komunikaty bledow logowania — Phase 93 -- [x] Popup podgladu zamowienia na liscie zamowien (zdjecia, personalizacja, notatki, kopiowanie) — Phase 94 -- [x] AJAX refresh tabeli i panelu statusow po zmianie statusu inline (bez reload strony) — Phase 95 -- [x] Automatyzacja: warunek "Metoda platnosci" (COD/Przelew/Karta/Inna) oparty na external_payment_type_id — Phase 96 -- [x] Polautomatyczne generowanie projektow graficznych PSD z zamowien (mapowania, komenda Claude, Photoshop API, flagi statusu) + rename external_status_id na status_code — Phase 97 -- [x] Event automatyzacji `order.imported` ogranicza sie do pierwszego importu zamowienia + backfill statusow w_realizacji -> wyslane dla zamowien z istniejaca przesylka — Phase 98 -- [x] Preset przesylek nadpisuje wylacznie wymiary+wage paczki + polling kolejki wydruku + auto-click ostatniej etykiety po utworzeniu przesylki + usuniecie placeholderow "-" — Phase 100 -- [x] Wizualna flaga wiekowa na liscie zamowien: czerwona ramka o rosnacej intensywnosci dla zamowien 4-7+ dniowych — Phase 101 -- [x] Naprawa tworzenia przesylek Apaczka dla dlugich adresow: auto-truncate dla uslug punktowych (ORLEN/Paczkomat), walidacja + blad dla uslug kurierskich — Phase 102 -- [x] Naprawa auto-click etykiety po utworzeniu przesylki: klik na najnowsza paczke zamiast najstarszej (buttons[0] vs buttons[length-1]) — Phase 103 -- [x] Apaczka Paczka w Weekend: checkbox "Dostawa w weekend (sobota)" dla uslug InPost paczkomatowych + mapowanie pole formularza weekend_delivery -> option[19] w API Apaczki — Phase 104 -- [x] Statystyki zamowien: widok `/statistics/orders` z filtrami (daty, kanaly multiselect, grupy statusow multiselect) i raportem dziennym per kanal (Allegro, shopPRO per integracja); hotfix collation MySQL + fallback netto 23% VAT — Phase 105 -- [x] Wersja mobilna — modul po module (v3.0) — shipped across phases 52–105 -- [x] Alert o kliencie z historia zwrotow: badge w liscie zamowien (kolumna buyer) + czerwony banner u gory szczegolow zamowienia; matching OR po email/phone/name; `
` z lista zwroconych zamowien — Phase 106 -- [x] Idempotentna jednorazowa wysylka e-mail per zamowienie: tabela deduplikacji `automation_email_once_deliveries` (UNIQUE KEY rule_id+action_id+order_id), checkbox "Wyslij tylko raz" w konfiguracji akcji, markSent() tylko po sukcesie — Phase 107 -- [x] Delivery Status Management: tabela `delivery_statuses` z CRUD panelem `/settings/delivery-statuses`, `DeliveryStatus::setRepository()` z DB fallbackiem, integracja DB-driven w dropdownach automatyzacji (warunek shipment_status + akcja update_shipment_status), osobna podstrona formularza CRUD (BREAKING: drop backward compat dla starych grupowych kluczy automatyzacji) — Phase 108 -- [x] Checkbox dropdown multi-select filters: `/statistics/orders` korzysta z progresywnie ulepszanych selectow multiple z checkboxami, opcja "Wszystkie" i zachowanym kontraktem GET — Phase 109 -- [x] Podsumowanie statystyk: `Statystyki -> Podsumowanie` z miesiecznymi wykresami liczby i wartosci zamowien per integracja plus `Razem`, Chart.js i fallback tabelaryczny — Phase 110 -- [x] Re-import zamowienia (Allegro + shopPRO) wykrywa tranzycje payment_status 0/1->2 i emituje `payment.status_changed` (chain reguly #7 zmienia status na `w_realizacji`); naprawa luki dla zamowien zaimportowanych przed potwierdzeniem platnosci (case #864) + backfill CLI — Phase 111 -- [x] Re-import istniejacego zamowienia jest delta-only: skip dla pozycji/adresow/notatek (stabilne `order_items.id`, ochrona `project_generated`), zawezony `updateOrderDelta()`, propagacja anulowania ze zrodla, identical-payload no-op guard (case #882) — Phase 112 -- [x] Fundament v3.7 Invoices: tabele `invoices`, `invoice_configs`, `invoice_number_counters`, `fakturownia_integration_settings` + `orders.invoice_requested`; CRUD kont Fakturowni z testem polaczenia API (`/settings/integrations/fakturownia`); karta w hubie integracji — Phase 113 -- [x] Ksiegowosc: refaktor `/settings/accounting` na hub-rozdroze + osobne podstrony `/receipts` i `/invoices` + edycja na osobnym widoku; pelen CRUD `invoice_configs` z opcja delegacji do Fakturowni (conditional integration_id, serwerowa walidacja); seed `Domyslny VAT`; globalny modul `confirm-delete.js` — Phase 114 -- [x] Wystawianie faktury z zamowienia: toggle `orders.invoice_requested` w zakladce Platnosci + auto-set z importu (Allegro `invoice.required` / shopPRO 5-key parser); formularz z auto-fillem NIP przez MF Biala Liste (publiczne API); dual flow lokalny (Dompdf + atomowy `invoice_number_counters`) / delegowany (POST do Fakturowni przed INSERT, redirect 302 do natywnego PDF); lista `/settings/accounting/invoices/issued` z filtrami; snapshot pattern w `invoices` JSON; PHP 8.5-compatible (curl_close removed) — Phase 115 -- [x] Integracja HostedSMS: pojedyncza globalna konfiguracja w `/settings/integrations/hostedsms`, szyfrowane haslo, karta w hubie integracji i realna wysylka testowego SMS z edytowalna trescia oraz czytelnym statusem MessageId — Phase 116 -- [x] Integracja SMSPLANET: pojedyncza globalna konfiguracja w `/settings/integrations/smsplanet`, szyfrowane sekrety, autoryzacja Bearer token albo key + password, karta w hubie integracji i realna wysylka testowego SMS — Phase 117 -- [x] Re-import ochrona `total_paid`: gdy `payment_status` sie nie zmienia, `updateOrderDelta()` nie nadpisuje `total_paid` (ani `is_canceled_by_buyer`, chyba ze cancel ze zrodla); chroni reczne korekty operatora (zwroty czesciowe). Dynamic SQL SET builder + 3 testy PHPUnit (Reflection + sqlite) — Phase 119 -- [x] Ujednolicony moduł alertów UI: reusable PHP komponent `resources/views/components/alert.php` z inline SVG ikoną per typ (info/success/warning/danger), opcjonalnym dismiss button (vanilla JS, idempotent); brakujący `.alert--info` (#eff6ff/#bfdbfe/#1e3a8a); `Flash::push/all` z BC dla `set/get` (heurystyka klucza legacy); centralny renderer flash w 3 layoutach (app/auth/public); 36 widoków zmigrowanych off inline alert markup; `.flash--*` usunięte z widoków — Phase 120 -- [x] Eksport XLSX paragonow w `/accounting`: nowe naglowki (Numer | Data wystawienia | Kwota brutto | Kwota netto | Stawka VAT | Kwota VAT) z osobnym wierszem per stawka VAT; `items_json` snapshot rozszerzony o `vat` per pozycja (z `order_items.tax_rate`, fallback 23.0); legacy fallback `net = brutto/1.23` — Phase 123 -- [x] Szablony SMS: CRUD w `/settings/sms-templates` (name + body + is_active), wspolny `SmsVariableResolver` wydzielony z Email\\VariableResolver (placeholdery `{{zamowienie.*|kupujacy.*|adres.*|firma.*|przesylka.*}}`), dropdown "Wybierz szablon" w zakladce SMS na `/orders/{id}` wstawia rozwiniete zmienne do textarea (z `OrderProAlerts.confirm` przy nadpisaniu); stopka SMSPLANET dalej doklejana wylacznie przez `SmsConversationService::buildFinalOutboundBody()` (Phase 122 contract preserved) — Phase 124 -- [x] Bugfix detekcji faktury przy imporcie: shopPRO order z `firm_nip` ustawia `invoice_requested=1` (mapper jako jedyne zrodlo heurystyki, sync service propaguje `aggregate['invoice_detected']`); Allegro rozszerzony o `naturalPerson=false`/`address.taxId`/`companyName` (wczesniej tylko `invoice.required`); usunieta legacy kolumna `orders.is_invoice` (Phase 115 dryft) + backfill 7 zamowien — Phase 125 -- [x] Fundament integracji Erli: pojedyncza globalna konfiguracja `/settings/integrations/erli`, szyfrowany Bearer API key, realny test `GET /svc/shop-api/inbox`, karta w hubie integracji oraz dokumentacja schematu/architektury — Phase 127 -- [x] Import zamowien Erli: pobieranie `/inbox` przez cron i recznie, mapper do orderPRO, delta-only re-import, `invoice_requested` z danych firmowych/NIP, bezpieczny ACK `/inbox/mark-read` po bezblednym batchu — Phase 128 -- [x] Mapowanie i synchronizacja statusow Erli: osobne pull/push mappings, discovery statusow z inboxa, reczny-only push `PATCH /orders/{id}/status`, cron `erli_status_sync` i zakladki w ustawieniach Erli — Phase 129 -- [x] Przesylki Erli: zakladka mapowania dostaw, etykiety przez lokalne providery InPost/Apaczka i rejestracja paczek zewnetrznych w Erli przez `POST /shipping/external` — Phase 130 -- [x] Tracking i automatyzacje Erli: lokalny provider tracking jak w Allegro, retry niekrytycznej rejestracji paczki zewnetrznej Erli z `shipment_tracking_sync`, wspolny kontekst `shipment.created`/`shipment.status_changed` dla regul e-mail/SMS/statystyk — Phase 131 -- [x] Hardening Erli: spojna diagnostyka importu/ACK w `integration_order_sync_state.last_error`, brak ACK po blednym batchu, testy jednostkowe import/status sync i dokumentacja obserwowalnosci bez nowej migracji — Phase 132 -- [x] Parytet Erli w powierzchniach wspolnych: filtr zrodla zamowien, kanaly statystyk dziennych/podsumowania, warunek integracji automatyzacji, menu integracji i etykiety `zrodlo` uzywaja wspolnego rejestru zrodel — Phase 133 -- [x] Backlog Reality Check: reczne wpisy z `.paul/codebase/todo.md` i dawny raport ryzyk sklasyfikowane przeciw aktualnemu kodowi/docs, z dowodami w `BACKLOG-AUDIT.md` i pierwotnym routingiem do kolejnych faz dlugu; nieaktualne fazy 140+ usuniete 2026-05-18 decyzja operatora — Phase 134 -- [x] Accounting Net Correctness: nowe paragony zapisuja VAT-aware `receipts.total_net`, a statystyki dzienne preferuja source-level net, potem `order_items` VAT fallback, z gross `/1.23` tylko jako legacy fallback — Phase 135 -- [x] Fakturownia Invoice Idempotency: delegowane faktury uzywaja stabilnego `oid=orders.internal_order_number`, lookup-first `GET /invoices.json?oid=...`, lokalnego stanu `pending_external`/`failed_retryable` i auto-attach po timeoutach — Phase 136 -- [x] Delivery Status Backlog Verification: `DELIVERY-STATUS-MGMT` zamkniete jako wdrozone; runtime korzysta z DB-driven statusow, a read-only DB check nie wykazal starych ani niepoprawnych kluczy automatyzacji — Phase 137 -- [x] Security and Legacy Hardening: test SMTP ma strict TLS by default z lokalnym `SMTP_ALLOW_SELF_SIGNED_DEV`, szablony e-mail/SMS blokuja nieznane placeholdery, raw `$_SESSION` jest izolowany w `Session`, a wskazane widoki uzywaja `$component()` zamiast hard `require` — Phase 138 -- [x] Sonar Critical/Major Cleanup: Phase 139 odswiezyla baseline Sonar i zmniejszyla OPEN BLOCKER/CRITICAL/MAJOR z 648 do 495 przez delivery-status/statistics cleanup, typowane wyjatki oraz szeroka migracje alert include/import patterns — Phase 139 -- [x] shopPRO Polkurier Delivery Mapping: zakladka `Dostawy` integracji shopPRO pozwala mapowac forme dostawy na Polkurier, laduje uslugi z `PolkurierShipmentService::getDeliveryServices()` i zapisuje `provider='polkurier'` w `carrier_delivery_method_mappings` bez migracji DB — Phase 140 -- [x] Integrations Hub Grouped Sections: `/settings/integrations` pokazuje lekkie sekcje dla marketplace, kurierow i pozostalych integracji, bez starego naglowka/opisu wspolnego panelu — Phase 141 -- [x] Polkurier Shipment Prepare Prefill: `/orders/{id}/shipment/prepare` rozpoznaje mapowania shopPRO z `provider='polkurier'`, preselectuje przewoznika i usluge oraz nie fallbackuje do Allegro — Phase 142 -- [x] Orders List Sidebar UI Hotfix: `/orders/list` startuje bez opisowego boksu "Zamowienia", a zapisany zwiniety sidebar jest stosowany przed pierwszym renderem strony — Phase 143 -- [x] Imported Notes Badge Count Hotfix: badge `[N]` na `/orders/list` zlicza wszystkie `order_notes` zamowienia, lacznie z notatkami importowanymi z shopPRO i notatkami autorskimi operatora — Phase 144 -- [x] Polkurier COD Return Time Hotfix: payload pobrania wysyla `COD.codtype='S'` oraz `COD.return_cod='BA'`, zamiast blednego `transfer` w polu terminu zwrotu pobrania — Phase 145 -- [x] Integracja polkurier.pl (fundament): pojedyncza globalna konfiguracja w `/settings/integrations/polkurier`, szyfrowany Token API + login, karta w hubie integracji obok Apaczki i realny test polaczenia przez `apimetod=test_auth_api` zweryfikowany na zywym koncie operatora; `ShipmentProviderRegistry` netkniety — `PolkurierShipmentService/TrackingService` w kolejnych fazach — Phase 127 -- [x] polkurier ShipmentService + TrackingService + UI prepare panel: pelen kontrakt API (createShipment/getLabel/getStatus/cancelOrder/getAvailableCarriers), `PolkurierShipmentService` implementujacy `ShipmentProviderInterface` z normalizacja shipmenttype (lowercase) i splitem ulicy na street/housenumber/flatnumber, `PolkurierTrackingService` mapujacy statusy O/P/A/WP/D/Z/W na znormalizowane, panel "polkurier" w `prepare.php` z dynamiczna lista uslug z `available_carriers`, seed migracja `delivery_status_mappings(provider='polkurier')` z 7 wpisami z PDF v1.11; live test na #114/#115 zakonczony sukcesem po 4 iteracjach (ReferenceError → uppercase shipmenttype → orderno parsing → A4/A6); rozmiar etykiety sterowany w panelu klienta polkurier.pl (Ustawienia konta → Preferencje etykiet), NIE przez API — Phase 128 -- [x] Order User Notes module (Phase 129): pelen CRUD notatek autorskich operatora per zamowienie. Reuse `order_notes` przez nowy `note_type='user'` z `user_id` (FK→users SET NULL) + `author_name` (snapshot) + indeks `idx_order_notes_type_order`. `OrderNotesService` z autoryzacja DB-level (`WHERE user_id = :user_id`, rowCount=0 ⇒ 403). Sekcja `#notes` w "Wiadomosci i zalaczniki" w `/orders/{id}` z inline edit form + delete przez `OrderProAlerts.confirm`. Badge `[N]` (indigo neutralny) przy nr zamowienia na `/orders/list`; od Phase 144 badge korzysta z `notes_count` i liczy wszystkie rekordy `order_notes`, takze importowane ze zrodla. Brak admin override (brak systemu rol w aplikacji) — edit/delete tylko dla autora — Phase 129/144 -- [x] polkurier delivery status mappings UI (Phase 130): polkurier jako 4. provider w dropdownie `/settings/delivery-statuses?tab=mapping`. `POLKURIER_MAP` + `POLKURIER_DESCRIPTIONS` w `DeliveryStatus.php` (7 wpisow O/P/A/WP/D/Z/W z oficjalnej dokumentacji v1.11, identyczne z migracja Phase 128 — DB seed staje sie no-op). `PROVIDERS` rozszerzone w `DeliveryStatusesController` + `DeliveryStatusMappingController`. `countAllUnmappedForBadge()` zlicza polkurier. Zero zmian w widoku (`_delivery-status-mappings-content.php` auto-iteruje po providerach z controllera) — Phase 130 - -### Deferred - -- [ ] Eliminacja zduplikowanego kodu: SslCertificateResolver, ToggleableRepositoryTrait, RedirectPathResolver, ReceiptService — Phase 68 -- [ ] Historical receipt net backfill: pominięte w Phase 135 decyzja operatora; wracac tylko jesli stare paragony maja byc korygowane raportowo - -### Active (In Progress) - -- None - v3.9 current milestone is complete. - -### Planned (Next) - -- [ ] ZarzÄ…dzanie produktami -- [ ] ZarzÄ…dzanie stanami magazynowymi -- [ ] Mobile Orders List / Mobile Order Details / Mobile Settings — pelna wersja mobilna pozostalych ekranow - -### Out of Scope - -- [Do zdefiniowania podczas planowania] - -## Target Users - -**Primary:** Sprzedawcy wielokanaĹ‚owi (Allegro, Erli, wĹ‚asny sklep) -- ObsĹ‚ugujÄ… zamĂłwienia z wielu platform jednoczeĹ›nie -- PotrzebujÄ… szybkiego nadawania przesyĹ‚ek -- ChcÄ… jednego miejsca do zarzÄ…dzania sprzedaĹĽÄ… - -## Context - -**Business Context:** -Rynek narzÄ™dzi do zarzÄ…dzania sprzedaĹĽÄ… wielokanaĹ‚owÄ… (podobne rozwiÄ…zania: base.com, apilo.com). Aplikacja budowana jako wĹ‚asne rozwiÄ…zanie. - -**Technical Context:** -PHP (XAMPP/Laravel), integracje z API marketplace'Ăłw (Allegro, Erli) oraz API przewoĹşnikĂłw (InPost i inne). - -## Constraints - -### Technical Constraints -- PHP/XAMPP — Ĺ›rodowisko Windows lokalne -- Medoo + prepared statements (bez sklejania SQL) -- Brak natywnych `alert()`/`confirm()` — uĹĽywać `window.OrderProAlerts` -- Metody pomocnicze string/date/color → `App\Core\Support\StringHelper` (nie powielać w klasach) -- ZarzÄ…dzanie tokenami OAuth Allegro → `App\Modules\Settings\AllegroTokenManager` -- Kompozycja obiektĂłw crona → `App\Modules\Cron\CronHandlerFactory` (jedyne miejsce `new AllegroIntegrationRepository` i in. w kontekĹ›cie crona) -- Pole CSRF w formularzach HTTP: zawsze `_token` (nie `_csrf_token`) - -### Business Constraints -- [Do zdefiniowania podczas planowania] - -## Key Decisions - -| Decision | Rationale | Date | Status | -|----------|-----------|------|--------| -| WĹ‚asne rozwiÄ…zanie zamiast gotowego SaaS | PeĹ‚na kontrola nad funkcjonalnoĹ›ciÄ… | 2026-03-12 | Active | -| AllegroTokenManager wydzielony z 4 klas OAuth | Eliminacja duplikacji logiki odĹ›wieĹĽania tokenĂłw | 2026-03-12 | Active | -| StringHelper jako final static class w Core/Support | Centralizacja 19 kopii helperĂłw string/date/color z 15+ klas | 2026-03-12 | Active | -| CronHandlerFactory jako jedyne miejsce kompozycji crona | Application.php i bin/cron.php byĹ‚y rozsynchronizowane — 2 bugi w bin/cron.php | 2026-03-13 | Active | -| Pole CSRF w formularzach: `_token` (nie `_csrf_token`) | Standardyzacja na nazwÄ™ uĹĽywanÄ… przez wiÄ™kszość kodu (10+ kontrolerĂłw); eliminacja ryzyka pomyĹ‚ki przy nowych formularzach | 2026-03-13 | Active | -| Flash messages: Flash::set('module.type') / Flash::get('module.type', '') | Jeden wzorzec w caĹ‚ej aplikacji; eliminacja bezpoĹ›rednich zapisĂłw $_SESSION | 2026-03-13 | Active | -| validateXxxInput(): ?string i validateXxxAccess(): ?Response jako wzorce helperĂłw walidacji | Redukcja return statements do ≤3; spĂłjny wzorzec kontrolerĂłw | 2026-03-13 | Active | -| God class split via move-method bez zmiany logiki | ShopproOrdersSyncService 39→9 metod; AllegroIntegrationController 35→25 — czysty podziaĹ‚ przez ekstrakcjÄ™ klas | 2026-03-13 | Active | -| AllegroIntegrationController pozostaje przy 25 metodach (nie ≤15) | PeĹ‚ny podziaĹ‚ wymaga AllegroImportScheduleService — poza zakresem v0.1 | 2026-03-13 | Active | -| dg/bypass-finals do testĂłw final classes | Wszystkie klasy final — mockowanie przez bypass-finals zamiast usuwania final | 2026-03-15 | Active | -| InPost ShipX API zamiast Allegro WZA remap | InpostIntegrationRepository jest pod ShipX; niezaleĹĽność od Allegro | 2026-03-15 | Active | -| vendor/ w ftp-kr ignore | Auto-upload dev deps na serwer powodowaĹ‚ Fatal Error | 2026-03-15 | Active | -| Snapshot pattern: seller/buyer/items jako JSON w receipts | Dane zamroĹĽone w momencie wystawienia — niezaleĹĽne od przyszĹ‚ych zmian ĹşrĂłdĹ‚a | 2026-03-15 | Active | -| Atomowe numerowanie paragonĂłw: INSERT ON DUPLICATE KEY UPDATE | Bezpieczne generowanie kolejnych numerĂłw bez race conditions | 2026-03-15 | Active | -| ModuĹ‚ Accounting w osobnym namespace | App\Modules\Accounting — separacja od Settings | 2026-03-15 | Active | -| ATTACHMENT_TYPES jako centralna mapa typĂłw załącznikĂłw | Rozszerzalność: nowy typ = 1 linia w tablicy PHP, bez zmian DB/widoku | 2026-03-16 | Active | -| Quill.js 2.0.3 CDN dla edytora szablonĂłw | Brak build pipeline w projekcie; CDN prostszy | 2026-03-16 | Active | -| Event automatyzacji `shipment.created` uruchamiany natychmiast po utworzeniu paczki | Reakcje automatyzacji nie czekaja na cron tracking; przeplyw jest natychmiastowy | 2026-03-28 | Active | -| Akcja `update_shipment_status` emituje `shipment.status_changed` tylko przy realnej zmianie | Brak petli automatyzacji i brak falszywych triggerow | 2026-03-28 | Active | -| Zmienne e-mail przesylki bazuja na najnowszej paczce `shipment_packages` i `DeliveryStatus::trackingUrl` | Jeden spojny kontrakt dla numeru i linku sledzenia w szablonach | 2026-03-28 | Active | -| Historia automatyzacji zapisywana per regula (success/failed) i czyszczona cronem po 30 dniach | Audyt wykonywania regul bez recznego utrzymania danych | 2026-03-28 | Active | -| Akcja update_order_status korzysta z OrdersRepository::updateOrderStatus | Spojnosc z historia statusow i activity log bez duplikowania logiki | 2026-03-28 | Active | -| Push waybilla do Allegro checkout forms wykonywany tylko dla zamowien source=allegro i jest niekrytyczny dla lokalnego tworzenia paczki | Eliminacja recznego kroku po stronie Allegro bez ryzyka utraty lokalnie utworzonej przesylki przy bledzie API | 2026-03-28 | Active | -| Erli tracking uzywa lokalnych providerow jak Allegro, bez osobnego ErliTrackingService/UI statusow dostawy | Lokalny delivery status pozostaje zrodlem prawdy, a Erli dostaje niekrytyczny retry external parcel/tracking z crona | 2026-05-16 | Active | -| HostedSMS startuje jako jedna globalna konfiguracja z realnym testowym SMS | Operator potrzebowal na start tylko ustawien i potwierdzenia dzialania; SimpleAPI nie ma osobnego ping endpointu | 2026-05-12 | Active | -| Odbior odpowiedzi SMS z HostedSMS odlozony do osobnej fazy | Dokumentacja przewiduje metody odbioru SMS, ale wymagaja aktywacji interfejsu po stronie DCS/HostedSMS | 2026-05-12 | Deferred | -| SMSPLANET startuje jako jedna globalna konfiguracja z realnym testowym SMS | Operator potrzebowal drugiej bramki porownywalnej z HostedSMS, bez automatyzacji SMS w tej fazie | 2026-05-12 | Active | -| SMSPLANET obsluguje Bearer token oraz key + password | Dokumentacja SMSPLANET rekomenduje Bearer, ale API wspiera tez klucz i haslo; UI pozwala przetestowac oba warianty | 2026-05-12 | Active | -| Test SMSPLANET nie uzywa parametru `test=1` | Wymaganie UAT: test ma realnie wysylac SMS i zapisac wynik API w hubie integracji | 2026-05-12 | Active | -| Event `order.imported` emitowany tylko przy pierwszym imporcie zamowienia | Unikniecie duplikatow reakcji automatyzacji przy kolejnych synchronizacjach | 2026-04-15 | Active | -| Preset przesylek nadpisuje wylacznie wymiary+wage + auto-submit po autofill | Single responsibility preseta + szybszy flow operatora | 2026-04-17 | Active | -| Re-import istniejacego zamowienia jest delta-only — `replaceAddresses/Items/Notes` tylko przy `created=true`; `updateOrderDelta()` zawezony do payment_status/total_paid/status_code/is_canceled_by_buyer/source_updated_at/payload_json/fetched_at | Zamowienia zarzadzane sa w orderPRO (nie w zrodle), wiec re-import nie powinien nadpisywac stanu lokalnego ani lamac stabilnosci `order_items.id` (case #882: znikajace `project_generated`) | 2026-05-07 | Active | -| Identical-payload no-op guard w re-imporcie via `normalizePayloadJson()` (decode->encode->compare) | Eliminacja niepotrzebnych write'ow do binloga/replikacji przy cyklicznym imporcie tych samych zamowien; fail-open gdy klucze JSON sa reorderowane miedzy syncami | 2026-05-07 | Active | -| Statistics channelSql: explicit `COLLATE utf8mb4_unicode_ci` na CASE z `CAST(integration_id AS CHAR)` | Unikniecie `1271 Illegal mix of collations` w `IN (...)` z parametrami bindowanymi; pattern dla przyszlych agregacji per-integration | 2026-04-19 | Active | -| Statistics netto fallback `ROUND(gross / 1.23, 2)` gdy `total_without_tax` puste | Superseded by Phase 135: statystyki preferuja source-level net i `order_items` VAT fallback; gross `/1.23` zostaje tylko dla legacy bez uzywalnych itemow | 2026-04-19 | Superseded | -| ON DUPLICATE KEY UPDATE created_at = created_at dla idempotentnego markSent() | Unikniece silent failure i race condition przy rownolegych cronach; thread-safe bez wyjatkow | 2026-04-25 | Active | -| send_once_per_order opt-in przez checkbox (domyslnie off) | Wsteczna zgodnosc — istniejace reguly nie zmieniaja zachowania; markSent() tylko po sukcesie wysylki | 2026-04-25 | Active | -| DeliveryStatus::setRepository() pattern: DB fallback dla static final class | Operator dodaje status w UI bez zmian kodu; `getAllOptions()`/`label()`/`getColor()` ladują z DB gdy repo ustawione, fallback na hardcoded ALL_STATUSES/LABEL_PL | 2026-04-27 | Active | -| Drop backward compat dla starych grupowych kluczy automatyzacji (Phase 108-02) | Kolizja semantyczna: stary `picked_up` mapował na `delivered`, nowy klucz DB `picked_up` to "Odebrana przez kuriera" — odwrotne końce cyklu. Hybrid evaluation by silently dawała wrong matches | 2026-04-27 | Active | -| Path params w controllerach via `$request->input('id')` (nie jako argumenty metody) | Konwencja routera projektu: handler wywoływany z jednym argumentem `$request`, params siedzą jako attributes — `ReceiptController::show()` jako wzorzec | 2026-04-27 | Active | -| Statistics Summary Chart.js CDN + start `2026-04-01` | Interaktywne wykresy bez zmiany build pipeline; historia podsumowania ma zaczynac sie od `04-2026` mimo starszych danych | 2026-04-28 | Active | -| Faktury: multi-account Fakturownia przez `integrations.type='fakturownia'` + `fakturownia_integration_settings(integration_id UNIQUE)` | Klient moze miec wiele kont (rozne marki/oddzialy); spojne z shopPRO; `invoice_configs.integration_id` wskazuje konkretne konto | 2026-05-10 | Active | -| Faktury: lokalna numeracja domyslna, delegacja przez `invoice_configs.is_delegated` | Pelna kontrola w default; opcja outsourcingu numeracji+PDF do Fakturowni gdy ksiegowy tak chce | 2026-05-10 | Active | -| Brak eventu automatyzacji `invoice.created` (na start v3.7) | `receipt.created` pozostaje czysty — regula wysylki paragonu mailem nie zostanie odpalona dla faktury; mozliwe rozszerzenie jako osobny plan w przyszlosci | 2026-05-10 | Active | -| Migracje no-op zawsze jako DDL (np. `ALTER TABLE COMMENT`), nigdy `SELECT 1;` | `SELECT` zwraca result set i pod PDO unbuffered blokuje kolejne migracje (SQLSTATE 2014) | 2026-05-10 | Active | -| Ksiegowosc: osobne podstrony `/settings/accounting/{receipts\|invoices}` zamiast tabow/jednej strony | Dlugie listy + rosnacy form faktury (conditional fields delegacji) nie mieszczace sie na jednej stronie | 2026-05-10 | Active | -| Legacy aliasy starych endpointow `/settings/accounting/save\|toggle\|delete` jako duplicate routes | Brak inwentaryzacji zewnetrznych referencji/bookmarkow - zero kosztu utrzymania, pelna wsteczna kompatybilnosc | 2026-05-10 | Active | -| `OrderProAlerts.confirm` to options-object API (`{title, message, onConfirm, danger, confirmLabel}`), nie pozycyjne argumenty | Pozycyjne wywolanie cicho fail'uje - callback ginie. Bug znaleziony w Phase 114-01 podczas smoke testu user. Pattern dla wszystkich przyszlych confirm dialogow | 2026-05-10 | Active | -| Globalny `confirm-delete.js` z `data-confirm-bound='1'` idempotent guard | Stare widoki maja inline scripts robiace to samo - guard zapobiega podwojnemu bindowi gdy modul globalny widzi juz-bound buttony. Mozna stopniowo migrowac stare widoki | 2026-05-10 | Active | -| Wystawianie faktury delegowanej do Fakturowni: pending local row PRZED POST z lookup-first po `oid` | Phase 136 zastapil stare POST-przed-INSERT: delegacja zapisuje `pending_external`, uzywa `oid=orders.internal_order_number`, sprawdza `GET /invoices.json?oid=...` przed POST i auto-podpina fakture po timeoutach. | 2026-05-17 | Active | -| NIP lookup przez MF Biala Liste (publiczne API) zamiast Fakturowni | Fakturownia API NIE MA endpointu GUS (sprawdzone w dokumentacji 2026-05-10). MF Biala Lista jest publiczna (bez rejestracji/klucza), zwraca nazwa+adres+REGON. Klient `MfWhitelistApiClient` w `src/Core/Http/` dostepny dla innych modulow | 2026-05-10 | Active | -| Fakturownia invoice payload: NIE wysylamy `seller_*` ani `department_id` | Konta z podwyzszonym security interpretuja roznice w seller_bank_account jako proba "utworz nowy dzial" -> HTTP 422. Fakturownia uzywa danych konta jako sprzedawca. Lokalny snapshot w `invoices.seller_data_json` zachowany dla audytu | 2026-05-10 | Active | -| PHP 8.5: zakaz `curl_close()` w nowym kodzie | Deprecated od 8.5 (no-op od 8.0). Wycieka HTML `
Deprecated...` przed JSON response -> "json is not valid" w fetch().json(). Pattern dla wszystkich httpGet/httpPost helperow w `src/Core/Http/` i `src/Modules/Settings/*ApiClient` | 2026-05-10 | Active | -| Auto-set `orders.invoice_requested` tylko przy `created=true` w imporcie | Delta-only re-import (Phase 112) zachowuje stabilnosc manualnej flagi operatora. Re-import nie nadpisuje stanu lokalnego, w tym manualnego "Klient prosi o fakture" | 2026-05-10 | Active | -| `OrderProAlerts.confirm` ZAWSZE options-object API (`{title, message, onConfirm, danger}`) | Phase 114 ustalil. Phase 115 uzyl w invoice_form.php. Pozycyjne wywolanie cicho fail'uje - callback ginie. Pattern obowiazuje dla wszystkich nowych confirm dialogow | 2026-05-10 | Active | -| Alerty stronowe: jedyny renderer markupu to `resources/views/components/alert.php` (params: `$type`, `$message`/`$messageHtml`, `$dismissible`, `$role`) | Phase 120: 36 widoków zunifikowane; ikona SVG + dismiss `[data-alert-dismiss]`; SCSS `.alert` jest flex z `__icon/__body/__dismiss`. Pattern dla wszystkich nowych alertów stronowych. Nie używać `
` inline | 2026-05-12 | Active | -| Flash dual API: `Flash::push(type, message)` (preferred, typed) + `Flash::set/get(key, value)` (BC) | Phase 120: layouty (app/auth/public) iterują `Flash::all()` automatycznie. Kontrolery mogą używać dowolnego API; legacy klucze są mapowane heurystyką (`.save/.created/.deleted/.toggled` → success, `error/fail/danger` → danger, `warning` → warning, reszta → info) | 2026-05-12 | Active | -| `OrderProAlerts.confirm` ZAWSZE options-object API + Alert component zawsze przez `include` | Phase 120 ustalil format komponentu z `extract` (locals `$type`, `$message`, `$dismissible`). Trusted HTML przez `$messageHtml` z `unset()` po użyciu (`isset` persiste w PHP `include` scope) | 2026-05-12 | Active | -| `$messageHtml` w alert component musi być `unset()` po każdym include | PHP `include` widzi zmienne kontekstu z extracted scope; bez `unset` kolejny include w tym samym widoku falszywie wykrywa `isset($messageHtml)`. Pattern dla wszystkich miejsc używających `$messageHtml` (4 widoki: invoice_form, receipt-create, printing, statistics/orders) | 2026-05-12 | Active | -| Erli startuje jako jedna globalna konfiguracja bez sandbox switcha | Operator wybral prosty model pojedynczego konta; srodowisko testowe Erli wymaga osobnej domeny z BOK, wiec nie trafia do Phase 127 | 2026-05-15 | Active | -| Test Erli uzywa realnego read-only `GET /inbox` | Operator wymagal realnego testu API, ale fundament nie moze jeszcze importowac zamowien ani oznaczac inboxa jako przeczytanego | 2026-05-15 | Active | -| Erli import uzywa `/inbox` jako glownego zrodla zdarzen | Model inbox jest event-driven i pasuje do bezpiecznego przetwarzania batchy oraz przyszlych aktualizacji statusow | 2026-05-15 | Active | -| ACK Erli przez `POST /inbox/mark-read` tylko po bezblednym batchu | Zapobiega utracie zdarzen, gdy lokalny import czesciowo sie nie powiedzie | 2026-05-15 | Active | -| Phase 128 ma domyslne mapowania statusow, a UI mapowan dopiero Phase 129 | Import ma realnie dzialac teraz, a pelne strojenie pull/push statusow wymaga osobnej fazy | 2026-05-15 | Active | -| Push statusow Erli obejmuje tylko reczne zmiany orderPRO (`change_source='manual'`) | Chroni przed petlami po imporcie, automatyzacjach i systemowych zmianach statusu | 2026-05-16 | Active | -| Erli -> orderPRO status pull uzywa tego samego inbox + ACK flow co import zamowien | Jedno bezpieczne zrodlo zdarzen Erli; brak osobnego status endpointu do utrzymania | 2026-05-16 | Active | -| Erli settings korzysta z zakladek Integracja/Statusy/Ustawienia | Po dodaniu mapowan strona wymagala parytetu UX z Allegro/shopPRO | 2026-05-16 | Active | -| Erli etykiety uzywaja lokalnych providerow, a Erli dostaje paczke zewnetrzna przez `POST /shipping/external` | Operator nie chce nadawac na umowie Erli; API wspiera zewnetrzne paczki/tracking | 2026-05-16 | Active | -| `carrier_delivery_method_mappings` przechowuje `source_vendor_code`/`source_service_id` dla Erli | Vendor Erli i lokalny provider to osobne kontrakty, nie nalezy ich mieszac w polach Apaczki/InPost | 2026-05-16 | Active | -| Erli hardening uzywa istniejacych powierzchni obserwowalnosci zamiast nowej tabeli logow | Operator wybral ujednolicenie istniejacych miejsc; `integration_order_sync_state.last_error`, wynik crona i activity log wystarczaja dla Phase 132 | 2026-05-16 | Active | -| Zrodla zamowien marketplace maja wspolny `OrderSourceRegistry` | Parytet Erli ma byc utrzymany wszedzie tam, gdzie kod potrzebuje listy lub etykiety zrodla; lokalne pary Allegro/shopPRO prowadzily do pominiec Erli | 2026-05-16 | Active | -| v3.9 debt phases start from evidence-backed backlog audit | Phase 134 rozdzielil wpisy aktywne, wdrozone, stale i decyzyjne. 2026-05-18 operator usunal nieaktualne fazy 140+ i zastapil je pilna faza mapowania shopPRO -> Polkurier. | 2026-05-16 | Active | -| Existing receipt `total_net` rows are not backfilled | Operator wybral zakres Phase 135 tylko dla nowych paragonow; historia pozostaje bez migracji/UPDATE | 2026-05-16 | Active | -| Accounting net fallbacks prefer explicit source data before assumptions | Phase 135: source-level net > item net/gross+VAT > legacy gross `/1.23`; dostawa fallback jako 23% VAT | 2026-05-16 | Active | -| SMTP mailbox TLS is strict by default | Phase 138: `ssl` and STARTTLS verify peer and host name; self-signed/unverified certificates require `SMTP_ALLOW_SELF_SIGNED_DEV=true` and local/dev/testing env. | 2026-05-17 | Active | -| Unknown e-mail/SMS template placeholders are blocked on save | Phase 138: `TemplateVariableCatalog` is the shared catalog; create/edit rejects unknown `{{group.variable}}` keys while existing DB rows are not migrated. | 2026-05-17 | Active | -| Raw session access belongs only in `App\Core\Support\Session` | Phase 138 moved auth, CSRF, flash and Allegro OAuth state access behind `Session::get/set/has/forget/pull`. | 2026-05-17 | Active | -| Phase 139 cleanup slices must stay behavior-preserving and leave god-class splits to a future refactor | Phase 139 reduced Sonar BLOCKER/CRITICAL/MAJOR from 648 to 495 without DB/schema/business-flow changes; `php:S1448` remains a dedicated architecture concern. Former Phase 141 was removed from the active roadmap on 2026-05-18. | 2026-05-17 | Active | -| polkurier startuje jako jedna globalna konfiguracja (single-instance, mirror Apaczka/HostedSMS/SMSPLANET) z realnym testowym wywolaniem `apimetod=test_auth_api` | Operator ma jedno konto polkurier; fundament musi byc zweryfikowany na zywym API zanim dolozymy `PolkurierShipmentService` | 2026-05-14 | Active | -| polkurier wymaga `login + token` razem w body `authorization` (nie samego tokena) | Zweryfikowane w SDK polkurier-sdk (`Auth.php`/`Request.php`); kolumna `login VARCHAR(190)` w `polkurier_integration_settings` mimo ze PLAN tego nie wymagal — kontrakt API to dyktuje | 2026-05-14 | Active | -| polkurier API: top-level `status` === `'success'` (nie `'ok'`), tresc bledu w polu `response` envelope'a | `ResponseStatus::SUCCESS = 'success'` z `src/Type/ResponseStatus.php` SDK; bledy rzucane przez `ErrorException($response->get('response'))` w `PolkurierWebService.php`. Pattern dla wszystkich przyszlych metod polkurier API (`createShipment`, `getLabel`, `getStatus`, `cancelOrder`, etc.) | 2026-05-14 | Active | -| polkurier API odrzuca `Content-Type` z parametrem (`application/json; charset=UTF-8`) — wymagany dokladnie `application/json` | Strict equality check po stronie polkuriera; pattern do reuse jezeli inne integracje sa rownie strict | 2026-05-14 | Active | -| polkurier dziala obok Apaczki (nie zamiast) | Decyzja operatora — oba dostawcy zyja niezaleznie, `ShipmentProviderRegistry` rejestruje obu (Apaczka netknieta w Phase 127; polkurier dodany w nastepnej fazie razem z `PolkurierShipmentService`) | 2026-05-14 | Active | -| polkurier `shipmenttype` wymaga lowercase z zbioru `[box, envelope, palette, small_parcel, parcel_size_20]` | API odrzuca uppercase `BOX` (komunikat: "Typ paczki musi przyjmowac jeden z parametrow ze zbioru ..."). `normalizeShipmentType()` w `PolkurierShipmentService` mapuje legacy PACKAGE/BOX/PARCEL/PACZKA/KOPERTA/PALETA na format polkuriera z aliasami i defaultem `box`. | 2026-05-14 | Active | -| polkurier `create_order` zwraca Order entity z polem `number` (nie `orderno`) i `waybills[0].number` | SDK Order.php uzywa setNumber()/addWaybill() — JSON shape entity, nie parametrow input. `extractOrderNumber` priorytetuje `number`, fallback na `orderno`/`order_no`/`order_number`/`order_id`/`id` + obsluga wrapperow `{order:{...}}` i list. `extractTrackingNumber` priorytetuje `waybills[0].number`. Pattern do reuse dla innych metod polkurier SDK. | 2026-05-14 | Active | -| polkurier API nie ma parametru rozmiaru etykiety (A4/A6) | Zweryfikowane na PDF v1.11: `get_label` przyjmuje wylacznie `orderno: Array`, `create_order` nie ma pola format/size. Rozmiar sterowany w panelu klienta polkurier.pl (Ustawienia konta → Preferencje etykiet) — operator zmienia preferencje konta jednorazowo. `polkurier_integration_settings.default_label_format` (PDF/ZPL/EPL) odnosi sie tylko do typu pliku, NIE rozmiaru. | 2026-05-14 | Active | -| Brak dedykowanego selektora punktow paczkomatowych w UI polkurier (Phase 128) | Istnieje juz pole `name="receiver_point_id"` w sekcji Adres odbiorcy z auto-fillem `parcel_external_id` z importu zamowienia — operator wpisuje ID recznie (np. `POP-RZE54`). Usuniete: `lookupPickupPoints`/`ShipmentController::polkurierPoints`/AJAX route/JS handler. `getInpostParcelMachines`/`getCourierPoints` zachowane jako stuby w API client — gotowe dla kolejnej fazy paczkomaty UI. | 2026-05-14 | Active | -| Diagnostyka silent-fail w ShipmentService — zapis surowej odpowiedzi do `error_message` | Gdy parsing API odpowiedzi zwraca pusty wynik mimo `status=success` (np. nieznany shape pola order number), zapisuj fragment surowej odpowiedzi (400 znakow) do `shipment_packages.error_message` — widoczne operatorowi w UI bez podgladu serwerowych logow. Pattern uratowal 3. iteracje live testu Phase 128. Reuse dla nowych integracji z API o nieznanym shape odpowiedzi. | 2026-05-14 | Active | -| `order_notes` jako jedna tabela dla notatek importowanych ze zrodla i autorskich operatora (Phase 129) | Reuse istniejacej tabeli przez nowy `note_type='user'` z `user_id`/`author_name` — mniej obiektow DB, jeden punkt zarzadzania. UNIQUE `(order_id, source_note_id)` nadal dziala bo MySQL traktuje wiele NULL jako unique (user notes maja `source_note_id=NULL`). `loadOrderNotes()` zawezone do `note_type <> 'user'`; notatki autorskie ladowane przez `OrderNotesService::listUserNotes()`. | 2026-05-14 | Active | -| Autoryzacja CRUD przez `WHERE user_id = :user_id` + rowCount=0 ⇒ `RuntimeException(403)` (Phase 129) | Eliminacja konieczności osobnego SELECT pre-check'a — atomowy UPDATE/DELETE z filtrem user_id robi to w jednym query. Wzorzec do reuse dla innych zasobow "ownership-based" w aplikacji. | 2026-05-14 | Active | -| Brak admin override dla notatek (Phase 129) — tylko autor edit/delete | Aplikacja nie ma systemu rol (`grep is_admin\|role=` zwrocil 0 trafien). Odlozone do osobnej fazy gdy beda role; obecnie operator ktory dodal notatke moze ja modyfikowac, inni widzą ale nie modyfikują. | 2026-05-14 | Deferred | -| Badge `[N]` w `order_ref` przy nr zamowienia (Phase 129) — neutralny indigo, NIE alertowy | Subtelniejszy niz `.risk-return-badge` (czerwony, alertowy) — notatki to informacja, nie ostrzezenie. Klik scrolluje do `#notes` w szczegolach zamowienia. Pattern do reuse dla kolejnych metryk per-order (np. liczba SMS, liczba dokumentow). | 2026-05-14 | Active | -| Polkurier COD defaults: `codtype='S'`, `return_cod='BA'` | API Polkurier rozdziela termin zwrotu pobrania (`S/1D/4D/16D`) od sposobu zwrotu (`BA/PO/MB`). orderPRO uzywa standardowego terminu i przelewu na konto, zgodnie z dotychczasowa walidacja rachunku bankowego. | 2026-05-18 | Active | -| Provider-addition recipe dla `/settings/delivery-statuses?tab=mapping` (Phase 130) | 5 punktow edycji w 4 plikach: (1) const definition `XXX_MAP`/`XXX_DESCRIPTIONS` w `DeliveryStatus.php`, (2) rejestracja w `PROVIDER_MAPS`/`PROVIDER_DESCRIPTIONS`, (3) match arms w `normalize()`/`description()`, (4) `PROVIDERS` const w `DeliveryStatusesController` + `DeliveryStatusMappingController`, (5) lista providerow w `DeliveryStatusMappingRepository::countAllUnmappedForBadge()`. Widok `_delivery-status-mappings-content.php` automatycznie iteruje. Pattern do reuse dla kazdego nowego przewoznika. | 2026-05-14 | Active | -| Defaultowe mapowania statusow dostawy hardcoded w kodzie (nie tylko z DB seed) | Spojnosc z InPost/Apaczka/Allegro — wszyscy maja hardcoded fallback w `DeliveryStatus.php`. UI dziala od razu po deploy, niezaleznie czy operator uruchomil migracje seed. DB override (`delivery_status_mappings`) nadal dziala dla kazdego raw statusu — pattern dual-source (kod default + DB override) zachowany. | 2026-05-14 | Active | - -## Success Metrics - -| Metric | Target | Current | Status | -|--------|--------|---------|--------| -| Liczba zintegrowanych ĹşrĂłdeĹ‚ zamĂłwieĹ„ | ≥3 | 3 zrodla importu (Allegro, shopPRO, Erli); Erli complete in code, live smoke pending operator | Complete in code | -| Generowanie etykiet | DziaĹ‚a | InPost + Erli przez lokalne providery po mapowaniu; live smoke pending operator | Complete in code | - -## Tech Stack - -| Layer | Technology | Notes | -|-------|------------|-------| -| Framework | PHP (custom/Laravel) | XAMPP lokalnie | -| Frontend | HTML/CSS/JS + SCSS | jQuery Alerts module | -| Database | MySQL (Medoo) | Prepared statements | -| Auth | Sesje PHP | | -| Integracje | Allegro API, Erli API | PrzewoĹşnicy: InPost (ShipX), Apaczka | -| Testing | PHPUnit 11.5 + dg/bypass-finals | Unit tests w tests/Unit/ | - -## Specialized Flows - -See: .paul/SPECIAL-FLOWS.md - -Quick Reference: -- /feature-dev → Nowe funkcjonalnoĹ›ci i integracje (optional) -- /code-review → PrzeglÄ…d kodu przed UNIFY (optional) -- /frontend-design → Komponenty UI i widoki (optional) -- /simplify → Refaktoryzacja po implementacji (optional) -- SonarQube / `sonar-scanner` → reczny skan na zadanie operatora; nie jest wymagany w PLAN/APPLY/UNIFY - ---- -*PROJECT.md — Updated when requirements or context change* -*Last updated: 2026-05-18 after Sonar workflow policy update* +## Wartosc rdzenna +Centralizacja obslugi zamowien, integracji kurierskich i generowania projektow graficznych w jednym, szybkim panelu operacyjnym. +## Aktualny status +Projekt produkcyjny, aktywnie rozwijany. Glowna galaz: `main`. +## Trwale wymagania i ograniczenia +- PHP 8.4, autoload PSR-4 `App\\` -> `src/`. +- Baza danych przez `medoo` z prepared statements (zakaz sklejania SQL). +- Runtime aplikacji uzywa `DB_HOST`; `DB_HOST_REMOTE` jest tylko dla operacji recznych agenta. +- Frontend: SCSS w `resources/scss/`, build do `public/assets/css/`; brak inline CSS w widokach. +- Alerty/potwierdzenia UI przez modul `resources/modules/jquery-alerts` (`window.OrderProAlerts`). +- Komunikacja z uzytkownikiem i dokumentacja PAUL: jezyk polski. +- Dokumentacja techniczna w `.paul/codebase/` (`db_schema.md`, `architecture.md`, `tech_changelog.md`). diff --git a/.paul/SPECIAL-FLOWS.md b/.paul/SPECIAL-FLOWS.md deleted file mode 100644 index 0e2345c..0000000 --- a/.paul/SPECIAL-FLOWS.md +++ /dev/null @@ -1,31 +0,0 @@ -# Specialized Flows: orderPRO - -## Project-Level Dependencies - -| Typ pracy | Skill/Komenda | Priorytet | Kiedy | -|-----------|---------------|-----------|-------| -| Nowe funkcjonalnosci (integracje marketplace, przewoznicy, moduly) | /feature-dev | optional | Przed implementacja kazdej nowej funkcji lub integracji | -| Przeglad kodu przed zamknieciem planu (bezpieczenstwo, jakosc, SQL) | /code-review | optional | Po implementacji, przed UNIFY | -| Komponenty UI (listy zamowien, dashboard, formularze, modale) | /frontend-design | optional | Przy tworzeniu nowych widokow lub redesignie istniejacych | -| Refaktoryzacja i upraszczanie kodu po implementacji | /simplify | optional | Po zakonczeniu APPLY, gdy kod wymaga porzadkowania | -| Skanowanie jakosci SonarQube | `sonar-scanner` / `$paul-quality-gate` | manual | Tylko na wyrazne zadanie operatora | - -## SonarQube - tryb reczny - -SonarQube nie jest czescia automatycznego workflow PAUL dla orderPRO. - -- Nie uruchamiaj `sonar-scanner` automatycznie po APPLY ani przed UNIFY. -- Nie oznaczaj braku `sonar-scanner` jako gap w SUMMARY/STATE. -- Uruchamiaj SonarQube tylko po wyraznym poleceniu operatora, np. `uruchom Sonar`, `$paul-quality-gate` albo recznie wskazane `sonar-scanner`. -- Jezeli Sonar zostanie uruchomiony recznie, wyniki mozna dopisac do `DOCS/todo.md` albo `.paul/codebase/quality_risks.md` zgodnie z celem danego skanu. - -## Phase Overrides - -Brak - domyslne skille wystarczaja dla wszystkich nowych planow. - -## Templates & Assets - -Brak - caly projekt dostepny bezposrednio w srodowisku. - ---- -*SPECIAL-FLOWS.md - Updated: 2026-05-18* diff --git a/.paul/STATE.md b/.paul/STATE.md index 7333538..e03f5ec 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -1,276 +1,23 @@ -# Project State +# STATE — orderPRO -## Project Reference +**Tryb:** plan-first +**Ostatnia aktualizacja:** 2026-05-19 -See: .paul/PROJECT.md (updated 2026-05-18) +## Aktywna praca +Brak aktywnego PLAN.md w `.paul/plans/`. -**Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami. -**Current focus:** Polish UI Copy plan unified; ready for next PLAN. +## Kontekst sesji +- Galaz: `main` (czysta). +- Ostatnie commity: `cff0635 UPDATE`, `9ea26ad update`, `d30a459 fix(145) polkurier cod return codes`. -## Current Position +## Sugerowana nastepna akcja +1. `$paul-map-codebase` — pelny skan repozytorium i odswiezenie raportow Quality Radar. +2. `$paul-plan [opis pracy]` — jezeli temat jest juz znany, przejdz od razu do planowania. -Current plan: 20260518-2305-polskie-tlumaczenia - Poprawne polskie tlumaczenia UI - complete -Status: Ready for next PLAN -Last activity: 2026-05-18 23:40 - Unified .paul/plans/20260518-2305-polskie-tlumaczenia/PLAN.md - -Previous milestone: v3.14 Polkurier COD Return Time Hotfix -Previous phase: 145 of 145 (Polkurier COD Return Time Hotfix) - Complete -Previous plan: 145-01 complete - -Progress: -- Milestone v3.14: [##########] 100% (1 of 1 phases complete) -- Phase 145: [##########] 100% (complete) - -## Loop Position - -Current loop state: -``` -PLAN --> APPLY --> UNIFY - x x x [Loop complete - ready for next PLAN] -``` - -## Session Continuity - -Last session: 2026-05-18 23:40 -Stopped at: Plan 20260518-2305-polskie-tlumaczenia UNIFY complete -Next action: `$paul-plan [next work]` or `$paul-verify .paul/plans/20260518-2305-polskie-tlumaczenia/SUMMARY.md` -Resume file: .paul/plans/20260518-2305-polskie-tlumaczenia/SUMMARY.md - -## Pending parallel work -- None — Phase 118, 121, 122 wszystkie zacommitowane (8f14851, 360eef1). - -## Git State - -Last commit: HEAD fix(145): correct polkurier cod return codes -Last phase commit: HEAD fix(145): correct polkurier cod return codes -Previous: fix(144): count imported order notes in list badge -Branch: main - -### Skill Audit (Phase 139) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | invoked | Local PATH did not contain the scanner, but the official Windows x64 scanner was downloaded to `%TEMP%` and used successfully before and after cleanup. | -| `sonar-scanner` 139-02 | invoked | Reused the official Windows x64 scanner from `%TEMP%`; final scan succeeded with analysis `2c18a5b3-40b4-41d8-b826-df88615749db` and 495 OPEN BLOCKER/CRITICAL/MAJOR issues. | - -### Skill Audit (Phase 140) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | `sonar-project.properties` exists, but `sonar-scanner` is not available in PATH and the Phase 139 `%TEMP%` fallback scanner is not present. | - -### Skill Audit (Phase 141) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 142) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 143) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 144) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 145) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (20260518-2305 Polish UI Copy) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | -| `jscpd` | invoked | `npx --yes jscpd` succeeded for the targeted UI-copy scope and wrote `.paul/codebase/radar/jscpd-i18n-post-apply/jscpd-report.json`. | - -### Skill Audit (Phase 129) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted before UNIFY; CLI is not available in PATH. | - -### Skill Audit (Phase 130) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY; CLI is not available in PATH. | - -### Skill Audit (Phase 131) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY; CLI is not available in PATH. | - -### Skill Audit (Phase 132) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY; CLI is not available in PATH. | - -### Skill Audit (Phase 133) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY; CLI is not available in PATH. | - -### Skill Audit (Phase 134) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 135) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 136) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -### Skill Audit (Phase 138) - -| Expected | Invoked | Notes | -|----------|---------|-------| -| `sonar-scanner` | gap documented | Attempted after APPLY with `sonar-scanner --version`; CLI is not available in PATH. | - -## Accumulated Context - -### Recent Decisions - -- Phase 145 fixed the Polkurier COD payload contract: `COD.codtype='S'` for standard return time and `COD.return_cod='BA'` for bank-account transfer. No UI configurability or schema change was added. -- Phase 144 changed the `/orders/list` notes badge contract from operator-only notes to all `order_notes` rows; detail view grouping and note CRUD/import behavior remain unchanged. -- Phase 134 is documentation-only: no runtime code or schema changes were made. -- Backlog entries are annotated, not deleted; stale/implemented cleanup is deferred to later phases. -- Phase 135 completed confirmed accounting net issues: `RECEIPT-NET-FIX` and `STAT-NET` are resolved for new/runtime behavior. -- Phase 135 applies only to new receipts; historical receipt `total_net` rows are not backfilled by operator decision. -- Phase 135 delivery net fallback uses 23% VAT when no source-level delivery VAT exists. -- Phase 139 must refresh Sonar before cleanup because the current concern counts are a stale baseline. -- Phase 136 resolved `INVOICE-IDEMP-115`: Fakturownia delegated invoices use `orders.internal_order_number` as stable `oid`; retry flow is lookup-first by `GET /invoices.json?oid=...`, persists `pending_external`/`failed_retryable` state, and auto-attaches remote invoices found after timeout. -- Phase 137 closed `DELIVERY-STATUS-MGMT` as implemented and verified: runtime code is DB-driven, old group maps are not present in source, and read-only remote DB check found 0 old/invalid shipment-status automation keys. -- Phase 138 hardened SMTP mailbox tests: TLS certificate and peer-name verification are strict by default; `SMTP_ALLOW_SELF_SIGNED_DEV=true` works only in local/dev/development/testing. -- Phase 138 blocks newly saved e-mail/SMS templates that contain unknown `{{group.variable}}` placeholders via the shared `TemplateVariableCatalog`. -- Phase 138 centralized raw `$_SESSION` access in `Session` and replaced targeted hard view `require`/inline `\App\...` patterns. -- Phase 139 is confirmed by operator. Plan 139-01 must run a fresh `sonar-scanner` before code cleanup; stale API-only results are not enough. Scope should fix as many confirmed issues as safely possible, split across multiple plans if needed. -- Phase 139-01 fresh scan found 648 OPEN BLOCKER/CRITICAL/MAJOR issues; final scan after cleanup found 605. Delivery status target files are clean; `OrdersStatisticsRepository` still needs a class split for `php:S1448`. -- Phase 139-02 final scan found 495 OPEN BLOCKER/CRITICAL/MAJOR issues. `php:S4833` dropped to 3 and selected `php:S112` generic exception clusters were replaced with typed exceptions. -- Phase 141 grouped `/settings/integrations` into presentation-only sections: marketplace, couriers and other. Provider row contracts, routes and settings pages remain unchanged. -- Phase 143 removed the descriptive intro card from `/orders/list` and added desktop sidebar pre-hydration through `html.has-collapsed-sidebar` so saved collapsed state applies before first paint. - -### Blockers / Concerns - -- Polish UI Copy APPLY: `sonar-scanner` is unavailable in PATH and manual browser smoke was not run in this session. PHP lint, translation array load check, residual placeholder/mojibake scans, targeted `jscpd`, and `git diff --check` passed. -- Phase 145 APPLY: `vendor/bin/phpunit` is missing, so `tests/Unit/PolkurierShipmentServiceTest.php` was linted and covered by an ad-hoc runtime smoke instead of PHPUnit; `sonar-scanner` is unavailable in PATH. -- Phase 144 APPLY: `vendor/bin/phpunit` is missing, so `tests/Unit/OrdersRepositoryNotesCountTest.php` was linted and covered by an ad-hoc SQLite runtime smoke instead of PHPUnit; `sonar-scanner` is unavailable in PATH. -- Phase 134: `sonar-scanner` is still unavailable in PATH. -- Phase 135: `vendor/bin/phpunit` and `sonar-scanner` are unavailable in PATH/checkout; syntax checks and ad-hoc SQLite/runtime smoke passed. -- Phase 136: Fakturownia idempotency strategy implemented and UNIFY complete; runtime migration still needs local MySQL online. -- Phase 136 APPLY: `php bin/migrate.php` could not run because local MySQL refused connection; `vendor/bin/phpunit` is missing; `sonar-scanner` is unavailable in PATH. PHP lint, documentation grep, git diff check and ad-hoc SQLite repository smoke passed. -- Phase 138 APPLY: `vendor/bin/phpunit` is missing, so new unit tests were linted but not run; `sonar-scanner` is unavailable in PATH. PHP lint, targeted `rg` checks and `git diff --check` passed. -- Phase 139 APPLY: local PATH still does not contain `sonar-scanner`, but the official Windows x64 scanner was downloaded to `%TEMP%` and used successfully. `vendor/bin/phpunit` remains unavailable because `vendor/` is missing and Composer is not installed in PATH. -- Phase 140 APPLY: manual UI smoke was not run because local app/DB session was not started; Sonar scan could not run because `sonar-scanner` is unavailable. -- Phase 141 APPLY: manual UI smoke was not run because local app/browser session was not started; Sonar scan could not run because `sonar-scanner` is unavailable. -- Phase 143 APPLY: manual UI smoke was not run because local app/browser session was not started; Sonar scan could not run because `sonar-scanner` is unavailable. -- Obsolete Phase 140+ debt plans were removed from the active roadmap on 2026-05-18 by operator decision; performance/debt items can be reintroduced later only if still relevant. - -### Deferred Issues - -- Backlog items and concern groups classified in `.paul/phases/134-backlog-reality-check/BACKLOG-AUDIT.md`; obsolete Phase 140+ debt work removed from active roadmap by operator decision on 2026-05-18. - -## Pending Actions - -- Polish UI Copy follow-up: manual smoke main pages with changed copy (`/orders/list`, order detail, settings integrations/templates, accounting, shipments prepare). Sonar is now manual on-demand only. -- Phase 145 follow-up: after restoring `vendor/`, run `vendor/bin/phpunit tests/Unit/PolkurierShipmentServiceTest.php`. -- Phase 145 follow-up: with explicit operator intent, create one live Polkurier COD shipment and confirm API accepts `codtype='S'` / `return_cod='BA'` without the previous return-time error. -- Phase 138 follow-up: run `vendor/bin/phpunit tests/Unit/SmtpSecurityContextFactoryTest.php tests/Unit/TemplateVariableCatalogTest.php` after dependencies are installed. -- Phase 139 follow-up: split `OrdersStatisticsRepository` (`php:S1448`, 43 methods) in a future god-class refactor if still relevant. -- Phase 139 follow-up: continue with confirmed groups `php:S1142`, `php:S3776`, `php:S1172`, `php:S1192`, `php:S112`, plus Web table/accessibility issues. `php:S4833` is now only 3 core framework require issues. -- Phase 140 follow-up: manual smoke `/settings/integrations/shoppro?tab=delivery` -> wybierz Polkurier -> zapisz -> odswiez -> mapowanie pozostaje; potem przygotuj przesylke shopPRO i potwierdz preselect `provider='polkurier'`. -- Phase 141 follow-up: manual smoke `/settings/integrations` -> potwierdz sekcje marketplace/kurierzy/pozostale, osobne wiersze Allegro Sandbox/Production i poprawne linki Ustawienia. -- Phase 142 follow-up: manual smoke `/orders/1164/shipment/prepare` -> potwierdz, ze mapowanie shopPRO -> Polkurier preselectuje przewoznika i usluge. -- Phase 142 follow-up: `composer install` / przywroc `vendor/`, potem uruchom `vendor/bin/phpunit tests/Unit/ShipmentPreparePolkurierMappingTest.php`. -- Phase 143 follow-up: manual smoke `/orders/list` -> potwierdz brak boksu "Zamowienia / Kompaktowa lista..." oraz status panel/table layout. -- Phase 143 follow-up: manual smoke desktop sidebar -> ustaw `localStorage.sidebarCollapsed='1'`, odswiez strone i potwierdz brak widocznego expanded-to-collapsed flash. -- Phase 138 manual smoke: test a real SMTP SSL/STARTTLS mailbox in strict mode; test invalid and valid e-mail/SMS template saves in UI. -- Manualne testy AC-1..AC-7 dla Phase 112 na zywej bazie (XAMPP online). -- Backfill zamowienia #882 - operator robi recznie po wdrozeniu (poza zakresem planu). -- Uruchom migracje gdy XAMPP online: `php bin/migrate.php` (delivery_statuses). -- Recznie odtworzyc istniejace reguly automatyzacji z grupowymi kluczami (BREAKING z 108-02). -- HostedSMS inbound replies: requires DCS/HostedSMS activation before implementation. -- Phase 117 follow-up: run migration when XAMPP MySQL is online and manually test real SMSPLANET sends for Bearer token and key + password. -- Phase 119 follow-up: `composer install` + `vendor/bin/phpunit tests/Unit/OrderImportRepositoryTest.php` to run the 3 new tests; manual smoke test re-syncing order #976 from shoppro to confirm `total_paid=91.00` persists across re-import. -- Phase 121 follow-up: manually verify SMSPLANET settings/test send, inbound webhook insertion, order SMS tab, and notification polling/browser notification. -- Phase 121 transition note: git commit was not created during UNIFY because the worktree contains unrelated Phase 118/local dirty files; prepare a scoped commit manually. -- Phase 122 follow-up: manually verify settings save/reload and real SMSPLANET test/order sends with non-empty and empty footer; manually trigger over-limit final body rejection in UI. -- Phase 123 follow-up: wystaw nowy paragon i potwierdz `items_json` zawiera `vat` per pozycja; eksport XLSX z paragonem multi-rate (np. mix 23% + 8%) — sprawdz osobne wiersze; eksport "wybrane paragony" zachowuje breakdown. -- Phase 136 follow-up: uruchom `php bin/migrate.php` gdy lokalny MySQL/XAMPP jest online; migracja `20260517_000118_add_invoice_external_idempotency_state.sql` dodaje stan idempotencji delegowanych faktur. -- Phase 124 follow-up: `php bin/migrate.php` (XAMPP MySQL online) — utworzy `sms_templates`. Operator nastepnie tworzy szablony manualnie z `/settings/sms-templates`. -- Phase 124 follow-up: real smoke wysylki SMS z szablonu (zamowienie z paczka + skonfigurowana stopka SMSPLANET) — sprawdzic ze `sms_messages.body` ma stopke raz, finalna tresc <= 918 znakow. -- Phase 124 follow-up: regresja Email — wyslij e-mail z istniejacym szablonem aby potwierdzic ze refaktor `Email\VariableResolver` na fasade nie zlamal `EmailSendingService`. -- Phase 125 follow-up: uruchom `php bin/migrate.php` (XAMPP MySQL online) — backfill 7 zamowien + DROP COLUMN `orders.is_invoice`. Weryfikacja: `SELECT id, invoice_requested FROM orders WHERE id=1089;` -> `1`; `SHOW COLUMNS FROM orders LIKE 'is_invoice';` -> empty. -- Phase 125 follow-up: ponowne uruchomienie migracji powinno byc no-op (`ALTER TABLE orders COMMENT = 'phase-125 backfill no-op'`). -- Phase 125 follow-up: zaimportuj nowe zamowienie shopPRO z `firm_nip` (bez kluczy w 5-elementowej liscie wczesniejszej heurystyki) -> potwierdz ze UI w zakladce Platnosci pokazuje zaznaczony checkbox „Klient prosi o fakture" i widoczny przycisk „Wystaw fakture". -- Phase 121 transition note (rozwiązane): commit 360eef1 obejmuje Phase 121 i Phase 122 razem; per-faza hunk-split nie wykonany ze względu na nakładkowe modyfikacje plików. -- Phase 126 follow-up: manual smoke `/orders/1090/invoice/create` (JDG, NIP 5170167517) -> "Imie i nazwisko"="JACEK PYZIAK", "Nazwa firmy"="Project-Pro Pyziak Jacek" niezmieniona; drugi smoke na zamowieniu spolki z aktywnym KRS; `curl /api/nip/lookup?nip=5170167517` -> `data.is_jdg=true`. -- Phase 127 follow-up: uruchom `php bin/migrate.php` gdy lokalny MySQL/XAMPP jest online, zapisz prawdziwy klucz Erli w `/settings/integrations/erli`, wykonaj realny test polaczenia i potwierdz wpis w hubie integracji. -- Phase 128 follow-up: uruchom `php bin/migrate.php`, wlacz import Erli w `/settings/integrations/erli`, kliknij `Importuj zamowienia teraz`, potwierdz `orders.source='erli'` i sprawdz, ze przy bezblednym batchu inbox ACK `POST /inbox/mark-read` nie zostawia nieprzeczytanych zdarzen. -- Phase 128 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, wiec test `tests/Unit/ErliOrderMapperTest.php` nie zostal uruchomiony przez PHPUnit; wykonano `php -l` i runtime smoke mappera. -- Phase 129 follow-up: uruchom `php bin/migrate.php`, sprawdz `/settings/integrations/erli` mapowania pull/push i zakladki, zapisz mapowania, ustaw `orderPRO -> Erli`, zmien recznie status zamowienia Erli i uruchom cron `erli_status_sync`. -- Phase 129 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, a globalny XAMPP PHPUnit jest niekompatybilny z PHP (`each()` removed), wiec testy `ErliOrderMapperTest` i `ErliStatusSyncServiceTest` nie zostaly uruchomione przez PHPUnit; wykonano `php -l`, runtime smoke mappera i `git diff --check`. -- Phase 130 follow-up: uruchom `php bin/migrate.php` (dodaje `carrier_delivery_method_mappings.source_service_id/source_vendor_code`), otworz `/settings/integrations/erli?tab=delivery`, zapisz mapowanie metody Erli na InPost/Apaczka oraz vendor Erli, a potem utworz etykiete dla zamowienia Erli i potwierdz `POST /shipping/external`. -- Phase 130 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, wiec test `tests/Unit/ErliExternalShipmentServiceTest.php` nie zostal uruchomiony przez PHPUnit; wykonano `php -l` i `git diff --check`. -- Phase 130 skill gap: `sonar-scanner` nie jest dostepny w PATH, wiec skan SonarQube nie zostal uruchomiony. -- Phase 131 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, wiec testy `tests/Unit/ErliExternalShipmentServiceTest.php` i `tests/Unit/AutomationServiceTest.php` nie zostaly uruchomione przez PHPUnit; wykonano `php -l` i `git diff --check`. -- Phase 131 skill gap: `sonar-scanner` nie jest dostepny w PATH, wiec skan SonarQube nie zostal uruchomiony. -- Phase 131 follow-up: manualny smoke po migracjach/konfiguracji Erli — utworz paczke dla zamowienia Erli z lokalnym providerem, potwierdz `shipment.created`, uruchom `shipment_tracking_sync`, sprawdz `shipment.status_changed` i retry `POST /shipping/external` tylko po pojawieniu sie tracking number. -- Phase 132 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, a globalny XAMPP PHPUnit jest niekompatybilny z PHP (`each()` removed), wiec testy `ErliOrdersSyncServiceTest`, `ErliStatusSyncServiceTest` i `ErliOrderMapperTest` nie zostaly uruchomione przez PHPUnit; wykonano `php -l` i `git diff --check`. -- Phase 132 skill gap: `sonar-scanner` nie jest dostepny w PATH, wiec skan SonarQube nie zostal uruchomiony. -- Phase 133 follow-up: manualny smoke `/orders/list` -> filtr `Zrodlo` ma Allegro, shopPRO i Erli; `/statistics/orders` i `/statistics/summary` -> kanal Erli widoczny i liczony; edycja automatyzacji -> aktywna integracja Erli dostepna w warunku Integracja. -- Phase 133 verification gap: `vendor/bin/phpunit` nie istnieje w checkoutcie, wiec testy `OrderSourceRegistryTest` i `OrdersStatisticsRepositoryTest` nie zostaly uruchomione przez PHPUnit; wykonano `php -l`, ad-hoc SQLite smoke i `git diff --check`. -- Phase 133 skill gap: `sonar-scanner` nie jest dostepny w PATH, wiec skan SonarQube nie zostal uruchomiony. -- Phase 134 skill gap: `sonar-scanner` nie jest dostepny w PATH, wiec skan SonarQube nie zostal uruchomiony; baseline concerns pozostaje stale do odswiezenia przed Phase 139. -- Phase 127 follow-up: zaplanowac kolejna faze polkurier — `PolkurierShipmentService` (CreateOrder + GetLabel + OrderValuationV2 + AvailableCarriers mapping + UI mapowan metod dostawy + presety przesylek) — fundament + zweryfikowany kontrakt API gotowy. -- Phase 127 follow-up: drugi krok — `PolkurierTrackingService` + wpisy w `delivery_status_mappings` (provider='polkurier'). -- Phase 127 follow-up: po polkurier shipment service rozwazyc fazy paczkomaty (`InpostParcelMachines` / `PocztexPostOffices` / `Kurier48PostOffices` API juz dostepne w SDK polkuriera). -- Phase 128 follow-up: uruchom migracje gdy XAMPP MySQL online: `php bin/migrate.php` (seed 7 wpisow `provider='polkurier'` w `delivery_status_mappings`). -- Phase 128 follow-up: weryfikacja crona `shipment_tracking_sync` przy pierwszej zywej paczce polkurier w `in_transit` — sprawdz ze `shipment_packages.delivery_status` aktualizuje sie z `D`/`WP`/`Z` przez `DeliveryStatus::normalizeWithOverrides('polkurier', ...)`. -- Phase 128 follow-up: rozmiar etykiety A4 vs A6 sterowany jest w panelu klienta polkurier.pl (Ustawienia konta → Preferencje etykiet), NIE przez API — operator ustawil A6. -- Phase 129 follow-up: uruchom migracje gdy XAMPP MySQL online: `php bin/migrate.php` (utworzy `order_notes.user_id` + `author_name` + FK + indeks `idx_order_notes_type_order`). -- Phase 129 follow-up: manualny smoke — `/orders/{X}` → sekcja "Notatki" widoczna, dodanie notatki tworzy wiersz + wpis w `order_activity_log`. Drugi user (`session.user_id != note.user_id`) nie widzi przycisków Edytuj/Usuń; POST `/notes/{noteId}/delete` jako inny user → 403 flash. -- Phase 129 follow-up: `/orders/list` → badge `[N]` widoczny przy zamówieniach z notatkami autorskimi; klik scrolluje do `#notes` w szczegółach. Sprawdzić że badge zwrotów (Phase 106) działa równolegle. -- Phase 130 follow-up: manualny smoke `/settings/delivery-statuses?tab=mapping` → dropdown ma 4 pozycje; `?provider=polkurier` → 7 wierszy (O/P/A/WP/D/Z/W) z `is_custom=false`. Override (zapis nowego mapowania) → wiersz przechodzi w `is_custom=true`. -- Phase 130 follow-up: migracja Phase 128 (`20260514_000115_seed_polkurier_delivery_status_mappings.sql`) staje się no-op — można ją uruchomić lub pominąć, defaulty z kodu pokryją tę samą wartość. - -## Deferred to Next Milestones - -- Phase 68 - Code Deduplication Refactor (0/2 Planning, nigdy nie rozpoczety). -- Historical receipt net backfill - skipped in Phase 135 by operator decision; revisit only if needed for old receipt reporting. -- Mobile Orders List / Mobile Order Details / Mobile Settings. -- INDEX-106-01 - indeksy DB dla query `customer_returned_count`: `order_addresses(order_id, address_type)`, `shipment_packages(order_id, delivery_status)` (gdy dataset >50k wierszy). - -## Skill Requirements - -- SonarQube / `sonar-scanner` is no longer part of the automatic PAUL PLAN/APPLY/UNIFY workflow for orderPRO. Use it only on explicit operator request via `$paul-quality-gate`, `uruchom Sonar`, or a manually provided `sonar-scanner` command. -- Historical Sonar gaps in older phase summaries remain archival context and should not be carried into new plans as required checks. +## Legacy +Pliki `ROADMAP.md` / `MILESTONES.md` sa opcjonalne i obecnie nie sa wymagane. ### Codebase Mapped - -Date: 2026-05-18 +Date: 2026-05-19 Documents: `.paul/codebase/` -Quality Radar: partial (`jscpd` ok through `npx`; `codebase-memory-mcp` installed globally at 0.6.1, enabled in Codex MCP config, and initial index completed in a fresh Codex process: 8165 nodes / 13610 edges; `ast-grep` installed globally and working after Windows wrapper repair) +Quality Radar: ok (codebase-memory-mcp: 4217 nodes / 11649 edges; jscpd/ast-grep disabled by policy) diff --git a/.paul/changelog/2026-04-07.md b/.paul/changelog/2026-04-07.md deleted file mode 100644 index 1c1383c..0000000 --- a/.paul/changelog/2026-04-07.md +++ /dev/null @@ -1,16 +0,0 @@ -# 2026-04-07 - -## Co zrobiono - -- [Phase 85, Plan 01] Filtrowanie zamowien po grupie statusow -- Klikalna nazwa grupy na panelu statusow z licznikiem sumy zamowien -- Backend: parametr status_group z filtrem IN() w repozytorium -- Frontend: hover effect, count badge, active state z border-left - -## Zmienione pliki - -- `src/Modules/Orders/OrdersRepository.php` -- `src/Modules/Orders/OrdersController.php` -- `resources/views/components/order-status-panel.php` -- `resources/scss/app.scss` -- `public/assets/css/app.css` diff --git a/.paul/changelog/2026-04-08.md b/.paul/changelog/2026-04-08.md deleted file mode 100644 index dbf004e..0000000 --- a/.paul/changelog/2026-04-08.md +++ /dev/null @@ -1,67 +0,0 @@ -# 2026-04-08 - -## Co zrobiono - -- [Phase 86, Plan 01] Naprawa bledu API Apaczka przy tworzeniu przesylki COD -- Dodano pole `bankaccount` (numer konta bankowego) do payloadu COD w ApaczkaShipmentService -- Walidacja: brak numeru konta w ustawieniach firmy rzuca czytelny blad -- Czyszczenie numeru konta z prefixu PL i spacji do 26 cyfr - -- [Phase 87, Plan 01] Usuwanie przesylek z zakladki Przesylki w szczegolach zamowienia -- Metoda delete() w ShipmentPackageRepository i ShipmentController -- Endpoint POST /orders/{id}/shipment/{packageId}/delete z CSRF i owner check -- Cleanup pliku etykiety z dysku, activity log shipment_deleted -- Przycisk "Usun" z potwierdzeniem OrderProAlerts.confirm w tabeli przesylek - -- [Phase 88, Plan 01] Dodanie naglowka User-Agent do wszystkich requestow Allegro API -- Dodano buildUserAgent() do AllegroApiClient, AllegroOAuthClient, AllegroTrackingService -- Dodano zmienne APP_VERSION i ALLEGRO_USER_AGENT_URL do .env/.env.example -- Format: orderPRO/1.0.0 (+https://orderpro.pl/info) - -- [Phase 89, Plan 01] Publiczna strona /info dla Allegro User-Agent URL -- InfoController + widok info/allegro.php + layout public.php -- Route GET /info bez authMiddleware -- Tresc: opis wewnetrznej aplikacji Project PRO, integracja z Allegro API, kontakt - -- [Bugfix] Warunek payment_status w automatyzacji nie dzialal z eventem order.imported -- Dodano `new_payment_status` do kontekstu triggera `order.imported` w AllegroOrderImportService i ShopproOrdersSyncService -- Wartosc pochodzi z mapped order (`payment_status`: 0/1/2) — zgodna z istniejacym evaluatePaymentStatusCondition - -- [Phase 90, Plan 01] Naprawa zapisu delivery_price przy imporcie zamowien -- Dodano delivery_price do INSERT/UPDATE/orderParams w OrderImportRepository -- AllegroOrderImportService: resolveDeliveryCost (obiekt {amount,currency} lub plain number) -- ShopproOrderMapper: delivery_price = $transportCost -- Migracja backfill: ALTER TABLE + UPDATE z JSON_EXTRACT (preferences_json/payload_json) -- bin/reissue_receipt.php: skrypt CLI do ponownego wystawiania paragonu z remote DB - -## Zmienione pliki - -- `src/Modules/Info/InfoController.php` -- `resources/views/info/allegro.php` -- `resources/views/layouts/public.php` -- `src/Modules/Settings/AllegroApiClient.php` -- `src/Modules/Settings/AllegroOAuthClient.php` -- `src/Modules/Shipments/AllegroTrackingService.php` -- `.env.example` -- `.env` -- `src/Modules/Shipments/ApaczkaShipmentService.php` -- `src/Modules/Shipments/ShipmentPackageRepository.php` -- `src/Modules/Shipments/ShipmentController.php` -- `routes/web.php` -- `resources/views/orders/show.php` -- `src/Modules/Settings/AllegroOrderImportService.php` -- `src/Modules/Settings/ShopproOrdersSyncService.php` -- `src/Modules/Orders/OrderImportRepository.php` -- `src/Modules/Settings/ShopproOrderMapper.php` -- `database/migrations/20260408_000090_backfill_delivery_price.sql` -- `bin/reissue_receipt.php` - -- [Phase 91, Plan 01] Resilient polling w OrderPROPrint — 3 warstwy obrony przed zawieszeniem -- Dodano CancellationTokenSource (45s) per cykl pollingu jako safety net -- Dodano watchdog: force-reset _isProcessing po 60s gdy poll zawisnie -- Propagacja CancellationToken do metod HTTP w PrintApiClient - -## Zmienione pliki (Phase 91) - -- `clients/windows/OrderPROPrint/Services/PollingService.cs` -- `clients/windows/OrderPROPrint/Services/PrintApiClient.cs` diff --git a/.paul/changelog/2026-04-09.md b/.paul/changelog/2026-04-09.md deleted file mode 100644 index 26f3571..0000000 --- a/.paul/changelog/2026-04-09.md +++ /dev/null @@ -1,14 +0,0 @@ -# 2026-04-09 - -## Co zrobiono - -- [Phase 92, Plan 01] Ikona kopiowania imienia i nazwiska kupujacego w szczegolach zamowienia -- Dodano SVG clipboard icon przy nazwie w sekcji "Dane zamawiajacego" -- Clipboard copy via navigator.clipboard.writeText() z wizualnym feedbackiem (checkmark 1.5s) -- Style .copy-btn-inline i .copy-name-row w SCSS - -## Zmienione pliki - -- `resources/views/orders/show.php` -- `resources/scss/shared/_ui-components.scss` -- `public/assets/css/app.css` diff --git a/.paul/changelog/2026-04-10.md b/.paul/changelog/2026-04-10.md deleted file mode 100644 index ad4b669..0000000 --- a/.paul/changelog/2026-04-10.md +++ /dev/null @@ -1,38 +0,0 @@ -# 2026-04-10 - -## Co zrobiono - -- [Phase 93, Plan 01] Checkbox "Zapamietaj mnie" z persistent cookie 30 dni -- Migracja: kolumna remember_token w tabeli users (hash SHA-256) -- Backend: generowanie/walidacja tokena, auto-login z middleware, czyszczenie przy logout -- Frontend: checkbox w formularzu logowania, usuniecie zasleppki bledu logowania -- Tlumaczenie pl.php: klucz remember_me - -## Zmienione pliki - -- `database/migrations/20260410_000081_add_remember_token_to_users.sql` -- `src/Modules/Users/UserRepository.php` -- `src/Modules/Auth/AuthService.php` -- `src/Modules/Auth/AuthController.php` -- `src/Modules/Auth/AuthMiddleware.php` -- `resources/views/auth/login.php` -- `resources/scss/login.scss` -- `resources/lang/pl.php` -- `public/assets/css/login.css` - -- [Phase 94, Plan 01] Popup podgladu zamowienia na liscie zamowien -- Endpoint AJAX: GET /api/orders/{id}/preview (HTML fragment) -- Modal z danymi kupujacego, adresem dostawy, produktami (zdjecia + personalizacja), notatkami klienta, podsumowaniem -- Ikona oka w kolumnie nr zamowienia, kopiowanie do schowka (clipboard API) - -## Zmienione pliki (Phase 94) - -- `src/Modules/Orders/OrdersController.php` -- `routes/web.php` -- `resources/views/orders/partials/preview-content.php` (nowy) -- `resources/views/orders/partials/preview-modal.php` (nowy) -- `resources/views/orders/list.php` -- `resources/scss/modules/_order-preview-modal.scss` (nowy) -- `resources/scss/app.scss` -- `resources/lang/pl.php` -- `public/assets/css/app.css` diff --git a/.paul/changelog/2026-04-11.md b/.paul/changelog/2026-04-11.md deleted file mode 100644 index 3006649..0000000 --- a/.paul/changelog/2026-04-11.md +++ /dev/null @@ -1,22 +0,0 @@ -# 2026-04-11 - -## Co zrobiono - -- [Phase 95, Plan 01] AJAX refresh tabeli i panelu statusow po zmianie statusu inline -- Controller index() wykrywa AJAX request i zwraca JSON z fragmentami HTML (tableHtml + panelHtml) -- JS inline-status-change.js: fetch + DOM replacement zamiast location.reload() -- Scroll, filtry, paginacja zachowane po odswiezeniu - -- [Phase 96, Plan 01] Nowy warunek automatyzacji "Metoda platnosci" -- 4 opcje: Platnosc przy odbiorze (COD), Przelew bankowy, Karta/online, Inna -- Ewaluacja oparta na external_payment_type_id z pattern matching (StringHelper::isCodPayment) -- Frontend: checkbox-group w formularzu + dynamiczne generowanie JS - -## Zmienione pliki - -- `src/Modules/Orders/OrdersController.php` -- `public/assets/js/modules/inline-status-change.js` -- `src/Modules/Automation/AutomationController.php` -- `src/Modules/Automation/AutomationService.php` -- `resources/views/automation/form.php` -- `public/assets/js/modules/automation-form.js` diff --git a/.paul/changelog/2026-04-12.md b/.paul/changelog/2026-04-12.md deleted file mode 100644 index 49305cd..0000000 --- a/.paul/changelog/2026-04-12.md +++ /dev/null @@ -1,43 +0,0 @@ -# 2026-04-12 - -## Co zrobiono - -- [Phase 97, Plan 01] Polautomatyczne generowanie projektow graficznych PSD z danych zamowien -- Skrypt Python buteleczki_wzor1.py — Photoshop API, podmiana tekstow w Smart Object z zachowaniem pozycji -- Tabela project_mappings + CRUD w panelu (Ustawienia > Mapowanie projektow) -- Komenda Claude Code /wygeneruj-projekty — Claude jako silnik interpretacji danych klienta -- Kolumny project_generated / project_generated_at w order_items -- Flagi statusu projektow na liscie zamowien (ikonki) i w szczegolach (badge przy produkcie) -- Rename kolumny orders.external_status_id na orders.status_code (13+ plikow + migracja) -- Test end-to-end: zamowienie OP000000159 (Kinga Klimczak) wygenerowane i oznaczone - -## Zmienione pliki - -- `tools/generowanie/buteleczki_wzor1.py` -- `database/migrations/20260412_000097_add_project_generation.sql` -- `database/migrations/20260412_000098_rename_external_status_id_to_status_code.sql` -- `src/Modules/Settings/ProjectMappingRepository.php` -- `src/Modules/Settings/ProjectMappingController.php` -- `resources/views/settings/project-mappings.php` -- `resources/scss/modules/_project-mappings.scss` -- `.claude/commands/wygeneruj-projekty.md` -- `routes/web.php` -- `resources/views/layouts/app.php` -- `resources/lang/pl.php` -- `resources/scss/app.scss` -- `src/Modules/Orders/OrdersRepository.php` -- `src/Modules/Orders/OrdersController.php` -- `src/Modules/Orders/OrderImportRepository.php` -- `resources/views/orders/show.php` -- `src/Modules/Automation/OrderStatusAgedService.php` -- `src/Modules/Automation/AutomationService.php` -- `src/Modules/Settings/AllegroOrderImportService.php` -- `src/Modules/Settings/AllegroStatusSyncService.php` -- `src/Modules/Settings/ShopproStatusSyncService.php` -- `src/Modules/Settings/ShopproPaymentStatusSyncService.php` -- `src/Modules/Settings/ShopproOrderMapper.php` -- `bin/randomize_order_statuses.php` -- `bin/deploy_and_seed_orders.php` -- `DOCS/DB_SCHEMA.md` -- `DOCS/ARCHITECTURE.md` -- `DOCS/TECH_CHANGELOG.md` diff --git a/.paul/changelog/2026-04-13.md b/.paul/changelog/2026-04-13.md deleted file mode 100644 index af1ba27..0000000 --- a/.paul/changelog/2026-04-13.md +++ /dev/null @@ -1,40 +0,0 @@ -# 2026-04-13 - -## Co zrobiono - -- [Phase 98, Plan 01] Event automatyzacji `order.imported` ogranicza sie do pierwszego importu zamowienia (gating po `$wasCreated` w AllegroOrderImportService i ShopproOrdersSyncService) -- [Phase 98, Plan 01] Backfill `bin/backfill_shipped_status_98.php`: 4 zamowienia (#275, #340, #396, #422) w statusie `w_realizacji` z istniejaca przesylka przestawione na `wyslane` przez `OrdersRepository::updateOrderStatus` (z historia statusu i activity log) -- [Phase 98, Plan 01] Skrypt idempotentny: drugie uruchomienie zwraca 0 kandydatow -- [Phase 100, Plan 01] Preset Scope & Print UX — presety nadpisuja wylacznie wymiary+wage paczki (carrier/serwis/sender_point/label_format nietykane) -- [Phase 100, Plan 01] GET /api/print/jobs/status + polling w orders/show.php i shipments/prepare.php — przycisk "W kolejce" wraca do "Drukuj" po wydruku (max 3s opoznienia) -- [Phase 100, Plan 01] Po utworzeniu przesylki redirect z `?printLast=1` i auto-click na ostatniej etykiecie -- [Phase 100, Plan 01] Usuniete placeholdery "-" przed przyciskiem Drukuj w obu widokach -- [Phase 99] Order Delivery & Payment Edit — plan zamkniety bez implementacji (cancelled) -- [Phase 101, Plan 01] Aged Orders Row Highlight — wiersze zamowien 4-7+ dniowych dostaja czerwona ramke o rosnacej intensywnosci (4 poziomy, `order-row-aged-{4..7}`) -- [Phase 101, Plan 01] `components/table-list.php` obsluguje opcjonalny `_row_class` na rekordach, OrdersController liczy wiek z `ordered_at` - -## Zmienione pliki - -- `src/Modules/Settings/AllegroOrderImportService.php` -- `src/Modules/Settings/ShopproOrdersSyncService.php` -- `bin/backfill_shipped_status_98.php` -- `.paul/phases/98-order-imported-first-only/98-01-PLAN.md` -- `.paul/phases/98-order-imported-first-only/98-01-SUMMARY.md` -- `.paul/STATE.md` -- `.paul/ROADMAP.md` -- `.paul/PROJECT.md` -- `resources/views/shipments/prepare.php` -- `resources/views/orders/show.php` -- `src/Modules/Printing/PrintApiController.php` -- `src/Modules/Printing/PrintJobRepository.php` -- `src/Modules/Shipments/ShipmentController.php` -- `routes/web.php` -- `.paul/phases/100-preset-scope-print-ux/100-01-PLAN.md` -- `.paul/phases/100-preset-scope-print-ux/100-01-SUMMARY.md` -- `.paul/phases/99-order-delivery-payment-edit/99-01-SUMMARY.md` -- `resources/views/components/table-list.php` -- `src/Modules/Orders/OrdersController.php` -- `resources/scss/app.scss` -- `public/assets/css/app.css` -- `.paul/phases/101-aged-orders-row-highlight/101-01-PLAN.md` -- `.paul/phases/101-aged-orders-row-highlight/101-01-SUMMARY.md` diff --git a/.paul/changelog/2026-04-16.md b/.paul/changelog/2026-04-16.md deleted file mode 100644 index 4bb3b6b..0000000 --- a/.paul/changelog/2026-04-16.md +++ /dev/null @@ -1,10 +0,0 @@ -# 2026-04-16 - -## Co zrobiono - -- [Phase 103, Plan 01] Naprawa auto-click etykiety po utworzeniu przesylki — klika najnowsza paczke zamiast najstarszej -- Zmiana selektora JS: buttons[0] zamiast buttons[buttons.length - 1] (tabela sortowana DESC) - -## Zmienione pliki - -- `resources/views/orders/show.php` diff --git a/.paul/changelog/2026-04-17.md b/.paul/changelog/2026-04-17.md deleted file mode 100644 index 1e5cec1..0000000 --- a/.paul/changelog/2026-04-17.md +++ /dev/null @@ -1,25 +0,0 @@ -# 2026-04-17 - -## Co zrobiono - -- [Phase 104, Plan 01] Apaczka Weekend Delivery — opcjonalna usluga "Paczka w Weekend" dla przesylek Apaczki paczkomatowych InPost -- Backend: `ApaczkaShipmentService::buildOptionsPayload()` mapuje pole `weekend_delivery` na `option[19] = 1` w payloadzie API Apaczki -- Stala `OPTION_KEYS = ['weekend_delivery' => 19]` jako rozszerzalne mapowanie pole formularza -> id opcji Apaczki -- Frontend: checkbox "Dostawa w weekend (sobota)" w formularzu prepare.php widoczny tylko dla supplier=INPOST + paczkomat (door_to_point=1 lub point_to_point=1) -- JS toggle oparty na atrybutach `data-supplier`/`data-paczkomat` na