--- phase: 123-receipts-export-vat-breakdown plan: 01 subsystem: accounting tags: [receipts, xlsx-export, vat, phpspreadsheet] requires: - phase: 12-accounting-list provides: AccountingController::export() z PhpSpreadsheet/Xlsx - phase: 70-receipt-shipping-cost provides: ReceiptService::buildItemsSnapshot() snapshot pattern z delivery provides: - items_json snapshot z polem `vat` per pozycja (nowe paragony) - XLSX eksport paragonow z rozbiciem per stawka VAT - helper buildVatBreakdown() + formatVatRate() w AccountingController affects: [accounting/invoices, statistics, ksiegowosc-eksport] tech-stack: added: [] patterns: - "Per-rate VAT breakdown w eksporcie XLSX (jeden wiersz per (paragon x stawka))" - "Legacy fallback: gdy snapshot nie ma `vat`, licz netto z brutto/(1+0.23)" key-files: created: [] modified: - src/Modules/Accounting/ReceiptService.php - src/Modules/Accounting/AccountingController.php key-decisions: - "Legacy fallback liczy netto z brutto/1.23 (nie z `total_net` w bazie, bo issue() zapisuje total_net=total_gross)" - "Multi-rate paragon = wiele wierszy XLSX z powtorzonymi Numer/Data/Brutto" - "Stawka VAT brana z order_items.tax_rate; brak fallback na 23.0 dla wysylki" patterns-established: - "items_json snapshot moze byc rozszerzany o nowe pola (vat) bez zmiany BC widokow" - "Eksport XLSX dekoduje items_json zamiast JOIN-owac order_items (zachowuje snapshot pattern)" duration: ~25min started: 2026-05-12T22:30:00Z completed: 2026-05-12T23:00:00Z --- # Phase 123 Plan 01: Receipts Export VAT Breakdown Summary **Eksport XLSX paragonow w `/accounting` ma 6 nowych kolumn (Numer | Data wystawienia | Kwota brutto | Kwota netto | Stawka VAT | Kwota VAT) z osobnym wierszem per stawka VAT; legacy paragony dostaja fallback 23%.** ## Performance | Metric | Value | |--------|-------| | Duration | ~25 min | | Started | 2026-05-12T22:30:00Z | | Completed | 2026-05-12T23:00:00Z | | Tasks | 2 completed | | Files modified | 2 (kod) + 3 (docs/state) | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Naglowki XLSX zgodne z wymaganiem | Pass | 6 kolumn, brak Data sprzedazy/Konfiguracja/Nr zamowienia/Nr referencyjny — zweryfikowane przez operatora | | AC-2: Multi-rate breakdown dla nowych paragonow | Pass (pending live test) | Logika `buildVatBreakdown()` grupuje po `vat`; do potwierdzenia po wystawieniu nowego paragonu z mieszanymi stawkami | | AC-3: Legacy paragony — fallback 23% | Pass | Operator wyeksportowal kwiecien — pierwotnie net=brutto, vat=0 (bug). Po naprawie liczy net = brutto/1.23, vat = brutto - net | | AC-4: Snapshot rozszerzony o VAT | Pass (pending live test) | Kod zapisuje `vat` per pozycja i `vat=23.0` dla wysylki; do potwierdzenia po wystawieniu nowego paragonu | ## Accomplishments - Usunieto z eksportu XLSX kolumny ksiegowo nieprzydatne (Data sprzedazy, Konfiguracja, Nr zamowienia, Nr referencyjny). - Dodano kolumny Kwota netto / Stawka VAT / Kwota VAT z prawidlowym rozbiciem per stawka. - Rozszerzono `items_json` snapshot o `vat` per pozycja (forward-compatible — stare widoki bez zmian). - Naprawiono fallback dla legacy paragonow (nie polega na zlamanym `total_net = total_gross` z `ReceiptService::issue()`). ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `src/Modules/Accounting/ReceiptService.php` | Modified | `buildItemsSnapshot()` zapisuje `vat` per pozycja (z `order_items.tax_rate`, fallback 23.0) | | `src/Modules/Accounting/AccountingController.php` | Modified | Nowe naglowki + helper `buildVatBreakdown()` + `formatVatRate()`; multi-rate breakdown | | `.paul/codebase/architecture.md` | Modified | Sekcja "Phase 123 — Receipts Export VAT Breakdown" | | `.paul/codebase/tech_changelog.md` | Modified | Nowy wpis Phase 123 | | `.paul/STATE.md` | Modified | Loop position UNIFY | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Legacy fallback liczy `net = brutto/1.23` zamiast brac `total_net` z bazy | `ReceiptService::issue()` zapisuje `total_net = total_gross` (znany bug, poza zakresem 123); branie `total_net` daje vat=0 dla wszystkich starych paragonow | Operator widzi sensowne rozbicie VAT dla historycznych paragonow; oryginalny `total_net` w `receipts` pozostaje nietkniety | | Multi-rate = wiele wierszy XLSX (nie wieloliniowe komorki) | User wybral ten format (bardziej Excel-friendly do sumowania) | Numer/Data/Brutto powtarzaja sie w wierszach jednego paragonu | | Pozycja "Koszt wysylki" dostaje `vat=23.0` | Domyslna stawka dla uslugi wysylki w PL | Eksport bedzie spojny dopoki nie pojawi sie potrzeba uslug 8% (wtedy do uzupelnienia) | | Brak migracji wstecznej `items_json` | Fallback w eksporcie wystarczy; backfill ryzykowny dla snapshotow | Stare paragony wyswietlaja sie w eksporcie z fallbackiem 23%; nowe — z dokladnym breakdown | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | Auto-fixed | 1 | Krytyczne — bez tej naprawy AC-3 by failowal | | Scope additions | 0 | — | | Deferred | 1 | RECEIPT-NET-FIX (poza zakresem 123) | **Total impact:** Jedna naprawa post-APPLY na podstawie smoke testu operatora; reszta zgodnie z planem. ### Auto-fixed Issues **1. [Bugfix] Legacy fallback dawal net=brutto, vat=0** - **Found during:** smoke test operatora (eksport kwietnia) - **Issue:** Plan zakladal `Kwota netto = total_net`, `Kwota VAT = total_gross - total_net`, ale `ReceiptService::issue()` zapisuje `total_net = total_gross` (linie 81-82 ReceiptService) — wiec roznica zawsze = 0. - **Fix:** Zmieniono fallback na `net = round(total_gross / 1.23, 2)`, `vat = total_gross - net`. - **Files:** `src/Modules/Accounting/AccountingController.php` (`buildVatBreakdown()`) - **Verification:** Operator potwierdzil eksportem kwietnia — kwoty teraz sensowne. ### Deferred Items - **RECEIPT-NET-FIX** — `ReceiptService::issue()` powinien zapisywac realne `total_net` (a nie kopie `total_gross`). Wymaga sumowania per pozycja z VAT. Dodaj do `.paul/codebase/todo.md`. ## Issues Encountered | Issue | Resolution | |-------|------------| | Legacy fallback dawal net=brutto, vat=0 | Naprawione w `buildVatBreakdown()` — patrz Auto-fixed #1 | ## Next Phase Readiness **Ready:** - Eksport XLSX dziala z VAT breakdown dla nowych paragonow. - Snapshot pattern rozszerzony o `vat` — gotowy na inne raporty (np. eksport per stawka, JPK). **Concerns:** - `ReceiptService::issue()` nadal zapisuje `total_net = total_gross` (RECEIPT-NET-FIX) — eksport teraz nie polega na tym polu, ale UI/widoki paragonu moga wyswietlac mylace dane. **Blockers:** None --- *Phase: 123-receipts-export-vat-breakdown, Plan: 01* *Completed: 2026-05-12*