--- phase: 11-receipt-print plan: 01 type: execute wave: 1 depends_on: ["10-01"] files_modified: - src/Modules/Accounting/ReceiptController.php - resources/views/receipts/show.php - resources/views/receipts/print.php - resources/views/orders/show.php - routes/web.php - resources/lang/pl.php - resources/scss/shared/_ui-components.scss - resources/scss/app.scss - public/assets/css/app.css - composer.json - DOCS/ARCHITECTURE.md autonomous: false --- ## Goal Podglad paragonu w formie HTML oraz generowanie PDF — uzytkownik moze otworzyc paragon, zobaczyc jego tresc i pobrac/wydrukować jako PDF. ## Purpose Bez podgladu i wydruku wystawione paragony sa tylko rekordami w bazie — nie mozna ich przekazac klientowi ani zweryfikowac wizualnie. Ta faza zamyka cykl: wystawienie → podglad → wydruk/PDF. ## Output - Widok podgladu paragonu (HTML w layoucie aplikacji) - Widok druku paragonu (standalone HTML, bez nawigacji, gotowy do window.print()) - Generowanie PDF przez dompdf - Aktywny link "Podglad" w zakladce Dokumenty ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Prior Work @.paul/phases/10-receipt-issue/10-01-SUMMARY.md — ReceiptRepository, snapshoty JSON, przycisk w zamowieniu ## Source Files @src/Modules/Accounting/ReceiptRepository.php @src/Modules/Accounting/ReceiptController.php @resources/views/orders/show.php @routes/web.php ## Required Skills (from SPECIAL-FLOWS.md) | Skill | Priority | When to Invoke | Loaded? | |-------|----------|----------------|---------| | sonar-scanner | required | Po APPLY, przed UNIFY | ○ | ## Skill Invocation Checklist - [ ] sonar-scanner uruchomiony po APPLY ## AC-1: Podglad paragonu w layoucie aplikacji ```gherkin Given paragon o id={receiptId} istnieje dla zamowienia {orderId} When uzytkownik otwiera /orders/{orderId}/receipt/{receiptId} Then wyswietlany jest podglad paragonu z danymi: - numer paragonu, data wystawienia, data sprzedazy - dane sprzedawcy (z seller_data_json) - dane nabywcy (z buyer_data_json, jesli is_named) - tabela pozycji (z items_json): nazwa, ilosc, cena, wartosc - suma brutto - numer referencyjny zamowienia (jesli skonfigurowany) And widoczne sa przyciski: "Drukuj", "Pobierz PDF", "Powrot" ``` ## AC-2: Widok druku (standalone HTML) ```gherkin Given uzytkownik jest na podgladzie paragonu When klika przycisk "Drukuj" Then otwiera sie nowe okno/zakladka z czystym widokiem paragonu (bez nawigacji aplikacji) And automatycznie uruchamia sie window.print() ``` ## AC-3: Generowanie PDF ```gherkin Given paragon o id={receiptId} istnieje When uzytkownik klika "Pobierz PDF" lub otwiera /orders/{orderId}/receipt/{receiptId}/pdf Then przeglądarka pobiera plik PDF z trescia paragonu And plik ma nazwe: {receipt_number}.pdf (znaki specjalne zamienione na _) ``` ## AC-4: Aktywny link "Podglad" w zakladce Dokumenty ```gherkin Given zamowienie ma wystawione paragony When uzytkownik otwiera zakladke "Dokumenty" Then przycisk "Podglad" przy kazdym paragonie jest aktywny (nie disabled) And prowadzi do /orders/{orderId}/receipt/{receiptId} ``` ## AC-5: Obsluga bledu — nieistniejacy paragon ```gherkin Given paragon o danym id nie istnieje lub nie nalezy do zamowienia When uzytkownik otwiera /orders/{orderId}/receipt/{receiptId} Then zwracany jest 404 Not Found ``` Task 1: Instalacja dompdf + metody kontrolera (show, print, pdf) composer.json, src/Modules/Accounting/ReceiptController.php, routes/web.php 1. **Instalacja dompdf:** - `composer require dompdf/dompdf` (w katalogu projektu) - UWAGA: vendor/ jest w ftp-kr ignore — po deploy trzeba recznie zainstalowac na serwerze 2. **ReceiptController — nowe metody:** - **show(Request): Response** — GET /orders/{id}/receipt/{receiptId} - Pobierz paragon: ReceiptRepository::findById($receiptId) - Waliduj: paragon istnieje i paragon.order_id == $orderId, inaczej 404 - Dekoduj JSON: seller_data_json, buyer_data_json, items_json - Pobierz config name: ReceiptConfigRepository::findById(config_id) - Renderuj widok `receipts/show` w layoucie `layouts/app` - **printView(Request): Response** — GET /orders/{id}/receipt/{receiptId}/print - Te same dane co show() - Renderuj widok `receipts/print` BEZ layoutu (standalone HTML) - **pdf(Request): Response** — GET /orders/{id}/receipt/{receiptId}/pdf - Te same dane co show() - Renderuj widok `receipts/print` do stringa HTML - Uzyj Dompdf do konwersji HTML → PDF - Zwroc Response z Content-Type: application/pdf i Content-Disposition: attachment - Nazwa pliku: receipt_number z / zamienione na _ + .pdf 3. **routes/web.php — 3 nowe trasy:** - `GET /orders/{id}/receipt/{receiptId}` → `[$receiptController, 'show']` - `GET /orders/{id}/receipt/{receiptId}/print` → `[$receiptController, 'printView']` - `GET /orders/{id}/receipt/{receiptId}/pdf` → `[$receiptController, 'pdf']` - Dodaj PRZED trasami shipment (analogicznie do create/store) Wzorzec: Uzyj Template::render() z layoutem dla show, bez layoutu dla print. Dla PDF: `$dompdf = new \Dompdf\Dompdf(); $dompdf->loadHtml($html); $dompdf->setPaper('A4'); $dompdf->render();` - `php -l src/Modules/Accounting/ReceiptController.php` - `php -l routes/web.php` - `composer show dompdf/dompdf` — zainstalowany AC-1 backend, AC-2 backend, AC-3 backend, AC-5 spelnione Task 2: Widoki receipts/show.php i receipts/print.php + SCSS resources/views/receipts/show.php, resources/views/receipts/print.php, resources/lang/pl.php, resources/scss/shared/_ui-components.scss, resources/scss/app.scss, public/assets/css/app.css 1. **receipts/show.php** (w layoucie aplikacji): - Naglowek: "Paragon {receipt_number}" + link powrotny do zamowienia - Przyciski: "Drukuj" (target=_blank do /print), "Pobierz PDF" (link do /pdf), "Powrot" - Sekcja danych sprzedawcy (z seller_data_json): firma, NIP, adres, tel, email - Sekcja danych nabywcy (z buyer_data_json — jesli istnieje): nazwa, adres, NIP - Tabela pozycji (z items_json): Lp, Nazwa, Ilosc, Cena, Wartosc - Podsumowanie: suma brutto - Metadane: data wystawienia, data sprzedazy, konfiguracja, nr referencyjny - Uzyj klas .card, .section-title, .order-kv, .table — istniejace style 2. **receipts/print.php** (standalone, BEZ layoutu): - Pelny dokument HTML z inline CSS (lub do app.css) - Uklad paragonowy: kompaktowy, A4-friendly - Naglowek: dane sprzedawcy (lewo) + "PARAGON" + numer (prawo) - Dane nabywcy (jesli is_named w konfiguracji) - Tabela pozycji z podsumowaniem - Stopka: data wystawienia, data sprzedazy, nr referencyjny - Na koncu: `` — auto-print po zaladowaniu - CSS @media print: ukryj elementy kontrolne, ustaw marginesy 3. **resources/lang/pl.php:** - Dodaj klucze: `receipts.show.title`, `receipts.show.print`, `receipts.show.pdf`, `receipts.show.back` - `receipts.show.seller`, `receipts.show.buyer`, `receipts.show.items`, `receipts.show.total` - `receipts.show.issue_date`, `receipts.show.sale_date`, `receipts.show.reference`, `receipts.show.config` 4. **SCSS:** - Dodaj klase `.receipt-print` dla widoku druku (kompaktowy, bez marginesow bocznych) - Dodaj `.receipt-header` (flexbox: dane sprzedawcy | tytul+numer) - Build SCSS do CSS - `php -l resources/views/receipts/show.php` - `php -l resources/views/receipts/print.php` - Otworz /orders/{id}/receipt/{receiptId} — podglad wyswietla sie poprawnie AC-1, AC-2 spelnione: widok podgladu i druku Task 3: Aktywacja linku "Podglad" w zakladce Dokumenty resources/views/orders/show.php W zakladce Dokumenty (data-order-tab-panel="documents"): - Zamien `Podglad` na: `Podglad` - Dodaj tez link "PDF": `PDF` - Otworz zamowienie z paragonem → zakladka Dokumenty → link "Podglad" jest aktywny i prowadzi do podgladu AC-4 spelnione: aktywny link Podglad + PDF w Dokumentach Podglad paragonu (HTML), widok druku (standalone + auto-print), generowanie PDF, aktywne linki w Dokumentach 1. Otworz zamowienie z paragonem → zakladka Dokumenty 2. Kliknij "Podglad" — otwiera sie strona z pelnym podgladem paragonu 3. Sprawdz: dane sprzedawcy, pozycje, suma, daty sa poprawne 4. Kliknij "Drukuj" — otwiera sie nowe okno z czystym widokiem + okno drukowania 5. Kliknij "Pobierz PDF" — przeglądarka pobiera plik PDF 6. Otworz PDF — tresc paragonu poprawna 7. Kliknij "PDF" bezposrednio z zakladki Dokumenty — pobiera PDF 8. Sprobuj otworzyc /orders/{id}/receipt/99999 — powinien byc 404 Type "approved" to continue, or describe issues to fix ## DO NOT CHANGE - database/migrations/* (schemat zablokowany) - src/Modules/Settings/ReceiptConfigRepository.php (gotowe z fazy 09) - src/Modules/Accounting/ReceiptRepository.php (gotowe z fazy 10 — tylko odczyt) ## SCOPE LIMITS - Brak edycji/anulowania paragonu — poza zakresem v0.3 - Brak logo firmy w paragonie — upload logo bedzie osobna funkcjonalnoscia - Format paragonu jest staly (nie konfigurowalny per-config) — uproszczenie v0.3 - PDF generowany server-side przez dompdf (nie client-side) Before declaring plan complete: - [ ] `composer show dompdf/dompdf` — zainstalowany - [ ] `php -l src/Modules/Accounting/ReceiptController.php` — brak bledow - [ ] `php -l resources/views/receipts/show.php` — brak bledow - [ ] `php -l resources/views/receipts/print.php` — brak bledow - [ ] Podglad /orders/{id}/receipt/{receiptId} wyswietla dane paragonu - [ ] Druk otwiera czyste okno z window.print() - [ ] PDF pobiera sie poprawnie - [ ] Link "Podglad" w Dokumentach jest aktywny - [ ] 404 dla nieistniejacego paragonu - [ ] All acceptance criteria met - Wszystkie 3 taski auto + 1 checkpoint ukonczone - Wszystkie AC-1 do AC-5 spelnione - dompdf zainstalowany i dzialajacy - Brak bledow PHP - Weryfikacja manualna przez uzytkownika (checkpoint) After completion, create `.paul/phases/11-receipt-print/11-01-SUMMARY.md`