--- phase: 12-accounting-list plan: 01 type: execute wave: 1 depends_on: ["11-01"] files_modified: - src/Modules/Accounting/AccountingController.php - src/Modules/Accounting/ReceiptRepository.php - resources/views/accounting/index.php - resources/views/layouts/app.php - routes/web.php - resources/lang/pl.php - resources/scss/app.scss - public/assets/css/app.css - composer.json - DOCS/ARCHITECTURE.md autonomous: false --- ## Goal Sekcja Ksiegowosc w nawigacji glownej z lista wszystkich paragonow, filtrami, paginacja i eksportem do XLSX. ## Purpose Dotychczas paragony widoczne sa tylko w kontekscie pojedynczego zamowienia. Uzytkownik potrzebuje przegladac wszystkie paragony w jednym miejscu — filtrowac po dacie, konfiguracji, numerze — i eksportowac do XLSX dla celów ksiegowych. ## Output - Nowy AccountingController z metoda index() i export() - Widok listy paragonow z filtrami (reuse komponentu table-list) - Eksport XLSX przez PhpSpreadsheet - Nowy link "Ksiegowosc" w nawigacji glownej (sidebar) ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Prior Work @.paul/phases/11-receipt-print/11-01-SUMMARY.md — podglad, druk, PDF paragonu @.paul/phases/10-receipt-issue/10-01-SUMMARY.md — wystawianie paragonow, ReceiptRepository ## Source Files @src/Modules/Accounting/ReceiptRepository.php @src/Modules/Accounting/ReceiptController.php @resources/views/components/table-list.php @resources/views/orders/list.php — wzorzec listy z filtrami @src/Modules/Orders/OrdersController.php — wzorzec metody index() z tableList @resources/views/layouts/app.php — sidebar navigation ## 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: Link Ksiegowosc w nawigacji glownej ```gherkin Given uzytkownik jest zalogowany When widzi sidebar nawigacji Then widoczny jest nowy link "Ksiegowosc" prowadzacy do /accounting And link jest aktywny gdy uzytkownik jest na stronie /accounting ``` ## AC-2: Lista paragonow z paginacja ```gherkin Given istnieja paragony w bazie danych When uzytkownik otwiera /accounting Then wyswietlana jest tabela paragonow z kolumnami: - Numer paragonu, Data wystawienia, Data sprzedazy, Kwota brutto, Konfiguracja, Zamowienie And tabela jest paginowana (domyslnie 20 na strone) And mozna sortowac po: numer, data wystawienia, kwota brutto ``` ## AC-3: Filtry listy ```gherkin Given uzytkownik jest na stronie /accounting When uzywa filtrow Then moze filtrowac po: - Szukaj (numer paragonu, numer zamowienia) - Konfiguracja (select z aktywnych konfiguracji) - Data wystawienia od / do And filtry sa zachowane w URL (query string) ``` ## AC-4: Eksport XLSX ```gherkin Given uzytkownik jest na stronie /accounting z zastosowanymi filtrami When klika przycisk "Eksportuj XLSX" Then przeglądarka pobiera plik .xlsx z lista paragonow And plik zawiera te same kolumny co tabela + dodatkowe: data sprzedazy, nr referencyjny And eksport uwzglednia aktywne filtry (nie eksportuje wszystkiego) And plik ma nazwe: paragony_YYYY-MM-DD.xlsx ``` ## AC-5: Pusta lista ```gherkin Given brak paragonow spelniajacych kryteria (pusta baza lub filtr bez wynikow) When uzytkownik otwiera /accounting Then wyswietlany jest komunikat "Brak paragonow" ``` Task 1: ReceiptRepository — metoda paginate() i exportData() src/Modules/Accounting/ReceiptRepository.php 1. **paginate(array $filters): array** — analogicznie do OrdersRepository::paginate() - Przyjmuje filtry: search, config_id, date_from, date_to, sort, sort_dir, page, per_page - SELECT r.*, rc.name AS config_name, o.internal_order_number, o.external_order_id FROM receipts r LEFT JOIN receipt_configs rc ON rc.id = r.config_id LEFT JOIN orders o ON o.id = r.order_id - WHERE dynamiczne na podstawie filtrow: - search: LIKE na receipt_number i o.internal_order_number i o.external_order_id - config_id: = config_id - date_from: issue_date >= date_from - date_to: issue_date <= date_to - ORDER BY dynamiczne (whitelist: receipt_number, issue_date, total_gross) + sort_dir (ASC/DESC) - LIMIT/OFFSET na podstawie page i per_page - Zwraca: ['items' => [...], 'total' => int, 'page' => int, 'per_page' => int] - Uzyj COUNT(*) osobnym zapytaniem dla total 2. **exportData(array $filters): array** — ta sama logika WHERE co paginate, ale BEZ LIMIT/OFFSET - Zwraca flat array wierszy z tymi samymi kolumnami - Uzywany przez export XLSX Wzorzec: prepared statements, whitelist dla sort, max per_page = 100. - `php -l src/Modules/Accounting/ReceiptRepository.php` AC-2 backend, AC-3 backend, AC-4 backend Task 2: AccountingController + trasy + nawigacja + widok src/Modules/Accounting/AccountingController.php, routes/web.php, resources/views/accounting/index.php, resources/views/layouts/app.php, resources/lang/pl.php, composer.json 1. **Instalacja PhpSpreadsheet:** - `php composer.phar require phpoffice/phpspreadsheet --ignore-platform-reqs` 2. **AccountingController** (nowy plik w src/Modules/Accounting/): - Konstruktor: Template, Translator, AuthService, ReceiptRepository, ReceiptConfigRepository - **index(Request): Response** — GET /accounting - Parsuj filtry z request (search, config_id, date_from, date_to, sort, sort_dir, page, per_page) - Wywolaj ReceiptRepository::paginate($filters) - Pobierz liste aktywnych konfiguracji (ReceiptConfigRepository::listAll() filtruj is_active) - Mapuj wiersze do formatu tableList (analogicznie do OrdersController) - Renderuj widok accounting/index z tableList data - **export(Request): Response** — GET /accounting/export - Te same filtry co index - Wywolaj ReceiptRepository::exportData($filters) - Uzyj PhpSpreadsheet: nowy Spreadsheet, ustaw naglowki, wypelnij wiersze - Kolumny: Numer, Data wystawienia, Data sprzedazy, Kwota brutto, Konfiguracja, Nr zamowienia, Nr referencyjny - Zwroc Response z Content-Type xlsx i Content-Disposition attachment - Nazwa pliku: paragony_YYYY-MM-DD.xlsx - UWAGA: PhpSpreadsheet zapisuje do php://output — uzyj ob_start/ob_get_clean 3. **routes/web.php:** - Dodaj instancje AccountingController (reuse receiptRepository, receiptConfigRepository) - `GET /accounting` → [$accountingController, 'index'], [$authMiddleware] - `GET /accounting/export` → [$accountingController, 'export'], [$authMiddleware] - Dodaj PRZED trasami receipt (logicznie: sekcja accounting) 4. **resources/views/accounting/index.php:** - Uzyj komponentu table-list (include components/table-list.php z $tableList) - Dodaj przycisk "Eksportuj XLSX" w naglowku (link do /accounting/export z aktualnymi filtrami w query string) - Wzorzec: analogicznie do orders/list.php 5. **resources/views/layouts/app.php:** - Dodaj nowa sekcje w sidebar PRZED "Ustawienia": ```php ... ``` - Uzyj ikony dokumentu/receipt (inline SVG) 6. **resources/lang/pl.php:** - Dodaj klucze: `navigation.accounting_section` => 'Ksiegowosc' - `accounting.title`, `accounting.export`, `accounting.empty` - `accounting.filters.*`: search, config, date_from, date_to, any - `accounting.columns.*`: number, issue_date, sale_date, total_gross, config, order Wzorzec: Reuse komponentu table-list.php, analogia do OrdersController::index(). - `php -l src/Modules/Accounting/AccountingController.php` - `php -l routes/web.php` - `php -l resources/views/accounting/index.php` - `php -l resources/views/layouts/app.php` - `composer show phpoffice/phpspreadsheet` — zainstalowany AC-1, AC-2, AC-3, AC-4, AC-5 spelnione Task 3: SCSS build + aktualizacja dokumentacji resources/scss/app.scss, public/assets/css/app.css, DOCS/ARCHITECTURE.md 1. Build SCSS do CSS (jesli nowe klasy dodane) 2. Zaktualizuj DOCS/ARCHITECTURE.md: - Dodaj AccountingController (index, export) do sekcji Modules/Accounting - Dodaj ReceiptRepository::paginate(), exportData() - Dodaj trasy /accounting i /accounting/export - `npx sass --style=compressed --no-source-map resources/scss/app.scss public/assets/css/app.css` - Brak bledow Dokumentacja zaktualizowana, CSS zbudowany Sekcja Ksiegowosc: lista paragonow z filtrami, paginacja, eksport XLSX, link w nawigacji 1. Otworz aplikacje → sidebar → kliknij "Ksiegowosc" 2. Sprawdz: tabela paragonow wyswietla sie z kolumnami 3. Uzyj filtrow: szukaj po numerze, wybierz konfiguracje, ustaw daty 4. Sprawdz paginacje: zmien strone, zmien ilosc na strone 5. Kliknij "Eksportuj XLSX" — plik pobiera sie 6. Otworz XLSX — dane poprawne, filtry uwzglednione 7. Sprawdz czy link do zamowienia w tabeli dziala 8. Sprawdz pusta liste (filtr bez wynikow) — komunikat "Brak paragonow" 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/ReceiptController.php (gotowe z fazy 11 — tylko odczyt) - resources/views/receipts/* (gotowe z fazy 11) ## SCOPE LIMITS - Brak edycji/anulowania paragonu — poza zakresem v0.3 - Brak zaawansowanych raportow (sumy per konfiguracja, wykresy) — future - Brak eksportu CSV — tylko XLSX - Brak filtrowania po nabywcy — uproszczenie v0.3 Before declaring plan complete: - [ ] `composer show phpoffice/phpspreadsheet` — zainstalowany - [ ] `php -l src/Modules/Accounting/AccountingController.php` - [ ] `php -l src/Modules/Accounting/ReceiptRepository.php` - [ ] `php -l resources/views/accounting/index.php` - [ ] `php -l routes/web.php` - [ ] Link "Ksiegowosc" widoczny w sidebar nawigacji - [ ] Lista paragonow wyswietla sie z paginacja - [ ] Filtry dzialaja (search, config, date_from, date_to) - [ ] Sortowanie dziala (numer, data, kwota) - [ ] Eksport XLSX pobiera sie i zawiera poprawne dane - [ ] Pusta lista wyswietla komunikat - [ ] All acceptance criteria met - Wszystkie 3 taski auto + 1 checkpoint ukonczone - Wszystkie AC-1 do AC-5 spelnione - PhpSpreadsheet zainstalowany i dzialajacy - Brak bledow PHP - Weryfikacja manualna przez uzytkownika (checkpoint) After completion, create `.paul/phases/12-accounting-list/12-01-SUMMARY.md`