Files
finansePRO/.paul/plans/20260721-2324-import-json-grosze-ceny/PLAN.md
T
2026-07-22 00:27:20 +02:00

136 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
plan_id: 20260721-2324-import-json-grosze-ceny
title: Poprawka parsowania cen z paragonu JSON (grosze → złote)
storage: plan-first
legacy_phase: null
created: 2026-07-21T23:24:13+02:00
status: planned
type: execute
autonomous: true
delegation: auto
files_modified: [app/Libraries/ReceiptParser.php]
quality_radar: degraded
---
<objective>
## Goal
Naprawić parsowanie kwot przy imporcie paragonu z pliku JSON (eParagon / JPK_KASA_PARAGON), gdzie ceny są 100× za duże (np. `3,69` odczytane jako `369 zł`).
## Purpose
Import z JSON zwraca zawyżone kwoty, więc zaksięgowane wydatki są błędne. To realny błąd danych finansowych — musi być deterministyczny, nie „mniej więcej".
## Output
Zmodyfikowany `app/Libraries/ReceiptParser.php` — prompt informuje model, że w surowym JSON z kasy fiskalnej wartości kwotowe to liczby CAŁKOWITE w groszach i trzeba je podzielić przez 100.
</objective>
<context>
## Project Docs
@.paul/PROJECT.md
@.paul/STATE.md
@.paul/codebase/architecture.md
@.paul/codebase/impact_map.md
@.paul/codebase/quality_risks.md
## Source Files
@app/Libraries/ReceiptParser.php
## Dowód (analiza pliku d:\telefon-download\2607202229016050.json)
Format eParagon trzyma WSZYSTKIE kwoty jako liczby całkowite w groszach:
- `sellLine.price=369, total=369, quantity=1` → 3,69 zł (DrozdzKrem)
- `sellLine.price=129, total=258, quantity=2` → 1,29 zł/szt, 2,58 zł razem (CukChupa)
- `sumInCurrency.fiscalTotal=1315` → 13,15 zł; `totalWithPacks=1365` → 13,65 zł
- Kaucja `pack.price=50` → 0,50 zł
`ReceiptParser::parse()` (linia 59) wysyła surowy JSON jako `input_text` bez informacji o jednostce; prompt (`prompt()`) opisuje tylko kolumny paragonu obrazkowego/PDF. Model odczytuje `369` dosłownie jako 369 zł.
</context>
<clarifications>
- Zakres celowo minimalny: poprawka w prompt, bez nowej ścieżki parsowania JSON w PHP i bez zmian w kontrolerze/zapisie. Pełny deterministyczny parser eParagon = osobny, większy plan (patrz Explicit Deferrals) — tu niepotrzebny.
</clarifications>
<impact_scan>
## Quality Radar
**Status:** degraded (jscpd/ast-grep wyłączone polityką w `config.md`; brak pełnego indeksu codebase-memory-mcp — analiza ręczna kodu i pliku wejściowego).
**Tools:** analiza ręczna `ReceiptParser.php` + przykładowy JSON.
## Affected Areas
- Import paragonów (Plan 3): `app/Libraries/ReceiptParser.php` — jedyny plik zmieniany. Gałąź `else` (JSON/tekst) w `parse()` i treść `prompt()`.
- Bez zmian: `Receipts.php`, modele, `receipt_category_map`, migracje, trasy, widoki, ścieżka obrazów/PDF.
## Duplicate / Hardcoded Risks
- Niedeterminizm OCR/LLM (znany, `quality_risks.md`): dla JSON „podziel przez 100" to reguła deterministyczna dla modelu rozumującego — obsłużone w Task 1, weryfikowane realnym importem (AC-1).
- Brak drugiego źródła prawdy: reguła w prompcie, żadnych nowych stałych ani powielonej logiki kwot.
## Explicit Deferrals
- Pełny natywny parser eParagon w PHP (pominięcie AI dla JSON, zero tokenów, 100% determinizm) — odroczone (YAGNI): straciłby ładne nazwy `display` i podpowiedzi kategorii z AI, a to szerszy refaktor. Podnieść tylko jeśli reguła promptu okaże się zawodna dla JSON.
- Kwoty ze ścieżki obrazka/PDF — bez zmian, nie dotyczy tego błędu.
</impact_scan>
<skills>
Brak SPECIAL-FLOWS.md — sekcja skills pominięta.
</skills>
<acceptance_criteria>
## AC-1: Ceny z JSON w złotych, nie w groszach
```gherkin
Given plik d:\telefon-download\2607202229016050.json importowany przez ekran paragonu
When ReceiptParser sparsuje pozycje
Then pozycja "DrozdzKremPorz110g" ma amount 3.69 (nie 369)
And "CukChupaZegarek14,7g" (qty 2) ma amount 2.58 (nie 258)
And total = 13.65 (nie 1365)
```
## AC-2: Import obrazka/PDF bez regresji
```gherkin
Given paragon jako zdjęcie lub PDF (nie JSON)
When ReceiptParser sparsuje paragon
Then kwoty są odczytane jak dotychczas (bez dzielenia przez 100)
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Dodać regułę „grosze → złote" do promptu dla wejścia JSON</name>
<files>app/Libraries/ReceiptParser.php</files>
<action>
W metodzie `prompt()` dodać zasadę informującą model, że jeśli dane wejściowe to surowy JSON z kasy fiskalnej (eParagon / JPK_KASA_PARAGON), to wszystkie pola kwotowe (m.in. `price`, `total`, `brutto`, `cena`, `wart`, `fiscalTotal`, `totalWithPacks`, `amount`) są liczbami CAŁKOWITYMI w GROSZACH i należy podzielić je przez 100, aby uzyskać wartość w złotych. Reguła dotyczy TYLKO wejścia JSON — dla zdjęcia/PDF kwoty odczytywać jak dotąd.
Doprecyzować, że w JSON `amount` pozycji = pole `total` danego wiersza sprzedaży podzielone przez 100 (łączna wartość pozycji, nie cena jednostkowa), a `total` paragonu = kwota do zapłaty (`totalWithPacks`) / 100.
Nie zmieniać sygnatury metod, gałęzi `image/`/`application/pdf`, ani `normalize()`.
</action>
<verify>php -l app/Libraries/ReceiptParser.php</verify>
<done>AC-1, AC-2 (reguła warunkowa tylko dla JSON)</done>
</task>
</tasks>
<boundaries>
## Do Not Change
- Ścieżka obrazka (`input_image`) i PDF (`input_file`) w `parse()`.
- `normalize()`, sygnatury metod, model OpenAI, klucz `.env`.
- Kontroler `Receipts`, modele, `receipt_category_map`, migracje, trasy, widoki.
## Scope Limits
- Bez natywnego parsera JSON w PHP (odroczone).
- Bez zmian formatu wyświetlania kwot ani logiki księgowania w `confirm()`.
</boundaries>
<verification>
- [ ] `php -l app/Libraries/ReceiptParser.php` — brak błędów składni.
- [ ] Import realny `d:\telefon-download\2607202229016050.json`: pozycje 3,69 / 5,29 / 2,58 / 0,34 / 1,25, total 13,65 (AC-1).
- [ ] Kontrolny import zdjęcia lub PDF — kwoty bez zmian (AC-2).
- [ ] Quality Radar: ryzyko niedeterminizmu obsłużone regułą deterministyczną + weryfikacją realnym importem.
</verification>
<success_criteria>
- [ ] AC-1 i AC-2 spełnione.
- [ ] Zmiana ograniczona do `app/Libraries/ReceiptParser.php`.
- [ ] Brak regresji ścieżki obrazek/PDF.
</success_criteria>
<output>
SUMMARY.md path: `.paul/plans/20260721-2324-import-json-grosze-ceny/SUMMARY.md`
</output>