# orderPRO

## What This Is

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.

## Core Value

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.8.0-dev |
| Status | v3.8 Erli Marketplace Integration in progress — Phase 127 shipped (Erli settings/API foundation); Phase 128 next |
| Last Updated | 2026-05-15 (Phase 127 closed) |

## 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; `<details>` 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

### Deferred

- [ ] Eliminacja zduplikowanego kodu: SslCertificateResolver, ToggleableRepositoryTrait, RedirectPathResolver, ReceiptService — Phase 68
- [ ] STAT-NET: pobieranie netto z shopPRO lub wyliczanie z `order_items.tax_rate` (unikniecie sztywnego 23% VAT) — `.paul/TODO.md`

### Active (In Progress)

- [ ] v3.8 Erli Marketplace Integration — Phase 127 shipped; Phase 128 next: pobieranie zamowien Erli przez cron/import reczny, mapper do wspolnego modelu orderPRO i state cursor.

### Planned (Next)

- [ ] Erli status mapping + sync — Phase 129
- [ ] Erli shipments + labels — Phase 130
- [ ] Erli tracking + automation hooks — Phase 131
- [ ] Erli hardening, observability + docs — Phase 132
- [ ] 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 |
| 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 | shopPRO nie wysyla netto ani w zamowieniu ani w `order_items`; tymczasowy fallback — docelowy fix w `.paul/TODO.md` (STAT-NET) | 2026-04-19 | Active |
| 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: POST PRZED INSERT lokalnym | Brak orphan rows w `invoices` gdy API padnie. On success zapis `external_invoice_id`/`external_pdf_url`/`invoice_number` z odpowiedzi Fakturowni. Trade-off: brak idempotencji przy double-POST -> INVOICE-IDEMP-115 w todo.md | 2026-05-10 | 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 `<br/><b>Deprecated</b>...` 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ć `<div class="alert alert--TYPE">` 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 |

## Success Metrics

| Metric | Target | Current | Status |
|--------|--------|---------|--------|
| Liczba zintegrowanych ĹşrĂłdeĹ‚ zamĂłwieĹ„ | â‰Ą3 | 2 aktywne importy + fundament Erli | In progress |
| Generowanie etykiet | DziaĹ‚a | InPost | In progress |

## 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)

---
*PROJECT.md — Updated when requirements or context change*
*Last updated: 2026-05-15 after Phase 127 (Erli Integration Foundation) closure; v3.8 milestone in progress*


