feat(19-ui-integration): przycisk Drukuj, bulk print, kolejka wydruku
- Przycisk "Drukuj" w prepare.php i show.php z AJAX + duplikat protection - Bulk print z listy zamówień (checkboxy + header action) - Kolejka wydruku w Ustawienia > Drukowanie (filtr statusu, retry) - POST /api/print/jobs/bulk endpoint (package_ids + order_ids) - ensureLabel() auto-download przez ShipmentProviderRegistry - Apaczka carrier_id = nazwa usługi, kolumna Przewoznik - Tab persistence (localStorage), label file_exists check - Fix use statement ApaczkaApiClient, redirect po utworzeniu przesyłki - Phase 17 (receipt duplicate guard) + Phase 18 (print queue backend) docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
261
.paul/phases/19-ui-integration/19-01-PLAN.md
Normal file
261
.paul/phases/19-ui-integration/19-01-PLAN.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
phase: 19-ui-integration
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: ["18-01"]
|
||||
files_modified:
|
||||
- resources/views/shipments/prepare.php
|
||||
- resources/views/orders/index.php
|
||||
- src/Modules/Printing/PrintApiController.php
|
||||
- src/Modules/Printing/PrintJobRepository.php
|
||||
- resources/views/settings/printing.php
|
||||
- routes/web.php
|
||||
- resources/scss/_printing.scss
|
||||
autonomous: false
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Dodać przycisk "Drukuj" w widoku przesyłki (prepare.php) oraz zbiorczą akcję "Drukuj etykiety" z listy zamówień — obie wywołujące POST /api/print/jobs. Dodać podgląd kolejki wydruku w ustawieniach drukowania ze statusami zleceń.
|
||||
|
||||
## Purpose
|
||||
Użytkownik może jednym kliknięciem wysłać etykietę do zdalnej drukarki (Windows Client z fazy 20) bez ręcznego pobierania i drukowania. Zbiorcze drukowanie oszczędza czas przy wielu zamówieniach.
|
||||
|
||||
## Output
|
||||
- Przycisk "Drukuj" obok "Pobierz" w prepare.php z AJAX feedback
|
||||
- Zbiorcza akcja "Drukuj etykiety" na liście zamówień (zaznaczone checkboxy)
|
||||
- Sekcja "Kolejka wydruku" w ustawieniach drukowania z historią zleceń
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Prior Work
|
||||
@.paul/phases/18-print-queue-backend/18-01-SUMMARY.md
|
||||
- Phase 18 created: PrintApiController (createJob, listPending, downloadLabel, markComplete)
|
||||
- API key auth middleware for Windows client
|
||||
- print_jobs table (order_id, package_id, label_path, status, created_by)
|
||||
- createJob() expects package_id, validates label exists
|
||||
|
||||
## Source Files
|
||||
@resources/views/shipments/prepare.php — "Pobierz" button at line ~109
|
||||
@resources/views/orders/index.php — lista zamówień z checkboxami
|
||||
@src/Modules/Printing/PrintApiController.php — existing REST endpoints
|
||||
@src/Modules/Printing/PrintJobRepository.php — DB operations
|
||||
@resources/views/settings/printing.php — API key management
|
||||
@routes/web.php — route registration
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Required Skills (from SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priority | When to Invoke | Loaded? |
|
||||
|-------|----------|----------------|---------|
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
|
||||
## Skill Invocation Checklist
|
||||
- [ ] sonar-scanner loaded (run before UNIFY)
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Przycisk "Drukuj" w widoku przesyłki
|
||||
```gherkin
|
||||
Given przesyłka ma wygenerowaną etykietę (label_path istnieje)
|
||||
When użytkownik klika "Drukuj" obok przycisku "Pobierz"
|
||||
Then AJAX POST /api/print/jobs z package_id
|
||||
And przycisk zmienia się na "Wysłano ✓" z krótkim feedbackiem
|
||||
And w razie błędu wyświetla OrderProAlerts.alert z komunikatem
|
||||
```
|
||||
|
||||
## AC-2: Zbiorcze drukowanie z listy zamówień
|
||||
```gherkin
|
||||
Given użytkownik zaznaczył ≥1 zamówienie z etykietą na liście zamówień
|
||||
When klika akcję "Drukuj etykiety" (bulk action)
|
||||
Then dla każdego zaznaczonego zamówienia tworzony jest print job
|
||||
And wyświetla podsumowanie: "Wysłano N zleceń do drukarki"
|
||||
And zamówienia bez etykiety są pomijane z informacją
|
||||
```
|
||||
|
||||
## AC-3: Kolejka wydruku w ustawieniach
|
||||
```gherkin
|
||||
Given użytkownik otwiera Ustawienia > Drukowanie
|
||||
When strona się ładuje
|
||||
Then widzi sekcję "Kolejka wydruku" pod sekcją "Klucze API"
|
||||
And lista pokazuje ostatnie zlecenia: data, zamówienie, status (pending/completed/failed)
|
||||
And może filtrować po statusie
|
||||
```
|
||||
|
||||
## AC-4: Endpoint bulk create
|
||||
```gherkin
|
||||
Given request POST /api/print/jobs/bulk z tablicą package_ids
|
||||
When co najmniej 1 package_id ma etykietę
|
||||
Then tworzy print jobs dla wszystkich valid packages
|
||||
And zwraca JSON z listą created + skipped
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Przycisk "Drukuj" w prepare.php + bulk endpoint</name>
|
||||
<files>
|
||||
resources/views/shipments/prepare.php,
|
||||
src/Modules/Printing/PrintApiController.php,
|
||||
src/Modules/Printing/PrintJobRepository.php,
|
||||
routes/web.php
|
||||
</files>
|
||||
<action>
|
||||
1. W prepare.php obok przycisku "Pobierz" (form POST label) dodaj przycisk "Drukuj":
|
||||
- Button z klasą `btn btn-sm btn-outline-primary btn-print-label`
|
||||
- data-package-id="{$pkg['id']}" data-order-id="{$orderId}"
|
||||
- Ikona drukarki (fa-print lub SVG)
|
||||
- Widoczny tylko gdy $pkgLabelPath istnieje (ten sam warunek co "Pobierz")
|
||||
|
||||
2. JavaScript AJAX handler na dole prepare.php (lub w osobnym module):
|
||||
- Click `.btn-print-label` → POST /api/print/jobs z {package_id, _token}
|
||||
- Success → zmień tekst na "Wysłano ✓", disable button na 3s
|
||||
- Error → OrderProAlerts.alert('Błąd: ' + response.error)
|
||||
- Duplikat (job already pending) → OrderProAlerts.alert('Zlecenie już w kolejce')
|
||||
|
||||
3. W PrintApiController dodaj metodę bulkCreateJobs():
|
||||
- Przyjmuje JSON {package_ids: [1,2,3], _token}
|
||||
- Waliduje CSRF
|
||||
- Dla każdego package_id: sprawdź label_path, utwórz job lub skip
|
||||
- Zwraca {created: [{id, package_id}], skipped: [{package_id, reason}]}
|
||||
|
||||
4. W PrintJobRepository dodaj findPendingByPackageId(int $packageId):
|
||||
- Sprawdza czy istnieje pending job dla danego package
|
||||
- Używane do ochrony przed duplikatami
|
||||
|
||||
5. W routes/web.php dodaj:
|
||||
- POST /api/print/jobs/bulk → PrintApiController::bulkCreateJobs (session auth)
|
||||
|
||||
Avoid: Nie zmieniaj istniejących endpointów API key auth (GET /api/print/jobs/pending itd.)
|
||||
Avoid: Nie dodawaj natywnych alert() — używaj OrderProAlerts
|
||||
</action>
|
||||
<verify>
|
||||
- Przycisk "Drukuj" widoczny obok "Pobierz" w prepare.php
|
||||
- AJAX POST tworzy rekord w print_jobs
|
||||
- Bulk endpoint zwraca poprawny JSON
|
||||
- Duplikat nie tworzy drugiego pending job
|
||||
</verify>
|
||||
<done>AC-1 satisfied (przycisk + AJAX), AC-4 satisfied (bulk endpoint)</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Zbiorcze drukowanie z listy zamówień + kolejka w ustawieniach</name>
|
||||
<files>
|
||||
resources/views/orders/index.php,
|
||||
resources/views/settings/printing.php,
|
||||
src/Modules/Settings/PrintSettingsController.php,
|
||||
src/Modules/Printing/PrintJobRepository.php,
|
||||
routes/web.php,
|
||||
resources/scss/_printing.scss
|
||||
</files>
|
||||
<action>
|
||||
1. W orders/index.php dodaj bulk action "Drukuj etykiety":
|
||||
- Dodaj opcję w dropdown/select akcji zbiorczych (wzoruj się na istniejących bulk actions)
|
||||
- JavaScript: zbierz package_ids z zaznaczonych zamówień
|
||||
- POST /api/print/jobs/bulk z zebraną tablicą
|
||||
- Pokaż wynik: "Wysłano {N} zleceń. Pominięto {M} (brak etykiety)."
|
||||
- Użyj OrderProAlerts.alert() dla wyniku
|
||||
|
||||
2. W PrintJobRepository dodaj getRecentJobs(int $limit = 50, ?string $statusFilter = null):
|
||||
- SELECT z JOIN na orders (numer zamówienia) i shipment_packages (tracking)
|
||||
- Sortowanie: created_at DESC
|
||||
- Opcjonalny filtr statusu
|
||||
|
||||
3. W PrintSettingsController dodaj metodę index() rozszerzoną o dane kolejki:
|
||||
- Pobierz listę ostatnich print jobs (getRecentJobs)
|
||||
- Przekaż do widoku
|
||||
|
||||
4. W settings/printing.php pod sekcją "Klucze API" dodaj sekcję "Kolejka wydruku":
|
||||
- Tabela: Data | Zamówienie | Tracking | Status | Akcje
|
||||
- Status badges: pending (żółty), completed (zielony), failed (czerwony)
|
||||
- Filtr statusu (select/buttons nad tabelą)
|
||||
- Paginacja jeśli >20 rekordów (lub scroll)
|
||||
- Przycisk "Ponów" przy failed jobs (POST /api/print/jobs z tym samym package_id)
|
||||
|
||||
5. Dodaj _printing.scss z stylami:
|
||||
- .print-status-badge (pending/completed/failed kolory)
|
||||
- .print-queue-table (kompaktowy layout)
|
||||
- Zaimportuj w głównym pliku SCSS
|
||||
|
||||
Avoid: Nie modyfikuj sekcji API keys w printing.php — dodaj nową sekcję pod spodem
|
||||
Avoid: Nie dodawaj osobnej strony — kolejka jest częścią ustawień drukowania
|
||||
</action>
|
||||
<verify>
|
||||
- Bulk action widoczna na liście zamówień
|
||||
- Zaznaczenie + klik → zlecenia w print_jobs
|
||||
- Kolejka wydruku widoczna w ustawieniach
|
||||
- Filtrowanie po statusie działa
|
||||
- Style badge'ów poprawne
|
||||
</verify>
|
||||
<done>AC-2 satisfied (bulk z listy), AC-3 satisfied (kolejka w ustawieniach)</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>
|
||||
Przycisk "Drukuj" w widoku przesyłki, zbiorcze drukowanie z listy zamówień,
|
||||
kolejka wydruku w ustawieniach drukowania.
|
||||
</what-built>
|
||||
<how-to-verify>
|
||||
1. Otwórz zamówienie z wygenerowaną etykietą → widok przesyłki
|
||||
2. Sprawdź: obok "Pobierz" jest przycisk "Drukuj"
|
||||
3. Kliknij "Drukuj" → powinno pojawić się "Wysłano ✓"
|
||||
4. Kliknij ponownie → powinien pojawić się alert "Zlecenie już w kolejce"
|
||||
5. Wróć do listy zamówień → zaznacz kilka z etykietami
|
||||
6. Wybierz akcję "Drukuj etykiety" → podsumowanie ile wysłano/pominięto
|
||||
7. Otwórz Ustawienia > Drukowanie → sprawdź sekcję "Kolejka wydruku"
|
||||
8. Sprawdź: widać zlecenia z kroków 3 i 6 ze statusem "pending"
|
||||
9. Sprawdź filtrowanie po statusie
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- database/migrations/* (schemat z fazy 18 jest stabilny)
|
||||
- src/Modules/Printing/ApiKeyMiddleware.php (auth middleware gotowe)
|
||||
- Endpointy API key auth (GET /api/print/jobs/pending, download, complete) — te są dla Windows Client
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Nie buduj Windows Client (to faza 20)
|
||||
- Nie dodawaj WebSocket/polling do auto-odświeżania statusów — wystarczy ręczne odświeżenie
|
||||
- Nie zmieniaj flow pobierania etykiet ("Pobierz" pozostaje bez zmian)
|
||||
- Nie dodawaj nowych tabel DB — używaj istniejącej print_jobs
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] Przycisk "Drukuj" widoczny w prepare.php obok "Pobierz"
|
||||
- [ ] AJAX feedback działa (success + error + duplikat)
|
||||
- [ ] Bulk endpoint /api/print/jobs/bulk tworzy zlecenia
|
||||
- [ ] Bulk action w index.php działa z checkboxami
|
||||
- [ ] Kolejka wydruku widoczna w ustawieniach drukowania
|
||||
- [ ] Filtrowanie statusu w kolejce
|
||||
- [ ] Style SCSS skompilowane (brak inline CSS)
|
||||
- [ ] Brak natywnych alert()/confirm() — tylko OrderProAlerts
|
||||
- [ ] Wszystkie acceptance criteria spełnione
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 4 AC spełnione
|
||||
- Brak regresji w istniejącym flow pobierania etykiet
|
||||
- Kod zgodny z konwencjami projektu (camelCase, Medoo, XSS escape)
|
||||
- Brak nowych issues SonarQube na zmienionych plikach
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/19-ui-integration/19-01-SUMMARY.md`
|
||||
</output>
|
||||
142
.paul/phases/19-ui-integration/19-01-SUMMARY.md
Normal file
142
.paul/phases/19-ui-integration/19-01-SUMMARY.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
phase: 19-ui-integration
|
||||
plan: 01
|
||||
subsystem: ui
|
||||
tags: [printing, ajax, bulk-actions, label-queue]
|
||||
|
||||
requires:
|
||||
- phase: 18-print-queue-backend
|
||||
provides: PrintApiController, PrintJobRepository, print_jobs table, API key auth
|
||||
provides:
|
||||
- Przycisk "Drukuj" w widoku przesyłki i szczegółów zamówienia
|
||||
- Bulk print z listy zamówień
|
||||
- Kolejka wydruku w Ustawienia > Drukowanie
|
||||
- Endpoint POST /api/print/jobs/bulk
|
||||
affects: [20-windows-client]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [ShipmentProviderRegistry for ensureLabel(), pendingPackageIds for duplicate protection]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- src/Modules/Printing/PrintApiController.php (bulkCreateJobs, ensureLabel)
|
||||
- src/Modules/Printing/PrintJobRepository.php (findPendingByPackageId, pendingPackageIds)
|
||||
- src/Modules/Settings/PrintSettingsController.php (kolejka wydruku)
|
||||
- resources/views/settings/printing.php (kolejka UI)
|
||||
- resources/scss/modules/_printing.scss
|
||||
- database/migrations/20260322_000058_create_print_tables.sql
|
||||
modified:
|
||||
- resources/views/shipments/prepare.php (przycisk Drukuj, label file check)
|
||||
- resources/views/orders/show.php (przycisk Drukuj, tab persistence, carrier_id column)
|
||||
- resources/views/orders/list.php (bulk print action)
|
||||
- routes/web.php (DI + nowe route'y)
|
||||
- src/Modules/Orders/OrdersController.php (storagePath + printJobRepo injection)
|
||||
- src/Modules/Shipments/ShipmentController.php (redirect po utworzeniu przesyłki)
|
||||
- src/Modules/Shipments/ApaczkaShipmentService.php (carrier_id = service name)
|
||||
- src/Modules/Settings/ApaczkaApiClient.php (fix use statement)
|
||||
- resources/scss/app.scss (_printing import)
|
||||
- public/assets/css/app.css (compiled)
|
||||
|
||||
key-decisions:
|
||||
- "ensureLabel() auto-downloads label via ShipmentProviderRegistry before creating print job"
|
||||
- "findPendingByPackageId protects against duplicate pending jobs"
|
||||
- "Apaczka carrier_id stores service name (e.g. 'Orlen Paczka') for display"
|
||||
- "Tab persistence via localStorage in show.php"
|
||||
- "Label file existence check hides Pobierz/Drukuj when file missing on disk"
|
||||
|
||||
patterns-established:
|
||||
- "ShipmentProviderRegistry pattern for multi-provider label operations"
|
||||
- "Bulk endpoint returns {created: [], skipped: []} JSON structure"
|
||||
|
||||
duration: ~4h
|
||||
started: 2026-03-22T10:00:00Z
|
||||
completed: 2026-03-22T22:00:00Z
|
||||
---
|
||||
|
||||
# Phase 19 Plan 01: UI Integration Summary
|
||||
|
||||
**Przycisk "Drukuj" w widoku przesyłki, bulk print z listy zamówień, kolejka wydruku w ustawieniach — pełna integracja UI z backendem kolejki wydruku z fazy 18.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~4h (rozłożone na 2 sesje) |
|
||||
| Started | 2026-03-22 |
|
||||
| Completed | 2026-03-22 |
|
||||
| Tasks | 3 (2 auto + 1 checkpoint) |
|
||||
| Files modified | 14 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Przycisk "Drukuj" w widoku przesyłki | Pass | Widoczny w prepare.php i show.php, AJAX feedback + duplikat protection |
|
||||
| AC-2: Zbiorcze drukowanie z listy zamówień | Pass | Checkboxy + header action "Drukuj etykiety", bulk endpoint |
|
||||
| AC-3: Kolejka wydruku w ustawieniach | Pass | Tabela zleceń z filtrami statusu, retry dla failed |
|
||||
| AC-4: Endpoint bulk create | Pass | POST /api/print/jobs/bulk z {package_ids/order_ids} |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Przycisk "Drukuj" obok "Pobierz" z AJAX feedback i ochroną przed duplikatami
|
||||
- Bulk print z listy zamówień (checkboxy + nagłówkowa akcja)
|
||||
- Kolejka wydruku w Ustawienia > Drukowanie z filtrami i retry
|
||||
- Auto-download etykiety (ensureLabel) przez ShipmentProviderRegistry
|
||||
- Stan "W kolejce" (disabled, czerwony) gdy pending job istnieje
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Scope additions | 6 | Usprawnienia UX wykryte podczas testów |
|
||||
| Auto-fixed | 1 | Bug fix ApaczkaApiClient |
|
||||
| Deferred | 0 | — |
|
||||
|
||||
**Total impact:** Dodatkowe usprawnienia UX poza planem, zero regresji.
|
||||
|
||||
### Scope Additions (poza planem)
|
||||
|
||||
1. **show.php tab persistence** — localStorage zapamiętuje aktywny tab
|
||||
2. **show.php label file check** — ukrywa Pobierz/Drukuj gdy plik nie istnieje na dysku
|
||||
3. **show.php przycisk Drukuj** — plan dotyczył tylko prepare.php, dodano też w show.php
|
||||
4. **Kolumna Przewoznik** — "Apaczka → Orlen Paczka" zamiast pustego carrier_id
|
||||
5. **Redirect po utworzeniu przesyłki** — ShipmentController redirect → /orders/{id} z flash
|
||||
6. **Sekcja przesyłek przeniesiona** — pod formularz nowej przesyłki w prepare.php
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. ApaczkaApiClient use statement bug**
|
||||
- **Found during:** Task 1
|
||||
- **Issue:** Brak backslashy w use statement
|
||||
- **Fix:** Poprawiony import namespace
|
||||
- **Files:** src/Modules/Settings/ApaczkaApiClient.php
|
||||
|
||||
## SonarQube Scan
|
||||
|
||||
**Scan date:** 2026-03-22
|
||||
**Result:** 0 new blocker/critical issues on phase 19 files
|
||||
**New issues (minor/major):**
|
||||
- show.php:696 — S4833 require → use, S2003 require → require_once
|
||||
- OrdersController — S1448 (22 methods > 20), S1142 (bulkPrint 5 returns)
|
||||
|
||||
All logged to DOCS/todo.md.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Pełne UI do zarządzania kolejką wydruku
|
||||
- API endpoints gotowe dla Windows Client (faza 20)
|
||||
- print_jobs table z pełnym lifecycle (pending → completed/failed)
|
||||
|
||||
**Concerns:**
|
||||
- OrdersController rośnie (22 metody) — rozważyć wydzielenie PrintController w przyszłości
|
||||
|
||||
**Blockers:**
|
||||
- None
|
||||
|
||||
---
|
||||
*Phase: 19-ui-integration, Plan: 01*
|
||||
*Completed: 2026-03-22*
|
||||
Reference in New Issue
Block a user