9.4 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | |||
|---|---|---|---|---|---|---|---|---|---|---|
| 05-finances-fakturownia-import | 04 | execute | 1 |
|
false | off |
Purpose
Zgloszony bug: faktura kosztowa 486639934 nie pojawila sie w finansach po imporcie. Phase 5 dostarczyla mechanizm importu, ale obecna logika FakturowniaApiClient::fetchCostDocuments() i FakturowniaInvoiceImporter::processDocumentType() ma trzy potencjalne dziury, przez ktore dokumenty kosztowe typu invoices.json?income=no moga zostac calkowicie pominiete.
Output
- Poprawiony
FakturowniaApiClientzawsze odpytujacy/invoices.json?income=nodla kosztow (z/costs.jsoni/expenses.jsonjako uzupelnienie, a nie jako early-exit). - Poprawiony
FakturowniaInvoiceImporter: usuniete pressie "wczesnego przerwania" na podstawie daty z listy oraz warunkoweperiod=this_monthdla kosztow. - Test jednostkowy odtwarzajacy brak faktury 486639934 i potwierdzajacy fix.
- UAT: ponowny import zwraca faktura 486639934 do panelu mapowan lub do finansow.
Prior Work
@.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md @.paul/phases/05-finances-fakturownia-import/05-03-SUMMARY.md
Source Files
@autoload/Domain/Finances/FakturowniaApiClient.php @autoload/Domain/Finances/FakturowniaInvoiceImporter.php @autoload/Domain/Finances/FakturowniaImportRepository.php @tests/Domain/Finances/FakturowniaInvoiceImporterTest.php
<acceptance_criteria>
AC-1: Koszty pobierane zawsze z /invoices.json?income=no
Given token Fakturowni jest skonfigurowany
And faktura kosztowa istnieje pod /invoices/486639934 (income=false)
When importer wywoluje fetchCostDocuments
Then zapytanie do /invoices.json?income=no jest wykonane niezaleznie od odpowiedzi /costs.json i /expenses.json
And lista zwrocona importerowi zawiera rekord 486639934
AC-2: Brak filtra period=this_month dla kosztow
Given FAKTUROWNIA_START_DATE jest pierwszym dniem biezacego miesiaca
When fetchCostDocuments buduje query
Then parametr period nie jest wysylany
And API zwraca takze faktury z wczesniejszych dni miesiaca wg issue_date
AC-3: Importer nie przerywa paginacji na podstawie dat listy
Given pierwsza strona z API zawiera dokumenty posortowane malejaco po updated_at
And wszystkie dokumenty na stronie maja issue_date starsze niz startDate
When processDocumentType przetwarza strone
Then petla kontynuuje do kolejnej strony dopoki API zwraca pelna strone (per_page)
And faktura 486639934 nie jest pomijana wylacznie z powodu sortowania
AC-4: Test regresyjny
Given test z fake'owym api clientem zwracajacym liste dokumentow z jednym kosztem income=false
When FakturowniaInvoiceImporter::import zostaje wywolany
Then dokument trafia do kolejki unmapped lub do finance_operations (nie jest skipped)
</acceptance_criteria>
Task 1: Napraw fetchCostDocuments w FakturowniaApiClient autoload/Domain/Finances/FakturowniaApiClient.php Przebuduj fetchCostDocuments tak, by: - Zawsze probowal /invoices.json?income=no (to jest primary source — URL faktury to /invoices/ID). - Uzupelniajaco probowal /costs.json i /expenses.json i laczyl wyniki (dedup po id), aby nie gubic dokumentow obecnych pod jednym endpointem a nieobecnych pod innym. - NIE stosowal period=this_month dla kosztow (usun canUseCurrentMonthPeriod z tej sciezki; sales moze zostac bez zmian albo tez ma byc usuniete — zdecyduj w ramach Task 1 spojnie i udokumentuj w komentarzu). - Zachowal softFail dla endpointow pobocznych (/costs.json, /expenses.json zwracajacych 404), ale traktowal 2xx z pusta lista jako "ta sciezka pusta" i szedl dalej zamiast zwracac wynik. - W razie gdy wszystkie trzy sciezki zwroca puste listy BEZ bledu HTTP, zwraca [] (nie rzuca wyjatku). Wyjatek tylko gdy wszystkie trzy rzucily bledy. Unikaj: dodawania nowych zaleznosci, zmiany sygnatur publicznych metod, ukrywania bledow HTTP. php -l autoload/Domain/Finances/FakturowniaApiClient.php Manualne wywolanie z tokenem testowym: var_dump($client->fetchCostDocuments('2026-04-01', 1)) zawiera faktura 486639934. AC-1, AC-2 spelnione Task 2: Popraw paginacje i filtr dat w FakturowniaInvoiceImporter autoload/Domain/Finances/FakturowniaInvoiceImporter.php W processDocumentType: - Usun wczesne przerywanie petli na podstawie !hasRelevantDateInPage. API moze sortowac po updated_at lub created_at, nie po issue_date — wczesne przerwanie gubi faktury z odroznionym issue_date. - Zachowaj twardy limit paginacji ($page > 100) jako safety-valve. - Zostaw filtr "za stare" na poziomie processSingleDocument (tam gdzie porownuje $document['date'] z startDate). Ten filtr dziala per-dokument i jest bezpieczny. Dodatkowo w normalizeDocument: dla dokumentow bez positions w liscie (gdy API zwraca skrocona forme), upewnij sie ze fallback do apiClient->fetchInvoiceDetails dziala i nie konsumuje zbyt wielu requestow (logika juz jest w resolvePositions — zweryfikuj ze nie regresuje przy naprawie). Unikaj: rekurencyjnego pobierania wszystkich stron w nieskonczonosc, cichego polykania wyjatkow API. php -l autoload/Domain/Finances/FakturowniaInvoiceImporter.php php tests/run.php (istniejace testy przechodza). AC-3 spelnione Task 3: Test regresyjny dla faktury kosztowej typu invoice tests/Domain/Finances/FakturowniaInvoiceImporterTest.php Dodaj test case "cost_invoice_from_invoices_endpoint_is_imported": - Zamockuj FakturowniaApiClient (interface lub testowa podklasa) tak, by fetchCostDocuments zwracalo [[ 'id' => 486639934, 'number' => 'FV 100/04/2026', 'kind' => 'vat', 'income' => false, 'issue_date' => '2026-04-05', 'seller_name' => 'Dostawca Sp. z o.o.', 'seller_tax_no' => '5252344567', 'positions' => ]]. - Uruchom importer z czystymi tabelami mapowan. - Oczekuj: summary['unmapped'] === 1 (bo brak mapowania klienta) oraz wpis w kolejce unmapped dla client_key='tax:5252344567'. - Dodatkowy test: z pre-zalozonym mapowaniem klienta i pozycji — oczekuj summary['imported'] === 1 i rekordu w finance_operations z amount = -1230.00. Unikaj: zaleznosci od prawdziwego API, pomijania czyszczenia bazy testowej miedzy testami. php tests/run.php — oba nowe testy zielone. AC-4 spelnione Poprawiony import kosztow z Fakturowni + test regresyjny. 1. Uruchom import recznie: otworz /finances/main_view/ i kliknij "Importuj z Fakturowni" (lub wywolaj cron.php). 2. Sprawdz komunikat podsumowania — powinno byc co najmniej 1 nowy rekord w kategoriach imported/unmapped. 3. W bazie: SELECT * FROM fakturownia_import_documents WHERE external_id = '486639934' — rekord istnieje. 4. Jesli klient niezmapowany: panel mapowan w /finances/main_view/ pokazuje faktura 486639934 w kolejce unmapped. 5. Po zmapowaniu klienta i pozycji: ponowny import tworzy rekord w finance_operations z ujemna kwota (koszt). Napisz "approved" lub opisz problem do naprawy.DO NOT CHANGE
- FakturowniaImportRepository.php (schemat tabel zablokowany — zmiany tylko jesli niezbedne do poprawki bugu).
- Logika mapowania klientow po NIP (05-02) — nie modyfikuj buildClientKey / normalizeTaxNo.
- Logika filtra proforma (05-03) — isProformaDocument zostaje bez zmian.
- Publiczny kontrakt FakturowniaInvoiceImporter::import() (zwracany shape summary).
SCOPE LIMITS
- Nie dodajemy nowych endpointow API Fakturowni (tylko naprawiamy uzycie istniejacych).
- Nie zmieniamy UI panelu mapowan w /finances/main_view/.
- Nie wprowadzamy nowego cachingu ani retry-logic — tylko poprawa logiki pobierania/paginacji.
- Nie refaktoryzujemy importera pod testy E2E z prawdziwym API.
<success_criteria>
- Faktura 486639934 pojawia sie w wynikach importu (imported lub unmapped, zaleznie od mapowan).
- Nowy test regresyjny przechodzi i zostaje w suite.
- Zadne istniejace testy nie regresuja.
- Brak nowych warningow php -l. </success_criteria>