This commit is contained in:
2026-04-03 14:53:58 +02:00
parent 2b4f24e766
commit 164b9b6a46
9 changed files with 510 additions and 23 deletions

View File

@@ -0,0 +1,158 @@
---
phase: 05-finances-fakturownia-import
plan: 02
type: execute
wave: 1
depends_on: ["05-01"]
files_modified:
- autoload/Domain/Finances/FakturowniaInvoiceImporter.php
- templates/finances/fakturownia-import-panel.php
autonomous: true
---
<objective>
## Goal
Usprawnic mapowanie klienta w imporcie Fakturownia tak, aby priorytetowo mapowac po NIP i ograniczyc reczne mapowanie tej samej firmy przy kolejnych fakturach kosztowych.
## Purpose
W aktualnym imporcie czesc dokumentow kluczuje klienta po `client_id`, co moze powodowac tworzenie kolejnych rekordow "brak mapowania" dla tego samego kontrahenta. Zmiana ma zapewnic stabilny klucz po NIP.
## Output
- Zmieniony algorytm `buildClientKey()` z priorytetem NIP
- Normalizacja NIP do wspolnego formatu klucza
- Kompatybilnosc wsteczna: fallback do starego klucza `id:...` podczas importu
- Widoczny NIP przy brakujacych mapowaniach klienta w panelu finansow
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@.paul/phases/05-finances-fakturownia-import/05-01-PLAN.md
@.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md
## Source Files
@autoload/Domain/Finances/FakturowniaInvoiceImporter.php
@templates/finances/fakturownia-import-panel.php
@autoload/Controllers/FinancesController.php
@autoload/Domain/Finances/FakturowniaImportRepository.php
</context>
<acceptance_criteria>
## AC-1: Priorytet mapowania klienta po NIP
```gherkin
Given dokument z Fakturowni zawiera NIP kontrahenta
When importer buduje klucz klienta
Then klucz jest oparty o NIP (prefiks `tax:`) niezaleznie od obecnosci `client_id`
```
## AC-2: Stabilna normalizacja NIP
```gherkin
Given NIP wystepuje w roznych formatach (spacje, myslniki, inne separatory)
When importer normalizuje NIP
Then wszystkie formy daja ten sam klucz mapowania klienta
```
## AC-3: Kompatybilnosc wsteczna mapowan
```gherkin
Given istnieje historyczne mapowanie klienta zapisane po kluczu `id:...`
When importer nie znajdzie mapowania po nowym kluczu `tax:...`
Then wykona fallback do starego klucza `id:...` i zaimportuje dokument bez ponownego recznego mapowania
```
## AC-4: NIP widoczny w panelu brakow mapowania
```gherkin
Given klient trafia do listy "Brakujace mapowania klientow"
When uzytkownik otwiera panel w `/finances/main_view/`
Then przy rekordzie widzi NIP z payloadu (jesli dostepny), co ulatwia wybor klienta CRM
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Zmienic algorytm klucza klienta na NIP-first z normalizacja</name>
<files>autoload/Domain/Finances/FakturowniaInvoiceImporter.php</files>
<action>
1. Zmienic `buildClientKey()` tak, aby kolejnosc byla:
- `tax:{normalized_tax_no}`
- `id:{client_id}`
- `name:{normalized_name}`
2. Dodac pomocnicza normalizacje NIP usuwajaca znaki nienumeryczne i biale znaki.
3. Gdy normalizacja da pusty wynik, traktowac NIP jako niedostepny i przejsc do fallbacku.
Unikac: zmiany semantyki mapowania pozycji (`buildItemKey`) i modyfikacji niezwiązanych z klientem.
</action>
<verify>
Odczyt kodu potwierdza, ze `buildClientKey()` sprawdza najpierw NIP, a NIP jest normalizowany do stalego formatu.
</verify>
<done>AC-1 i AC-2 satisfied</done>
</task>
<task type="auto">
<name>Task 2: Dodac fallback odczytu mapowania po historycznym kluczu id</name>
<files>autoload/Domain/Finances/FakturowniaInvoiceImporter.php</files>
<action>
1. W `processSingleDocument()` po braku mapowania po nowym `client_key` wykonac probe odczytu mapowania po starym kluczu `id:{client_id}`, o ile `client_id` istnieje i nowy klucz jest inny.
2. Jesli fallback znajdzie mapowanie, kontynuowac import bez queue dla klienta.
3. Jesli fallback nie znajdzie mapowania, zachowac obecne zachowanie queue `client`.
Unikac: zapisu nowego mapowania automatycznie bez decyzji uzytkownika.
</action>
<verify>
Sciezka warunkowa importera zawiera probe fallbacku `id:` przed `queueUnmapped('client', ...)`.
</verify>
<done>AC-3 satisfied</done>
</task>
<task type="auto">
<name>Task 3: Pokazac NIP w panelu brakujacych mapowan klientow</name>
<files>templates/finances/fakturownia-import-panel.php</files>
<action>
1. W tabeli "Brakujace mapowania klientow" wyswietlic NIP z payloadu (`tax_no`) przy danym rekordzie, z escapowaniem.
2. Zachowac dotychczasowe informacje o kluczu i liczbie wystapien.
3. Nie zmieniac endpointow zapisu mapowania i CSRF.
</action>
<verify>
Widok panelu renderuje dodatkowa linie z NIP (gdy payload ma `tax_no`) i pozostaje bezpieczny pod XSS.
</verify>
<done>AC-4 satisfied</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- mechanizm importu pozycji i mapowania kategorii
- struktura tabel SQL w `FakturowniaImportRepository` (bez migracji w tym planie)
- endpointy i routing niezwiązane z finansami
## SCOPE LIMITS
- Tylko mapowanie klienta i prezentacja NIP w panelu
- Bez tworzenia klientow CRM automatycznie
- Bez zmian w harmonogramie cron
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `buildClientKey()` ma priorytet `tax -> id -> name`
- [ ] NIP jest normalizowany do stabilnego formatu klucza
- [ ] Importer ma fallback odczytu mapowania po historycznym `id:...`
- [ ] Panel brakow mapowan klientow wyswietla NIP (jesli dostępny)
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Brak ponownego mapowania tej samej firmy, gdy dokumenty roznia sie `client_id`, ale maja ten sam NIP
- Istniejace mapowania po `id:` nie przestaja dzialac po wdrozeniu zmiany
- Uzytkownik widzi NIP w panelu i szybciej mapuje klienta
</success_criteria>
<output>
After completion, create `.paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md`
</output>