This commit is contained in:
2026-04-02 12:00:38 +02:00
parent 46dae22a71
commit e743245cee
21 changed files with 2105 additions and 196 deletions

View File

@@ -0,0 +1,223 @@
---
phase: 05-finances-fakturownia-import
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- cron.php
- autoload/class.Cron.php
- autoload/Controllers/FinancesController.php
- autoload/Domain/Finances/FinanceRepository.php
- autoload/Domain/Finances/FakturowniaApiClient.php
- autoload/Domain/Finances/FakturowniaImportRepository.php
- autoload/Domain/Finances/FakturowniaInvoiceImporter.php
- templates/finances/main-view.php
- templates/finances/fakturownia-import-panel.php
- .env.example
autonomous: true
---
<objective>
## Goal
Dodac automatyczny import faktur przychodowych i kosztowych z Fakturowni do finansow crmPRO, z mechanizmem uczenia mapowan klientow i produktow/uslug.
## Purpose
Zminimalizowac reczna prace w finansach: pierwsze faktury wymagaja mapowania, ale kolejne dokumenty z tymi samymi klientami i pozycjami maja importowac sie juz calkowicie automatycznie.
## Output
- Warstwa integracji API Fakturowni z konfiguracja przez `.env`
- Trwale mapowania klientow i produktow/uslug do struktur finansowych crmPRO
- Automatyczny import przez cron z idempotencja i data startu
- Panel w finansach do obslugi brakujacych mapowan
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Source Files
@cron.php
@autoload/class.Cron.php
@autoload/Controllers/FinancesController.php
@autoload/Domain/Finances/FinanceRepository.php
@templates/finances/main-view.php
@config.php
</context>
<acceptance_criteria>
## AC-1: Konfiguracja API i data startu importu
```gherkin
Given w pliku .env ustawiono dane dostepowe Fakturowni oraz date startu importu
When cron uruchamia proces importu
Then importer laczy sie z API Fakturowni i pobiera tylko dokumenty od skonfigurowanej daty
And brakujaca konfiguracja zwraca czytelny blad bez przerwania calego crona
```
## AC-2: Import przychodow i kosztow z idempotencja
```gherkin
Given faktura przychodowa lub kosztowa istnieje w Fakturowni
When dokument ma komplet mapowan klienta i pozycji
Then powstaje operacja finansowa w crmPRO z poprawnym znakiem kwoty (przychod > 0, koszt < 0)
And ponowne uruchomienie importu nie tworzy duplikatu tej samej faktury
```
## AC-3: Mechanizm uczenia mapowan
```gherkin
Given dokument zawiera klienta lub pozycje bez mapowania
When importer przetwarza dokument
Then dokument nie jest importowany do finansow, a brakujace mapowania trafiaja na liste do recznego przypisania
And po zapisaniu mapowania kolejne faktury z tym klientem/pozycja importuja sie automatycznie
```
## AC-4: Obsluga mapowan w zakladce finansow
```gherkin
Given uzytkownik jest na /finances/main_view/
When otwiera panel importu Fakturownia
Then widzi brakujace mapowania klientow i produktow/uslug
And moze przypisac klienta CRM i kategorie finansowa
And zapis mapowania jest chroniony tokenem CSRF
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Zbudowac warstwe integracji Fakturownia + trwawe mapowania</name>
<files>
autoload/Domain/Finances/FakturowniaApiClient.php,
autoload/Domain/Finances/FakturowniaImportRepository.php,
autoload/Domain/Finances/FinanceRepository.php,
.env.example
</files>
<action>
1. Dodac loader `.env` (bez nowych bibliotek) i zdefiniowac klucze:
- `FAKTUROWNIA_API_DOMAIN`
- `FAKTUROWNIA_API_TOKEN`
- `FAKTUROWNIA_START_DATE`
- `FAKTUROWNIA_PAGE_LIMIT` (opcjonalnie)
2. Dodac klienta API Fakturowni z obsluga paginacji i timeoutow:
- pobieranie faktur przychodowych (np. endpoint invoices)
- pobieranie faktur kosztowych (np. endpoint costs/expenses)
3. Dodac repozytorium importu z tabelami tworzonymi przez `CREATE TABLE IF NOT EXISTS`:
- tabela mapowania klientow Fakturownia -> crm_client.id
- tabela mapowania pozycji (nazwa produktu/uslugi) -> finance_categories.id
- tabela stanu importu i idempotencji (external_id + typ dokumentu)
- tabela kolejki brakujacych mapowan do panelu finansow
4. Wszystkie zapytania SQL wykonywac przez medoo/query z parametrami bindowanymi (bez sklejania SQL z danymi wejsciowymi).
5. W `FinanceRepository` dodac metody pomocnicze do pobierania kategorii i klientow dla panelu mapowan.
Unikac: trzymania tokenu API w `config.php`, mapowan w sesji i importu bez kontroli duplikatow.
</action>
<verify>
- Odczyt `.env.example` potwierdza nowe klucze integracji.
- Odczyt nowych klas potwierdza osobne odpowiedzialnosci (API, repo mapowan, state importu).
- Test manualny: dwukrotne wywolanie zapisu importu dla tego samego external_id nie tworzy duplikatu.
</verify>
<done>AC-1 i AC-2 i AC-3 satisfied: konfiguracja, idempotencja i struktury mapowan gotowe</done>
</task>
<task type="auto">
<name>Task 2: Dodac importer dokumentow i podpiac go pod cron</name>
<files>
autoload/Domain/Finances/FakturowniaInvoiceImporter.php,
autoload/class.Cron.php,
cron.php
</files>
<action>
1. Dodac serwis importera, ktory:
- pobiera dokumenty od `FAKTUROWNIA_START_DATE`,
- scala dane klienta i pozycji,
- sprawdza mapowania klienta i pozycji,
- przy komplecie mapowan zapisuje operacje finansowe,
- przy brakach wpisuje rekordy do kolejki brakow mapowan i pomija import dokumentu.
2. Dodac polityke znaku kwoty:
- przychodowe -> dodatnie `amount`
- kosztowe -> ujemne `amount`
3. Wprowadzic idempotencje na poziomie zrodlowego `external_id` + typ dokumentu.
4. Rozszerzyc `Cron` i `cron.php` o krok `import_finances_from_fakturownia()`:
- uruchamiany przy kazdym cyklu crona,
- zwraca statusy `ok|empty|error` analogicznie do obecnych zadan,
- loguje krotki komunikat o liczbie zaimportowanych i pominietych dokumentow.
Unikac: przerywania calego crona przy pojedynczym bledzie faktury.
</action>
<verify>
- Suchy przebieg importera zwraca licznik imported/skipped/unmapped.
- Uruchomienie `php cron.php` wykonuje nowy krok i nie psuje istniejacych zadan cron.
- Powtorne uruchomienie dla tych samych danych nie dubluje wpisow w `finance_operations`.
</verify>
<done>AC-1 i AC-2 i AC-3 satisfied: cron importuje faktury cyklicznie i bez duplikatow</done>
</task>
<task type="auto">
<name>Task 3: Dodac panel mapowan Fakturowni w finansach i zapis mapowan</name>
<files>
autoload/Controllers/FinancesController.php,
templates/finances/main-view.php,
templates/finances/fakturownia-import-panel.php
</files>
<action>
1. Rozszerzyc `FinancesController` o akcje:
- pobranie brakujacych mapowan do widoku finansow,
- zapis mapowania klienta,
- zapis mapowania produktu/uslugi do kategorii,
- wszystkie zapisy z walidacja i `S::csrf_verify()`.
2. W `templates/finances/main-view.php` dolaczyc panel importu (partial) pokazujacy:
- liste nieprzypisanych klientow z Fakturowni + select klienta CRM,
- liste nieprzypisanych pozycji + select kategorii finansowej,
- status ostatniego importu (czas, liczba imported/skipped/unmapped).
3. W panelu uzyc escapingu danych wyjsciowych (np. `htmlspecialchars`) i komunikatow zgodnych z UI crmPRO.
Unikac: logiki biznesowej bezposrednio w widoku.
</action>
<verify>
- Wejscie na `/finances/main_view/` pokazuje panel mapowan bez regresji istniejacych statystyk.
- Zapis mapowania bez tokenu CSRF jest odrzucany.
- Po zapisaniu mapowania i ponownym imporcie dokument znika z listy brakow i tworzy operacje automatycznie.
</verify>
<done>AC-3 i AC-4 satisfied: mapowania sa obslugiwane z UI i kolejne faktury wpadaja automatycznie</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- modules niezwiązane z finansami (tasks, projects, wiki)
- mechanizm logowania i sesji poza niezbednym CSRF check
- istniejace endpointy email importera zadan
## SCOPE LIMITS
- Ten plan obejmuje tylko import i mapowania Fakturownia -> Finanse
- Bez refaktoryzacji calego modulu finansow
- Bez zmian w zewnetrznym harmonogramie systemowym (zakladamy, ze cron systemowy juz wywoluje `cron.php`)
- Bez automatycznego tworzenia nowych klientow CRM (tylko mapowanie do istniejacych)
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `.env.example` zawiera komplet nowych zmiennych Fakturowni
- [ ] Importer obsluguje dokumenty przychodowe i kosztowe
- [ ] Idempotencja blokuje duplikaty importu
- [ ] Brakujace mapowania sa kolejkowane i widoczne w finansach
- [ ] Zapis mapowan wymaga poprawnego tokenu CSRF
- [ ] `php cron.php` wykonuje import bez zatrzymywania pozostalych krokow
- [ ] All acceptance criteria met
</verification>
<success_criteria>
- Faktury przychodowe i kosztowe importuja sie automatycznie po uzupelnieniu mapowan
- Pierwszy import nie robi blednych przypisan: nieznane rekordy trafiaja do kolejki mapowania
- Kolejne dokumenty z tym samym klientem i pozycja sa przypisywane bez interwencji recznej
- Import uruchamia sie cyklicznie przez cron i jest bezpieczny na ponowne wykonanie
</success_criteria>
<output>
After completion, create `.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md`
</output>