# 2026-05-14

## Co zrobiono

- [Phase 127, Plan 01] polkurier.pl Integration Foundation — pojedyncza globalna konfiguracja brokera kurierskiego polkurier (login + Token API zaszyfrowany przez `IntegrationSecretCipher`), karta w hubie integracji obok Apaczki, realny test polaczenia przez `apimetod=test_auth_api`. Zweryfikowane na zywym koncie operatora (`Autoryzacja: 1`).
- Task 1: Migracja DDL (`polkurier_integration_settings` + seed `integrations.type='polkurier'`) + `PolkurierIntegrationRepository` (single-instance, mirror HostedSMS/SMSPLANET).
- Task 2: `PolkurierApiClient` (POST do `https://api.polkurier.pl/`, JSON envelope `{authorization, apimetod, data}`) + `PolkurierIntegrationController` + widok formularza + 3 routy + i18n.
- Task 3: Wpiecie polkuriera do `IntegrationsHubController` (`buildPolkurierRow()`, kolejnosc: po Apaczce) + aktualizacja `.paul/codebase/{db_schema,architecture,tech_changelog}.md`.
- Auto-fix (live debugging): `status='success'` zamiast `'ok'` (ResponseStatus z SDK), `Content-Type: application/json` bez charset suffix (polkurier strict), parser bledu z pola `response` envelope'a.
- Scope deviation vs PLAN: kolumna `login` dodana (API wymaga login+token), kolumna `environment` pominieta (polkurier nie ma sandbox).

## Zmienione pliki

- `database/migrations/20260514_000114_create_polkurier_integration_settings.sql`
- `src/Modules/Settings/PolkurierIntegrationRepository.php`
- `src/Modules/Settings/PolkurierApiClient.php`
- `src/Modules/Settings/PolkurierIntegrationController.php`
- `resources/views/settings/polkurier.php`
- `routes/web.php`
- `src/Modules/Settings/IntegrationsHubController.php`
- `resources/lang/pl.php`
- `.paul/codebase/db_schema.md`
- `.paul/codebase/architecture.md`
- `.paul/codebase/tech_changelog.md`
- `.paul/STATE.md`
- `.paul/ROADMAP.md`
- `.paul/phases/127-polkurier-integration-foundation/127-01-PLAN.md`
- `.paul/phases/127-polkurier-integration-foundation/127-01-SUMMARY.md`

## Co zrobiono (cd.)

- [Phase 128, Plan 01] polkurier ShipmentService + TrackingService + UI prepare panel + delivery_status_mappings seed. polkurier zarejestrowany jako 4. provider w `ShipmentProviderRegistry` (obok allegro_wza/apaczka/inpost). Operator tworzy paczki z `/orders/{id}/shipment/prepare`, etykieta A6 generowana, cron tracking gotowy do mapowania O/P/A/WP/D/Z/W → created/confirmed/cancelled/in_transit/delivered/returned/problem.
- Task 1: `PolkurierApiClient` rozszerzony z stubów Phase 127 do 7 metod (createShipment/getLabel/getStatus/cancelOrder/getAvailableCarriers/getInpostParcelMachines/getCourierPoints). Wspólny prywatny `call($apimetod, $data, $login, $token)` parsuje envelope `{status, response}`. Kontrakt zweryfikowany na oficjalnej dokumentacji PDF v1.11 (pobrana i zachowana w `.paul/phases/128-polkurier-shipment-service/polkurier-api-docs.txt`).
- Task 2: `PolkurierShipmentService` (~520 LOC, implements ShipmentProviderInterface) + `PolkurierTrackingService` (~110 LOC, implements ShipmentTrackingInterface). `normalizeShipmentType()` mapuje legacy PACKAGE/BOX/PARCEL na lowercase zbiór polkuriera. `extractOrderNumber`/`extractTrackingNumber` priorytetują SDK Order entity (`number`, `waybills[0].number`).
- Task 3: Wiring `routes/web.php` + `CronHandlerFactory` + `ShipmentController.prepare/create` (rozszerzony o `service_code`/`pickup_*` w form data). UI panel "polkurier" w `prepare.php` z dynamiczną listą usług + JS toggle. `DeliveryStatus::trackingUrl` fallback dla provider='polkurier'.
- Task 4 (checkpoint live test #114/#115): 4 iteracje — ReferenceError w JS `clearHiddenFields` → uppercase `shipmenttype` → parsing `number` vs `orderno` → A4 vs A6 etykieta. Każda iteracja autopoprawiona w tej samej sesji APPLY.
- Task 5: Migracja `20260514_000115_seed_polkurier_delivery_status_mappings.sql` z 7 wpisami z oficjalnej tabeli ORDER_STATUS PDF v1.11 (O/P/A/WP/D/Z/W). Idempotentna `ON DUPLICATE KEY UPDATE`.
- Task 6: Aktualizacja `.paul/codebase/{architecture,db_schema,tech_changelog}.md` z sekcją Phase 128.
- Scope removal vs PLAN: UI selektor punktów paczkomatowych usunięty (operator zgłosił duplikat z polem "Punkt odbioru" w sekcji Adres odbiorcy). `lookupPickupPoints` + AJAX route + JS handler usunięte. `getInpostParcelMachines`/`getCourierPoints` zostawione jako stuby na przyszłą fazę paczkomatów UI.
- Decyzja: rozmiar etykiety A4/A6 sterowany w panelu klienta polkurier.pl, NIE przez API (zweryfikowane w PDF v1.11). Operator zmienia preferencje konta jednorazowo.

## Zmienione pliki (cd.)

- `src/Modules/Settings/PolkurierApiClient.php` (rozszerzenie z stubów do 7 metod)
- `src/Modules/Shipments/PolkurierShipmentService.php` (nowy plik)
- `src/Modules/Shipments/PolkurierTrackingService.php` (nowy plik)
- `src/Modules/Shipments/DeliveryStatus.php` (fallback URL polkurier)
- `src/Modules/Shipments/ShipmentController.php` (polkurierServices + service_code/pickup_*)
- `src/Modules/Cron/CronHandlerFactory.php` (rejestracja PolkurierTrackingService)
- `routes/web.php` (rejestracja PolkurierShipmentService w registry)
- `resources/views/shipments/prepare.php` (panel polkurier + JS)
- `database/migrations/20260514_000115_seed_polkurier_delivery_status_mappings.sql` (nowy plik)
- `.paul/phases/128-polkurier-shipment-service/128-01-PLAN.md` (nowy plik)
- `.paul/phases/128-polkurier-shipment-service/128-01-SUMMARY.md` (nowy plik)
- `.paul/phases/128-polkurier-shipment-service/polkurier-api-docs.txt` (nowy plik — referencyjna doca z PDF v1.11)

## Co zrobiono (cd. — Phase 129)

- [Phase 129, Plan 01] Order User Notes module — pelen CRUD notatek autorskich operatora per zamowienie z badge `[N]` na liscie zamowien. Reuse istniejacej tabeli `order_notes` przez nowy `note_type='user'` z `user_id` (FK→users SET NULL) i `author_name` (snapshot). Sekcja `#notes` w "Wiadomosci i zalaczniki" w szczegolach zamowienia z inline edit form + delete przez `OrderProAlerts.confirm`.
- Task 1: Migracja `20260514_000116_extend_order_notes_user_authored.sql` (ADD COLUMN user_id + author_name + FK + indeks `idx_order_notes_type_order`) z idempotentnymi `INFORMATION_SCHEMA` guard'ami i DDL no-op fallback'iem.
- Task 2: `OrderNotesService` (5 metod CRUD + autoryzacja przez `WHERE user_id = :user_id`, rowCount=0 ⇒ 403). `OrdersRepository::userNotesCountSubquerySql()` + kolumna `user_notes_count` w paginate. `OrdersController::storeNote/updateNote/deleteNote` + badge HTML w `toTableRow()`. 3 nowe POST routes.
- Task 3: Sekcja `#notes` w `show.php` (3 bloki — lista user notes + form dodawania + opcjonalny block "Wiadomosci ze zrodla"). SCSS `_order-notes.scss` z `.order-notes-badge` (indigo neutralny). JS `order-notes.js` (inline edit toggle + delete confirm). 9 nowych kluczy i18n PL. `npm run build:css` rebuilt.
- Auto-fix: plan referowal nieistniejaca metode `formatOrderRow()` — wlasciwa nazwa `toTableRow()` znaleziona przez Grep "public function". Edycja zaaplikowana w wlasciwej metodzie.
- Brak admin override w CRUD (decyzja podczas planowania): aplikacja nie ma systemu rol, autoryzacja przez `note.user_id = session.user_id` — odlozone do osobnej fazy.

## Zmienione pliki (cd. — Phase 129)

- `database/migrations/20260514_000116_extend_order_notes_user_authored.sql` (nowy plik)
- `src/Modules/Orders/OrderNotesService.php` (nowy plik)
- `src/Modules/Orders/OrdersController.php` (3 nowe akcje + badge HTML)
- `src/Modules/Orders/OrdersRepository.php` (subquery `user_notes_count` + `loadOrderNotes` zawezone do `note_type <> 'user'`)
- `routes/web.php` (3 nowe routes + `OrderNotesService` instancjonowany)
- `resources/views/orders/show.php` (sekcja `#notes` + inline edit form)
- `resources/views/layouts/app.php` (script `order-notes.js`)
- `resources/lang/pl.php` (9 kluczy `orders.details.notes_user_*` + `notes_imported_title`)
- `resources/scss/modules/_order-notes.scss` (nowy plik)
- `resources/scss/app.scss` (`@use "modules/order-notes"`)
- `public/assets/js/modules/order-notes.js` (nowy plik)
- `public/assets/css/app.css` (rebuilt)
- `.paul/codebase/db_schema.md` (sekcja `order_notes` rozszerzona)
- `.paul/codebase/tech_changelog.md` (wpis Phase 129)
- `.paul/STATE.md`, `.paul/ROADMAP.md`
- `.paul/phases/129-order-user-notes/129-01-PLAN.md` (nowy plik)
- `.paul/phases/129-order-user-notes/129-01-SUMMARY.md` (nowy plik)

## Co zrobiono (cd. — Phase 130)

- [Phase 130, Plan 01] polkurier delivery status mappings UI — polkurier widoczny jako 4. provider w dropdownie `/settings/delivery-statuses?tab=mapping`. 7 oficjalnych kodow ORDER_STATUS z dokumentacji polkurier v1.11 (O/P/A/WP/D/Z/W) hardcoded w `DeliveryStatus::POLKURIER_MAP`/`POLKURIER_DESCRIPTIONS` jako defaulty (spojnie z InPost/Apaczka/Allegro). Badge "niezmapowane" w menu zlicza teraz polkurier obok innych providerow.
- Task 1: `DeliveryStatus.php` — `POLKURIER_MAP` (7 wpisow) + `POLKURIER_DESCRIPTIONS` + rejestracja w `PROVIDER_MAPS`, `PROVIDER_DESCRIPTIONS`, oraz w match expressions `normalize()`/`description()`. Wartosci identyczne z migracja Phase 128 (DB seed staje sie no-op).
- Task 2: Stale `PROVIDERS` w `DeliveryStatusesController` i `DeliveryStatusMappingController` rozszerzone o `'polkurier' => 'polkurier'`. `DeliveryStatusMappingRepository::countAllUnmappedForBadge()`: lista providerow rozszerzona z 3 do 4.
- Brak deviacji vs PLAN — wszystkie 5 punktow edycji zaaplikowane czysto, PHP lint clean na 4 plikach, runtime `getDefaultMappings('polkurier')` zwrocil oczekiwane 7 wpisow.

## Zmienione pliki (cd. — Phase 130)

- `src/Modules/Shipments/DeliveryStatus.php` (+25 linii)
- `src/Modules/Settings/DeliveryStatusesController.php` (+1)
- `src/Modules/Settings/DeliveryStatusMappingController.php` (+1)
- `src/Modules/Shipments/DeliveryStatusMappingRepository.php` (1 ↔)
- `.paul/phases/130-polkurier-delivery-status-mappings/130-01-PLAN.md` (nowy plik)
- `.paul/phases/130-polkurier-delivery-status-mappings/130-01-SUMMARY.md` (nowy plik)
- `.paul/STATE.md`, `.paul/ROADMAP.md`
