feat(140): shoppro polkurier delivery mapping
Phase 140 complete: - add Polkurier as shopPRO delivery mapping provider - reuse PolkurierShipmentService delivery services - update PAUL state, docs, and changelog
This commit is contained in:
@@ -13,8 +13,8 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów
|
||||
| Attribute | Value |
|
||||
|-----------|-------|
|
||||
| Version | 3.9.0-dev |
|
||||
| Status | v3.9 Stabilizacja i splata dlugu technicznego in progress - Phase 139 Sonar Critical/Major Cleanup complete; Phase 140 ready to plan |
|
||||
| Last Updated | 2026-05-17 (Phase 139 closed) |
|
||||
| Status | v3.9 Stabilizacja i splata dlugu technicznego complete - Phase 140 shopPRO Polkurier Delivery Mapping closed |
|
||||
| Last Updated | 2026-05-18 (Phase 140 unified) |
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -133,12 +133,13 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów
|
||||
- [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: `.paul/codebase/todo.md` i `.paul/codebase/concerns.md` sklasyfikowane przeciw aktualnemu kodowi/docs, z dowodami w `BACKLOG-AUDIT.md` i routingiem do faz 135-142 — Phase 134
|
||||
- [x] Backlog Reality Check: `.paul/codebase/todo.md` i `.paul/codebase/concerns.md` 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] 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` (subquery `user_notes_count` w paginate). Brak admin override (brak systemu rol w aplikacji) — edit/delete tylko dla autora — Phase 129
|
||||
@@ -151,7 +152,7 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów
|
||||
|
||||
### Active (In Progress)
|
||||
|
||||
- [ ] v3.9 Stabilizacja i splata dlugu technicznego — Phase 140 Performance Safeguards ready to plan after Phase 139.
|
||||
- None - v3.9 current milestone is complete.
|
||||
|
||||
### Planned (Next)
|
||||
|
||||
@@ -267,13 +268,13 @@ PHP (XAMPP/Laravel), integracje z API marketplace'Ăłw (Allegro, Erli) oraz API
|
||||
| `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; kolejne fazy 135-142 maja naprawiac tylko potwierdzone problemy | 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 Phase 141 | Phase 139 reduced Sonar BLOCKER/CRITICAL/MAJOR from 648 to 495 without DB/schema/business-flow changes; `php:S1448` remains a dedicated architecture concern. | 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 |
|
||||
@@ -321,6 +322,6 @@ Quick Reference:
|
||||
|
||||
---
|
||||
*PROJECT.md — Updated when requirements or context change*
|
||||
*Last updated: 2026-05-17 after Phase 139 (Sonar Critical/Major Cleanup) closure*
|
||||
*Last updated: 2026-05-18 after Phase 140 (shopPRO Polkurier Delivery Mapping) closure*
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Milestone porzadkujacy zbudowany z `.paul/codebase/todo.md` i `.paul/codebase/co
|
||||
|
||||
Rule for every phase/plan: przed implementacja sprawdzic w kodzie i dokumentacji, czy wpis nadal jest aktualny i czy nie zostal juz wdrozony; nastepnie przedstawic krotki plan operatorowi i zapytac o potwierdzenie. Dopiero po akceptacji wolno wprowadzac zmiany i uruchamiac testy. Jezeli wpis jest nieaktualny albo juz zrealizowany, faza/planu ma zamknac go dokumentacyjnie bez niepotrzebnej zmiany kodu.
|
||||
|
||||
Progress: 6 of 9 phases complete (67%).
|
||||
Progress: 7 of 7 phases complete (100%).
|
||||
|
||||
| Phase | Name | Plans | Status |
|
||||
|-------|------|-------|--------|
|
||||
@@ -22,9 +22,7 @@ Progress: 6 of 9 phases complete (67%).
|
||||
| 137 | Delivery Status Backlog Verification | 1/1 | Complete (2026-05-17; verification-only closure, no stale automation keys found) |
|
||||
| 138 | Security and Legacy Hardening | 1/1 | Complete (2026-05-17; SMTP TLS/template/session/view hardening, PHPUnit/Sonar env gaps documented) |
|
||||
| 139 | Sonar Critical/Major Cleanup | 2/2 | Complete (2026-05-17; Sonar BLOCKER/CRITICAL/MAJOR reduced 648 -> 495 across two cleanup slices) |
|
||||
| 140 | Performance Safeguards | TBD | Not started |
|
||||
| 141 | God Classes and Duplication Refactor | TBD | Not started |
|
||||
| 142 | Architecture Guardrails | TBD | Not started |
|
||||
| 140 | shopPRO Polkurier Delivery Mapping | 1/1 | Complete (2026-05-18; shopPRO delivery mapping supports Polkurier, manual UI/Sonar follow-up pending) |
|
||||
|
||||
### Phase 134: Backlog Reality Check
|
||||
|
||||
@@ -56,20 +54,10 @@ Plans: 138-01 (complete; `.paul/phases/138-security-and-legacy-hardening/138-01-
|
||||
Focus: Zmniejszyc potwierdzone problemy SonarQube z `concerns.md`: generic exceptions, zbyt wiele returnow, powtarzajace sie literaly, cognitive complexity, unused parameters, use-namespace-import oraz accessibility (`aria-label`, `<output>`). Przed kazda grupa zmian odswiezyc stan skanu albo lokalnie potwierdzic wystepowanie problemu.
|
||||
Plans: 139-01 (complete; `.paul/phases/139-sonar-critical-major-cleanup/139-01-SUMMARY.md`); 139-02 (complete; `.paul/phases/139-sonar-critical-major-cleanup/139-02-SUMMARY.md`)
|
||||
|
||||
### Phase 140: Performance Safeguards
|
||||
### Phase 140: shopPRO Polkurier Delivery Mapping
|
||||
|
||||
Focus: Zweryfikowac i wdrozyc potwierdzone zabezpieczenia wydajnosciowe: deferred indexes `INDEX-106-01`, potencjalne N+1 w szczegolach zamowienia oraz ryzyko wzrostu kolejki cron bez backoffu. Indeksy i migracje wykonywac zgodnie z obecnym progiem danych i po potwierdzeniu operatora.
|
||||
Plans: TBD (defined during $paul-plan)
|
||||
|
||||
### Phase 141: God Classes and Duplication Refactor
|
||||
|
||||
Focus: Wrocic do odlozonego Phase 68 i potwierdzonych `S1448`: `OrdersRepository`, `OrdersController`, `AutomationService`, `ShopproOrderMapper`, `ApaczkaShipmentService`, `ShopproIntegrationsController`, plus duplikacje `SslCertificateResolver`, `ToggleableRepositoryTrait`, `RedirectPathResolver` oraz overlap `ReceiptService`/accounting.
|
||||
Plans: TBD (defined during $paul-plan)
|
||||
|
||||
### Phase 142: Architecture Guardrails
|
||||
|
||||
Focus: Po pilniejszych poprawkach zdecydowac, ktore guardraile sa warte wdrozenia teraz: interfejsy repozytoriow do testow, typowane event/action names, wspolna warstwa walidacji, ewentualne naglowki cache i lokalne query caching. Kazdy element wymaga osobnej decyzji, bo czesc ma niski impact.
|
||||
Plans: TBD (defined during $paul-plan)
|
||||
Focus: Dodac Polkurier do zakladki Dostawy w ustawieniach integracji shopPRO, aby formy dostawy z zamowien shopPRO mogly byc mapowane na lokalna usluge Polkurier i pozniej automatycznie preselectowane przy przygotowaniu przesylki.
|
||||
Plans: 140-01 (complete; `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md`)
|
||||
|
||||
## Previous Milestone
|
||||
|
||||
@@ -633,4 +621,4 @@ Archive: `.paul/milestones/v0.1-ROADMAP.md`
|
||||
|
||||
---
|
||||
*Roadmap created: 2026-03-12*
|
||||
*Last updated: 2026-05-17 - Phase 139 complete; Phase 140 ready to plan*
|
||||
*Last updated: 2026-05-18 - Phase 140 complete; v3.9 milestone complete; obsolete phases 140+ removed*
|
||||
|
||||
@@ -2,45 +2,46 @@
|
||||
|
||||
## Project Reference
|
||||
|
||||
See: .paul/PROJECT.md (updated 2026-05-17)
|
||||
See: .paul/PROJECT.md (updated 2026-05-18)
|
||||
|
||||
**Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami.
|
||||
**Current focus:** v3.9 Stabilizacja i splata dlugu technicznego; Phase 139 Sonar Critical/Major Cleanup complete, Phase 140 Performance Safeguards ready to plan.
|
||||
**Current focus:** v3.9 Stabilizacja i splata dlugu technicznego complete; Phase 140 shopPRO Polkurier Delivery Mapping unified.
|
||||
|
||||
## Current Position
|
||||
|
||||
Milestone: v3.9 Stabilizacja i splata dlugu technicznego
|
||||
Phase: 140 of 142 (Performance Safeguards)
|
||||
Plan: Not started
|
||||
Status: Ready to plan
|
||||
Last activity: 2026-05-17 23:21 - Phase 139 complete; transitioned to Phase 140
|
||||
Phase: 140 of 140 (shopPRO Polkurier Delivery Mapping) - Complete
|
||||
Plan: 140-01 complete
|
||||
Status: Milestone complete, ready for next milestone or release decision
|
||||
Last activity: 2026-05-18 00:00 - Unified .paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-PLAN.md
|
||||
|
||||
Progress:
|
||||
- Milestone v3.9: [#######---] 67% (6 of 9 phases complete)
|
||||
- Phase 140: [----------] 0% (ready to plan)
|
||||
- Milestone v3.9: [##########] 100% (7 of 7 phases complete)
|
||||
- Phase 140: [##########] 100% (complete)
|
||||
|
||||
## Loop Position
|
||||
|
||||
Current loop state:
|
||||
```
|
||||
PLAN -> APPLY -> UNIFY
|
||||
done done done [Phase 139 loop complete; ready for Phase 140 PLAN]
|
||||
done done done [Loop complete - milestone complete]
|
||||
```
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-05-17 23:21
|
||||
Stopped at: Phase 139 complete, ready to plan Phase 140
|
||||
Next action: $paul-plan for Phase 140 Performance Safeguards
|
||||
Resume file: .paul/ROADMAP.md
|
||||
Last session: 2026-05-18 00:00
|
||||
Stopped at: Phase 140 complete; v3.9 milestone complete
|
||||
Next action: Run $paul-complete-milestone or start next milestone planning
|
||||
Resume file: .paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md
|
||||
|
||||
## Pending parallel work
|
||||
- None — Phase 118, 121, 122 wszystkie zacommitowane (8f14851, 360eef1).
|
||||
|
||||
## Git State
|
||||
|
||||
Last phase commit: HEAD feat(139): sonar critical major cleanup
|
||||
Previous: feat(136): fakturownia invoice idempotency
|
||||
Last commit: HEAD feat(140): shoppro polkurier delivery mapping
|
||||
Last phase commit: HEAD feat(140): shoppro polkurier delivery mapping
|
||||
Previous: feat(139): sonar critical major cleanup
|
||||
Branch: main
|
||||
|
||||
### Skill Audit (Phase 139)
|
||||
@@ -50,6 +51,12 @@ Branch: main
|
||||
| `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 129)
|
||||
|
||||
| Expected | Invoked | Notes |
|
||||
@@ -131,17 +138,20 @@ Branch: main
|
||||
- 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: deferred indexes should be applied only after operator confirms dataset size/prod timing.
|
||||
- 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.
|
||||
- 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`; remaining implementation deferred to phases 136-142.
|
||||
- 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
|
||||
|
||||
- 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) or include it in Phase 141 god-class refactor.
|
||||
- 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 140 follow-up: uruchom SonarQube scan po przywroceniu `sonar-scanner` w PATH albo ponownym pobraniu oficjalnego scanner fallback.
|
||||
- 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).
|
||||
|
||||
24
.paul/changelog/2026-05-18.md
Normal file
24
.paul/changelog/2026-05-18.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# 2026-05-18
|
||||
|
||||
## Co zrobiono
|
||||
|
||||
- [Phase 140, Plan 01] Dodano mapowanie form dostawy shopPRO na uslugi Polkurier.
|
||||
- Rozszerzono zakladke `Dostawy` integracji shopPRO o przewoznika Polkurier i wyszukiwalna liste uslug.
|
||||
- Zapis mapowan shopPRO obsluguje `provider='polkurier'` oraz zapis service code i nazwy uslugi w `carrier_delivery_method_mappings`.
|
||||
- Zaktualizowano dokumentacje architektury, techniczny changelog oraz stan PAUL; stare nieaktualne fazy 140+ usunieto z aktywnej roadmapy.
|
||||
- Gap: manualny smoke UI i SonarQube scan pozostaja do wykonania po uruchomieniu app/DB i przywroceniu `sonar-scanner`.
|
||||
|
||||
## Zmienione pliki
|
||||
|
||||
- `.paul/PROJECT.md`
|
||||
- `.paul/ROADMAP.md`
|
||||
- `.paul/STATE.md`
|
||||
- `.paul/changelog/2026-05-18.md`
|
||||
- `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-PLAN.md`
|
||||
- `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md`
|
||||
- `DOCS/ARCHITECTURE.md`
|
||||
- `DOCS/TECH_CHANGELOG.md`
|
||||
- `resources/lang/pl.php`
|
||||
- `resources/views/settings/shoppro.php`
|
||||
- `routes/web.php`
|
||||
- `src/Modules/Settings/ShopproIntegrationsController.php`
|
||||
@@ -0,0 +1,185 @@
|
||||
---
|
||||
phase: 140-shoppro-polkurier-delivery-mapping
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- routes/web.php
|
||||
- src/Modules/Settings/ShopproIntegrationsController.php
|
||||
- resources/views/settings/shoppro.php
|
||||
- resources/lang/pl.php
|
||||
- DOCS/ARCHITECTURE.md
|
||||
- DOCS/TECH_CHANGELOG.md
|
||||
autonomous: true
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Dodac Polkurier jako dostepnego lokalnego providera w mapowaniu form dostawy shopPRO, tak aby operator mogl przypisac forme dostawy z zamowienia shopPRO do uslugi Polkurier i zeby przygotowanie przesylki pozniej korzystalo z zapisanego mapowania.
|
||||
|
||||
## Purpose
|
||||
Sprzedawca ma nadawac przesylki z orderPRO bez recznego przelaczania providera przy kazdym zamowieniu. shopPRO ma miec parytet z istniejacym flow przygotowania przesylek, gdzie `carrier_delivery_method_mappings` wskazuje provider, usluge i nazwe uslugi.
|
||||
|
||||
## Output
|
||||
Zakladka `/settings/integrations/shoppro?tab=delivery` pokazuje Polkurier obok Allegro/InPost/Apaczki, pobiera uslugi z istniejacego `PolkurierShipmentService::getDeliveryServices()` i zapisuje mapowanie jako `provider='polkurier'`, `provider_service_id=<servicecode>`, `provider_service_name=<name>`.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
<clarifications>
|
||||
- **Zakres fazy** - Czy potraktowac to jako pilna nowa faze PAUL, czy jako hotfix poza roadmapowym nurtem?
|
||||
-> Odpowiedz: Jako nowa faza. Stare fazy od 140 w gore sa do usuniecia (nieaktualne).
|
||||
- **Zakres funkcji** - Czy shopPRO ma dostac Polkurier jako kolejnego providera obok Allegro/InPost/Apaczka z lista uslug z `PolkurierShipmentService::getDeliveryServices()` i zapisem `provider='polkurier'`, `provider_service_id=servicecode`, `provider_service_name=name`?
|
||||
-> Odpowiedz: Tak.
|
||||
</clarifications>
|
||||
|
||||
## Project Context
|
||||
@AGENTS.md
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
@DOCS/DB_SCHEMA.md
|
||||
@DOCS/ARCHITECTURE.md
|
||||
|
||||
## Source Files
|
||||
@routes/web.php
|
||||
@src/Modules/Settings/ShopproIntegrationsController.php
|
||||
@src/Modules/Settings/CarrierDeliveryMethodMappingRepository.php
|
||||
@src/Modules/Shipments/PolkurierShipmentService.php
|
||||
@resources/views/settings/shoppro.php
|
||||
@resources/lang/pl.php
|
||||
@resources/views/shipments/prepare.php
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Required Skills (from SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priority | When to Invoke | Loaded? |
|
||||
|-------|----------|----------------|---------|
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
| /feature-dev | optional | Przy implementacji nowej funkcji integracyjnej | ○ |
|
||||
| /frontend-design | optional | Przy korekcie formularza mapowan dostawy | ○ |
|
||||
| /code-review | optional | Po implementacji, przed UNIFY | ○ |
|
||||
|
||||
**BLOCKING:** `sonar-scanner` jest wymagany przez `.paul/SPECIAL-FLOWS.md` po APPLY. Jezeli lokalny PATH nadal go nie ma, uzyc sprawdzonego fallbacku z Phase 139 albo zapisac gap w SUMMARY.
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Polkurier Widoczny W Mapowaniu shopPRO
|
||||
```gherkin
|
||||
Given istnieje zapisana integracja shopPRO oraz wykryte formy dostawy z zamowien tej integracji
|
||||
When operator otwiera /settings/integrations/shoppro?tab=delivery
|
||||
Then w kolumnie przewoznika moze wybrac Polkurier, a w kolumnie uslugi moze wybrac usluge Polkurier z listy dostepnych uslug
|
||||
```
|
||||
|
||||
## AC-2: Zapis Mapowania Polkurier
|
||||
```gherkin
|
||||
Given operator wybral Polkurier i konkretna usluge dla formy dostawy shopPRO
|
||||
When zapisuje formularz mapowania dostaw
|
||||
Then `carrier_delivery_method_mappings` dla tej formy dostawy zapisuje `source_system='shoppro'`, `provider='polkurier'`, `provider_service_id` jako kod uslugi Polkurier i `provider_service_name` jako jej nazwe
|
||||
```
|
||||
|
||||
## AC-3: Wczytanie Istniejacego Mapowania
|
||||
```gherkin
|
||||
Given forma dostawy shopPRO ma zapisane mapowanie na Polkurier
|
||||
When operator ponownie otwiera zakladke Dostawy shopPRO
|
||||
Then wiersz pokazuje wybranego przewoznika Polkurier i zaznaczona poprzednio usluge bez utraty zapisanych mapowan dla Allegro, InPost i Apaczki
|
||||
```
|
||||
|
||||
## AC-4: Przygotowanie Przesylki Korzysta Z Mapowania
|
||||
```gherkin
|
||||
Given zamowienie shopPRO ma forme dostawy zmapowana na Polkurier
|
||||
When operator przechodzi do przygotowania przesylki dla tego zamowienia
|
||||
Then istniejacy flow preselectu providera otrzymuje `provider='polkurier'` oraz `delivery_method_id` rowny zapisanej usludze Polkurier
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Podlaczyc uslugi Polkurier do shopPRO delivery tab</name>
|
||||
<files>routes/web.php, src/Modules/Settings/ShopproIntegrationsController.php</files>
|
||||
<action>
|
||||
Rozszerz `ShopproIntegrationsController` o opcjonalna zaleznosc `PolkurierShipmentService`.
|
||||
- W `index()` przekaz do widoku `polkurierDeliveryServices`.
|
||||
- W `loadDeliveryServices()` albo osobnej malej metodzie doladuj uslugi Polkurier przez `getDeliveryServices()`; bledy traktuj jak brak listy i pokaz czytelny komunikat tylko jesli jest sensowny, bez blokowania Allegro/Apaczka.
|
||||
- W `saveDeliveryMappings()` obsluz `carrier[] = polkurier`, pobierz `polkurier_delivery_method_id[]` i zapisz `provider='polkurier'`, `provider_service_id`, pusty `provider_account_id`, `provider_carrier_id` opcjonalnie pusty/kod, oraz `provider_service_name`.
|
||||
- W `routes/web.php` ustaw DI tak, by ten sam `PolkurierShipmentService` byl przekazany do kontrolera shopPRO i do `ShipmentProviderRegistry`.
|
||||
Unikaj duplikowania wywolan `PolkurierApiClient` bezposrednio w kontrolerze, bo istniejacy provider juz normalizuje service list.
|
||||
</action>
|
||||
<verify>C:\xampp\php\php.exe -l src/Modules/Settings/ShopproIntegrationsController.php; C:\xampp\php\php.exe -l routes/web.php</verify>
|
||||
<done>AC-1 i AC-2 sa spelnione po stronie kontrolera i DI.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Dodac Polkurier do UI mapowan dostawy shopPRO</name>
|
||||
<files>resources/views/settings/shoppro.php, resources/lang/pl.php</files>
|
||||
<action>
|
||||
Rozszerz istniejaca tabele mapowan bez tworzenia nowego widoku.
|
||||
- Dodaj opcje `Polkurier` w select przewoznika.
|
||||
- Dodaj panel wyboru uslugi Polkurier analogiczny do Apaczki: wyszukiwalna lista z `data-value=<id>` i `data-label=<name>`.
|
||||
- Dodaj hidden input `polkurier_delivery_method_id[]` oraz wykorzystaj istniejacy hidden service-name, zeby zapis dostal nazwe uslugi.
|
||||
- Rozszerz JS `showPanel`, reset pol oraz `selectOption()` tak, by Polkurier czyscil pola Allegro/Apaczka i zapisywal poprawny provider service id.
|
||||
- Rozpoznawaj istniejace mapowanie `provider='polkurier'` jako aktualny carrier.
|
||||
- Zaktualizuj polskie etykiety/opisy: opis ma wspominac Allegro WZA/InPost/Apaczka/Polkurier, placeholder ma byc neutralny (`Szukaj uslugi...`), dodaj komunikat braku uslug Polkurier.
|
||||
Nie dodawaj inline CSS poza istniejacymi prostymi `style` uzytymi juz w tym widoku.
|
||||
</action>
|
||||
<verify>C:\xampp\php\php.exe -l resources/views/settings/shoppro.php; rg -n "polkurier|polkurierDeliveryServices|polkurier_delivery_method_id" resources/views/settings/shoppro.php resources/lang/pl.php</verify>
|
||||
<done>AC-1 i AC-3 sa spelnione w UI.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Udokumentowac kontrakt bez migracji</name>
|
||||
<files>DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md</files>
|
||||
<action>
|
||||
Zaktualizuj dokumentacje techniczna.
|
||||
- W `DOCS/ARCHITECTURE.md` dopisz, ze shopPRO delivery mapping obsluguje takze Polkurier przez `provider='polkurier'` i liste z `PolkurierShipmentService`.
|
||||
- W `DOCS/TECH_CHANGELOG.md` dodaj wpis z data 2026-05-18 opisujacy, co i dlaczego zmieniono.
|
||||
- Nie aktualizuj `DOCS/DB_SCHEMA.md`, bo plan nie zmienia tabel, kolumn, indeksow ani FK; istnieje juz `carrier_delivery_method_mappings`.
|
||||
</action>
|
||||
<verify>rg -n "shopPRO.*Polkurier|Polkurier.*shopPRO|2026-05-18" DOCS/ARCHITECTURE.md DOCS/TECH_CHANGELOG.md</verify>
|
||||
<done>Dokumentacja odzwierciedla AC-1..AC-4 i jasno wskazuje brak migracji.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Nie zmieniac schematu bazy danych ani migracji; `carrier_delivery_method_mappings` juz ma potrzebne pola.
|
||||
- Nie zmieniac kontraktu tworzenia przesylek Polkurier (`PolkurierShipmentService::createShipment()` i API payload) poza ewentualnym reuse listy uslug.
|
||||
- Nie przebudowywac calego widoku shopPRO ani systemu zakladek.
|
||||
- Nie usuwac obslugi Allegro, InPost ani Apaczki w mapowaniach shopPRO.
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Zakres dotyczy tylko mapowania form dostawy shopPRO na Polkurier.
|
||||
- Brak nowego selektora punktow odbioru Polkurier; przygotowanie przesylki nadal uzywa istniejacych pol `receiver_point_id`/`sender_point_id`.
|
||||
- Brak zmian w imporcie zamowien shopPRO.
|
||||
- Brak zmian w Erli, Allegro delivery mapping i statusach dostaw.
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `C:\xampp\php\php.exe -l routes/web.php`
|
||||
- [ ] `C:\xampp\php\php.exe -l src/Modules/Settings/ShopproIntegrationsController.php`
|
||||
- [ ] `C:\xampp\php\php.exe -l resources/views/settings/shoppro.php`
|
||||
- [ ] `rg -n "polkurier|polkurierDeliveryServices|polkurier_delivery_method_id" src/Modules/Settings/ShopproIntegrationsController.php resources/views/settings/shoppro.php resources/lang/pl.php`
|
||||
- [ ] Manual smoke, jesli aplikacja i DB sa dostepne: `/settings/integrations/shoppro?tab=delivery` -> wybierz Polkurier -> zapisz -> odswiez -> mapowanie pozostaje.
|
||||
- [ ] SonarQube scan zgodnie z `.paul/SPECIAL-FLOWS.md` albo udokumentowany gap/fallback.
|
||||
- [ ] Wszystkie acceptance criteria spelnione.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Polkurier jest dostepny w UI mapowania dostaw shopPRO.
|
||||
- Zapis mapowania tworzy rekord uzywany pozniej przez przygotowanie przesylki (`provider='polkurier'`, `provider_service_id`).
|
||||
- Istniejace mapowania Allegro/InPost/Apaczka pozostaja kompatybilne.
|
||||
- Dokumentacja techniczna opisuje nowy wariant bez sugerowania zmian schematu.
|
||||
- Weryfikacje z sekcji `<verification>` przeszly albo gap jest jasno opisany.
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
phase: 140-shoppro-polkurier-delivery-mapping
|
||||
plan: 01
|
||||
subsystem: settings
|
||||
tags: [shoppro, polkurier, delivery-mapping, shipments]
|
||||
requires:
|
||||
- phase: 128-polkurier-shipment-service
|
||||
provides: PolkurierShipmentService and delivery service list from polkurier available_carriers
|
||||
provides:
|
||||
- shopPRO delivery methods can be mapped to Polkurier services
|
||||
- carrier_delivery_method_mappings rows can store provider='polkurier' for shopPRO
|
||||
affects: [shoppro, shipments, carrier_delivery_method_mappings]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [reuse existing ShipmentProviderInterface service list for settings mapping]
|
||||
key-files:
|
||||
created:
|
||||
- .paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md
|
||||
modified:
|
||||
- routes/web.php
|
||||
- src/Modules/Settings/ShopproIntegrationsController.php
|
||||
- resources/views/settings/shoppro.php
|
||||
- resources/lang/pl.php
|
||||
- DOCS/ARCHITECTURE.md
|
||||
- DOCS/TECH_CHANGELOG.md
|
||||
key-decisions:
|
||||
- "Use existing carrier_delivery_method_mappings; no schema change."
|
||||
- "Load Polkurier services via PolkurierShipmentService instead of duplicating API calls in settings."
|
||||
patterns-established:
|
||||
- "shopPRO delivery mapping can add local providers by extending provider-specific hidden field + shared provider_service_name snapshot."
|
||||
duration: 1h
|
||||
started: 2026-05-18T00:00:00+02:00
|
||||
completed: 2026-05-18T00:00:00+02:00
|
||||
---
|
||||
|
||||
# Phase 140 Plan 01 Summary: shopPRO Polkurier Delivery Mapping
|
||||
|
||||
shopPRO delivery forms can now be mapped directly to Polkurier services and later reused by the existing shipment prepare flow.
|
||||
|
||||
## Status
|
||||
UNIFY complete. Phase complete.
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~1h |
|
||||
| Started | 2026-05-18T00:00:00+02:00 |
|
||||
| Completed | 2026-05-18T00:00:00+02:00 |
|
||||
| Tasks | 3 completed |
|
||||
| Files modified | 11 |
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
### Task 1: Podlaczyc uslugi Polkurier do shopPRO delivery tab
|
||||
- `ShopproIntegrationsController` dostal opcjonalna zaleznosc `PolkurierShipmentService`.
|
||||
- Zakladka `delivery` przekazuje do widoku `polkurierDeliveryServices`.
|
||||
- `saveDeliveryMappings()` obsluguje `carrier[]=polkurier` i zapisuje `provider='polkurier'` z `provider_service_id` z `polkurier_delivery_method_id[]`.
|
||||
- `routes/web.php` przekazuje ten sam `PolkurierShipmentService` do kontrolera shopPRO i do `ShipmentProviderRegistry`.
|
||||
|
||||
### Task 2: Dodac Polkurier do UI mapowan dostawy shopPRO
|
||||
- W `resources/views/settings/shoppro.php` dodano opcje `Polkurier`, panel wyszukiwalnej listy uslug i hidden input `polkurier_delivery_method_id[]`.
|
||||
- Istniejace mapowanie `provider='polkurier'` jest rozpoznawane i odtwarzane po odswiezeniu.
|
||||
- JS czysci i synchronizuje pola Allegro/InPost/Apaczka/Polkurier bez zmiany schematu formularza.
|
||||
- Tlumaczenia opisow i placeholderow w `resources/lang/pl.php` zostaly zaktualizowane.
|
||||
|
||||
### Task 3: Udokumentowac kontrakt bez migracji
|
||||
- `DOCS/ARCHITECTURE.md` opisuje mapowanie shopPRO -> Polkurier przez `carrier_delivery_method_mappings`.
|
||||
- `DOCS/TECH_CHANGELOG.md` ma wpis z 2026-05-18.
|
||||
- `DOCS/DB_SCHEMA.md` bez zmian, bo tabela juz miala potrzebne pola.
|
||||
|
||||
## Verification
|
||||
- PASS: `C:\xampp\php\php.exe -l routes/web.php`
|
||||
- PASS: `C:\xampp\php\php.exe -l src/Modules/Settings/ShopproIntegrationsController.php`
|
||||
- PASS: `C:\xampp\php\php.exe -l resources/views/settings/shoppro.php`
|
||||
- PASS: `rg -n "polkurier|polkurierDeliveryServices|polkurier_delivery_method_id" src/Modules/Settings/ShopproIntegrationsController.php resources/views/settings/shoppro.php resources/lang/pl.php`
|
||||
- PASS: `rg -n "shopPRO.*Polkurier|Polkurier.*shopPRO|2026-05-18" DOCS/ARCHITECTURE.md DOCS/TECH_CHANGELOG.md`
|
||||
- PASS: `git diff --check` (only Git CRLF warnings, no whitespace errors)
|
||||
|
||||
## Gaps / Not Run
|
||||
- Manual UI smoke was not run because the local app/DB session was not started during APPLY.
|
||||
- SonarQube scan was not run: `sonar-project.properties` exists, but `sonar-scanner` is not available in PATH and the Phase 139 `%TEMP%` fallback scanner is not present.
|
||||
|
||||
## Files Modified
|
||||
- `routes/web.php`
|
||||
- `src/Modules/Settings/ShopproIntegrationsController.php`
|
||||
- `resources/views/settings/shoppro.php`
|
||||
- `resources/lang/pl.php`
|
||||
- `DOCS/ARCHITECTURE.md`
|
||||
- `DOCS/TECH_CHANGELOG.md`
|
||||
- `.paul/PROJECT.md`
|
||||
- `.paul/ROADMAP.md`
|
||||
- `.paul/STATE.md`
|
||||
- `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-PLAN.md`
|
||||
- `.paul/phases/140-shoppro-polkurier-delivery-mapping/140-01-SUMMARY.md`
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Polkurier Widoczny W Mapowaniu shopPRO | Pass | UI includes Polkurier and lists services from `PolkurierShipmentService::getDeliveryServices()`. |
|
||||
| AC-2: Zapis Mapowania Polkurier | Pass | Save handler writes `provider='polkurier'`, selected service code and service name snapshot. |
|
||||
| AC-3: Wczytanie Istniejacego Mapowania | Pass | Existing `provider='polkurier'` rows rehydrate the selected carrier and service. |
|
||||
| AC-4: Przygotowanie Przesylki Korzysta Z Mapowania | Pass | Existing prepare flow reads shared mapping and receives `provider='polkurier'` plus mapped method id. |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Reuse `carrier_delivery_method_mappings` | Existing table already stores source, provider, service id and service name. | No migration required. |
|
||||
| Reuse `PolkurierShipmentService::getDeliveryServices()` | Provider service already normalizes Polkurier available carriers. | Avoids a duplicate settings-only Polkurier API path. |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Deferred verification | 2 | Manual UI smoke and Sonar scan documented as gaps. |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Phase 140 is complete in code and documentation.
|
||||
- The active v3.9 roadmap has no remaining phases after obsolete 140+ debt phases were removed by operator decision.
|
||||
|
||||
**Concerns:**
|
||||
- Manual UI smoke should be run when local app/DB are available.
|
||||
- Sonar scan should be run once `sonar-scanner` is restored or downloaded again.
|
||||
|
||||
**Blockers:**
|
||||
- None for phase closure.
|
||||
@@ -139,6 +139,7 @@ Phase 135 fixes daily net totals: `OrdersStatisticsRepository::netAmountSql()` p
|
||||
### Shipment Flow
|
||||
|
||||
Phase 130 adds an Erli-specific post-label step: for `orders.source='erli'`, `ShipmentController` calls `ErliExternalShipmentService::syncPackage()` after a local provider has a tracking number. Phase 131 extends the same Allegro-like contract into cron tracking: `ShipmentTrackingHandler` retries the Erli external parcel sync after a provider returns tracking status, but the retry is non-critical and never blocks local `delivery_status` updates. The service posts `vendor/status/trackingNumber/orderId` to Erli `POST /shipping/external` and stores the response in `shipment_packages.payload_json.erli_external_parcel`; failures are activity-log warnings.
|
||||
Phase 140 extends shopPRO delivery mapping with Polkurier. `/settings/integrations/shoppro?tab=delivery` now lists Polkurier services from `PolkurierShipmentService::getDeliveryServices()` and stores selected rows in `carrier_delivery_method_mappings` as `source_system='shoppro'`, `provider='polkurier'`, `provider_service_id=<servicecode>`, and `provider_service_name=<name>`. No schema change is required; the existing shipment prepare flow already reads the shared mapping and preselects `provider='polkurier'` with the stored delivery method id.
|
||||
1. **Create** — `ShipmentController::create()` → `ShipmentProviderRegistry` → carrier `ShipmentService::createShipment()` → `ShipmentPackageRepository::insert()`
|
||||
2. **Track** — Cron `ShipmentTrackingHandler` → `ShipmentTrackingRegistry` → carrier tracking API → optional Erli external parcel retry → `ShipmentPackageRepository::updateDeliveryStatus()` → shared `shipment.status_changed` automation event when normalized status really changes.
|
||||
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# Technical Changelog
|
||||
|
||||
## 2026-05-18 - Phase 140 Plan 01: shopPRO Polkurier Delivery Mapping
|
||||
|
||||
**Co zrobiono:**
|
||||
- Dodano Polkurier jako lokalnego providera w zakladce `Dostawy` ustawien integracji shopPRO.
|
||||
- Lista uslug Polkurier w mapowaniu shopPRO korzysta z istniejacego `PolkurierShipmentService::getDeliveryServices()`, bez duplikowania klienta API w kontrolerze ustawien.
|
||||
- Zapis mapowania formy dostawy shopPRO obsluguje `provider='polkurier'`, `provider_service_id=<servicecode>` i snapshot `provider_service_name`.
|
||||
- Zachowano dotychczasowe mapowania Allegro WZA/InPost/Apaczka oraz istniejacy kontrakt tabeli `carrier_delivery_method_mappings`.
|
||||
|
||||
**Dlaczego:**
|
||||
- Operator musi mapowac formy dostawy shopPRO na Polkurier, aby pozniej przygotowanie przesylki automatycznie wybieralo wlasciwego providera i usluge bez recznego przelaczania.
|
||||
|
||||
**BREAKING / migracja:**
|
||||
- Brak migracji DB i brak zmian breaking; wykorzystano istniejaca tabele `carrier_delivery_method_mappings`.
|
||||
|
||||
## 2026-05-17 - Phase 139 Plan 02: Sonar Critical/Major Cleanup
|
||||
|
||||
**Co zrobiono:**
|
||||
|
||||
@@ -1289,17 +1289,18 @@ return [
|
||||
],
|
||||
'delivery' => [
|
||||
'title' => 'Formy dostawy',
|
||||
'description' => 'Mapowanie form dostawy shopPRO do uslug nadawczych Allegro WZA/InPost.',
|
||||
'description' => 'Mapowanie form dostawy shopPRO do uslug nadawczych Allegro WZA/InPost/Apaczka/Polkurier.',
|
||||
'select_integration_first' => 'Najpierw wybierz lub zapisz integracje w zakladce Integracja.',
|
||||
'empty_orders' => 'Brak form dostawy shopPRO wykrytych w zamowieniach tej integracji.',
|
||||
'not_connected' => 'Brak aktywnego polaczenia Allegro. Podlacz konto Allegro, aby pobrac liste uslug dostawy.',
|
||||
'no_inpost_services' => 'Brak uslug InPost (sprawdz polaczenie z Allegro).',
|
||||
'no_polkurier_services' => 'Brak uslug Polkurier (sprawdz konfiguracje w Ustawienia > Integracje > polkurier).',
|
||||
'fields' => [
|
||||
'order_method' => 'Forma dostawy shopPRO',
|
||||
'carrier' => 'Przewoznik',
|
||||
'allegro_service' => 'Usluga dostawy',
|
||||
'no_mapping' => 'brak mapowania',
|
||||
'search_placeholder' => 'Szukaj uslugi Allegro...',
|
||||
'search_placeholder' => 'Szukaj uslugi...',
|
||||
'select_carrier_first' => 'Najpierw wybierz przewoznika.',
|
||||
],
|
||||
'actions' => [
|
||||
|
||||
@@ -16,6 +16,7 @@ $dmMappings = is_array($deliveryMappings ?? null) ? $deliveryMappings : [];
|
||||
$dmOrderMethods = is_array($orderDeliveryMethods ?? null) ? $orderDeliveryMethods : [];
|
||||
$dmAllegroServices = is_array($allegroDeliveryServices ?? null) ? $allegroDeliveryServices : [];
|
||||
$dmApaczkaServices = is_array($apaczkaDeliveryServices ?? null) ? $apaczkaDeliveryServices : [];
|
||||
$dmPolkurierServices = is_array($polkurierDeliveryServices ?? null) ? $polkurierDeliveryServices : [];
|
||||
$dmInpostServices = is_array($inpostDeliveryServices ?? null) ? $inpostDeliveryServices : [];
|
||||
$dmServicesError = (string) ($allegroDeliveryServicesError ?? '');
|
||||
$dmMappingsByMethod = [];
|
||||
@@ -480,7 +481,9 @@ foreach ($dmMappings as $dm) {
|
||||
$currentServiceName = $currentMapping !== null ? trim((string) ($currentMapping['provider_service_name'] ?? '')) : '';
|
||||
$currentProviderCarrierId = $currentMapping !== null ? trim((string) ($currentMapping['provider_carrier_id'] ?? '')) : '';
|
||||
$currentCarrier = '';
|
||||
if ($currentProvider === 'apaczka') {
|
||||
if ($currentProvider === 'polkurier') {
|
||||
$currentCarrier = 'polkurier';
|
||||
} elseif ($currentProvider === 'apaczka') {
|
||||
$currentCarrier = 'apaczka';
|
||||
} elseif (stripos($currentProviderCarrierId, 'inpost') !== false) {
|
||||
$currentCarrier = 'inpost';
|
||||
@@ -499,12 +502,14 @@ foreach ($dmMappings as $dm) {
|
||||
<option value="allegro"<?= $currentCarrier === 'allegro' && $currentMethodId !== '' ? ' selected' : '' ?>>Allegro</option>
|
||||
<option value="inpost"<?= $currentCarrier === 'inpost' ? ' selected' : '' ?>>InPost</option>
|
||||
<option value="apaczka"<?= $currentCarrier === 'apaczka' ? ' selected' : '' ?>>Apaczka</option>
|
||||
<option value="polkurier"<?= $currentCarrier === 'polkurier' ? ' selected' : '' ?>>Polkurier</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<div class="dm-service-wrap" data-row="<?= $rowIdx ?>">
|
||||
<input type="hidden" name="allegro_delivery_method_id[]" class="dm-hidden-method-id" value="<?= $e($currentProvider !== 'apaczka' ? $currentMethodId : '') ?>">
|
||||
<input type="hidden" name="allegro_delivery_method_id[]" class="dm-hidden-method-id" value="<?= $e($currentProvider === 'allegro_wza' ? $currentMethodId : '') ?>">
|
||||
<input type="hidden" name="apaczka_delivery_method_id[]" class="dm-hidden-apaczka-method-id" value="<?= $e($currentProvider === 'apaczka' ? $currentMethodId : '') ?>">
|
||||
<input type="hidden" name="polkurier_delivery_method_id[]" class="dm-hidden-polkurier-method-id" value="<?= $e($currentProvider === 'polkurier' ? $currentMethodId : '') ?>">
|
||||
<input type="hidden" name="allegro_credentials_id[]" class="dm-hidden-credentials-id" value="<?= $e(trim((string) ($currentMapping['provider_account_id'] ?? ''))) ?>">
|
||||
<input type="hidden" name="allegro_carrier_id[]" class="dm-hidden-carrier-id" value="<?= $e($currentProviderCarrierId) ?>">
|
||||
<input type="hidden" name="allegro_service_name[]" class="dm-hidden-service-name" value="<?= $e($currentServiceName) ?>">
|
||||
@@ -602,6 +607,39 @@ foreach ($dmMappings as $dm) {
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="dm-polkurier-panel dm-searchable-select" data-provider="polkurier" data-current-id="<?= $e($currentCarrier === 'polkurier' ? $currentMethodId : '') ?>" data-current-name="<?= $e($currentCarrier === 'polkurier' ? $currentServiceName : '') ?>" style="<?= $currentCarrier !== 'polkurier' ? 'display:none' : '' ?>">
|
||||
<?php if ($dmPolkurierServices === []): ?>
|
||||
<div class="muted"><?= $e($t('settings.integrations.delivery.no_polkurier_services')) ?></div>
|
||||
<?php else: ?>
|
||||
<input type="text" class="form-control dm-search-input" placeholder="<?= $e($t('settings.integrations.delivery.fields.search_placeholder')) ?>" value="<?= $e($currentCarrier === 'polkurier' ? $currentServiceName : '') ?>" autocomplete="off">
|
||||
<div class="searchable-select__dropdown dm-dropdown">
|
||||
<div class="searchable-select__option dm-option-clear" data-value="" data-label="" data-credentials-id="" data-carrier-id="">
|
||||
<em class="muted">-- <?= $e($t('settings.integrations.delivery.fields.no_mapping')) ?> --</em>
|
||||
</div>
|
||||
<?php foreach ($dmPolkurierServices as $pSvc): ?>
|
||||
<?php
|
||||
if (!is_array($pSvc)) {
|
||||
continue;
|
||||
}
|
||||
$pSvcId = trim((string) ($pSvc['id'] ?? $pSvc['servicecode'] ?? $pSvc['code'] ?? ''));
|
||||
$pSvcName = trim((string) ($pSvc['name'] ?? $pSvcId));
|
||||
$pSvcLabel = $pSvcName !== '' ? $pSvcName : $pSvcId;
|
||||
if ($pSvcId === '') {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<div class="searchable-select__option"
|
||||
data-value="<?= $e($pSvcId) ?>"
|
||||
data-label="<?= $e($pSvcLabel) ?>"
|
||||
data-credentials-id=""
|
||||
data-carrier-id="">
|
||||
<?= $e($pSvcLabel) ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="dm-empty-panel muted" style="<?= $currentCarrier !== '' ? 'display:none' : ($currentMethodId !== '' ? 'display:none' : '') ?>">
|
||||
<?= $e($t('settings.integrations.delivery.fields.select_carrier_first')) ?>
|
||||
</div>
|
||||
@@ -690,9 +728,11 @@ foreach ($dmMappings as $dm) {
|
||||
var allegroPanel = serviceWrap.querySelector('.dm-allegro-panel');
|
||||
var inpostPanel = serviceWrap.querySelector('.dm-inpost-panel');
|
||||
var apaczkaPanel = serviceWrap.querySelector('.dm-apaczka-panel');
|
||||
var polkurierPanel = serviceWrap.querySelector('.dm-polkurier-panel');
|
||||
var emptyPanel = serviceWrap.querySelector('.dm-empty-panel');
|
||||
var hiddenMethodId = serviceWrap.querySelector('.dm-hidden-method-id');
|
||||
var hiddenApaczkaMethodId = serviceWrap.querySelector('.dm-hidden-apaczka-method-id');
|
||||
var hiddenPolkurierMethodId = serviceWrap.querySelector('.dm-hidden-polkurier-method-id');
|
||||
var hiddenCredentialsId = serviceWrap.querySelector('.dm-hidden-credentials-id');
|
||||
var hiddenCarrierId = serviceWrap.querySelector('.dm-hidden-carrier-id');
|
||||
var hiddenServiceName = serviceWrap.querySelector('.dm-hidden-service-name');
|
||||
@@ -701,6 +741,7 @@ foreach ($dmMappings as $dm) {
|
||||
if (allegroPanel) allegroPanel.style.display = carrier === 'allegro' ? '' : 'none';
|
||||
if (inpostPanel) inpostPanel.style.display = carrier === 'inpost' ? '' : 'none';
|
||||
if (apaczkaPanel) apaczkaPanel.style.display = carrier === 'apaczka' ? '' : 'none';
|
||||
if (polkurierPanel) polkurierPanel.style.display = carrier === 'polkurier' ? '' : 'none';
|
||||
if (emptyPanel) emptyPanel.style.display = carrier === '' ? '' : 'none';
|
||||
}
|
||||
|
||||
@@ -711,6 +752,7 @@ foreach ($dmMappings as $dm) {
|
||||
showPanel(carrier);
|
||||
if (hiddenMethodId) hiddenMethodId.value = '';
|
||||
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
|
||||
if (hiddenPolkurierMethodId) hiddenPolkurierMethodId.value = '';
|
||||
if (hiddenCredentialsId) hiddenCredentialsId.value = '';
|
||||
if (hiddenCarrierId) hiddenCarrierId.value = '';
|
||||
if (hiddenServiceName) hiddenServiceName.value = '';
|
||||
@@ -723,7 +765,7 @@ foreach ($dmMappings as $dm) {
|
||||
if (allegroDropdown) {
|
||||
allegroDropdown.classList.remove('is-open');
|
||||
}
|
||||
[inpostPanel, apaczkaPanel].forEach(function (panel) {
|
||||
[inpostPanel, apaczkaPanel, polkurierPanel].forEach(function (panel) {
|
||||
if (!panel) return;
|
||||
var inp = panel.querySelector('.dm-search-input');
|
||||
if (inp) { inp.value = ''; inp.blur(); }
|
||||
@@ -742,6 +784,7 @@ foreach ($dmMappings as $dm) {
|
||||
|
||||
var hiddenMethodId = serviceWrap.querySelector('.dm-hidden-method-id');
|
||||
var hiddenApaczkaMethodId = serviceWrap.querySelector('.dm-hidden-apaczka-method-id');
|
||||
var hiddenPolkurierMethodId = serviceWrap.querySelector('.dm-hidden-polkurier-method-id');
|
||||
var hiddenCredentialsId = serviceWrap.querySelector('.dm-hidden-credentials-id');
|
||||
var hiddenCarrierId = serviceWrap.querySelector('.dm-hidden-carrier-id');
|
||||
var hiddenServiceName = serviceWrap.querySelector('.dm-hidden-service-name');
|
||||
@@ -751,16 +794,24 @@ foreach ($dmMappings as $dm) {
|
||||
|
||||
var provider = wrapper.getAttribute('data-provider') || '';
|
||||
var isApaczka = provider === 'apaczka';
|
||||
var isPolkurier = provider === 'polkurier';
|
||||
|
||||
function selectOption(opt) {
|
||||
var val = opt.getAttribute('data-value') || '';
|
||||
if (isApaczka) {
|
||||
if (hiddenMethodId) hiddenMethodId.value = '';
|
||||
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = val;
|
||||
if (hiddenPolkurierMethodId) hiddenPolkurierMethodId.value = '';
|
||||
if (hiddenCredentialsId) hiddenCredentialsId.value = '';
|
||||
} else if (isPolkurier) {
|
||||
if (hiddenMethodId) hiddenMethodId.value = '';
|
||||
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
|
||||
if (hiddenPolkurierMethodId) hiddenPolkurierMethodId.value = val;
|
||||
if (hiddenCredentialsId) hiddenCredentialsId.value = '';
|
||||
} else {
|
||||
if (hiddenMethodId) hiddenMethodId.value = val;
|
||||
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
|
||||
if (hiddenPolkurierMethodId) hiddenPolkurierMethodId.value = '';
|
||||
if (hiddenCredentialsId) hiddenCredentialsId.value = opt.getAttribute('data-credentials-id') || '';
|
||||
}
|
||||
if (hiddenCarrierId) hiddenCarrierId.value = opt.getAttribute('data-carrier-id') || '';
|
||||
|
||||
@@ -188,6 +188,19 @@ return static function (Application $app): void {
|
||||
$auth,
|
||||
$inpostIntegrationRepository
|
||||
);
|
||||
$companySettingsRepository = new CompanySettingsRepository($app->db());
|
||||
$shipmentPackageRepository = new ShipmentPackageRepository($app->db());
|
||||
$polkurierIntegrationRepository = new PolkurierIntegrationRepository(
|
||||
$app->db(),
|
||||
(string) $app->config('app.integrations.secret', '')
|
||||
);
|
||||
$polkurierShipmentService = new PolkurierShipmentService(
|
||||
$polkurierIntegrationRepository,
|
||||
new PolkurierApiClient(),
|
||||
$shipmentPackageRepository,
|
||||
$companySettingsRepository,
|
||||
new OrdersRepository($app->db())
|
||||
);
|
||||
$shopproIntegrationsRepository = new ShopproIntegrationsRepository(
|
||||
$app->db(),
|
||||
(string) $app->config('app.integrations.secret', '')
|
||||
@@ -206,7 +219,8 @@ return static function (Application $app): void {
|
||||
$allegroOAuthClient,
|
||||
new AllegroApiClient(),
|
||||
$apaczkaIntegrationRepository,
|
||||
$apaczkaApiClient
|
||||
$apaczkaApiClient,
|
||||
$polkurierShipmentService
|
||||
);
|
||||
$fakturowniaIntegrationRepository = new FakturowniaIntegrationRepository(
|
||||
$app->db(),
|
||||
@@ -233,10 +247,6 @@ return static function (Application $app): void {
|
||||
new HostedSmsApiClient(),
|
||||
new IntegrationsRepository($app->db())
|
||||
);
|
||||
$polkurierIntegrationRepository = new PolkurierIntegrationRepository(
|
||||
$app->db(),
|
||||
(string) $app->config('app.integrations.secret', '')
|
||||
);
|
||||
$polkurierIntegrationController = new PolkurierIntegrationController(
|
||||
$template,
|
||||
$translator,
|
||||
@@ -314,7 +324,6 @@ return static function (Application $app): void {
|
||||
$deliveryStatusMappingRepository,
|
||||
$deliveryStatusRepository
|
||||
);
|
||||
$companySettingsRepository = new CompanySettingsRepository($app->db());
|
||||
$companySettingsController = new CompanySettingsController(
|
||||
$template,
|
||||
$translator,
|
||||
@@ -482,7 +491,6 @@ return static function (Application $app): void {
|
||||
new MfWhitelistApiClient()
|
||||
);
|
||||
$allegroApiClient = new AllegroApiClient();
|
||||
$shipmentPackageRepository = new ShipmentPackageRepository($app->db());
|
||||
$shipmentService = new AllegroShipmentService(
|
||||
$allegroTokenManager,
|
||||
$allegroApiClient,
|
||||
@@ -503,13 +511,6 @@ return static function (Application $app): void {
|
||||
$companySettingsRepository,
|
||||
new OrdersRepository($app->db())
|
||||
);
|
||||
$polkurierShipmentService = new PolkurierShipmentService(
|
||||
$polkurierIntegrationRepository,
|
||||
new PolkurierApiClient(),
|
||||
$shipmentPackageRepository,
|
||||
$companySettingsRepository,
|
||||
new OrdersRepository($app->db())
|
||||
);
|
||||
$shipmentProviderRegistry = new ShipmentProviderRegistry([
|
||||
$shipmentService,
|
||||
$apaczkaShipmentService,
|
||||
|
||||
@@ -15,6 +15,7 @@ use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
use App\Core\Constants\IntegrationSources;
|
||||
use App\Core\Constants\RedirectPaths;
|
||||
use App\Modules\Shipments\PolkurierShipmentService;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
@@ -47,7 +48,8 @@ final class ShopproIntegrationsController
|
||||
private readonly AllegroOAuthClient $allegroOAuthClient,
|
||||
private readonly AllegroApiClient $allegroApiClient,
|
||||
private readonly ?ApaczkaIntegrationRepository $apaczkaRepository = null,
|
||||
private readonly ?ApaczkaApiClient $apaczkaApiClient = null
|
||||
private readonly ?ApaczkaApiClient $apaczkaApiClient = null,
|
||||
private readonly ?PolkurierShipmentService $polkurierShipmentService = null
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -80,7 +82,7 @@ final class ShopproIntegrationsController
|
||||
: [];
|
||||
$deliveryServicesData = $activeTab === 'delivery'
|
||||
? $this->loadDeliveryServices()
|
||||
: [[], [], ''];
|
||||
: [[], [], [], ''];
|
||||
$deliveryMappings = $selectedIntegration !== null
|
||||
? $this->deliveryMappings->listMappings(IntegrationSources::SHOPPRO, (int) ($selectedIntegration['id'] ?? 0))
|
||||
: [];
|
||||
@@ -109,7 +111,8 @@ final class ShopproIntegrationsController
|
||||
'orderDeliveryMethods' => $orderDeliveryMethods,
|
||||
'allegroDeliveryServices' => $deliveryServicesData[0],
|
||||
'apaczkaDeliveryServices' => $deliveryServicesData[1],
|
||||
'allegroDeliveryServicesError' => $deliveryServicesData[2],
|
||||
'polkurierDeliveryServices' => $deliveryServicesData[2],
|
||||
'allegroDeliveryServicesError' => $deliveryServicesData[3],
|
||||
'inpostDeliveryServices' => array_values(array_filter(
|
||||
$deliveryServicesData[0],
|
||||
static fn (array $svc): bool => stripos((string) ($svc['carrierId'] ?? ''), 'inpost') !== false
|
||||
@@ -383,6 +386,7 @@ final class ShopproIntegrationsController
|
||||
$carriers = (array) $request->input('carrier', []);
|
||||
$allegroMethodIds = (array) $request->input('allegro_delivery_method_id', []);
|
||||
$apaczkaMethodIds = (array) $request->input('apaczka_delivery_method_id', []);
|
||||
$polkurierMethodIds = (array) $request->input('polkurier_delivery_method_id', []);
|
||||
$credentialsIds = (array) $request->input('allegro_credentials_id', []);
|
||||
$carrierIds = (array) $request->input('allegro_carrier_id', []);
|
||||
$serviceNames = (array) $request->input('allegro_service_name', []);
|
||||
@@ -392,10 +396,12 @@ final class ShopproIntegrationsController
|
||||
foreach ($orderMethods as $index => $orderMethod) {
|
||||
$orderMethodValue = trim((string) $orderMethod);
|
||||
$carrier = trim((string) ($carriers[$index] ?? 'allegro'));
|
||||
$provider = $carrier === 'apaczka' ? 'apaczka' : 'allegro_wza';
|
||||
$providerServiceId = $provider === 'apaczka'
|
||||
? trim((string) ($apaczkaMethodIds[$index] ?? ''))
|
||||
: trim((string) ($allegroMethodIds[$index] ?? ''));
|
||||
$provider = $this->resolveDeliveryProvider($carrier);
|
||||
$providerServiceId = match ($provider) {
|
||||
'apaczka' => trim((string) ($apaczkaMethodIds[$index] ?? '')),
|
||||
'polkurier' => trim((string) ($polkurierMethodIds[$index] ?? '')),
|
||||
default => trim((string) ($allegroMethodIds[$index] ?? '')),
|
||||
};
|
||||
if ($orderMethodValue === '' || $providerServiceId === '') {
|
||||
continue;
|
||||
}
|
||||
@@ -423,6 +429,15 @@ final class ShopproIntegrationsController
|
||||
return Response::redirect($redirectTo);
|
||||
}
|
||||
|
||||
private function resolveDeliveryProvider(string $carrier): string
|
||||
{
|
||||
return match (trim($carrier)) {
|
||||
'apaczka' => 'apaczka',
|
||||
'polkurier' => 'polkurier',
|
||||
default => 'allegro_wza',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed>|null $integration
|
||||
* @return array<string, mixed>
|
||||
@@ -920,18 +935,35 @@ final class ShopproIntegrationsController
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{0: array<int, array<string, mixed>>, 1: array<int, array<string, mixed>>, 2: string}
|
||||
* @return array{0: array<int, array<string, mixed>>, 1: array<int, array<string, mixed>>, 2: array<int, array<string, mixed>>, 3: string}
|
||||
*/
|
||||
private function loadDeliveryServices(): array
|
||||
{
|
||||
[$allegroServices, $errorMessage] = $this->loadAllegroDeliveryServices();
|
||||
[$apaczkaServices, $apaczkaError] = $this->loadApaczkaServices();
|
||||
$polkurierServices = $this->loadPolkurierServices();
|
||||
|
||||
if ($errorMessage === '' && $apaczkaError !== '') {
|
||||
$errorMessage = $apaczkaError;
|
||||
}
|
||||
|
||||
return [$allegroServices, $apaczkaServices, $errorMessage];
|
||||
return [$allegroServices, $apaczkaServices, $polkurierServices, $errorMessage];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function loadPolkurierServices(): array
|
||||
{
|
||||
if ($this->polkurierShipmentService === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->polkurierShipmentService->getDeliveryServices();
|
||||
} catch (Throwable) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user