Files
orderPRO/.paul/phases/123-receipts-export-vat-breakdown/123-01-SUMMARY.md
Jacek Pyziak 0227f2d072 feat(123): receipts export xlsx VAT breakdown
- AccountingController::export(): new headers (Numer | Data wystawienia | Kwota brutto | Kwota netto | Stawka VAT | Kwota VAT), removed Data sprzedazy/Konfiguracja/Nr zamowienia/Nr referencyjny
- buildVatBreakdown() helper groups items_json by vat rate, emits one XLSX row per (receipt x rate); legacy receipts (no `vat` in snapshot) fallback to net=brutto/1.23
- ReceiptService::buildItemsSnapshot(): writes `vat` per item from order_items.tax_rate (fallback 23.0); shipping cost item gets vat=23.0
- RECEIPT-NET-FIX deferred (.paul/codebase/todo.md): ReceiptService::issue() still saves total_net=total_gross

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:06:53 +02:00

138 lines
6.6 KiB
Markdown

---
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*