update
This commit is contained in:
214
.paul/phases/100-preset-scope-print-ux/100-01-PLAN.md
Normal file
214
.paul/phases/100-preset-scope-print-ux/100-01-PLAN.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
phase: 100-preset-scope-print-ux
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- resources/views/shipments/prepare.php
|
||||
- resources/views/orders/show.php
|
||||
- src/Modules/Printing/PrintApiController.php
|
||||
- src/Modules/Printing/PrintJobRepository.php
|
||||
- routes/web.php
|
||||
autonomous: true
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Zawezic dzialanie presetow przesylek do wymiarow+wagi oraz poprawic UX przycisku "Drukuj" po utworzeniu przesylki: auto-klikniecie ostatniej etykiety, polling kolejki wydruku, usuniecie zbednego "-".
|
||||
|
||||
## Purpose
|
||||
Presety sa uzywane do szybkiego wypelniania parametrow paczki dla tego samego typu produktu, natomiast przewoznik/serwis zazwyczaj zalezy od konkretnego zamowienia — obecne nadpisywanie carrier/delivery wywoluje pomylki. Przycisk "W kolejce" nie resetuje sie nawet po wydrukowaniu etykiety, co wymaga recznego odswiezania strony i utrudnia kolejne nadania.
|
||||
|
||||
## Output
|
||||
- applyPreset() w prepare.php zawezone do package_type/length/width/height/weight
|
||||
- Auto-click na przycisku "Drukuj" dla ostatniej (najnowszej) etykiety po utworzeniu przesylki
|
||||
- Polling statusu print_jobs w orders/show.php i prepare.php (GET /api/print/jobs/status)
|
||||
- Usuniecie placeholderu "-" przed przyciskiem Drukuj
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.paul/PROJECT.md
|
||||
@.paul/STATE.md
|
||||
@resources/views/shipments/prepare.php
|
||||
@resources/views/orders/show.php
|
||||
@src/Modules/Printing/PrintApiController.php
|
||||
@src/Modules/Printing/PrintJobRepository.php
|
||||
@routes/web.php
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Preset zmienia tylko paczke
|
||||
```gherkin
|
||||
Given formularz /shipments/prepare z wybranym przewoznikiem X i serwisem Y
|
||||
When uzytkownik klika preset P ktory w bazie ma inny carrier/delivery_method
|
||||
Then carrier pozostaje X, serwis Y pozostaje wybrany
|
||||
And pola package_type, length_cm, width_cm, height_cm, weight_kg sa nadpisane wartosciami z presetu
|
||||
And formularz jest nadal auto-submitowany po autofill (zachowanie Phase 78)
|
||||
```
|
||||
|
||||
## AC-2: Auto-click ostatniej etykiety
|
||||
```gherkin
|
||||
Given zamowienie z pakietami P1,P2 (P2 ma status label_ready i jest najnowszy)
|
||||
When uzytkownik tworzy nowa przesylke P3 i widok /orders/{id} ladowany jest ponownie z aktywna zakladka przesylki
|
||||
Then po zaladowaniu strony automatycznie uruchamiany jest click na btn-print-label dla P3 (najnowsza pozycja)
|
||||
And wysylane jest POST /api/print/jobs dla P3
|
||||
And przycisk P3 przechodzi w stan "W kolejce"
|
||||
```
|
||||
|
||||
## AC-3: Polling kolejki wydruku
|
||||
```gherkin
|
||||
Given przycisk Drukuj dla paczki X w stanie "W kolejce" (print_job status=pending)
|
||||
When agent drukarki oznaczy job jako completed (print_job status=completed)
|
||||
Then nie pozniej niz 10 sekund od oznaczenia przycisk X wraca do etykiety "Drukuj"
|
||||
And przycisk odzyskuje klase btn--secondary i jest aktywny
|
||||
And gdy brak aktywnych wpisow pending dla widoku, polling sie zatrzymuje
|
||||
```
|
||||
|
||||
## AC-4: Brak placeholdera "-"
|
||||
```gherkin
|
||||
Given widok /orders/{id} lub /shipments/prepare dla paczki bez pliku etykiety lub w stanie przejsciowym
|
||||
When tabela przesylek jest renderowana
|
||||
Then w komorce etykiety nie pojawia sie znak "-" przed przyciskiem Drukuj
|
||||
And puste stany pokazuja jedynie sam przycisk Drukuj (lub brak dla is-manual)
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Zawezic applyPreset() i usunac placeholder "-"</name>
|
||||
<files>resources/views/shipments/prepare.php, resources/views/orders/show.php</files>
|
||||
<action>
|
||||
W resources/views/shipments/prepare.php, funkcja applyPreset() (ok. linii 957-999):
|
||||
- Usun caly blok ustawiajacy carrierSelect, hiddenInput, credentialsInput, carrierInput, providerInput i wywolanie _syncTrigger + dispatch change.
|
||||
- Usun setTimeout() 200ms (juz niepotrzebny — nie zmieniamy carrier).
|
||||
- Usun wywolanie selectDeliveryService(preset); funkcja selectDeliveryService moze zostac w pliku jesli uzywana gdzie indziej, ale nie jest wywolywana z applyPreset.
|
||||
- Zostaw wywolania setFieldValue() dla: package_type, length_cm, width_cm, height_cm, weight_kg.
|
||||
- USUN wywolania setFieldValue() dla sender_point_id i label_format — nalezy do "formy dostawy".
|
||||
- Zostaw auto-submit formularza po autofill (zachowanie Phase 78) — ma sie odpalac bezposrednio po setFieldValue() z krotkim opoznieniem 100 ms.
|
||||
|
||||
W resources/views/shipments/prepare.php usun placeholder "-" w kolumnie etykiety (ok. linii 415-417):
|
||||
- Usun gale `<?php else: ?> - <?php endif; ?>` (zachowujac przypadek "Generowanie etykiety...").
|
||||
|
||||
W resources/views/orders/show.php usun placeholder "-" przed przyciskiem Drukuj (ok. linii 580-582):
|
||||
- Usun caly `<?php elseif ($pkgStatus !== 'error'): ?> - <?php endif; ?>` (pobierz zostaje bez fallbacku).
|
||||
|
||||
Avoid: modyfikacji form samych presetow CRUD (Settings) — zakres to tylko autofill. Nie dotykaj selectDeliveryService() jesli uzywane poza applyPreset — usuniecie wywolania wystarczy.
|
||||
</action>
|
||||
<verify>
|
||||
1. Otworz /shipments/prepare?orderId=X, wybierz carrier A + serwis a1, kliknij preset z carrier B
|
||||
2. Potwierdz ze carrier nadal = A, serwis = a1, ale wymiary/waga = wartosci z presetu
|
||||
3. Potwierdz ze formularz sie auto-submituje
|
||||
4. Otworz /orders/{id} z istniejacymi paczkami — brak znaku "-" w kolumnie etykiet
|
||||
</verify>
|
||||
<done>AC-1, AC-4 satisfied</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Endpoint GET /api/print/jobs/status + repo method</name>
|
||||
<files>src/Modules/Printing/PrintJobRepository.php, src/Modules/Printing/PrintApiController.php, routes/web.php</files>
|
||||
<action>
|
||||
PrintJobRepository.php — dodaj metode:
|
||||
```
|
||||
/**
|
||||
* @param list<int> $packageIds
|
||||
* @return list<int> package_ids ktore maja job status=pending
|
||||
*/
|
||||
public function filterPendingPackageIds(array $packageIds): array
|
||||
```
|
||||
Implementacja: jesli pusta tablica -> return []; przygotuj IN (...) placeholdery, SELECT DISTINCT package_id FROM print_jobs WHERE status='pending' AND package_id IN (...).
|
||||
|
||||
PrintApiController.php — dodaj publiczna metode `status(Request $request): Response`:
|
||||
- Pobierz parametr `package_ids` (CSV lub query array), parsuj do list<int>, odfiltruj <=0, limit 100 wartosci.
|
||||
- Jesli pusty -> zwroc JSON {"pending":[]}.
|
||||
- Wywolaj PrintJobRepository::filterPendingPackageIds()
|
||||
- Zwroc JSON {"pending":[1,2,3]} (pakiety nadal w kolejce).
|
||||
- Auth: authMiddleware (ten sam co createJob) — tylko zalogowani uzytkownicy.
|
||||
|
||||
routes/web.php — zarejestruj:
|
||||
```
|
||||
$router->get('/api/print/jobs/status', [$printApiController, 'status'], [$authMiddleware]);
|
||||
```
|
||||
przy pozostalych trasach /api/print/jobs.
|
||||
|
||||
Avoid: dodawania kolumn do print_jobs, zmian w logice completed/failed, nie ruszaj apiKeyMiddleware tras (listPending/download/complete).
|
||||
</action>
|
||||
<verify>
|
||||
curl "http://localhost/api/print/jobs/status?package_ids=1,2,3" (z sesja) zwraca {"pending":[...]} JSON
|
||||
</verify>
|
||||
<done>Endpoint dostepny dla AC-3</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Polling kolejki + auto-click ostatniej etykiety (JS)</name>
|
||||
<files>resources/views/orders/show.php, resources/views/shipments/prepare.php</files>
|
||||
<action>
|
||||
W orders/show.php (w istniejacym bloku script ~ linia 897-935):
|
||||
- Po kliknieciu btn-print-label i ustawieniu "W kolejce" wywolaj schedulePrintQueuePoll(packageId, btn).
|
||||
- Dodaj funkcje schedulePrintQueuePoll(ids, btnMap):
|
||||
- trzymaj mape packageId -> btn element
|
||||
- co 3 sekundy fetch GET /api/print/jobs/status?package_ids=<csv>
|
||||
- dla kazdego ID NIEobecnego w response.pending: zrevertuj przycisk do stanu Drukuj (innerHTML='Drukuj', disabled=false, remove btn--danger, add btn--secondary)
|
||||
- gdy mapa pusta — clearInterval
|
||||
- max 120 iteracji (6 minut) jako safety; po tym clear.
|
||||
- Przy wejsciu na strone (DOMContentLoaded) zbierz wszystkie istniejace `button[disabled]` z textem "W kolejce" i ich data-package-id pobrane z siostrzanego .btn-print-label lub z dodanego atrybutu data-package-id na samym disabled button. Zmodyfikuj szablon PHP aby disabled button "W kolejce" mial `data-package-id` i klase `js-print-queue-pending` — dla obu widokow.
|
||||
- Dla kazdego znalezionego `.js-print-queue-pending` uruchom schedulePrintQueuePoll.
|
||||
|
||||
Auto-click ostatniej etykiety po utworzeniu przesylki (orders/show.php):
|
||||
- Read query param `?shipment_created=1` lub (prefered) flash session `shipment.created_package_id` ustawiana przez OrdersController/ShipmentsController po utworzeniu paczki.
|
||||
- Jezeli nie chcesz ruszac kontrolera — zastosuj fallback JS: po zaladowaniu strony jesli URL ma fragment `#tab=shipments` lub query `?printLast=1`, znajdz ostatni wiersz tabeli przesylek (tbody tr:last-child) ktory ma .btn-print-label i wywolaj btn.click().
|
||||
- WYBIERZ: dolozyc query param `printLast=1` w redirect z ShipmentsController po pomyslnym utworzeniu paczki (jesli istnieje taki redirect -> /orders/{id}#shipments). Znajdz redirect post utworzeniu paczki w ShipmentsController i dolaczaj ?printLast=1 do URL.
|
||||
- JS w show.php: jesli location.search zawiera `printLast=1`, poczekaj 300ms po inicjalizacji tabow, znajdz w tabeli przesylek OSTATNI .btn-print-label (nie disabled) i wywolaj .click(). Nastepnie wyczysc parametr z URL przez history.replaceState.
|
||||
|
||||
Powtorz logike polling w shipments/prepare.php — dokladnie te same fragmenty (wspolna implementacja w widoku, bo oba pliki maja lokalne skrypty; DRY nie jest tu wymagany, ale jesli latwo to wydziel do resources/views/components/print-queue-poll.php i includuj).
|
||||
|
||||
Avoid: dotykania logiki tworzenia przesylki (backend), zmian w API createJob, zmian w Windows clients.
|
||||
</action>
|
||||
<verify>
|
||||
1. /orders/{id} z jedna paczka label_ready — kliknij Drukuj, sprawdz ze pojawia sie "W kolejce"
|
||||
2. W DB: UPDATE print_jobs SET status='completed' WHERE package_id=X
|
||||
3. W ciagu <=10s przycisk wraca do "Drukuj"
|
||||
4. Stworz nowa przesylke z /shipments/prepare — po redirecie na /orders/{id}?printLast=1 automatycznie pojawia sie "W kolejce" dla nowej paczki
|
||||
</verify>
|
||||
<done>AC-2, AC-3 satisfied</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Logika tworzenia print_job po stronie backendu (createJob, PrintJobRepository::create)
|
||||
- Windows client OrderPROPrint (poll interval / timeout)
|
||||
- Preset CRUD w Settings (formularz, walidacja, zapis DB)
|
||||
- Kolumna etykiety dla shipments "is_manual" (zostawia —)
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Polling tylko dla paczek widocznych na biezacej stronie (nie globalny)
|
||||
- Endpoint /api/print/jobs/status tylko GET, read-only
|
||||
- Nie zmieniamy schemy print_jobs ani dodawania nowych statusow
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
- [ ] php -l resources/views/shipments/prepare.php
|
||||
- [ ] php -l resources/views/orders/show.php
|
||||
- [ ] php -l src/Modules/Printing/PrintApiController.php
|
||||
- [ ] php -l src/Modules/Printing/PrintJobRepository.php
|
||||
- [ ] Rebuild CSS niepotrzebny (brak zmian SCSS)
|
||||
- [ ] Manualny test AC-1..AC-4 zgodnie z verify w taskach
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie AC spelnione
|
||||
- Brak nowych bledow PHP lint / konsoli JS
|
||||
- Istniejace zachowania presetow (auto-submit) i tworzenia przesylek niezmienione
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Po ukonczeniu stworz `.paul/phases/100-preset-scope-print-ux/100-01-SUMMARY.md`
|
||||
</output>
|
||||
133
.paul/phases/100-preset-scope-print-ux/100-01-SUMMARY.md
Normal file
133
.paul/phases/100-preset-scope-print-ux/100-01-SUMMARY.md
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
phase: 100-preset-scope-print-ux
|
||||
plan: 01
|
||||
subsystem: ui
|
||||
tags: [shipments, print-queue, presets, polling]
|
||||
|
||||
requires:
|
||||
- phase: 23-25-shipment-presets
|
||||
provides: Preset autofill mechanics (applyPreset, selectDeliveryService)
|
||||
- phase: 18-20-print-queue
|
||||
provides: print_jobs table, POST /api/print/jobs, PrintJobRepository
|
||||
|
||||
provides:
|
||||
- Presety nadpisuja wylacznie wymiary+wage paczki
|
||||
- GET /api/print/jobs/status endpoint (session auth)
|
||||
- Polling kolejki wydruku w orders/show.php i shipments/prepare.php
|
||||
- Auto-click ostatniej etykiety po utworzeniu przesylki (?printLast=1)
|
||||
- Usuniecie placeholderow "-" przed przyciskiem Drukuj
|
||||
|
||||
affects: [shipments, printing, presets, orders-detail]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "JS polling pattern: per-view map packageId->btn + setInterval(3s) + auto-stop when map empty"
|
||||
- "Redirect query param (?printLast=1) + history.replaceState do jednokrotnej akcji po reloadzie"
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- resources/views/shipments/prepare.php
|
||||
- resources/views/orders/show.php
|
||||
- src/Modules/Printing/PrintApiController.php
|
||||
- src/Modules/Printing/PrintJobRepository.php
|
||||
- src/Modules/Shipments/ShipmentController.php
|
||||
- routes/web.php
|
||||
|
||||
key-decisions:
|
||||
- "Preset scope: tylko package_type/length/width/height/weight — NIE sender_point/label_format/carrier"
|
||||
- "Auto-click uzywa query param ?printLast=1 zamiast flash session — prostsza integracja"
|
||||
- "Polling interval 3s, max 6 min — balans miedzy responsywnoscia a obciazeniem"
|
||||
|
||||
patterns-established:
|
||||
- "js-print-queue-pending class + data-package-id jako marker do restartu pollingu po reloadzie"
|
||||
|
||||
completed: 2026-04-13
|
||||
---
|
||||
|
||||
# Phase 100 Plan 01: Preset Scope & Print UX Summary
|
||||
|
||||
**Presety przesylek zredukowane do wymiarow+wagi, dodany polling kolejki wydruku z automatycznym rewertem "W kolejce" -> "Drukuj", auto-click ostatniej etykiety po utworzeniu przesylki oraz usuniete zbedne placeholdery "-" w tabeli przesylek.**
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Preset zmienia tylko paczke | Pass | applyPreset() zawezone do 5 pol; carrier/serwis nietykane |
|
||||
| AC-2: Auto-click ostatniej etykiety | Pass | Redirect ?printLast=1 + JS `autoClickLastLabel()` z polluje do 30s za `.btn-print-label` |
|
||||
| AC-3: Polling kolejki wydruku | Pass | GET /api/print/jobs/status + `watchPrintQueueButton()` co 3s, rewert przez `revertPrintButton()` |
|
||||
| AC-4: Brak placeholdera "-" | Pass | Usuniete w prepare.php i show.php |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Presety nie nadpisuja juz carrier/serwis/sender_point/label_format — eliminacja pomylek przy roznych typach zamowien
|
||||
- Przycisk "W kolejce" automatycznie wraca do "Drukuj" po faktycznym wydruku (max 3s opoznienia poll)
|
||||
- Nowa przesylka = jeden klik uzytkownika (formularz) -> reszta automatyczna (redirect + auto-click drukuj)
|
||||
- Endpoint `/api/print/jobs/status` read-only z prepared statement IN(...), limit 100 ID, session auth
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `resources/views/shipments/prepare.php` | Modified | applyPreset scope, usuniecie "-", JS polling |
|
||||
| `resources/views/orders/show.php` | Modified | usuniecie "-", JS polling, auto-click ?printLast=1 |
|
||||
| `src/Modules/Printing/PrintApiController.php` | Modified | metoda `status()` |
|
||||
| `src/Modules/Printing/PrintJobRepository.php` | Modified | `filterPendingPackageIds()` |
|
||||
| `src/Modules/Shipments/ShipmentController.php` | Modified | redirect `?printLast=1` po sukcesie create() |
|
||||
| `routes/web.php` | Modified | GET /api/print/jobs/status (authMiddleware) |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Usuniecie sender_point_id i label_format z applyPreset | Naleza do "formy dostawy" per intencja uzytkownika | Presety sa czysto "paczka", nie "dostawa" |
|
||||
| ?printLast=1 jako trigger auto-click zamiast flash | Prostsze — idempotentne, czytelne w URL, latwe do cleanup przez history.replaceState | Jednorazowa akcja bez dependency na session state |
|
||||
| Polling interval 3s, max 120 tickow | 3s = responsywnie; 6 min = safety bez nieskonczonej petli | Brak wyciekow timerow, rozsadne obciazenie API |
|
||||
| `js-print-queue-pending` class + data-package-id | Marker do restartu polling po reloadzie strony gdy sa juz pending jobs | DRY: ten sam kod polling dzialajac dla klikow i dla reloadu |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 0 | — |
|
||||
| Scope additions | 0 | — |
|
||||
| Deferred | 0 | — |
|
||||
|
||||
**Total impact:** Plan wykonany dokladnie wg specyfikacji.
|
||||
|
||||
### Deferred Items
|
||||
None — plan wykonany w calosci.
|
||||
|
||||
## Issues Encountered
|
||||
None — wszystkie `php -l` zielone, zero retryow.
|
||||
|
||||
## Verification Results
|
||||
|
||||
```
|
||||
php -l resources/views/shipments/prepare.php -> No syntax errors
|
||||
php -l resources/views/orders/show.php -> No syntax errors
|
||||
php -l src/Modules/Printing/PrintApiController.php -> No syntax errors
|
||||
php -l src/Modules/Printing/PrintJobRepository.php -> No syntax errors
|
||||
php -l src/Modules/Shipments/ShipmentController.php -> No syntax errors
|
||||
php -l routes/web.php -> No syntax errors
|
||||
```
|
||||
|
||||
Manualny UAT AC-1..AC-4 wymaga uruchomienia aplikacji — rekomendowany po commitcie.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Kolejna faza v3.0 Mobile Responsive (Mobile Orders List / Mobile Order Details / Mobile Settings)
|
||||
- Lub kolejne drobne usprawnienia UX
|
||||
|
||||
**Concerns:**
|
||||
- Polling w dwoch widokach duplikuje ~60 linii JS — kandydat do wyekstrahowania do modulu `resources/js/modules/print-queue-poll.js` w przyszlej fazie
|
||||
|
||||
**Blockers:** None
|
||||
|
||||
---
|
||||
*Phase: 100-preset-scope-print-ux, Plan: 01*
|
||||
*Completed: 2026-04-13*
|
||||
Reference in New Issue
Block a user