From 164b9b6a465e5d18df70316b305086668411011f Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Fri, 3 Apr 2026 14:53:58 +0200 Subject: [PATCH] update --- .paul/ROADMAP.md | 9 +- .paul/STATE.md | 22 +-- .../05-01-SUMMARY.md | 121 ++++++++++++++ .../05-02-PLAN.md | 158 ++++++++++++++++++ .../05-02-SUMMARY.md | 91 ++++++++++ .serena/project.yml | 30 +++- .vscode/ftp-kr.sync.cache.json | 66 +++++++- .../Finances/FakturowniaInvoiceImporter.php | 32 +++- .../finances/fakturownia-import-panel.php | 4 + 9 files changed, 510 insertions(+), 23 deletions(-) create mode 100644 .paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md create mode 100644 .paul/phases/05-finances-fakturownia-import/05-02-PLAN.md create mode 100644 .paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index 0030758..4117fe7 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -6,7 +6,7 @@ Stabilizacja i poprawa jakosci kodu crmPRO oraz rozwoj finansow o automatyczny i ## Current Milestone **v0.1 Stabilizacja i jakosc kodu + import finansow** (v0.1.0) Status: In progress -Phases: 1 of 5 complete +Phases: 2 of 5 complete ## Phases @@ -16,7 +16,7 @@ Phases: 1 of 5 complete | 2 | Naprawa bledow krytycznych | TBD | Next | - | | 3 | Naprawa bledow glownych | TBD | Not started | - | | 4 | Poprawa pokrycia testami | TBD | Not started | - | -| 5 | Import finansow z Fakturowni | 0/1 | Planning | - | +| 5 | Import finansow z Fakturowni | 2/2 | Complete | 2026-04-03 | ## Phase Details @@ -89,8 +89,9 @@ Phases: 1 of 5 complete - Panel mapowania brakow w `/finances/main_view/` **Plans:** -- [ ] 05-01: Integracja Fakturownia i automatyczny import do finansow +- [x] 05-01: Integracja Fakturownia i automatyczny import do finansow +- [x] 05-02: Mapowanie klienta po NIP + kompatybilnosc mapowan historycznych --- *Roadmap created: 2026-03-15* -*Last updated: 2026-04-02 - Phase 5 planned* +*Last updated: 2026-04-03 - Phase 5 completed (05-01, 05-02)* diff --git a/.paul/STATE.md b/.paul/STATE.md index bbd1048..83bae9a 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -10,29 +10,29 @@ See: .paul/PROJECT.md (updated 2026-03-15) ## Current Position Milestone: v0.1 Stabilizacja i jakosc kodu -Phase: 5 of 5 (Import finansow z Fakturowni) - Apply complete -Plan: 05-01 executed, awaiting unify -Status: APPLY complete, ready for UNIFY -Last activity: 2026-04-02 11:03 - Executed .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md +Phase: 5 of 5 (Import finansow z Fakturowni) - Complete +Plan: 05-02 unified +Status: Loop complete, ready for next PLAN +Last activity: 2026-04-03 14:48 - Unified .paul/phases/05-finances-fakturownia-import/05-02-PLAN.md Progress: -- Milestone: [#######---] 35% -- Phase 5: [########--] 80% +- Milestone: [########--] 40% +- Phase 5: [##########] 100% ## Loop Position Current loop state: ``` PLAN --> APPLY --> UNIFY - ✓ ✓ ○ [Apply completed, ready for reconciliation] + ✓ ✓ ✓ [Loop complete - ready for next PLAN] ``` ## Session Continuity -Last session: 2026-04-02 11:03 -Stopped at: Apply finished for plan 05-01 -Next action: Run $paul-unify .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md -Resume file: .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md +Last session: 2026-04-03 14:48 +Stopped at: Plan 05-02 closed +Next action: Plan next work item (recommended: $paul-plan for Phase 2) +Resume file: .paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md --- *STATE.md - Updated after every significant action* diff --git a/.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md b/.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md new file mode 100644 index 0000000..6c8edb1 --- /dev/null +++ b/.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md @@ -0,0 +1,121 @@ +--- +phase: 05-finances-fakturownia-import +plan: 01 +subsystem: finances +tags: [php, medoo, cron, fakturownia, import] +requires: + - phase: 01-sonarqube-baseline + provides: baseline quality and project instrumentation +provides: + - fakturownia api integration for income and cost invoices + - persistent client and item mappings with unmapped queue + - cron step for cyclical import with idempotency +affects: [finances, cron, fakturownia-import] +tech-stack: + added: [] + patterns: [repository for import state, importer service, controller actions with csrf] +key-files: + created: + - autoload/Domain/Finances/FakturowniaApiClient.php + - autoload/Domain/Finances/FakturowniaImportRepository.php + - autoload/Domain/Finances/FakturowniaInvoiceImporter.php + - templates/finances/fakturownia-import-panel.php + modified: + - autoload/Controllers/FinancesController.php + - autoload/Domain/Finances/FinanceRepository.php + - autoload/class.Cron.php + - cron.php + - templates/finances/main-view.php + - .env.example +key-decisions: + - "Client mapping key supports id/tax/name with deterministic fallback order." + - "Invoice import is atomic per document (transaction per document)." +patterns-established: + - "Queue-first approach for missing mappings instead of creating partial operations." + - "Idempotency stored by external document key (type:id)." +duration: ~1d +started: 2026-04-02T09:00:00+02:00 +completed: 2026-04-03T14:24:00+02:00 +--- + +# Phase 5 Plan 01: Fakturownia import summary + +Automatyczny import faktur przychodowych i kosztowych z Fakturowni zostal wdrozony razem z panelami mapowania klientow i pozycji. + +## Performance + +| Metric | Value | +|--------|-------| +| Duration | ~1 day | +| Started | 2026-04-02T09:00:00+02:00 | +| Completed | 2026-04-03T14:24:00+02:00 | +| Tasks | 3 completed | +| Files modified | 10 | + +## Acceptance Criteria Results + +| Criterion | Status | Notes | +|-----------|--------|-------| +| AC-1: Konfiguracja API i data startu importu | Pass | `.env` config, walidacja i pobieranie od daty startu sa zaimplementowane | +| AC-2: Import przychodow i kosztow z idempotencja | Pass | importer rozroznia income/cost, kwoty maja poprawny znak, duplikaty sa blokowane | +| AC-3: Mechanizm uczenia mapowan | Pass | brak mapowan trafia do queue, po zapisaniu mapowan kolejne importy dzialaja automatycznie | +| AC-4: Obsluga mapowan w zakladce finansow | Pass | panel `/finances/main_view/` pokazuje braki i zapisuje mapowania z CSRF | + +## Accomplishments + +- Dodano kompletna warstwe domenowa integracji z Fakturownia (API client, importer, repository stanu/mapowan). +- Podpieto import do crona i zapis podsumowania ostatniego importu. +- Dodano UI mapowan klientow i pozycji w module finansow. + +## Task Commits + +Repozytorium zawiera zbiorcze commity `update`, bez atomowych commitow task-per-task dla tego planu. + +## Files Created/Modified + +| File | Change | Purpose | +|------|--------|---------| +| `autoload/Domain/Finances/FakturowniaApiClient.php` | Created | Komunikacja z API Fakturowni | +| `autoload/Domain/Finances/FakturowniaImportRepository.php` | Created | Tabele i operacje mapowan/stanu importu | +| `autoload/Domain/Finances/FakturowniaInvoiceImporter.php` | Created | Logika importu dokumentow | +| `autoload/class.Cron.php` | Modified | Nowy krok importu finansow | +| `cron.php` | Modified | Uruchamianie importu w harmonogramie | +| `autoload/Controllers/FinancesController.php` | Modified | Dane panelu i akcje zapisu mapowan | +| `templates/finances/main-view.php` | Modified | Osadzenie panelu importu | +| `templates/finances/fakturownia-import-panel.php` | Created | Widok brakow mapowania i formularze zapisu | +| `autoload/Domain/Finances/FinanceRepository.php` | Modified | Listy klientow/kategorii do mapowania | +| `.env.example` | Modified | Konfiguracja integracji Fakturownia | + +## Decisions Made + +| Decision | Rationale | Impact | +|----------|-----------|--------| +| Zapis idempotencji po `document_type:id` | unikniecie duplikatow przy cyklicznym cronie | bezpieczne wielokrotne uruchomienia | +| Braki mapowan trafiaja do queue | brak ryzyka blednych przypisan | wymusza kontrolowana decyzje uzytkownika | +| Mapowanie klienta oparte o klucz z fallbackiem | rozne payloady API | baza pod dalsze usprawnienia mapowania po NIP | + +## Deviations from Plan + +Brak istotnych odchylen od zakresu. W trakcie UAT wykryto potrzebe doprecyzowania mapowania klienta po NIP (zaplanowane jako kolejny plan 05-02). + +## Issues Encountered + +| Issue | Resolution | +|-------|------------| +| Powtarzalne mapowanie tego samego kontrahenta dla czesci faktur kosztowych | Dodane jako nowy plan 05-02 (priorytet: NIP-first + normalizacja) | + +## Next Phase Readiness + +**Ready:** +- Integracja i UI sa gotowe do iteracji nad jakoscia mapowania klienta. +- Struktura tabel i kolejek pozwala rozszerzyc mapowanie bez refaktoryzacji crona. + +**Concerns:** +- Dla czesci dokumentow klucz klienta moze byc oparty o `id:` zamiast NIP. + +**Blockers:** +- None + +--- +*Phase: 05-finances-fakturownia-import, Plan: 01* +*Completed: 2026-04-03* diff --git a/.paul/phases/05-finances-fakturownia-import/05-02-PLAN.md b/.paul/phases/05-finances-fakturownia-import/05-02-PLAN.md new file mode 100644 index 0000000..64c1f45 --- /dev/null +++ b/.paul/phases/05-finances-fakturownia-import/05-02-PLAN.md @@ -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 +--- + + +## 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 + + + +## 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 + + + + +## 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 +``` + + + + + + + Task 1: Zmienic algorytm klucza klienta na NIP-first z normalizacja + autoload/Domain/Finances/FakturowniaInvoiceImporter.php + + 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. + + + Odczyt kodu potwierdza, ze `buildClientKey()` sprawdza najpierw NIP, a NIP jest normalizowany do stalego formatu. + + AC-1 i AC-2 satisfied + + + + Task 2: Dodac fallback odczytu mapowania po historycznym kluczu id + autoload/Domain/Finances/FakturowniaInvoiceImporter.php + + 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. + + + Sciezka warunkowa importera zawiera probe fallbacku `id:` przed `queueUnmapped('client', ...)`. + + AC-3 satisfied + + + + Task 3: Pokazac NIP w panelu brakujacych mapowan klientow + templates/finances/fakturownia-import-panel.php + + 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. + + + Widok panelu renderuje dodatkowa linie z NIP (gdy payload ma `tax_no`) i pozostaje bezpieczny pod XSS. + + AC-4 satisfied + + + + + + +## 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 + + + + +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 + + + +- 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 + + + +After completion, create `.paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md` + diff --git a/.paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md b/.paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md new file mode 100644 index 0000000..17aa9ac --- /dev/null +++ b/.paul/phases/05-finances-fakturownia-import/05-02-SUMMARY.md @@ -0,0 +1,91 @@ +--- +phase: 05-finances-fakturownia-import +plan: 02 +subsystem: finances +tags: [php, fakturownia, mapping, nip] +requires: + - phase: 05-finances-fakturownia-import + provides: import engine and mapping UI from plan 05-01 +provides: + - nip-first client key strategy + - backward compatibility for legacy id-based mappings + - nip visibility in pending client mappings panel +affects: [finances, fakturownia-import] +tech-stack: + added: [] + patterns: [key normalization, compatibility fallback] +key-files: + created: [] + modified: + - autoload/Domain/Finances/FakturowniaInvoiceImporter.php + - templates/finances/fakturownia-import-panel.php +key-decisions: + - "Client key now prefers normalized tax number over client_id." + - "Importer reads legacy id mapping before queuing unmapped client." +patterns-established: + - "NIP normalization by stripping non-digits." +duration: ~20min +started: 2026-04-03T14:24:00+02:00 +completed: 2026-04-03T14:48:00+02:00 +--- + +# Phase 5 Plan 02: NIP-first mapping summary + +Mapowanie klienta w imporcie Fakturownia zostalo domkniete: klucz klienta ma priorytet NIP, a historyczne mapowania po `id:` pozostaja zgodne wstecznie. + +## Performance + +| Metric | Value | +|--------|-------| +| Duration | ~20 min | +| Started | 2026-04-03T14:24:00+02:00 | +| Completed | 2026-04-03T14:48:00+02:00 | +| Tasks | 3 completed | +| Files modified | 2 | + +## Acceptance Criteria Results + +| Criterion | Status | Notes | +|-----------|--------|-------| +| AC-1: Priorytet mapowania klienta po NIP | Pass | `buildClientKey()` preferuje `tax:` przed `id:` | +| AC-2: Stabilna normalizacja NIP | Pass | NIP normalizowany przez usuwanie znakow nienumerycznych | +| AC-3: Kompatybilnosc wsteczna mapowan | Pass | fallback odczytu mapowania po `id:` przed queue unmapped | +| AC-4: NIP widoczny w panelu brakow mapowania | Pass | UI pokazuje NIP z payloadu przy kliencie | + +## Accomplishments + +- Zmieniono strategie klucza klienta na NIP-first (`tax -> id -> name`). +- Dodano fallback na historyczne klucze `id:{client_id}`. +- Rozszerzono panel brakow mapowania o widok NIP. + +## Files Created/Modified + +| File | Change | Purpose | +|------|--------|---------| +| `autoload/Domain/Finances/FakturowniaInvoiceImporter.php` | Modified | NIP-first key, normalizacja NIP i fallback legacy `id:` | +| `templates/finances/fakturownia-import-panel.php` | Modified | Wyswietlanie NIP dla brakujacych mapowan klientow | + +## Verification Results + +- `php -l autoload/Domain/Finances/FakturowniaInvoiceImporter.php` -> no syntax errors +- `php -l templates/finances/fakturownia-import-panel.php` -> no syntax errors + +## Deviations from Plan + +Brak odchylen od planu. + +## Next Phase Readiness + +**Ready:** +- Import ma docelowe mapowanie klienta po NIP. +- Wsteczna zgodnosc z mapowaniami `id:` zostala zachowana. + +**Concerns:** +- Istniejace wpisy queue z kluczem `id:` moga jeszcze byc widoczne do czasu kolejnego poprawnego przebiegu importu. + +**Blockers:** +- None + +--- +*Phase: 05-finances-fakturownia-import, Plan: 02* +*Completed: 2026-04-03* diff --git a/.serena/project.yml b/.serena/project.yml index ed0db3e..8ba41e7 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -53,7 +53,9 @@ ignored_paths: [] # Added on 2025-04-18 read_only: false -# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. +# list of tool names to exclude. +# This extends the existing exclusions (e.g. from the global configuration) +# # Below is the complete list of tools for convenience. # To make sure you have the latest list of tools, and to view their descriptions, # execute `uv run scripts/print_tool_overview.py`. @@ -94,7 +96,8 @@ read_only: false # * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. excluded_tools: [] -# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default) +# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). +# This extends the existing inclusions (e.g. from the global configuration). included_optional_tools: [] # fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. @@ -125,3 +128,26 @@ initial_prompt: "" # This overrides the corresponding setting in the global configuration; see the documentation there. # If null or missing, use the setting from the global configuration. symbol_info_budget: + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] + +# list of regex patterns for memories to completely ignore. +# Matching memories will not appear in list_memories or activate_project output +# and cannot be accessed via read_memory or write_memory. +# To access ignored memory files, use the read_file tool on the raw file path. +# Extends the list from the global configuration, merging the two lists. +# Example: ["_archive/.*", "_episodes/.*"] +ignored_memory_patterns: [] + +# advanced configuration option allowing to configure language server-specific options. +# Maps the language key to the options. +# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available. +# No documentation on options means no options are available. +ls_specific_settings: {} diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index d5fbc20..2af7a87 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -313,7 +313,7 @@ }, "cron.php": { "type": "-", - "size": 2093, + "size": 2499, "lmtime": 0, "modified": true }, @@ -333,11 +333,23 @@ } } }, + ".env": { + "type": "-", + "size": 185, + "lmtime": 0, + "modified": false + }, + ".env.example": { + "type": "-", + "size": 187, + "lmtime": 0, + "modified": false + }, ".gitignore": { "type": "-", - "size": 14, + "size": 19, "lmtime": 1773532569285, - "modified": false + "modified": true }, ".htaccess": { "type": "-", @@ -821,24 +833,72 @@ "modified": false } }, + "__tmp_cleanup_imported_ops.php": { + "type": "-", + "size": 1510, + "lmtime": 0, + "modified": false + }, + "__tmp_cleanup_netto_reset.php": { + "type": "-", + "size": 1510, + "lmtime": 0, + "modified": false + }, + "__tmp_count.php": { + "type": "-", + "size": 1569, + "lmtime": 0, + "modified": false + }, "_tmp_db_check.php": { "type": "-", "size": 696, "lmtime": 0, "modified": false }, + "__tmp_db_ping.php": { + "type": "-", + "size": 680, + "lmtime": 0, + "modified": false + }, "tmp_debug_mail_import.php": { "type": "-", "size": 1238, "lmtime": 0, "modified": false }, + "__tmp_diag.php": { + "type": "-", + "size": 2037, + "lmtime": 0, + "modified": false + }, + "__tmp_ft_filter_test.php": { + "type": "-", + "size": 1582, + "lmtime": 0, + "modified": false + }, "_tmp_mail_name_check.php": { "type": "-", "size": 62, "lmtime": 0, "modified": false }, + "__tmp_preview_cleanup.php": { + "type": "-", + "size": 1400, + "lmtime": 0, + "modified": false + }, + "__tmp_queue.php": { + "type": "-", + "size": 733, + "lmtime": 0, + "modified": false + }, "TODO.md": { "type": "-", "size": 0, diff --git a/autoload/Domain/Finances/FakturowniaInvoiceImporter.php b/autoload/Domain/Finances/FakturowniaInvoiceImporter.php index a49cb18..10ea20f 100644 --- a/autoload/Domain/Finances/FakturowniaInvoiceImporter.php +++ b/autoload/Domain/Finances/FakturowniaInvoiceImporter.php @@ -128,6 +128,12 @@ class FakturowniaInvoiceImporter return 'skipped'; $clientMap = $this -> repo -> getClientMapping( $document['client_key'] ); + if ( !$clientMap && $document['legacy_client_key'] !== '' && $document['legacy_client_key'] !== $document['client_key'] ) + { + // Backward compatibility for historical mappings saved as id:{client_id}. + $clientMap = $this -> repo -> getClientMapping( $document['legacy_client_key'] ); + } + if ( !$clientMap ) { $this -> repo -> queueUnmapped( 'client', $document['client_key'], $document['client_name'], [ @@ -331,6 +337,7 @@ class FakturowniaInvoiceImporter 'client_name' => $clientName, 'client_tax_no' => $clientTaxNo, 'client_key' => $this -> buildClientKey( $rawDocument, $clientName, $clientTaxNo ), + 'legacy_client_key' => $this -> buildLegacyClientKey( $rawDocument ), 'positions' => $positions, 'total_amount' => $this -> normalizeAmount( $totalAmount, $documentType ) ]; @@ -379,14 +386,33 @@ class FakturowniaInvoiceImporter } private function buildClientKey( $rawDocument, $clientName, $clientTaxNo ) + { + $normalizedTaxNo = $this -> normalizeTaxNo( $clientTaxNo ); + if ( $normalizedTaxNo !== '' ) + return 'tax:' . $normalizedTaxNo; + + $legacyClientKey = $this -> buildLegacyClientKey( $rawDocument ); + if ( $legacyClientKey !== '' ) + return $legacyClientKey; + + return 'name:' . $this -> normalizeKeyValue( $clientName ); + } + + private function buildLegacyClientKey( $rawDocument ) { if ( isset( $rawDocument['client_id'] ) && (string)$rawDocument['client_id'] !== '' ) return 'id:' . (string)$rawDocument['client_id']; - if ( $clientTaxNo !== '' ) - return 'tax:' . preg_replace( '/\s+/', '', $clientTaxNo ); + return ''; + } - return 'name:' . $this -> normalizeKeyValue( $clientName ); + private function normalizeTaxNo( $taxNo ) + { + $normalizedTaxNo = preg_replace( '/\D+/', '', (string)$taxNo ); + if ( !is_string( $normalizedTaxNo ) || $normalizedTaxNo === '' ) + return ''; + + return $normalizedTaxNo; } private function buildItemKey( $rawPosition, $name ) diff --git a/templates/finances/fakturownia-import-panel.php b/templates/finances/fakturownia-import-panel.php index 5c26a33..8ae772b 100644 --- a/templates/finances/fakturownia-import-panel.php +++ b/templates/finances/fakturownia-import-panel.php @@ -56,6 +56,10 @@ $esc = function( $value )
+ + + NIP:
+ Klucz: | wystapienia: