Files
orderPRO/.paul/phases/17-receipt-duplicate-guard/17-01-PLAN.md
Jacek Pyziak 02d06298ea 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>
2026-03-22 21:16:54 +01:00

7.0 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
17-receipt-duplicate-guard 01 execute 1
src/Modules/Accounting/ReceiptController.php
resources/views/orders/receipt-create.php
true
## Goal Zablokować wystawienie kolejnego paragonu do zamówienia, które już ma paragon — nie całkowicie, ale z wyraźnym potwierdzeniem (alert) przed wysłaniem formularza.

Purpose

Ochrona przed przypadkowym wystawieniem duplikatu paragonu. Użytkownik widzi ostrzeżenie z listą istniejących paragonów i musi świadomie potwierdzić, że chce kontynuować.

Output

  • Zmodyfikowany ReceiptController::create() — przekazuje istniejące paragony do widoku
  • Zmodyfikowany widok receipt-create.php — alert z potwierdzeniem + lista istniejących paragonów
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@src/Modules/Accounting/ReceiptController.php @src/Modules/Accounting/ReceiptRepository.php @resources/views/orders/receipt-create.php

## Required Skills (from SPECIAL-FLOWS.md)
Skill Priority When to Invoke Loaded?
sonar-scanner required Po APPLY, przed UNIFY

No specialized flows configured for this plan type.

<acceptance_criteria>

AC-1: Formularz pokazuje ostrzeżenie gdy zamówienie ma paragon

Given zamówienie ma już wystawiony co najmniej jeden paragon
When użytkownik otwiera formularz wystawiania paragonu (GET /orders/{id}/receipt/create)
Then widzi ostrzeżenie z informacją o istniejących paragonach (numer, data, kwota)

AC-2: Submit wymaga potwierdzenia gdy istnieją paragony

Given zamówienie ma już wystawiony paragon i użytkownik jest na formularzu
When użytkownik kliknie przycisk "Wystaw paragon"
Then pojawia się OrderProAlerts.confirm z pytaniem o potwierdzenie
And formularz wysyła się dopiero po potwierdzeniu "Tak"
And formularz NIE wysyła się po kliknięciu "Anuluj"

AC-3: Brak ostrzeżenia gdy zamówienie nie ma paragonów

Given zamówienie nie ma żadnych wystawionych paragonów
When użytkownik otwiera formularz wystawiania paragonu
Then NIE widzi żadnego ostrzeżenia
And przycisk "Wystaw paragon" działa normalnie bez dodatkowego potwierdzenia

</acceptance_criteria>

Task 1: Przekazanie istniejących paragonów z kontrolera do widoku src/Modules/Accounting/ReceiptController.php W metodzie `create()` (linia ~36-72): 1. Po walidacji istnienia zamówienia (linia 36-39), dodać zapytanie o istniejące paragony: `$existingReceipts = $this->receipts->findByOrderId($orderId);` 2. Przekazać `existingReceipts` do widoku w tablicy `render()` (linia 58-70): `'existingReceipts' => $existingReceipts,`
Nie zmieniać: metody `store()`, logiki walidacji, żadnych innych metod.
Otworzyć formularz paragonu dla zamówienia z istniejącym paragonem — zmienna $existingReceipts dostępna w widoku z poprawną liczbą wpisów. AC-1 częściowo: dane o istniejących paragonach przekazane do widoku Task 2: Ostrzeżenie i potwierdzenie w widoku formularza resources/views/orders/receipt-create.php 1. Na początku pliku dodać zmienną: `$existingReceiptsList = is_array($existingReceipts ?? null) ? $existingReceipts : [];`
2. Po nagłówku (po linii ~19, przed `<form>`), jeśli `$existingReceiptsList !== []`, wyświetlić box ostrzeżenia:
   - Klasa CSS: `alert alert--warning mt-12` (reuse istniejącego stylu alertów)
   - Ikona + tekst: "Do tego zamówienia wystawiono już N paragon(ów):"
   - Lista paragonów: numer (`receipt_number`), data (`issue_date`), kwota (`total_gross`), config (`config_name`)
   - Tekst: "Czy na pewno chcesz wystawić kolejny?"

3. Na formularzu `<form>` dodać `id="receipt-create-form"`

4. Zmienić `<button type="submit">` na `<button type="button" id="receipt-submit-btn">` (tylko gdy są istniejące paragony — użyć warunku PHP)
   - Gdy brak istniejących paragonów: przycisk submit działa normalnie (type="submit")
   - Gdy są istniejące paragony: przycisk type="button" z JS handlerem

5. Na dole pliku dodać blok `<script>` (tylko gdy `$existingReceiptsList !== []`):
   ```javascript
   document.getElementById('receipt-submit-btn').addEventListener('click', function() {
       window.OrderProAlerts.confirm(
           'Do tego zamówienia istnieje już paragon. Czy na pewno chcesz wystawić kolejny?',
           function() {
               document.getElementById('receipt-create-form').submit();
           }
       );
   });
   ```

Nie zmieniać: struktury tabeli pozycji, danych sprzedawcy, logiki formularza poza submit.
Nie dodawać nowych plików CSS — użyć istniejących klas `.alert` / `.alert--warning`.
1. Otworzyć formularz paragonu dla zamówienia BEZ paragonu → brak ostrzeżenia, submit działa normalnie 2. Otworzyć formularz paragonu dla zamówienia Z paragonem → widoczne ostrzeżenie z danymi paragonu, kliknięcie "Wystaw" wymaga potwierdzenia w alercie AC-1 satisfied: ostrzeżenie z listą paragonów widoczne. AC-2 satisfied: submit wymaga potwierdzenia. AC-3 satisfied: brak ostrzeżenia gdy brak paragonów.

DO NOT CHANGE

  • src/Modules/Accounting/ReceiptRepository.php (metoda findByOrderId() już istnieje i wystarczy)
  • src/Modules/Accounting/ReceiptController.php metoda store() (logika zapisu bez zmian)
  • database/migrations/* (brak zmian schematu)
  • resources/modules/jquery-alerts/* (reuse, nie modyfikować)

SCOPE LIMITS

  • Tylko ostrzeżenie + potwierdzenie — NIE blokada całkowita
  • Brak zmian w logice zapisu (store) — to frontend guard
  • Brak nowych plików SCSS — użyć istniejących klas alertów
  • Nie dodawać walidacji server-side w store() — użytkownik świadomie potwierdził
Before declaring plan complete: - [ ] Formularz dla zamówienia bez paragonu — brak ostrzeżenia, normalny submit - [ ] Formularz dla zamówienia z paragonem — widoczne ostrzeżenie z numerem/datą/kwotą - [ ] Kliknięcie "Wystaw" z ostrzeżeniem → alert confirm z OrderProAlerts - [ ] Potwierdzenie w alercie → formularz się wysyła → paragon wystawiony - [ ] Anulowanie w alercie → formularz się nie wysyła - [ ] Brak błędów PHP i JS w konsoli - [ ] All acceptance criteria met

<success_criteria>

  • All tasks completed
  • All verification checks pass
  • No errors or warnings introduced
  • Istniejące paragony widoczne w ostrzeżeniu (numer, data, kwota)
  • Potwierdzenie wymagane tylko gdy istnieją paragony </success_criteria>
After completion, create `.paul/phases/17-receipt-duplicate-guard/17-01-SUMMARY.md`