136 lines
6.1 KiB
Markdown
136 lines
6.1 KiB
Markdown
---
|
||
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>
|