feat(47-shipment-created-automation): immediate shipment automation trigger

Phase 47 complete:

- add event shipment.created triggered immediately after shipment creation

- add action update_shipment_status with real-change guard and chain-safe emit

- update automation UI/options, docs, and PAUL state artifacts
This commit is contained in:
2026-03-28 13:24:20 +01:00
parent d3f4bdaecd
commit ad9087d5e4
17 changed files with 784 additions and 310 deletions

View File

@@ -13,8 +13,8 @@ Sprzedawca moĹĽe obsĹugiwać zamĂłwienia ze wszystkich kanaĹĂłw
| Attribute | Value |
|-----------|-------|
| Version | 1.0.0 |
| Status | v1.7 Complete |
| Last Updated | 2026-03-27 |
| Status | v1.9 Complete |
| Last Updated | 2026-03-28 |
## Requirements
@@ -54,6 +54,8 @@ Sprzedawca moĹĽe obsĹugiwać zamĂłwienia ze wszystkich kanaĹĂłw
- [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
### Active (In Progress)
@@ -118,6 +120,8 @@ PHP (XAMPP/Laravel), integracje z API marketplace'Ăłw (Allegro, Erli) oraz API
| 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 |
## Success Metrics
@@ -149,5 +153,5 @@ Quick Reference:
---
*PROJECT.md — Updated when requirements or context change*
*Last updated: 2026-03-27 after Phase 45 completion (ShopPRO Status Push)*
*Last updated: 2026-03-28 after Phase 47 completion (Shipment Creation Automation)*

View File

@@ -6,17 +6,56 @@ orderPRO to narzÄ™dzie do wielokanaĹowego zarzÄ…dzania sprzedaĹĽÄ
## Current Milestone
v1.7 ShopPRO Status Push - Complete (2026-03-27)
No active milestone (v1.9 complete)
Implementacja synchronizacji statusów zamówień w kierunku orderPRO → shopPRO. Cron pushuje zmiany statusów do shopPRO API (PUT /api.php?endpoint=orders&action=change_status).
Gotowe do zaplanowania kolejnego milestone (obszary planowane: zarzadzanie produktami i stanami magazynowymi).
| Phase | Name | Status | Plans |
|------|------|--------|-------|
| 45 | ShopPRO Status Push | Complete (2026-03-27) | 1/1 (`45-01-PLAN.md`) |
| - | - | - | - |
Next action: utworzyc nowy milestone i roadmape kolejnego zakresu.
## Completed Milestones
<details>
<summary>v1.9 Shipment Automation Immediate Trigger - 2026-03-28 (1 phase, 1 plan)</summary>
Wdrozenie natychmiastowego eventu automatyzacji po utworzeniu przesylki oraz nowej akcji automatyzacji do zmiany statusu przesylki.
| Phase | Name | Plans | Completed |
|-------|------|-------|-----------|
| 47 | Shipment Creation Automation | 1/1 | 2026-03-28 |
Archive: `.paul/phases/47-shipment-created-automation/`
</details>
<details>
<summary>v1.8 Allegro Status Push - 2026-03-28 (1 phase, 1 plan)</summary>
Wdrozenie synchronizacji statusow zamowien w kierunku orderPRO -> Allegro oraz aktywacja opcji kierunku w ustawieniach integracji Allegro.
| Phase | Name | Plans | Completed |
|-------|------|-------|-----------|
| 46 | Allegro Status Push | 1/1 | 2026-03-28 |
Archive: `.paul/phases/46-allegro-status-push/`
</details>
<details>
<summary>v1.7 ShopPRO Status Push - 2026-03-27 (1 phase, 1 plan)</summary>
Implementacja synchronizacji statusow zamowien w kierunku orderPRO -> shopPRO. Cron pushuje zmiany statusow do shopPRO API (PUT /api.php?endpoint=orders&action=change_status).
| Phase | Name | Plans | Completed |
|-------|------|-------|-----------|
| 45 | ShopPRO Status Push | 1/1 | 2026-03-27 |
Archive: `.paul/phases/45-shoppro-status-push/`
## Completed Milestones
</details>
<details>
<summary>v1.6 Quick Status Change - 2026-03-27 (1 phase, 1 plan)</summary>
@@ -242,7 +281,4 @@ Archive: `.paul/milestones/v0.1-ROADMAP.md`
---
*Roadmap created: 2026-03-12*
*Last updated: 2026-03-27 - v1.7 ShopPRO Status Push complete*
*Last updated: 2026-03-28 - v1.8 Allegro Status Push completed*

View File

@@ -1,311 +1,49 @@
# Project State
# Project State
## Project Reference
See: .paul/PROJECT.md (updated 2026-03-12)
See: .paul/PROJECT.md (updated 2026-03-28)
**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 focus:** v1.7 complete — Phase 45 delivered
**Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami.
**Current focus:** v1.9 complete - ready to plan next milestone
## Current Position
Milestone: v1.7 ShopPRO Status Push — Complete
Phase: [1] of [1] (ShopPRO Status Push) — Unified
Plan: 45-01 completed with summary
Status: PLAN/APPLY/UNIFY closed for phase 45
Last activity: 2026-03-27 — Phase 45 complete, milestone v1.7 closed
Milestone: v1.9 Shipment Automation Immediate Trigger - Complete
Phase: Complete (47 - Shipment Creation Automation)
Plan: 47-01 complete
Status: Ready to plan next milestone
Last activity: 2026-03-28 14:35:00 - UNIFY completed, phase transitioned
Progress:
- v0.1 Initial Release: [##########] 100% done
- v0.2 Pre-Expansion Fixes: [##########] 100% done
- v0.3 Moduł Paragonów: [##########] 100% done
- v0.4 Moduł E-mail: [##########] 100% done
- v0.5 Moduł Automatyzacji: [##########] 100% done
- v0.6 Poprawki UX: [##########] 100% done
- v0.7 Zdalne drukowanie etykiet: [##########] 100% done
- v0.8 Poprawki źródła zamówień: [##########] 100% done
- v0.9 Poprawki ustawień firmy: [##########] 100% done
- v1.0 Presety przesyłek: [##########] 100% done
- v1.1 Ręczny numer przesyłki: [##########] 100% done
- v1.2 Śledzenie przesyłek: [##########] 100% done
- Phase 27: [##########] 100% done (1/1 plans)
- Phase 28: [##########] 100% done (1/1 plans)
- v1.3 Konfiguracja śledzenia przesyłek: [##########] 100% done
- Phase 29: [##########] 100% done (1/1 plans)
- v1.4 UI Readability Tweaks: [##########] 100% done
- Phase 30: [##########] 100% done (1/1 plans)
- v1.5 Operational Workflow Cleanup: [##########] 100% done
- Phase 40: [##########] Complete (1/1 plans)
- Phase 41: [##########] Complete (1/1 plans)
- Phase 42: [##########] Complete (1/1 plans)
- Phase 43: [##########] Complete (1/1 plans)
- v1.6 Quick Status Change: [##########] 100% done
- Phase 44: [##########] Complete (1/1 plans)
- v1.7 ShopPRO Status Push: [##########] 100% done
- Phase 45: [##########] Complete (1/1 plans)
- v1.9 Milestone: [##########] 100%
- Next milestone: [..........] 0%
## Loop Position
Current loop state:
```
PLAN --> APPLY --> UNIFY
done done done [Loop closed for phase 45]
done done done [Loop complete - ready for next PLAN]
```
## Accumulated Context
### Decisions
| Data | Decyzja | Faza | Wpływ |
|------|---------|------|-------|
| 2026-03-27 | Refactor executeRequest() w ShopproApiClient zamiast duplikacji curl logic | Faza 45 | Reuse GET/PUT, latwiejsze dodawanie metod HTTP |
| 2026-03-27 | Push tylko change_source=manual (nie import/sync) | Faza 45 | Brak petli synchronizacji |
| 2026-03-27 | Fallback 24h dla null cursor last_status_pushed_at | Faza 45 | Ograniczenie zakresu pierwszego synca |
| 2026-03-27 | Fixed positioning dropdown (document.body) zamiast absolute wewnatrz table-wrap | Faza 44 | Dropdown nie ucinany przez overflow:hidden na .table-wrap |
| 2026-03-27 | AJAX detect przez X-Requested-With header z fallback na redirect | Faza 44 | updateStatus() obsluguje oba tryby w jednej metodzie |
| 2026-03-25 | Import Allegro: trigger context + deduplikacja logow (`source_order_id + source_updated_at + trigger`) | Faza 41 | Czytelniejsza historia zamowienia i mniej duplikatow wpisow `import` |
| 2026-03-25 | Automatyzacja: event `shipment.status_changed` z warunkiem `shipment_status` (mapowanie biznes->techniczny) | Faza 42 | Reguly moga reagowac na realny status dostawy bez przebudowy engine |
| 2026-03-25 | Tracking cron triggeruje automatyzacje tylko przy realnej zmianie `delivery_status` | Faza 42 | Brak falszywych triggerow i mniejszy szum automatyzacji |
| 2026-03-25 | Kolejka druku: usuwanie wpisu przez panel ustawien z `OrderProAlerts.confirm` | Faza 43 | Operator moze bezpiecznie czyscic kolejke bez operacji SQL |
| 2026-03-25 | Override required skill: `sonar-scanner` pominięty w APPLY 40-01 (uruchomienie przesunięte przed UNIFY) | Faza 40 | Kontynuacja wdrożenia bez blokady, z jawnym ryzykiem jakości do domknięcia w UNIFY |
| 2026-03-25 | Rozdzielenie tokenow kolorow akcji (`--c-action-primary`) od naglowkow (`--c-primary`) | Faza 30 | Lepsza czytelnosc UI i szybsze rozpoznanie CTA |
| 2026-03-23 | Dwupoziomowy system statusĂłw: normalized + raw z API | Faza 27 | Max szczegĂłĹowoĹć dla usera + spĂłjna logika filtrowania |
| 2026-03-23 | Osobny ShipmentTrackingInterface (nie rozszerzenie ShipmentProviderInterface) | Faza 27 | Czysta separacja tracking vs creation; Ĺatwe dodawanie providerĂłw |
| 2026-03-23 | Idempotentne migracje (IF NOT EXISTS + INSERT IGNORE) | Faza 27 | Bezpieczne re-run migracji |
| 2026-03-12 | AllegroTokenManager wydzielony z 4 klas OAuth | Faza 01 | Centralizacja logiki tokenĂłw, brak duplikacji |
| 2026-03-12 | StringHelper jako final static class w Core/Support | Faza 01 | 19 duplikatów helperów usunięte z 15 klas |
| 2026-03-13 | CronHandlerFactory jako jedyne miejsce kompozycji crona | Faza 02 | Application.php i bin/cron.php zsynchronizowane; 2 bugi naprawione |
| 2026-03-13 | Pole CSRF w formularzach: `_token` (nie `_csrf_token`) | Faza 03 | Ustandaryzowane w OrdersController, ShipmentController i 2 widokach |
| 2026-03-13 | Flash messages: Flash::set('module.type') / Flash::get('module.type', '') | Faza 05 | OrdersController i ShipmentController zmigrowane; jeden wzorzec w caĹej aplikacji |
| 2026-03-13 | validateXxxInput(): ?string i validateXxxAccess(): ?Response jako wzorce helperów walidacji | Faza 06 | Redukcja return statements do ≤3; wzorzec do użycia w kolejnych planach |
| 2026-03-15 | dg/bypass-finals zamiast usuwania final z klas produkcyjnych | Faza 07 | Testy mockujÄ… final classes bez zmiany konwencji projektu |
| 2026-03-15 | 3 bugi use-statement naprawione (odkryte przez testy) | Faza 07 | RuntimeException catch w 401 retry wreszcie dziaĹa; AllegroOAuthException rzucane poprawnie |
| 2026-03-15 | InPost ShipX API (nie Allegro WZA) jako natywny provider | Faza 07 | InpostShipmentService niezależny od Allegro; workaround remap usunięty |
| 2026-03-15 | vendor/ dodany do ftp-kr ignore; deploy vendor ręcznie | Faza 07 | Auto-upload nie nadpisze vendor/ na serwerze |
| 2026-03-15 | Snapshot pattern: seller/buyer/items jako JSON | Faza 10 | Dane zamroĹĽone w momencie wystawienia paragonu |
| 2026-03-15 | Natywny stream_socket_client do testu SMTP (bez PHPMailer) | Faza 13 | Test poĹÄ…czenia SMTP bez nowych zaleĹĽnoĹci; PHPMailer w fazie 15 |
| 2026-03-15 | IntegrationSecretCipher do szyfrowania haseĹ SMTP | Faza 13 | Reuse istniejÄ…cego AES-256-CBC+HMAC; spĂłjny wzorzec |
| 2026-03-15 | Auto-reset is_default na email_mailboxes przy save | Faza 13 | Tylko jedna domyĹlna skrzynka |
| 2026-03-15 | Atomowe numerowanie: INSERT ON DUPLICATE KEY UPDATE | Faza 10 | Bezpieczne kolejne numery paragonĂłw |
| 2026-03-15 | ModuĹ Accounting w App\Modules\Accounting | Faza 10 | Separacja od Settings |
| 2026-03-15 | dompdf v3.1 server-side PDF generation | Faza 11 | Nowa zaleĹĽnoĹć composer; wymaga vendor/ na serwerze |
| 2026-03-15 | ftp-kr vendor/ nie ignorowany (zmiana na /vendor/bin) | Faza 11 | Automatyczny upload vendor/ przy zmianach; rewizja decyzji z fazy 07 |
| 2026-03-15 | PhpSpreadsheet v5.5 dla eksportu XLSX | Faza 12 | Nowa zaleĹĽnoĹć composer; XLSX lepszy od CSV dla ksiÄ™gowoĹci |
| 2026-03-15 | POST eksport z CSRF + dwa tryby (zaznaczone/wszystkie z filtra) | Faza 12 | Bezpieczny eksport; selectable table-list reuse |
| 2026-03-16 | ATTACHMENT_TYPES jako centralna mapa typĂłw zaĹÄ…cznikĂłw | Faza 14 | RozszerzalnoĹć: nowy typ = 1 linia w tablicy PHP |
| 2026-03-16 | Quill.js 2.0.3 CDN dla edytora szablonĂłw | Faza 14 | Brak build pipeline; CDN prostszy |
| 2026-03-17 | PHPMailer v7.0.2 jako SMTP transport | Faza 15 | Nowa zaleĹĽnoĹć composer; in-memory attachments (addStringAttachment) |
| 2026-03-17 | Email history jako wpisy w order_activity_log (nie osobna sekcja) | Faza 15 | SpĂłjnoĹć z istniejÄ…cym UX — jeden timeline zamiast fragmentacji |
| 2026-03-17 | VariableResolver wydzielony z EmailTemplateController | Faza 15 | Reuse logiki zmiennych; resolwer niezaleĹĽny od kontrolera szablonĂłw |
| Date | Decision | Impact |
|------|----------|--------|
| 2026-03-28 | Dodano event `shipment.created` triggerowany natychmiast po sukcesie tworzenia paczki | Reguly automatyzacji reaguja od razu, bez oczekiwania na cron |
| 2026-03-28 | Dodano akcje `update_shipment_status` z aktualizacja tylko przy realnej zmianie | Brak petli i duplikatow triggerow |
| 2026-03-28 | `AutomationService` rozszerzony o `ShipmentPackageRepository` i fallback wyboru paczki | Stabilne wykonanie akcji statusowej nawet bez `package_id` w kontekscie |
### Skill Audit (Faza 45, Plan 01)
| Oczekiwany | Wywolany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominieto na podstawie explicit user override; lint PHP PASS |
### Skill Audit (Faza 44, Plan 01)
| Oczekiwany | Wywolany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominieto na podstawie explicit user override; lint PHP + build CSS PASS |
### Skill Audit (Faza 43, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominięto na podstawie explicit user override; lint PHP + build CSS + grep PASS |
### Skill Audit (Faza 42, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominięto na podstawie explicit user override; lint PHP + grep PASS |
### Skill Audit (Faza 41, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominięto na podstawie explicit user override; lint PHP + grep PASS |
### Skill Audit (Faza 40, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | override | Pominięto na podstawie explicit user override; lint PHP + grep PASS |
### Skill Audit (Faza 29, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych unikalnych issues; 3x S1192 pre-existing DeliveryStatus, 1x S1142 pre-existing matchCarrierByName, 2x accessibility minor (pre-existing pattern) |
### Skill Audit (Faza 28, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych unikalnych issues; 1x S1448 CronRepository (22 metod, pre-existing pattern) |
### Skill Audit (Faza 27, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych unikalnych issues; 3 pre-existing patterns (2x S1192 DeliveryStatus, 1x S1172 handler) |
### Skill Audit (Faza 26, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues; 8 pre-existing na ShipmentController (S3776, S1192, S1142, S3358) |
### Skill Audit (Faza 25, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues na zmienionych plikach |
### Skill Audit (Faza 24, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues na zmienionych plikach |
### Skill Audit (Faza 23, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 issues na nowych plikach |
### Skill Audit (Faza 22, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues na zmienionym pliku; 1 pre-existing S1172 |
### Skill Audit (Faza 21, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues na zmienionych plikach; 18 pre-existing |
### Skill Audit (Faza 20, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | n/a | Projekt C# — poza zakresem skanera PHP |
### Skill Audit (Faza 19, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych blocker/critical; 4 minor/major zalogowane w DOCS/todo.md |
### Skill Audit (Faza 18, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 17, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | âś“ | 0 nowych issues na zmienionych plikach |
### Skill Audit (Faza 15, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym milestone |
### Skill Audit (Faza 14, Plan 02)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 13, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 12, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 11, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 10, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Required — do uruchomienia przed kolejnym UNIFY |
### Skill Audit (Faza 07, Plan 05)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | â—‹ | Zainstalowany (v4.3.5) ale nie uruchomiony w tym planie |
### Skill Audit (Faza 07, Plan 04)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — brak instalacji w PATH |
### Skill Audit (Faza 07, Plan 03)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — brak instalacji w PATH |
### Skill Audit (Faza 07, Plan 02)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — brak instalacji w PATH |
### Skill Audit (Faza 07, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — brak instalacji w PATH |
### Skill Audit (Faza 06, Plan 06)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — brak instalacji w PATH |
### Skill Audit (Faza 06, Plan 02)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | â—‹ | PominiÄ™to — brak instalacji w PATH; S1142 violations powinny spaĹć o ~12-15 po uruchomieniu |
### Skill Audit (Faza 05, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — uruchomić ręcznie przed następnym planem z kodem PHP |
### Skill Audit (Faza 04, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ○ | Pominięto — plan czysto dokumentacyjny (komentarze SQL, brak nowego kodu PHP); uruchomić przy kolejnym planie z kodem |
### Skill Audit (Faza 03, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| sonar-scanner | â—‹ | PominiÄ™to — przejĹcie do UNIFY bez skanowania; uruchomić przy kolejnym planie |
### Skill Audit (Faza 02, Plan 01)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| /code-review | ○ | Pominięto — jednolinijkowa naprawa oczywistego dead code |
| sonar-scanner | ○ | Pominięto — brak nowego kodu, zmiana kosmetyczna |
### Skill Audit (Faza 01, Plan 02)
| Oczekiwany | WywoĹany | Uwagi |
|------------|---------|-------|
| /feature-dev | ○ | Pominięto — plan byŠczysto refaktoryzacyjny |
| /code-review | â—‹ | PominiÄ™to — naleĹĽy wywoĹać przed kolejnym UNIFY |
| sonar-scanner | ○ | Nie uruchomiono — należy uruchomić i zaktualizować DOCS/todo.md |
### Deferred Issues
- **CI/CD SonarQube** — dodać GitHub Actions workflow (`.github/workflows/sonarqube.yml`) który odpala `sonar-scanner` automatycznie przy każdym pushu. Token projektu: `sqp_8ef2748d037777cf00cf1b38534f8d435b762d7d` (dodać jako GitHub Secret `SONAR_TOKEN`). Przypisać do fazy związanej z infrastrukturą/DevOps gdy tylko fazy zostaną zdefiniowane.
- **code-review** — wywoĹać /code-review przed kolejnym UNIFY (pominiÄ™to w obydwu planach fazy 01).
- **Delivery mapping "Szukaj..." layout** — JS `attachSelectFilter()` w allegro.php tworzy input search dla InPost/Apaczka selectów, wizualnie wygląda jakby należaŠdo wiersza powyżej. Pre-existing bug, do naprawy osobno.
### Git State
Last commit: 957fdda — feat(v1.6): inline status change on orders list — feat(v1.5): complete phases 40-43 workflow cleanup
Branch: main
Feature branches merged: none
### Blockers/Concerns
Brak.
### Skill Audit (Phase 47, Plan 01)
| Expected | Invoked | Notes |
|----------|---------|-------|
| sonar-scanner | ✓ | Scan wykonany w UNIFY; analysis successful na sonar.project-pro.pl |
## Session Continuity
Last session: 2026-03-27
Stopped at: v1.7 phase 45 completed (SUMMARY + docs + state updated)
Next action: Start next milestone planning (/paul:milestone or /paul:plan)
Resume file: .paul/ROADMAP.md
---
*STATE.md — Updated after every significant action*
Last session: 2026-03-28 14:35:00
Stopped at: Phase 47 complete, loop closed
Next action: Start next milestone planning ($paul-new-milestone)
Resume file: .paul/phases/47-shipment-created-automation/47-01-SUMMARY.md

View File

@@ -0,0 +1,210 @@
---
phase: 47-shipment-created-automation
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- src/Modules/Automation/AutomationController.php
- src/Modules/Automation/AutomationService.php
- src/Modules/Cron/CronHandlerFactory.php
- src/Modules/Shipments/ShipmentController.php
- src/Modules/Shipments/ShipmentPackageRepository.php
- resources/views/automation/form.php
- public/assets/js/modules/automation-form.js
- resources/views/automation/index.php
- DOCS/ARCHITECTURE.md
- DOCS/TECH_CHANGELOG.md
- DOCS/todo.md
autonomous: false
---
<objective>
## Goal
Dodac nowe zdarzenie automatyzacji `shipment.created`, ktore uruchamia sie od razu po utworzeniu przesylki w zamowieniu, oraz dodac nowa akcje automatyzacji `update_shipment_status` (UI: "Zmiana statusu przesylki").
## Purpose
Operator ma moc budowania automatyzacji natychmiast po wygenerowaniu przesylki (bez czekania na cron tracking) i moze reakcja reguly zmieniac status przesylki zgodnie z procesem operacyjnym firmy.
## Output
Kompletne rozszerzenie automatyzacji o:
- event `shipment.created` (natychmiastowy trigger),
- action `update_shipment_status`,
- konfiguracje w formularzu automatyzacji,
- aktualna dokumentacje techniczna.
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@DOCS/ARCHITECTURE.md
@DOCS/DB_SCHEMA.md
@DOCS/todo.md
## Prior Work (only if genuinely needed)
@.paul/phases/42-automation-shipment-status-event/42-01-PLAN.md
@.paul/phases/42-automation-shipment-status-event/42-01-SUMMARY.md
@.paul/phases/26-manual-tracking-number/26-01-SUMMARY.md
@.paul/phases/27-shipment-tracking-backend/27-01-SUMMARY.md
## Source Files
@src/Modules/Shipments/ShipmentController.php
@src/Modules/Shipments/ShipmentPackageRepository.php
@src/Modules/Automation/AutomationController.php
@src/Modules/Automation/AutomationService.php
@src/Modules/Cron/CronHandlerFactory.php
@resources/views/automation/form.php
@public/assets/js/modules/automation-form.js
@resources/views/automation/index.php
</context>
<skills>
## Required Skills (from SPECIAL-FLOWS.md)
| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| `sonar-scanner` | required | Po APPLY, przed UNIFY | o |
| /feature-dev | optional | Przed wdrazaniem nowej funkcjonalnosci | o |
| /code-review | optional | Po APPLY, przed UNIFY | o |
**BLOCKING:** Required skills MUST be loaded before APPLY proceeds.
## Skill Invocation Checklist
- [ ] `sonar-scanner` uruchomiony po APPLY
- [ ] /feature-dev (opcjonalnie)
- [ ] /code-review (opcjonalnie)
</skills>
<acceptance_criteria>
## AC-1: Event "Utworzenie przesylki" uruchamia sie natychmiast po sukcesie utworzenia
```gherkin
Given istnieje aktywna regula automatyzacji z eventem `shipment.created`
When uzytkownik utworzy przesylke dla zamowienia (provider API lub recznie)
Then system wywola AutomationService trigger w tym samym flow requestu
And nie wymaga to oczekiwania na cron `shipment_tracking_sync`
```
## AC-2: Nowa akcja "Zmiana statusu przesylki" jest konfigurowalna i walidowana
```gherkin
Given uzytkownik tworzy/edytuje regule automatyzacji
When dodaje akcje "Zmiana statusu przesylki"
Then moze wskazac docelowy status przesylki z dozwolonej listy
And zapis nie przechodzi dla nieprawidlowej konfiguracji akcji
```
## AC-3: Akcja poprawnie aktualizuje status przesylki i nie powoduje petli
```gherkin
Given regula uruchamia akcje `update_shipment_status`
When akcja jest wykonana dla zamowienia z paczka
Then status paczki zostaje zaktualizowany tylko przy realnej zmianie
And system nie wchodzi w nieskonczone petle triggerow automatyzacji
```
## AC-4: UI i dokumentacja sa spójne z nowymi elementami automatyzacji
```gherkin
Given wdrozenie nowego eventu i akcji
When uzytkownik otworzy formularz automatyzacji
Then widzi event "Utworzenie przesylki" i akcje "Zmiana statusu przesylki"
And ARCHITECTURE/TECH_CHANGELOG/todo opisuja zakres i ograniczenia implementacji
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Dodaj event `shipment.created` i natychmiastowy trigger po utworzeniu przesylki</name>
<files>src/Modules/Automation/AutomationController.php, src/Modules/Shipments/ShipmentController.php, src/Modules/Automation/AutomationService.php</files>
<action>
Rozszerz ALLOWED_EVENTS i etykiety UI o `shipment.created` ("Utworzenie przesylki").
W `ShipmentController::create()` i `ShipmentController::createManual()` po potwierdzonym utworzeniu paczki wywolaj `AutomationService->trigger('shipment.created', orderId, context)`.
Context powinien zawierac co najmniej: package_id, provider, tracking_number (jezeli dostepny), package_status.
Unikaj triggera w sciezkach bledu tworzenia przesylki.
</action>
<verify>rg -n "shipment\.created|trigger\('shipment\.created'|Utworzenie przesylki" src/Modules/Automation src/Modules/Shipments resources/views/automation</verify>
<done>AC-1 satisfied: event jest dostepny i odpalany od razu po utworzeniu przesylki.</done>
</task>
<task type="auto">
<name>Task 2: Dodaj akcje `update_shipment_status` i wykonanie backend</name>
<files>src/Modules/Automation/AutomationController.php, src/Modules/Automation/AutomationService.php, src/Modules/Shipments/ShipmentPackageRepository.php, src/Modules/Cron/CronHandlerFactory.php</files>
<action>
Dodaj nowy typ akcji do walidacji i parsera konfiguracji: `update_shipment_status`.
Konfiguracja akcji: docelowy status dostawy (`delivery_status`) z tej samej mapy statusow biznesowych co warunki shipment_status.
W `AutomationService` dodaj handler akcji, ktory wyszukuje docelowa paczke (z context package_id lub fallback: najnowsza aktywna paczka zamowienia) i wykonuje aktualizacje statusu tylko przy realnej zmianie.
Dodaj zabezpieczenie anty-petla: nie emituj kolejnego eventu przy braku zmiany; przy zmianie oznacz context zrodla automatyzacji i respektuj chain dedup.
Zaktualizuj factory DI, by serwis automatyzacji mial dostep do repo paczek.
</action>
<verify>rg -n "update_shipment_status|handleUpdateShipmentStatus|delivery_status|ALLOWED_ACTION_TYPES" src/Modules/Automation src/Modules/Shipments src/Modules/Cron</verify>
<done>AC-2 satisfied i AC-3 satisfied: akcja jest walidowana, wykonuje realna zmiane i nie petli sie.</done>
</task>
<task type="auto">
<name>Task 3: Rozszerz formularz automatyzacji oraz dokumentacje techniczna</name>
<files>resources/views/automation/form.php, public/assets/js/modules/automation-form.js, resources/views/automation/index.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md, DOCS/todo.md</files>
<action>
Dodaj opcje akcji "Zmiana statusu przesylki" do formularza oraz dynamiczny config (wybor statusu).
Zapewnij zgodnosc renderu create/edit i JS add-row.
Zaktualizuj dokumentacje: nowy event natychmiastowy i nowa akcja, z opisem kontekstu oraz ograniczen.
Dodaj/uzupelnij wpis w `DOCS/todo.md` dla nowego zakresu (zamkniecie po wdrozeniu).
</action>
<verify>rg -n "shipment\.created|Zmiana statusu przesylki|update_shipment_status" resources/views/automation public/assets/js/modules/automation-form.js DOCS/ARCHITECTURE.md DOCS/TECH_CHANGELOG.md DOCS/todo.md</verify>
<done>AC-4 satisfied: UI i dokumentacja sa spójne z wdrozonym zakresem.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Nowy natychmiastowy event `shipment.created` oraz nowa akcja automatyzacji `update_shipment_status`.</what-built>
<how-to-verify>
1. Otworz: Ustawienia > Zadania automatyczne > Dodaj zadanie.
2. Sprawdz event "Utworzenie przesylki" i akcje "Zmiana statusu przesylki".
3. Utworz regule: event `shipment.created`, warunek integracji, akcja zmiany statusu przesylki.
4. Utworz przesylke z poziomu zamowienia i potwierdz, ze regula wykonala sie od razu (bez cron).
5. Potwierdz, ze ponowne odpalenie bez realnej zmiany statusu nie generuje petli.
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- `database/migrations/*` (brak zmian schematu w tej fazie)
- Logika eventu `receipt.created` i istniejace akcje poza wymaganym rozszerzeniem
- Moduly niezwiazane z automatyzacja i przesylkami
## SCOPE LIMITS
- Tylko nowe zdarzenie i nowa akcja w module automatyzacji.
- Bez przebudowy calego silnika cron/tracking.
- Bez zmian UX poza formularzem i listowaniem automatyzacji.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `C:\xampp\php\php.exe -l src/Modules/Automation/AutomationController.php`
- [ ] `C:\xampp\php\php.exe -l src/Modules/Automation/AutomationService.php`
- [ ] `C:\xampp\php\php.exe -l src/Modules/Shipments/ShipmentController.php`
- [ ] `C:\xampp\php\php.exe -l src/Modules/Shipments/ShipmentPackageRepository.php`
- [ ] `C:\xampp\php\php.exe -l src/Modules/Cron/CronHandlerFactory.php`
- [ ] `C:\xampp\php\php.exe -l resources/views/automation/form.php`
- [ ] `C:\xampp\php\php.exe -l resources/views/automation/index.php`
- [ ] Manual checkpoint wykonany (event dziala od razu + akcja statusu)
- [ ] Dokumentacja zaktualizowana (`DOCS/ARCHITECTURE.md`, `DOCS/TECH_CHANGELOG.md`, `DOCS/todo.md`)
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Event `shipment.created` uruchamia automatyzacje natychmiast po utworzeniu przesylki.
- Akcja `update_shipment_status` jest dostepna, walidowana i dziala przewidywalnie.
- Brak petli automatyzacji przy ponownych wywolaniach bez zmiany statusu.
- Dokumentacja techniczna odzwierciedla nowy kontrakt event/action.
</success_criteria>
<output>
After completion, create `.paul/phases/47-shipment-created-automation/47-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,51 @@
---
phase: 47-shipment-created-automation
plan: 01
status: completed
completed: 2026-03-28
---
# Phase 47 Plan 01 Summary
## Result
- Dodano nowe zdarzenie automatyzacji `shipment.created` (UI: `Utworzenie przesylki`).
- Trigger `shipment.created` jest uruchamiany od razu po sukcesie tworzenia przesylki:
- `ShipmentController::create()` (provider API),
- `ShipmentController::createManual()` (reczny numer przesylki).
- Dodano nowy typ akcji automatyzacji `update_shipment_status` (UI: `Zmiana statusu przesylki`).
- `AutomationService` wykonuje aktualizacje `delivery_status` tylko przy realnej zmianie, zapisuje activity log i emituje `shipment.status_changed` z kontekstem zmiany.
## Acceptance Criteria
- AC-1: Pass
- AC-2: Pass
- AC-3: Pass
- AC-4: Pass
## Verification
- `C:\xampp\php\php.exe -l src/Modules/Automation/AutomationController.php` PASS
- `C:\xampp\php\php.exe -l src/Modules/Automation/AutomationService.php` PASS
- `C:\xampp\php\php.exe -l src/Modules/Shipments/ShipmentController.php` PASS
- `C:\xampp\php\php.exe -l src/Modules/Shipments/ShipmentPackageRepository.php` PASS
- `C:\xampp\php\php.exe -l src/Modules/Cron/CronHandlerFactory.php` PASS
- `C:\xampp\php\php.exe -l routes/web.php` PASS
- `C:\xampp\php\php.exe -l resources/views/automation/form.php` PASS
- `C:\xampp\php\php.exe -l resources/views/automation/index.php` PASS
- `rg -n "shipment\.created|update_shipment_status|shipment_status_key|automation_shipment_status_updated" src resources public routes` PASS
- `sonar-scanner` PASS (analysis successful): https://sonar.project-pro.pl/dashboard?id=orderPRO
## Manual Checkpoint
- UAT checkpoint wykonany i zatwierdzony przez uzytkownika (`approved`).
## Files
- `src/Modules/Automation/AutomationController.php`
- `src/Modules/Automation/AutomationService.php`
- `src/Modules/Cron/CronHandlerFactory.php`
- `src/Modules/Shipments/ShipmentController.php`
- `src/Modules/Shipments/ShipmentPackageRepository.php`
- `routes/web.php`
- `resources/views/automation/form.php`
- `resources/views/automation/index.php`
- `public/assets/js/modules/automation-form.js`
- `DOCS/ARCHITECTURE.md`
- `DOCS/TECH_CHANGELOG.md`
- `DOCS/todo.md`

View File

@@ -5,8 +5,9 @@
- UI korzysta z globalnego standardu naglowkow sekcji (`h2/h3/h4.section-title`) definiowanego centralnie w `resources/scss/app.scss` i buildowanego do `public/assets/css/app.css`.
- Kolory akcji UI (przyciski `btn--primary` i warianty `btn--outline-primary`) sa odseparowane od koloru naglowkow (`section-title`) przez dedykowane tokeny `--c-action-primary` i `--c-action-primary-dark` w `resources/scss/shared/_ui-components.scss`.
- Import Allegro zapisuje log `import` z kontekstem triggera (`manual_import`, `orders_sync`, `status_sync`) i deduplikuje powtarzalne wpisy bez realnej zmiany.
- Automatyzacja obsluguje zdarzenie `shipment.status_changed` i warunek `shipment_status` oparty o statusy biznesowe.
- Automatyzacja obsluguje zdarzenia `shipment.created` (natychmiast po utworzeniu paczki) i `shipment.status_changed` (po realnej zmianie statusu dostawy), oraz warunek `shipment_status` oparty o statusy biznesowe.
- Automatyzacja obsluguje akcje `issue_receipt` (Wystaw paragon) z parametrami: `receipt_config_id`, `issue_date_mode`, `duplicate_policy`.
- Automatyzacja obsluguje akcje `update_shipment_status` (Zmiana statusu przesylki) z parametrem `status_key` mapowanym na techniczny `delivery_status`.
- Orkiestracja automatyzacji obsluguje chain events: akcja moze emitowac kolejne zdarzenie (`emitEvent`), a engine propaguje wspolny kontekst lancucha.
- Zabezpieczenia chain automation (dla obecnych i przyszlych eventow):
- limit glebokosci lancucha (`MAX_CHAIN_DEPTH`),
@@ -157,7 +158,7 @@
- `App\Modules\Accounting\AccountingController` (index — lista paragonow, export — XLSX)
- `App\Modules\Automation\AutomationController` (index, create, store, edit, update, destroy, toggleStatus)
- `App\Modules\Automation\AutomationRepository` (findAll, findById, create, update, delete, toggleActive, findActiveByEvent)
- `App\Modules\Automation\AutomationService` (trigger, evaluateConditions, executeActions — watcher/executor regul automatyzacji; flow: ReceiptController::store() -> trigger('receipt.created') oraz ShipmentTrackingHandler::handle() -> trigger('shipment.status_changed', context) -> ewaluacja warunkow -> EmailSendingService::send() / auto issue_receipt)
- `App\Modules\Automation\AutomationService` (trigger, evaluateConditions, executeActions — watcher/executor regul automatyzacji; flow: ReceiptController::store() -> trigger('receipt.created'), ShipmentController::create()/createManual() -> trigger('shipment.created', context), ShipmentTrackingHandler::handle() -> trigger('shipment.status_changed', context) -> ewaluacja warunkow -> akcje: EmailSendingService::send() / auto issue_receipt / update_shipment_status)
- `App\Modules\Shipments\ShipmentProviderInterface`
- `App\Modules\Shipments\ShipmentProviderRegistry`
- `App\Modules\Shipments\ApaczkaShipmentService`
@@ -319,6 +320,7 @@
- `POST /orders/{id}/shipment/create`:
- `ShipmentController::create(Request): Response`,
- wybiera providera dynamicznie po `provider_code` i deleguje do `ShipmentProviderInterface::createShipment(...)`,
- po sukcesie tworzenia paczki triggeruje automatyzacje `shipment.created` z kontekstem paczki (`package_id`, `provider`, `tracking_number`, `package_status`, `delivery_status`),
- dla `apaczka` waliduje wymagane punkty odbioru/nadania wg definicji uslugi (`service_structure`) i przy bledzie wyceny zwraca rozszerzona diagnostyke parametrow,
- `apaczka` uzupelnia i wysyla `contact_person` dla nadawcy (z `Ustawienia > Dane firmy`) i odbiorcy (fallback z danych zamowienia),
- `apaczka` ustawia jawnie `pickup.type` (`SELF`/`COURIER`) na podstawie uslugi i obecnosci `sender_point_id`; dla `COURIER` dopelnia tez `pickup.date`, `pickup.hours_from`, `pickup.hours_to`,
@@ -336,6 +338,7 @@
- tworzy rekord w `shipment_packages` z `provider='manual'`, `status='created'` i podanym `tracking_number`,
- opcjonalnie zapisuje nazwe przewoznika w `carrier_id`,
- loguje zdarzenie `shipment_manual` w `order_activity_log`,
- po sukcesie triggeruje automatyzacje `shipment.created` dla recznie dodanej paczki,
- `ShipmentPackageRepository::createManual(int $orderId, string $trackingNumber, ?string $carrierName): int`.
## Przeplyw Ustawienia > Integracje > Allegro
@@ -403,7 +406,13 @@
- uruchamiany z crona (`allegro_status_sync`),
- respektuje ustawienie kierunku `allegro_status_sync_direction`,
- dla kierunku `allegro_to_orderpro` wykorzystuje mechanizm importu zamowien do aktualizacji statusow,
- dla kierunku `orderpro_to_allegro` zwraca wynik informacyjny (tryb przygotowany pod kolejny etap).
- dla kierunku `orderpro_to_allegro` pushuje reczne zmiany statusow (`order_status_history.change_source=manual`) do API Allegro,
- push buduje reverse mapping `orderpro_status_code -> allegro_status_code` z `allegro_order_status_mappings`,
- push aktualizuje kursor `integration_order_sync_state.last_status_pushed_at` po sukcesie.
- `AllegroApiClient::updateCheckoutFormFulfillment()`:
- PUT `/order/checkout-forms/{id}/fulfillment`,
- body JSON: `{"status":"<ALLEGRO_STATUS>"}`,
- uzywane przez `AllegroStatusSyncService` w kierunku `orderpro_to_allegro`.
## Log aktywnosci zamowien
- Tabela `order_activity_log` rejestruje wszystkie zdarzenia dotyczace zamowienia.
@@ -539,4 +548,3 @@
- laduje formy dostawy wykryte w zamowieniach danej instancji (`orders.source=shoppro` + `orders.integration_id`),
- laduje uslugi dostawy z Allegro API (`delivery-services`) z fallbackiem na odswiezenie tokenu OAuth,
- zapisuje mapowanie: forma dostawy shopPRO -> usluga Allegro/InPost WZA.

View File

@@ -1,5 +1,40 @@
# Tech Changelog
## 2026-03-28 (Phase 47 - Shipment Creation Automation, Plan 01)
- Automatyzacja:
- dodano nowe zdarzenie `shipment.created` (UI: `Utworzenie przesylki`),
- trigger jest uruchamiany natychmiast po sukcesie `ShipmentController::create()` oraz `ShipmentController::createManual()`,
- kontekst triggera zawiera m.in. `package_id`, `provider`, `tracking_number`, `package_status`, `delivery_status`.
- Dodano nowy typ akcji automatyzacji `update_shipment_status` (UI: `Zmiana statusu przesylki`):
- walidacja konfiguracji przez `AutomationController` (`shipment_status_key` -> `status_key`),
- wykonanie przez `AutomationService::handleUpdateShipmentStatus(...)`,
- aktualizacja `delivery_status` tylko przy realnej zmianie (bez falszywych triggerow),
- po zmianie statusu emitowane jest `shipment.status_changed` z kontekstem zmiany.
- Rozszerzono `AutomationService` o zaleznosc `ShipmentPackageRepository`:
- nowa metoda pomocnicza `ShipmentPackageRepository::findLatestByOrderId(int): ?array` (fallback wyboru paczki dla akcji).
- UI automatyzacji (`resources/views/automation/form.php`, `resources/views/automation/index.php`, `public/assets/js/modules/automation-form.js`) rozszerzono o:
- event `Utworzenie przesylki`,
- akcje `Zmiana statusu przesylki` z wyborem docelowego statusu biznesowego.
- Aktualizacja DI:
- `routes/web.php` i `src/Modules/Cron/CronHandlerFactory.php` przekazuja `ShipmentPackageRepository` do `AutomationService`,
- `ShipmentController` otrzymuje `AutomationService` jako zaleznosc konstruktora.
## 2026-03-28 (Allegro Status Push - orderPRO -> Allegro)
- Zaimplementowano kierunek synchronizacji statusow `orderpro_to_allegro` w `AllegroStatusSyncService`.
- `AllegroStatusSyncService`:
- pobiera reczne zmiany statusow (`order_status_history.change_source=manual`) dla zamowien Allegro,
- buduje reverse mapping (`orderpro_status_code -> allegro_status_code`) na podstawie `allegro_order_status_mappings`,
- pushuje statusy do API Allegro i raportuje `pushed/skipped/failed`,
- aktualizuje kursor `integration_order_sync_state.last_status_pushed_at`.
- Nowa metoda `AllegroApiClient::updateCheckoutFormFulfillment()`:
- PUT `/order/checkout-forms/{id}/fulfillment`,
- body JSON: `{"status":"<ALLEGRO_STATUS>"}`.
- `AllegroOrderSyncStateRepository`: dodano obsluge kursora push (`getLastStatusPushedAt`, `updateLastStatusPushedAt`).
- `AllegroStatusMappingRepository`: dodano reverse map builder `buildOrderproToAllegroMap()`.
- UI `Ustawienia > Integracje > Allegro > Ustawienia`:
- odblokowano wybor opcji `orderPRO -> Allegro` (usunieto `disabled` i dopisek `(wkrotce)`),
- zaktualizowano opis hintu kierunku synchronizacji.
- Dodano testy jednostkowe `tests/Unit/AllegroStatusSyncServiceTest.php` dla scenariuszy push/skip/fail/retry-401.
## 2026-03-27 (ShopPRO Status Push — orderPRO -> shopPRO)
- Zaimplementowano kierunek synchronizacji statusow `orderpro_to_shoppro` w `ShopproStatusSyncService`.
- Nowa metoda `ShopproApiClient::updateOrderStatus()` — PUT `/api.php?endpoint=orders&action=change_status&id={id}`.
@@ -702,3 +737,5 @@

View File

@@ -1,4 +1,4 @@
15. [x] W tym miejscu odwróć kolejność: najpierw źródło potem ID, <div class="orders-ref__meta"><span>f6079660-1af8-11f1-a7c9-231cf6ef29d1</span><span>allegro</span></div>
15. [x] W tym miejscu odwróć kolejność: najpierw źródło potem ID, <div class="orders-ref__meta"><span>f6079660-1af8-11f1-a7c9-231cf6ef29d1</span><span>allegro</span></div>
17. [x] Na liście zamówien jak jest źródło i id zamówienia to zamiast shopPRO musi pisać która integracja konkretnie. Oraz dodajemy napis ID: ...D
## SonarQube — post plany 02-02 i 02-03 (skan 2026-03-13)
@@ -10,7 +10,7 @@
## SonarQube — code quality (327 issues, skan 2026-03-12)
18. [] php:S112 (95x) — zastąpić generic `new \Exception` konkretnymi klasami wyjątków
19. [] php:S1142 (57x) — zredukować liczbę `return` w metodach (early return wydzielić metody)
19. [] php:S1142 (57x) — zredukować liczbę `return` w metodach (early return wydzielić metody)
20. [] php:S1192 (40x) — wyciągnąć powtarzające się string literals do stałych
21. [] php:S3776 (31x) — obniżyć złożoność kognitywną metod (wydzielić logikę do pomocniczych metod)
22. [] Web:S6827 (15x) — dodać brakujące atrybuty `alt` na tagach `<img>`
@@ -37,3 +37,192 @@
41. [x] Jaki jest sens tylu logów z importu allegro np w tym zamówieniu https://orderpro.projectpro.pl/orders/29, skąd taka ilość, co jest pobierane i sprawdzane?
42. [x] Nowy zdarzenie w zadaniach automatyczny -> zmiana statusu przesyłki, oraz nowe waruneki dla zdarzenia "zmiana statusu przesyłki": przesyłka zarejestrowana, przesyłka do odbioru, przesyłka nadana w punkcie, przesyłka odebrana, przesyłka anulowana, przesyłka nieodebrana, przesyłka odebrana (zwrot), chyba że takich statusów się nie da to trzeba sprawdzić jakie się da.
43. [x] Usuwanie wpisu z kolejki druku etykiet
## SonarQube — pełna lista błędów (new code period, skan 2026-03-28)
<!-- SONAR_ERRORS_START -->
- Źródło: SonarQube API `issues/search` dla `orderPRO` (`inNewCodePeriod=true`)
- Razem issue: 174
- Severity: MAJOR=110, CRITICAL=47, MINOR=16, BLOCKER=1
- Typy: CODE_SMELL=170, BUG=3, VULNERABILITY=1
### Lista issue
- [ ] [MINOR][BUG][php:S2003] resources/views/accounting/index.php:31 - Replace "require" with "require_once". (key: 6fe7d2de-4802-459e-a5a7-f9f1be183b8e)
- [ ] [MINOR][BUG][php:S2003] resources/views/orders/show.php:780 - Replace "require" with "require_once". (key: 98cef6cd-bb23-4bc8-acd9-01d4417f25e6)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/layouts/app.php:80 - Anchors must have content and the content must be accessible by a screen reader. (key: 64d29d8b-146d-4a20-803d-4aeb035b0391)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/orders/receipt-create.php:123 - Anchors must have content and the content must be accessible by a screen reader. (key: bbd01366-d6f2-4745-b5b2-8b06c3aec574)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/orders/show.php:669 - Anchors must have content and the content must be accessible by a screen reader. (key: 351a396c-239c-468d-a1bf-391adabd1b0a)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/receipts/show.php:19 - Anchors must have content and the content must be accessible by a screen reader. (key: cb8922ca-ccc4-4518-9466-e9c40d0aec4b)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/receipts/show.php:20 - Anchors must have content and the content must be accessible by a screen reader. (key: 29dd7510-9b95-4f90-9f47-0cf39d6318f2)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/receipts/show.php:21 - Anchors must have content and the content must be accessible by a screen reader. (key: 15deb0d4-dae8-4ede-b371-969ed668e0b7)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/settings/accounting.php:50 - Anchors must have content and the content must be accessible by a screen reader. (key: cffe0ae9-1c3f-4e5b-99d9-3dd6d528252b)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/settings/accounting.php:133 - Anchors must have content and the content must be accessible by a screen reader. (key: 816ae9c0-c782-406f-a3b4-d6d810119ebd)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/settings/delivery-status-mappings.php:24 - Anchors must have content and the content must be accessible by a screen reader. (key: a6e860d2-54dd-485b-82db-79415b2d4cb7)
- [ ] [MINOR][CODE_SMELL][Web:S6827] resources/views/settings/printing.php:138 - Anchors must have content and the content must be accessible by a screen reader. (key: 43949459-6186-48cf-b099-36064429e0dc)
- [ ] [MINOR][CODE_SMELL][php:S1488] src/Modules/Accounting/ReceiptRepository.php:139 - Immediately return this expression instead of assigning it to the temporary variable "$number". (key: 4cf8b055-d030-4fe5-b917-c4eae64c2e4d)
- [ ] [MINOR][CODE_SMELL][php:S1481] src/Modules/Settings/EmailTemplateController.php:91 - Remove this unused "$t" local variable. (key: 5e00928d-3bfa-40cb-82e3-f6d1886f8b09)
- [ ] [MINOR][CODE_SMELL][php:S1481] src/Modules/Settings/ShopproIntegrationsController.php:118 - Remove this unused "$redirectBase" local variable. (key: 22a0c0d1-5edf-4a80-8e42-dcab51ec880b)
- [ ] [MINOR][CODE_SMELL][php:S1481] src/Modules/Settings/ShopproIntegrationsController.php:185 - Remove this unused "$redirectBase" local variable. (key: 2d95f5c7-5f6b-4e60-a48e-59fe991831f3)
- [ ] [MAJOR][CODE_SMELL][php:S4833] resources/views/accounting/index.php:31 - Replace "require" with namespace import mechanism through the "use" keyword. (key: 349e8aeb-dc6d-4ac9-9c7e-f9b4cab594aa)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/automation/form.php:6 - Extract this nested ternary operation into an independent statement. (key: d9b92d37-73d9-4d70-804a-bde593b3253f)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/automation/form.php:7 - Extract this nested ternary operation into an independent statement. (key: 21a944af-e4fe-427a-9b30-4fedfb9f2211)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/automation/form.php:64 - Extract this nested ternary operation into an independent statement. (key: e253095f-e15e-468a-ac77-e143109b17fc)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/automation/index.php:21 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 0ce5f805-0818-495e-b8d1-fe8049b91a75)
- [ ] [MAJOR][CODE_SMELL][Web:S6853] resources/views/components/table-list.php:159 - A form label must be associated with a control and have accessible text. (key: b982e00b-4a3f-4e0c-bff4-f069fb33863a)
- [ ] [MAJOR][CODE_SMELL][Web:S6853] resources/views/orders/partials/email-send-modal.php:32 - A form label must be associated with a control and have accessible text. (key: e7bef918-f0fa-4163-a0ef-a1ef85202dd7)
- [ ] [MAJOR][CODE_SMELL][Web:S6853] resources/views/orders/partials/email-send-modal.php:36 - A form label must be associated with a control and have accessible text. (key: 3a807055-dbce-4e2b-a3d0-f464a1541203)
- [ ] [MAJOR][CODE_SMELL][Web:S6853] resources/views/orders/partials/email-send-modal.php:45 - A form label must be associated with a control and have accessible text. (key: d0367ef9-f2f2-4fb6-bf5e-8f63fa365dc7)
- [ ] [MAJOR][CODE_SMELL][php:S1066] resources/views/orders/show.php:232 - Merge this if statement with the enclosing one. (key: 60895f28-eb9d-4856-835f-ba52879ddf72)
- [ ] [MAJOR][CODE_SMELL][php:S4833] resources/views/orders/show.php:780 - Replace "require" with namespace import mechanism through the "use" keyword. (key: 7811b6ca-5d01-4735-9210-ec33bda2cb15)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/settings/accounting.php:15 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 070e9668-dbf0-4289-810a-3cf82a63c4dc)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/settings/accounting.php:125 - Extract this nested ternary operation into an independent statement. (key: 423b1c28-9cec-42e5-a7d6-04c76b0d85d1)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/settings/delivery-status-mappings.php:17 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 8589b27e-9d53-4391-bb9a-62b51bef8a09)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/settings/email-mailboxes.php:15 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 8e8fe629-0de9-4d70-a5b8-226f1384abf3)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/settings/email-mailboxes.php:148 - Extract this nested ternary operation into an independent statement. (key: a74eedd7-a231-4881-965f-24e56c1be8e7)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/settings/email-templates.php:18 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 9c0e2dc4-5c2c-46b2-a8d7-7bb9d4315f81)
- [ ] [MAJOR][CODE_SMELL][php:S3358] resources/views/settings/email-templates.php:115 - Extract this nested ternary operation into an independent statement. (key: 26857bc5-9bd2-4a33-86e6-060300b057fb)
- [ ] [MAJOR][CODE_SMELL][Web:S6819] resources/views/settings/printing.php:16 - Use <output> instead of the status role to ensure accessibility across all devices. (key: 298ffe0f-babf-4b9f-b919-f4b113b374b0)
- [ ] [MAJOR][CODE_SMELL][php:S108] src/Core/Application.php:305 - Either remove or fill this block of code. (key: 96a6ddf7-f8ef-44d9-b7ad-7a0121bb5dbf)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Accounting/ReceiptController.php:78 - This method has 5 returns, which is more than the 3 allowed. (key: 575a0744-73ce-4613-9695-1c738c76c6a8)
- [ ] [MAJOR][CODE_SMELL][php:S1068] src/Modules/Automation/AutomationController.php:36 - Remove this unused "$translator" private field. (key: a0396a4b-e5b1-4170-8fc3-cfaec4b3dc30)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Automation/AutomationController.php:43 - Remove the unused function parameter "$request". (key: 65a90d6a-ad36-4447-b2f9-ecdc7ba8adde)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Automation/AutomationController.php:61 - Remove the unused function parameter "$request". (key: 870d63e8-0901-448f-94a1-0e8b01912dae)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Automation/AutomationController.php:106 - This method has 4 returns, which is more than the 3 allowed. (key: 607368ad-fb0c-4f55-a356-7a7bbb2171c5)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Automation/AutomationController.php:244 - This method has 5 returns, which is more than the 3 allowed. (key: 4f1cf18f-0bfb-464f-a91c-96d55f727407)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Automation/AutomationController.php:386 - This method has 5 returns, which is more than the 3 allowed. (key: 30a04d0a-c531-4afc-9ea7-b4e3fac8bc9b)
- [ ] [MAJOR][CODE_SMELL][php:S112] src/Modules/Automation/AutomationRepository.php:133 - Define and throw a dedicated exception instead of using a generic one. (key: 3d4896bb-1b99-4ef1-9f5e-1882a2c96111)
- [ ] [MAJOR][CODE_SMELL][php:S1448] src/Modules/Automation/AutomationService.php:13 - Class "AutomationService" has 24 methods, which is greater than 20 authorized. Split it into smaller classes. (key: 306419f7-dc3e-426b-9f2b-af3da48cf961)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Automation/AutomationService.php:143 - This method has 4 returns, which is more than the 3 allowed. (key: be2ee4d3-cd59-43cd-8953-cc2e61590751)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Automation/AutomationService.php:249 - This method has 4 returns, which is more than the 3 allowed. (key: a5b8e06b-0d6f-4867-b4f0-9717e074ac2e)
- [ ] [MAJOR][CODE_SMELL][php:S1448] src/Modules/Cron/CronRepository.php:10 - Class "CronRepository" has 22 methods, which is greater than 20 authorized. Split it into smaller classes. (key: f57e5c77-cecf-4451-8cb4-9d3cd107743d)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Cron/ShipmentTrackingHandler.php:22 - Remove the unused function parameter "$payload". (key: df8cb6fd-8f1f-491b-9170-bcda370fcdc6)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Cron/ShipmentTrackingHandler.php:24 - Remove the unused function parameter "$_payload". (key: 4c8e00f0-d82a-4bb2-93e8-368acfddbc94)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Email/AttachmentGenerator.php:37 - This method has 5 returns, which is more than the 3 allowed. (key: ecc23d2e-409a-44da-855c-b0d1803b320c)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Email/EmailSendingService.php:31 - This method has 5 returns, which is more than the 3 allowed. (key: 6627aebd-7dce-4206-8dce-81fcdc7e0f65)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Email/EmailSendingService.php:165 - This method has 4 returns, which is more than the 3 allowed. (key: 3c755950-a760-48a2-806d-1c6977c5ab11)
- [ ] [MAJOR][CODE_SMELL][php:S107] src/Modules/Email/EmailSendingService.php:293 - This function has 11 parameters, which is greater than the 7 authorized. (key: bf3c667b-fefc-4ecc-8cd3-46810cf07b11)
- [ ] [MAJOR][CODE_SMELL][php:S1448] src/Modules/Orders/OrdersController.php:21 - Class "OrdersController" has 22 methods, which is greater than 20 authorized. Split it into smaller classes. (key: 8e4cf728-d4e5-41b9-9aee-e1f83b20fb98)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Orders/OrdersController.php:738 - This method has 5 returns, which is more than the 3 allowed. (key: 345e58a7-989a-4992-895d-e50e2aba8b5d)
- [ ] [MAJOR][CODE_SMELL][php:S1448] src/Modules/Orders/OrdersRepository.php:10 - Class "OrdersRepository" has 29 methods, which is greater than 20 authorized. Split it into smaller classes. (key: 99a725d0-e52c-4511-b2fe-0124ea396530)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Orders/OrdersRepository.php:765 - This method has 6 returns, which is more than the 3 allowed. (key: dee0f8dc-13eb-4bb5-a113-283e103c3e8d)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Printing/ApiKeyMiddleware.php:16 - This method has 5 returns, which is more than the 3 allowed. (key: ad20b5d4-2e4f-45c6-b7d6-67971c8985bf)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Printing/PrintApiController.php:24 - This method has 4 returns, which is more than the 3 allowed. (key: 8a9d1c4c-d76d-48ed-93e7-6c6220e11b60)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Printing/PrintApiController.php:48 - This method has 6 returns, which is more than the 3 allowed. (key: 5239c52c-cdd7-4c54-995e-fc8c079d1f33)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Printing/PrintApiController.php:93 - Remove the unused function parameter "$request". (key: 9e2cd6a3-816f-4600-85c7-539ca9bffa72)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Printing/PrintApiController.php:110 - This method has 5 returns, which is more than the 3 allowed. (key: abd439dc-6d09-4b90-9dbb-9b3ad8e39b00)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroApiClient.php:174 - This method has 4 returns, which is more than the 3 allowed. (key: 65fef8f7-212e-43b9-87de-5e045ff990ea)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroDeliveryMappingController.php:107 - This method has 6 returns, which is more than the 3 allowed. (key: f5b84a65-0df5-4188-9795-826c12de4bf5)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroDeliveryMappingController.php:163 - This method has 4 returns, which is more than the 3 allowed. (key: 76e0cad6-338c-47f8-b19f-b23d379b25c4)
- [ ] [MAJOR][CODE_SMELL][php:S1068] src/Modules/Settings/AllegroIntegrationController.php:54 - Remove this unused "$statusDiscoveryService" private field. (key: 7538d906-57ee-4332-9efe-93f818d96e15)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroIntegrationController.php:580 - This method has 5 returns, which is more than the 3 allowed. (key: 82bb5eef-a7e6-4d56-bc9d-1346dc6ae231)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroIntegrationController.php:601 - This method has 4 returns, which is more than the 3 allowed. (key: a83fb3eb-6b77-4e81-b88e-3603e25322d2)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroIntegrationController.php:? - This method has 6 returns, which is more than the 3 allowed. (key: 83c9cf56-26ac-4940-b95d-2c900e42842a)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroIntegrationController.php:? - This method has 4 returns, which is more than the 3 allowed. (key: 491a1bd5-469b-4cfc-91dd-0c3c42308f9a)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroOAuthClient.php:129 - This method has 4 returns, which is more than the 3 allowed. (key: 1327860b-f1fe-4afe-93bb-d7e7942deb18)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroOrderSyncStateRepository.php:116 - This method has 5 returns, which is more than the 3 allowed. (key: e07bea6a-b47c-4569-8424-7f3aad44dd91)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroStatusMappingController.php:24 - This method has 5 returns, which is more than the 3 allowed. (key: bdc7b785-b0f6-44da-a9aa-9141cbaa797a)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroStatusMappingController.php:60 - This method has 4 returns, which is more than the 3 allowed. (key: 9d61f6f0-681f-426a-ad7d-5c92ebe5d9f9)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroStatusSyncService.php:95 - This method has 4 returns, which is more than the 3 allowed. (key: 3ea41fce-c3e4-4130-b663-07e3539437a2)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/AllegroTokenManager.php:22 - This method has 4 returns, which is more than the 3 allowed. (key: b40ca0bb-c268-434f-85e5-23ed04992e74)
- [ ] [MAJOR][CODE_SMELL][php:S112] src/Modules/Settings/AllegroTokenManager.php:? - Define and throw a dedicated exception instead of using a generic one. (key: a90b3b80-375d-4b74-aa15-9d0dbed5a668)
- [ ] [MAJOR][CODE_SMELL][php:S112] src/Modules/Settings/AllegroTokenManager.php:? - Define and throw a dedicated exception instead of using a generic one. (key: 48f9a5e2-ed3f-4559-9236-f5d6cfb4d184)
- [ ] [MAJOR][CODE_SMELL][php:S112] src/Modules/Settings/AllegroTokenManager.php:? - Define and throw a dedicated exception instead of using a generic one. (key: 55989bbe-7ca8-4507-8ce1-60bfe9f787ba)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ApaczkaApiClient.php:12 - This method has 4 returns, which is more than the 3 allowed. (key: 3aaf7471-390f-4da6-9787-e2a90d85e757)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/DeliveryStatusMappingController.php:78 - This method has 4 returns, which is more than the 3 allowed. (key: 80297fac-393a-4c1f-9fdd-4c2c178b606f)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/EmailMailboxController.php:51 - This method has 5 returns, which is more than the 3 allowed. (key: 2fa910d3-968b-418b-8e72-a1583a704103)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/EmailMailboxController.php:149 - This method has 10 returns, which is more than the 3 allowed. (key: 970d4c0a-02d0-4d5a-ba4a-9d186ca91827)
- [ ] [MAJOR][CODE_SMELL][php:S3358] src/Modules/Settings/EmailMailboxController.php:173 - Extract this nested ternary operation into an independent statement. (key: 24f6a171-bd8f-4277-8664-2f4561db7499)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Settings/EmailMailboxController.php:184 - Remove the unused function parameter "$errno". (key: e10d7439-6df7-4ed0-af9d-be43df3d0ad0)
- [ ] [MAJOR][CODE_SMELL][php:S1066] src/Modules/Settings/EmailMailboxController.php:213 - Merge this if statement with the enclosing one. (key: 73174936-1909-41e0-93f6-27cd62529463)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/EmailTemplateController.php:180 - This method has 4 returns, which is more than the 3 allowed. (key: beec3100-a5ac-432f-a951-48e9b7e1454e)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Settings/EmailTemplateController.php:238 - Remove the unused function parameter "$request". (key: 2377826f-4c53-4fd9-83c8-e3b3a3cf160f)
- [ ] [MAJOR][CODE_SMELL][php:S112] src/Modules/Settings/EmailTemplateRepository.php:127 - Define and throw a dedicated exception instead of using a generic one. (key: f1d48d68-eb1c-4ed0-a4aa-8b1f9b3795be)
- [ ] [MAJOR][CODE_SMELL][php:S1068] src/Modules/Settings/PrintSettingsController.php:20 - Remove this unused "$translator" private field. (key: 1f25c1d8-16b8-491e-90b7-bf0729829270)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ReceiptConfigController.php:51 - This method has 4 returns, which is more than the 3 allowed. (key: 87ef6d59-5e41-4aa4-892b-fe434f1a6d33)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproApiClient.php:8 - This method has 4 returns, which is more than the 3 allowed. (key: d94d5549-57ce-4f6a-8f20-3f9e3ad1e398)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproApiClient.php:271 - This method has 6 returns, which is more than the 3 allowed. (key: 4adaba8d-505d-4021-964c-e759f5b643e2)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproIntegrationsController.php:417 - This method has 6 returns, which is more than the 3 allowed. (key: afeb41a5-6952-4bfb-9b33-3a6cd21a0164)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproIntegrationsController.php:845 - This method has 4 returns, which is more than the 3 allowed. (key: 4ba1161c-abf6-4962-a271-c3a9a036f89e)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproIntegrationsController.php:892 - This method has 4 returns, which is more than the 3 allowed. (key: ee0d2f35-63fe-4820-bbca-f37c80507ba8)
- [ ] [MAJOR][CODE_SMELL][php:S1448] src/Modules/Settings/ShopproOrderMapper.php:9 - Class "ShopproOrderMapper" has 25 methods, which is greater than 20 authorized. Split it into smaller classes. (key: e132d4d8-d7ef-43d9-9a56-bc73e29f04b5)
- [ ] [MAJOR][CODE_SMELL][php:S1066] src/Modules/Settings/ShopproOrderMapper.php:124 - Merge this if statement with the enclosing one. (key: 55b645d7-a07c-46bf-9650-6ee814db3823)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproOrderMapper.php:756 - This method has 5 returns, which is more than the 3 allowed. (key: 5d78c738-b8c0-4d64-bf60-d845a3ff79e5)
- [ ] [MAJOR][CODE_SMELL][php:S107] src/Modules/Settings/ShopproOrdersSyncService.php:148 - This function has 12 parameters, which is greater than the 7 authorized. (key: d752676c-26a9-41dc-9fc2-25fed7279945)
- [ ] [MAJOR][CODE_SMELL][php:S107] src/Modules/Settings/ShopproOrdersSyncService.php:205 - This function has 10 parameters, which is greater than the 7 authorized. (key: 8833dfe4-f5d4-41a8-9562-3900907ae83e)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproOrderSyncStateRepository.php:28 - This method has 6 returns, which is more than the 3 allowed. (key: 8f905c07-78cf-4821-91c0-07a00bf81294)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproOrderSyncStateRepository.php:119 - This method has 4 returns, which is more than the 3 allowed. (key: 568faf2a-c596-4a6d-a93b-3068ffb59018)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproOrderSyncStateRepository.php:187 - This method has 5 returns, which is more than the 3 allowed. (key: 1f865f5f-133c-4c6e-9f71-2bc16e67cf5c)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproOrderSyncStateRepository.php:233 - This method has 4 returns, which is more than the 3 allowed. (key: 78fdff90-b4e2-4788-badf-3e9c6120095d)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproProductImageResolver.php:67 - This method has 5 returns, which is more than the 3 allowed. (key: 3487bf7b-14b8-4a14-a7d5-04a06352f4e8)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproProductImageResolver.php:100 - This method has 4 returns, which is more than the 3 allowed. (key: 610094af-d885-41a3-882d-5f80b1811756)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Settings/ShopproStatusSyncService.php:85 - This method has 5 returns, which is more than the 3 allowed. (key: b96494b7-0abc-4a3c-850e-917ebb967162)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/AllegroTrackingService.php:? - This method has 4 returns, which is more than the 3 allowed. (key: fb96d9eb-76a8-4bed-bed8-51e40fb34637)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Shipments/ApaczkaShipmentService.php:? - Remove the unused function parameter "$pickupDate". (key: 89c3519a-8fd8-4f4b-8441-31dd1964d5c9)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/ApaczkaTrackingService.php:? - This method has 6 returns, which is more than the 3 allowed. (key: 7e398dc8-ba2c-46b5-a92b-c6215b5dae89)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/DeliveryStatus.php:298 - This method has 5 returns, which is more than the 3 allowed. (key: 826ef8c0-6ae2-4e6e-9362-efedcd7d4b3e)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/DeliveryStatus.php:325 - This method has 9 returns, which is more than the 3 allowed. (key: aa388daa-f00e-420e-890d-296d0bf887b7)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostShipmentService.php:162 - This method has 4 returns, which is more than the 3 allowed. (key: d6f7b0db-a66b-463f-a468-453d8c5e77e2)
- [ ] [MAJOR][CODE_SMELL][php:S108] src/Modules/Shipments/InpostShipmentService.php:259 - Either remove or fill this block of code. (key: 2c40580b-b1c5-46d1-99de-0ef17482c4fa)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostShipmentService.php:379 - This method has 4 returns, which is more than the 3 allowed. (key: 50211ce3-df60-4509-8006-0731330b33db)
- [ ] [MAJOR][CODE_SMELL][php:S3358] src/Modules/Shipments/InpostShipmentService.php:430 - Extract this nested ternary operation into an independent statement. (key: 5e93d138-15b2-42e2-aea8-cdb65fe73093)
- [ ] [MAJOR][CODE_SMELL][php:S3358] src/Modules/Shipments/InpostShipmentService.php:464 - Extract this nested ternary operation into an independent statement. (key: b4019378-ddc0-49d1-aa5b-f207191c25b9)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostShipmentService.php:481 - This method has 4 returns, which is more than the 3 allowed. (key: 52ab972c-121e-4ff9-845a-44a370a78d21)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostTrackingService.php:? - This method has 5 returns, which is more than the 3 allowed. (key: 79ec448a-2ccf-425e-b891-b5b575d32014)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostTrackingService.php:? - This method has 4 returns, which is more than the 3 allowed. (key: 25da7c1f-e8c4-4093-88e7-6273943092aa)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/InpostTrackingService.php:? - This method has 4 returns, which is more than the 3 allowed. (key: ad271852-0406-4aaa-b5bf-63c27b87c997)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/ShipmentController.php:341 - This method has 4 returns, which is more than the 3 allowed. (key: ac28cbe9-96be-4cbd-bcc4-8c61a3de54fe)
- [ ] [MAJOR][CODE_SMELL][php:S1172] src/Modules/Shipments/ShipmentPresetController.php:16 - Remove the unused function parameter "$request". (key: ca0f98ed-fd61-45c7-9983-1be5c4a3dc61)
- [ ] [MAJOR][CODE_SMELL][php:S1142] src/Modules/Shipments/ShipmentPresetController.php:36 - This method has 4 returns, which is more than the 3 allowed. (key: cafb4b15-3a32-4df7-89ed-fca044b6b2f2)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/automation/form.php:56 - Define a constant instead of duplicating this literal " selected" 10 times. (key: 1b785bca-9189-4e51-a983-1a6cd1ed413e)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/automation/form.php:64 - Define a constant instead of duplicating this literal " checked" 4 times. (key: f778b6e9-59c2-451f-b966-ee339dc056b3)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/settings/accounting.php:97 - Define a constant instead of duplicating this literal " selected" 8 times. (key: 1a039950-d513-403d-a535-63b84457aba0)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/settings/accounting.php:121 - Define a constant instead of duplicating this literal " checked" 3 times. (key: 9d152206-5833-4ae7-9814-39101c81a252)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/settings/email-mailboxes.php:121 - Define a constant instead of duplicating this literal " selected" 3 times. (key: 771b71dd-2b2e-46fe-a5a7-e58821c8b635)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] resources/views/settings/email-mailboxes.php:144 - Define a constant instead of duplicating this literal " checked" 3 times. (key: 8da76115-87b8-4eef-8448-b76492ddc805)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Accounting/AccountingController.php:51 - Define a constant instead of duplicating this literal "/accounting" 3 times. (key: 538274f1-117d-46cc-9898-95d01f1e7507)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Accounting/ReceiptController.php:38 - Define a constant instead of duplicating this literal "Not found" 5 times. (key: b2e1a08e-86f5-4429-8b0d-5c1d4896a59d)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Accounting/ReceiptController.php:44 - Define a constant instead of duplicating this literal "/orders/" 5 times. (key: 33203616-3238-415e-9883-1699fa6de54f)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Accounting/ReceiptController.php:78 - Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed. (key: f3ebebf5-028b-4dde-a2ba-ef10a0020ada)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Automation/AutomationController.php:73 - Define a constant instead of duplicating this literal "/settings/automation" 11 times. (key: f522e45e-6882-4185-ac9e-38ea4a482c82)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Automation/AutomationController.php:115 - Define a constant instead of duplicating this literal "Nieprawidlowy identyfikator" 4 times. (key: 9939d997-5fab-4101-b18a-a7a9c88a273c)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Cron/ShipmentTrackingHandler.php:24 - Refactor this function to reduce its Cognitive Complexity from 27 to the 15 allowed. (key: c46115eb-4adf-4c9d-b25d-c5523ed6f685)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Orders/OrdersController.php:153 - Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed. (key: 1b2e554e-f3ef-4c84-8ee1-d4d896150e59)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Orders/OrdersController.php:158 - Define a constant instead of duplicating this literal "Not found" 3 times. (key: 3c5e48e3-b063-4ea1-9b91-6cac61975952)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Orders/OrdersController.php:244 - Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed. (key: 72e50aff-63c1-4b6d-92e9-506a97020d17)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Printing/PrintApiController.php:? - Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed. (key: eef29972-3369-4b8e-ae62-6e00d8f90770)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/AllegroApiClient.php:239 - Define a constant instead of duplicating this literal "Accept: application/vnd.allegro.public.v1+json" 3 times. (key: 90cf597b-cda9-431f-aaf6-2ccc9caf53ad)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/AllegroApiClient.php:240 - Define a constant instead of duplicating this literal "Content-Type: application/vnd.allegro.public.v1+json" 3 times. (key: a4185ddd-bfd0-42e8-91af-d876eabaa82f)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/AllegroApiClient.php:256 - Define a constant instead of duplicating this literal "Nieprawidlowy JSON odpowiedzi API Allegro." 3 times. (key: d982750f-ff14-4e16-ad00-a1c89004ed3c)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/AllegroApiClient.php:288 - Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed. (key: 463978ad-d6dd-4fde-a4ec-518f58ed863a)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/AllegroStatusSyncService.php:95 - Refactor this function to reduce its Cognitive Complexity from 23 to the 15 allowed. (key: 722dad21-32a3-4ed6-b50e-0d1b56972c97)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/DeliveryStatusMappingController.php:91 - Define a constant instead of duplicating this literal "Brakuje wymaganych pA3l." 3 times. (key: ed96e62c-f7b6-49b1-943a-d0ddffe3320f)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/DeliveryStatusMappingController.php:92 - Define a constant instead of duplicating this literal "?provider=" 8 times. (key: 96f81947-608e-45cc-a136-4870e961017d)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/EmailMailboxController.php:54 - Define a constant instead of duplicating this literal "Nieprawidlowy token CSRF" 4 times. (key: 13fa7ac0-bcae-4a86-ab23-3c68cab37be0)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/EmailMailboxController.php:55 - Define a constant instead of duplicating this literal "/settings/email-mailboxes" 11 times. (key: f1865646-c867-4852-8957-3e99ebed3392)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/EmailMailboxController.php:149 - Refactor this function to reduce its Cognitive Complexity from 27 to the 15 allowed. (key: 375ad9aa-aedc-4b27-84ff-9f2c513322e1)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/EmailTemplateController.php:122 - Define a constant instead of duplicating this literal "Nieprawidlowy token CSRF" 5 times. (key: d707b40d-21df-4531-b377-bb28188d7fb4)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/EmailTemplateController.php:123 - Define a constant instead of duplicating this literal "/settings/email-templates" 9 times. (key: 5883ebc3-beb0-4e69-acf7-2ce30a969e0f)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/PrintSettingsController.php:57 - Define a constant instead of duplicating this literal "/settings/printing" 9 times. (key: 1767bc02-e977-418f-8014-4c07097ea449)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/ReceiptConfigController.php:54 - Define a constant instead of duplicating this literal "Nieprawidlowy token CSRF" 3 times. (key: 540bfead-9d65-4e6b-bd1f-ca39977ac9f9)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/ReceiptConfigController.php:55 - Define a constant instead of duplicating this literal "/settings/accounting" 10 times. (key: a20a4e43-843e-4e37-b19f-9abf814a1003)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproApiClient.php:271 - Refactor this function to reduce its Cognitive Complexity from 23 to the 15 allowed. (key: fae0cfa7-6155-4594-8b82-37224777f0e7)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproOrderMapper.php:61 - Refactor this function to reduce its Cognitive Complexity from 28 to the 15 allowed. (key: c4359cde-57d2-471b-96e5-33878b57343a)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproOrderMapper.php:527 - Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed. (key: a8351c51-818c-464c-bc58-3ee72da58ca3)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproOrdersSyncService.php:148 - Refactor this function to reduce its Cognitive Complexity from 21 to the 15 allowed. (key: 88925e9b-05a0-404e-a5ff-f941c2f5a556)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Settings/ShopproOrderSyncStateRepository.php:83 - Define a constant instead of duplicating this literal "Y-m-d H:i:s" 6 times. (key: eceb259a-a9fb-482f-b603-7415b57763f0)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproProductImageResolver.php:18 - Refactor this function to reduce its Cognitive Complexity from 25 to the 15 allowed. (key: 1eb00e5e-7193-4e11-8f6c-c0e546d2a585)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproProductImageResolver.php:67 - Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed. (key: bcc3a574-e087-4800-8051-063192de45b4)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Settings/ShopproStatusSyncService.php:85 - Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed. (key: a809b285-820d-4cd4-9adc-d67ae5550df7)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Shipments/DeliveryStatus.php:30 - Define a constant instead of duplicating this literal "W dorÄ?czeniu" 3 times. (key: eaeb76a3-3eb1-4ac2-9df4-7483fdb22772)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Shipments/DeliveryStatus.php:32 - Define a constant instead of duplicating this literal "DorÄ?czona" 5 times. (key: 9d4c98c6-6fb8-40ef-853a-2e5be1d042cc)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Shipments/DeliveryStatus.php:87 - Define a constant instead of duplicating this literal "Odebrana przez kuriera" 3 times. (key: 818a994a-9c79-4dbb-9fa9-ed4700c97235)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Shipments/DeliveryStatus.php:102 - Define a constant instead of duplicating this literal "ZwrA3cona do nadawcy" 4 times. (key: 1873fbed-290e-4268-8a76-bb485bdc343a)
- [ ] [CRITICAL][CODE_SMELL][php:S3776] src/Modules/Shipments/InpostShipmentService.php:48 - Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed. (key: 5ed92ef6-d6ae-46f5-b142-658d66290655)
- [ ] [CRITICAL][CODE_SMELL][php:S1192] src/Modules/Shipments/InpostShipmentService.php:177 - Define a constant instead of duplicating this literal "/shipments/" 3 times. (key: 60eb2ce3-d818-4199-8c2d-6157360e309c)
- [ ] [CRITICAL][VULNERABILITY][php:S4423] src/Modules/Settings/EmailMailboxController.php:223 - Change this code to use a stronger protocol. (key: 225d34b5-726e-4ace-aeba-5f9ca4d669dd)
- [ ] [BLOCKER][BUG][php:S5911] src/Modules/Settings/AllegroOrderImportService.php:? - Create class "RuntimeException" in namespace or check correct import of class (key: 1ac28e27-43e6-4115-af21-aa08f65d068e)
<!-- SONAR_ERRORS_END -->
47. [x] Zadania automatyczne: nowe zdarzenie Utworzenie przesylki uruchamiane od razu po utworzeniu paczki oraz nowa akcja Zmiana statusu przesylki.

View File

@@ -95,6 +95,20 @@
return html;
}
function buildShipmentStatusActionConfig(namePrefix) {
var html = '<select class="form-control" name="' + namePrefix + '[shipment_status_key]">'
+ '<option value="">-- Wybierz docelowy status przesylki --</option>';
Object.keys(data.shipmentStatusOptions || {}).forEach(function(statusKey) {
var config = data.shipmentStatusOptions[statusKey] || {};
var label = config.label || statusKey;
html += '<option value="' + escapeHtml(statusKey) + '">' + escapeHtml(label) + '</option>';
});
html += '</select>';
return html;
}
function addCondition() {
var idx = getNextIndex(conditionsContainer);
var namePrefix = 'conditions[' + idx + ']';
@@ -129,6 +143,7 @@
+ '<select class="form-control automation-row__type" name="' + namePrefix + '[type]" onchange="window.AutomationForm.onActionTypeChange(this)">'
+ '<option value="send_email" selected>Wyslij e-mail</option>'
+ '<option value="issue_receipt">Wystaw paragon</option>'
+ '<option value="update_shipment_status">Zmiana statusu przesylki</option>'
+ '</select>'
+ '<div class="automation-row__config">'
+ buildEmailActionConfig(namePrefix)
@@ -171,6 +186,10 @@
}
if (select.value === 'issue_receipt') {
configDiv.innerHTML = buildIssueReceiptActionConfig(namePrefix);
return;
}
if (select.value === 'update_shipment_status') {
configDiv.innerHTML = buildShipmentStatusActionConfig(namePrefix);
}
}

View File

@@ -8,6 +8,7 @@ $actions = $isEdit ? (is_array($rule['actions'] ?? null) ? $rule['actions'] : []
$eventLabels = [
'receipt.created' => 'Utworzono paragon',
'shipment.created' => 'Utworzenie przesylki',
'shipment.status_changed' => 'Zmiana statusu przesylki',
];
@@ -125,6 +126,7 @@ $shipmentStatusOptions = is_array($shipmentStatusOptions ?? null) ? $shipmentSta
<select class="form-control automation-row__type" name="actions[<?= $idx ?>][type]" onchange="window.AutomationForm.onActionTypeChange(this)">
<option value="send_email"<?= ((string) ($act['action_type'] ?? '')) === 'send_email' ? ' selected' : '' ?>>Wyslij e-mail</option>
<option value="issue_receipt"<?= ((string) ($act['action_type'] ?? '')) === 'issue_receipt' ? ' selected' : '' ?>>Wystaw paragon</option>
<option value="update_shipment_status"<?= ((string) ($act['action_type'] ?? '')) === 'update_shipment_status' ? ' selected' : '' ?>>Zmiana statusu przesylki</option>
</select>
<div class="automation-row__config">
<?php
@@ -156,6 +158,16 @@ $shipmentStatusOptions = is_array($shipmentStatusOptions ?? null) ? $shipmentSta
</option>
<?php endforeach; ?>
</select>
<?php elseif ($actionType === 'update_shipment_status'): ?>
<select class="form-control" name="actions[<?= $idx ?>][shipment_status_key]">
<option value="">-- Wybierz docelowy status przesylki --</option>
<?php foreach ($shipmentStatusOptions as $statusKey => $statusConfig): ?>
<?php $statusLabel = (string) ($statusConfig['label'] ?? $statusKey); ?>
<option value="<?= $e((string) $statusKey) ?>"<?= ((string) ($actConfig['status_key'] ?? '')) === (string) $statusKey ? ' selected' : '' ?>>
<?= $e($statusLabel) ?>
</option>
<?php endforeach; ?>
</select>
<?php else: ?>
<select class="form-control" name="actions[<?= $idx ?>][template_id]">
<option value="">-- Wybierz szablon --</option>

View File

@@ -3,6 +3,7 @@ $rules = is_array($rules ?? null) ? $rules : [];
$eventLabels = [
'receipt.created' => 'Utworzono paragon',
'shipment.created' => 'Utworzenie przesylki',
'shipment.status_changed' => 'Zmiana statusu przesylki',
];
?>

View File

@@ -252,7 +252,8 @@ return static function (Application $app): void {
new OrdersRepository($app->db()),
$companySettingsRepository,
$receiptRepository,
$receiptConfigRepository
$receiptConfigRepository,
$shipmentPackageRepositoryForOrders
);
$printJobRepository = new PrintJobRepository($app->db());
$ordersController = new OrdersController($template, $translator, $auth, $app->orders(), $shipmentPackageRepositoryForOrders, $receiptRepository, $receiptConfigRepository, $emailSendingService, $emailTemplateRepository, $emailMailboxRepository, $app->basePath('storage'), $printJobRepository);
@@ -308,6 +309,7 @@ return static function (Application $app): void {
$companySettingsRepository,
$shipmentProviderRegistry,
$shipmentPackageRepository,
$automationService,
$app->basePath('storage'),
$carrierDeliveryMappings,
$printJobRepository

View File

@@ -15,9 +15,9 @@ use Throwable;
final class AutomationController
{
private const ALLOWED_EVENTS = ['receipt.created', 'shipment.status_changed'];
private const ALLOWED_EVENTS = ['receipt.created', 'shipment.created', 'shipment.status_changed'];
private const ALLOWED_CONDITION_TYPES = ['integration', 'shipment_status'];
private const ALLOWED_ACTION_TYPES = ['send_email', 'issue_receipt'];
private const ALLOWED_ACTION_TYPES = ['send_email', 'issue_receipt', 'update_shipment_status'];
private const ALLOWED_RECIPIENTS = ['client', 'client_and_company', 'company'];
private const ALLOWED_RECEIPT_ISSUE_DATE_MODES = ['today', 'order_date', 'payment_date'];
private const ALLOWED_RECEIPT_DUPLICATE_POLICIES = ['skip_if_exists', 'allow_duplicates'];
@@ -416,6 +416,15 @@ final class AutomationController
];
}
if ($type === 'update_shipment_status') {
$statusKey = trim((string) ($action['shipment_status_key'] ?? ''));
if (!array_key_exists($statusKey, self::SHIPMENT_STATUS_OPTIONS)) {
return null;
}
return ['status_key' => $statusKey];
}
return null;
}

View File

@@ -8,6 +8,8 @@ use App\Modules\Email\EmailSendingService;
use App\Modules\Orders\OrdersRepository;
use App\Modules\Settings\CompanySettingsRepository;
use App\Modules\Settings\ReceiptConfigRepository;
use App\Modules\Shipments\DeliveryStatus;
use App\Modules\Shipments\ShipmentPackageRepository;
use Throwable;
final class AutomationService
@@ -32,7 +34,8 @@ final class AutomationService
private readonly OrdersRepository $orders,
private readonly CompanySettingsRepository $companySettings,
private readonly ReceiptRepository $receipts,
private readonly ReceiptConfigRepository $receiptConfigs
private readonly ReceiptConfigRepository $receiptConfigs,
private readonly ShipmentPackageRepository $shipmentPackages
) {
}
@@ -187,6 +190,11 @@ final class AutomationService
if ($type === 'issue_receipt') {
$this->handleIssueReceipt($config, $orderId, $ruleName, $context);
continue;
}
if ($type === 'update_shipment_status') {
$this->handleUpdateShipmentStatus($config, $orderId, $ruleName, $context);
}
}
}
@@ -355,6 +363,106 @@ final class AutomationService
}
}
/**
* @param array<string, mixed> $config
* @param array<string, mixed> $context
*/
private function handleUpdateShipmentStatus(array $config, int $orderId, string $ruleName, array $context): void
{
$statusKey = trim((string) ($config['status_key'] ?? ''));
$targetStatus = $this->resolveStatusFromActionKey($statusKey);
if ($targetStatus === null) {
return;
}
$targetPackage = $this->resolveTargetPackage($orderId, $context);
if ($targetPackage === null) {
return;
}
$packageId = (int) ($targetPackage['id'] ?? 0);
if ($packageId <= 0) {
return;
}
$previousStatus = trim((string) ($targetPackage['delivery_status'] ?? DeliveryStatus::UNKNOWN));
if ($previousStatus === '') {
$previousStatus = DeliveryStatus::UNKNOWN;
}
if ($previousStatus === $targetStatus) {
return;
}
$this->shipmentPackages->updateDeliveryStatus($packageId, $targetStatus, null);
$actorName = 'Automatyzacja: ' . $ruleName;
$this->orders->recordActivity(
$orderId,
'automation_shipment_status_updated',
$actorName . ' - zaktualizowano status przesylki',
[
'package_id' => $packageId,
'previous_status' => $previousStatus,
'delivery_status' => $targetStatus,
'status_key' => $statusKey,
],
'system',
$actorName
);
$this->emitEvent(
'shipment.status_changed',
$orderId,
$context,
[
'package_id' => $packageId,
'provider' => (string) ($targetPackage['provider'] ?? ''),
'delivery_status' => $targetStatus,
'delivery_status_raw' => '',
'previous_status' => $previousStatus,
'previous_status_raw' => '',
'automation_source' => 'update_shipment_status',
'automation_rule' => $ruleName,
]
);
}
private function resolveStatusFromActionKey(string $statusKey): ?string
{
if ($statusKey === '' || !isset(self::SHIPMENT_STATUS_OPTION_MAP[$statusKey])) {
return null;
}
$mappedStatuses = self::SHIPMENT_STATUS_OPTION_MAP[$statusKey];
if ($mappedStatuses === []) {
return null;
}
$candidate = trim((string) $mappedStatuses[0]);
if ($candidate === '' || !in_array($candidate, DeliveryStatus::ALL_STATUSES, true)) {
return null;
}
return $candidate;
}
/**
* @param array<string, mixed> $context
* @return array<string, mixed>|null
*/
private function resolveTargetPackage(int $orderId, array $context): ?array
{
$packageId = (int) ($context['package_id'] ?? 0);
if ($packageId > 0) {
$package = $this->shipmentPackages->findById($packageId);
if (is_array($package) && (int) ($package['order_id'] ?? 0) === $orderId) {
return $package;
}
}
return $this->shipmentPackages->findLatestByOrderId($orderId);
}
/**
* @param array<string, mixed> $order
* @param list<array<string, mixed>> $payments

View File

@@ -64,6 +64,7 @@ final class CronHandlerFactory
$apiClient = new AllegroApiClient();
$statusMappingRepository = new AllegroStatusMappingRepository($this->db);
$ordersRepository = new OrdersRepository($this->db);
$allegroSyncStateRepository = new AllegroOrderSyncStateRepository($this->db);
$orderImportService = new AllegroOrderImportService(
$integrationRepository,
@@ -76,7 +77,7 @@ final class CronHandlerFactory
$ordersSyncService = new AllegroOrdersSyncService(
$integrationRepository,
new AllegroOrderSyncStateRepository($this->db),
$allegroSyncStateRepository,
$tokenManager,
$apiClient,
$orderImportService
@@ -128,6 +129,11 @@ final class CronHandlerFactory
new AllegroStatusSyncService(
$cronRepository,
$orderImportService,
$apiClient,
$tokenManager,
$statusMappingRepository,
$allegroSyncStateRepository,
$integrationRepository,
$this->db
)
),
@@ -194,7 +200,8 @@ final class CronHandlerFactory
$ordersRepository,
$companySettingsRepository,
new ReceiptRepository($this->db),
new ReceiptConfigRepository($this->db)
new ReceiptConfigRepository($this->db),
new ShipmentPackageRepository($this->db)
);
}
}

View File

@@ -3,6 +3,7 @@ declare(strict_types=1);
namespace App\Modules\Shipments;
use App\Modules\Automation\AutomationService;
use App\Core\Http\Request;
use App\Core\Http\Response;
use App\Core\I18n\Translator;
@@ -26,6 +27,7 @@ final class ShipmentController
private readonly CompanySettingsRepository $companySettings,
private readonly ShipmentProviderRegistry $providerRegistry,
private readonly ShipmentPackageRepository $packageRepository,
private readonly AutomationService $automationService,
private readonly string $storagePath,
private readonly ?CarrierDeliveryMethodMappingRepository $deliveryMappings = null,
private readonly ?\App\Modules\Printing\PrintJobRepository $printJobRepo = null
@@ -213,6 +215,8 @@ final class ShipmentController
'user',
$actorName
);
$this->triggerShipmentCreatedAutomation($orderId, $packageId, $providerCode);
Flash::set('order.success', 'Przesylka utworzona. Sprawdz status w zakladce Przesylki.');
return Response::redirect('/orders/' . $orderId);
} catch (Throwable $exception) {
@@ -382,10 +386,35 @@ final class ShipmentController
$actorName
);
$this->triggerShipmentCreatedAutomation($orderId, $packageId, 'manual');
Flash::set('order.success', 'Numer przesylki dodany.');
return Response::redirect('/orders/' . $orderId);
}
private function triggerShipmentCreatedAutomation(int $orderId, int $packageId, string $providerCode): void
{
if ($orderId <= 0 || $packageId <= 0) {
return;
}
$package = $this->packageRepository->findById($packageId);
$context = [
'package_id' => $packageId,
'provider' => $providerCode,
'package_status' => is_array($package) ? (string) ($package['status'] ?? '') : '',
'tracking_number' => is_array($package) ? (string) ($package['tracking_number'] ?? '') : '',
'delivery_status' => is_array($package)
? (string) ($package['delivery_status'] ?? DeliveryStatus::UNKNOWN)
: DeliveryStatus::UNKNOWN,
];
try {
$this->automationService->trigger('shipment.created', $orderId, $context);
} catch (Throwable) {
// Blad automatyzacji nie powinien blokowac tworzenia przesylki
}
}
/**
* @param array<string, mixed>|null $deliveryAddr
* @param array<string, mixed>|null $customerAddr

View File

@@ -118,6 +118,20 @@ final class ShipmentPackageRepository
return $statement->fetchAll(PDO::FETCH_ASSOC) ?: [];
}
/**
* @return array<string, mixed>|null
*/
public function findLatestByOrderId(int $orderId): ?array
{
$statement = $this->pdo->prepare(
'SELECT * FROM shipment_packages WHERE order_id = :order_id ORDER BY created_at DESC, id DESC LIMIT 1'
);
$statement->execute(['order_id' => $orderId]);
$row = $statement->fetch(PDO::FETCH_ASSOC);
return is_array($row) ? $row : null;
}
/**
* @return array<string, mixed>|null
*/