MfWhitelistApiClient.lookupByNip() exposes is_jdg/krs from MF Biala Lista.
InvoiceController.nipLookup propagates is_jdg in JSON response.
invoice_form.php JS conditionally targets buyer_name (JDG) or
buyer_company_name (spolka z KRS); second field keeps zamowienie pre-fill.
Fixes apparent field swap on /orders/{id}/invoice/create after GUS lookup
for JDG (sole trader) where MF returns natural person in subject.name.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.7 KiB
8.7 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | |||
|---|---|---|---|---|---|---|---|---|---|---|
| 126-invoice-gus-field-mapping | 01 | execute | 1 |
|
true | off |
Purpose
Operator wystawiający fakturę dla JDG widzi obecnie efekt zamiany pól: pole "Imię i nazwisko"
pokazuje pełną nazwę firmy z zamówienia (np. "Project-Pro Pyziak Jacek"), a "Nazwa firmy" jest
nadpisywane samym imieniem i nazwiskiem z MF (np. "JACEK PYZIAK"). Przyczyna: MF Biała Lista dla
JDG zwraca w subject.name osobę fizyczną (nie nazwę firmy), a JS bezwarunkowo wpisuje tę wartość
do "Nazwa firmy". Po fixie operator nie musi już ręcznie korygować pól po lookupie.
Output
MfWhitelistApiClient::lookupByNip()zwraca dodatkowo flagęis_jdg(true gdysubject.krsjest null/pusty).InvoiceController::nipLookuppropaguje flagę w odpowiedzi JSON.- JS w
invoice_form.phpdlais_jdg=truewpisuje MFnamedo#buyer_name, a dlais_jdg=falsedo#buyer_company_name; drugiego pola nie nadpisuje. Adres (ulica/kod/miasto/NIP) nadpisywany jak dotychczas.
Project Context
@.paul/PROJECT.md @.paul/STATE.md @.paul/codebase/architecture.md
Source Files
@src/Core/Http/MfWhitelistApiClient.php @src/Modules/Accounting/InvoiceController.php @resources/views/accounting/invoice_form.php
<acceptance_criteria>
AC-1: JDG (krs=null) — name z MF trafia w "Imię i nazwisko", "Nazwa firmy" niezmieniona
Given otwarte /orders/1090/invoice/create
And w polu "NIP nabywcy" wpisany "5170167517"
And pole "Imię i nazwisko" zawiera "Project-Pro Pyziak Jacek" (pre-fill z zamówienia)
And pole "Nazwa firmy" zawiera "Project-Pro Pyziak Jacek" (pre-fill z zamówienia)
When operator klika "Pobierz z GUS"
Then pole "Imię i nazwisko" ma wartość "JACEK PYZIAK" (z MF)
And pole "Nazwa firmy" zachowuje wartość "Project-Pro Pyziak Jacek"
And pola adres (ulica/kod/miejscowość) są nadpisane danymi z MF
AC-2: Spółka z KRS — name z MF trafia w "Nazwa firmy", "Imię i nazwisko" niezmieniona
Given otwarte /orders/{id}/invoice/create dla zamówienia ze spółką (NIP z aktywnym KRS)
And pole "Imię i nazwisko" zawiera np. "Jan Kowalski" (osoba kontaktowa z zamówienia)
When operator klika "Pobierz z GUS"
Then pole "Nazwa firmy" otrzymuje legal name z MF (np. "ACME Sp. z o.o.")
And pole "Imię i nazwisko" zachowuje wartość "Jan Kowalski"
And pola adresowe są nadpisane danymi z MF
AC-3: Response JSON z /api/nip/lookup zawiera flagę is_jdg
Given autoryzowane GET /api/nip/lookup?nip=5170167517
When request zwraca 200 OK
Then JSON.data.is_jdg === true
And JSON.data.company_name === "JACEK PYZIAK"
And dla NIP-u spółki z aktywnym KRS JSON.data.is_jdg === false
</acceptance_criteria>
Task 1: MfWhitelistApiClient — eksponowanie flagi is_jdg src/Core/Http/MfWhitelistApiClient.php W `lookupByNip()` po wczytaniu `$subject`: - Wyciągnąć `$krs = trim((string) ($subject['krs'] ?? ''));` - W zwracanym array dodać klucz `'is_jdg' => $krs === '',` (oraz opcjonalnie `'krs' => $krs` dla debugowalności). - Zaktualizować docblock `@return array{...}` o `is_jdg: bool, krs: string`. Unikać: zmiany pozostałych pól / kontraktu (`name`, `tax_no`, address, regon, status_vat). Manualnie: w PHP REPL `(new MfWhitelistApiClient(new SslCertificateResolver()))->lookupByNip('5170167517')` zwraca `is_jdg=true`; dla NIP-u spółki z aktywnym KRS zwraca `is_jdg=false`. AC-3 satisfied (kontrakt klienta). Task 2: InvoiceController::nipLookup — propagacja is_jdg do JSON src/Modules/Accounting/InvoiceController.php W `nipLookup()` w bloku `data` rozszerzyć payload o `'is_jdg' => (bool) ($data['is_jdg'] ?? false),`. Zachować pozostałe klucze (`company_name`, `tax_number`, `street`, `postal_code`, `city`, `country`, `regon`, `status_vat`). Unikać: zmiany walidacji NIP, kontraktu błędów (422/502). `curl -s -H "X-Requested-With: XMLHttpRequest" "https://orderpro.projectpro.pl/api/nip/lookup?nip=5170167517"` zwraca JSON z `data.is_jdg=true`. AC-3 satisfied (kontrakt endpointu). Task 3: invoice_form.php — JS warunkowe mapowanie name w zależności od is_jdg resources/views/accounting/invoice_form.php W bloku `<script>` (handler `btn-gus-lookup`, ok. linii 250–270) zmienić obecne bezwarunkowe `buyer_company_name: d.company_name`: 1. Wydzielić mapowanie adresowe (street/postal/city) jako stałe. 2. Po pobraniu `d`: - `var nameTargetId = d.is_jdg ? 'buyer_name' : 'buyer_company_name';` - Wpisać `d.company_name` do `document.getElementById(nameTargetId)` (jeśli `d.company_name` niepuste). - Pole `buyer_tax_number` nadpisywać jak dotychczas (`d.tax_number`). - Pól `buyer_name`/`buyer_company_name` poza wybranym targetem NIE dotykać. 3. Pola adresowe (street/postal_code/city) nadpisywać niezmieniście.Unikać:
- tworzenia nowych zależności JS / bibliotek,
- czyszczenia drugiego pola (operator może mieć tam istotne pre-fill / własne dopiski),
- zmiany etykiet / kolejności pól HTML.
Manualnie w przeglądarce: `/orders/1090/invoice/create` → "Pobierz z GUS" → "Imię i nazwisko" = "JACEK PYZIAK",
"Nazwa firmy" pozostaje "Project-Pro Pyziak Jacek". Drugi smoke test na NIP spółki z aktywnym KRS:
"Nazwa firmy" otrzymuje legal name, "Imię i nazwisko" niezmienione.
AC-1 i AC-2 satisfied (UI mapuje pola zgodnie z heurystyką KRS).
DO NOT CHANGE
- Kontrakt
MfWhitelistApiClientpoza dodaniemis_jdg/krs(pozostałe pola muszą zostać dlaInvoiceService::extractBuyerTaxNumberi ewentualnych innych konsumentów w przyszłości). - Server-side merge w
InvoiceService::resolveBuyerSnapshot()— to operator decyduje finalnie co wpisuje w polach przed submitem; backend bierze wartości z requestu. - Server walidacja
nipLookup(regex 10 cyfr, kody błędów 422/502). - Etykiety i kolejność pól w HTML formularza.
- Pre-fill logiki w
invoice_form.php(linie 13–18).
SCOPE LIMITS
- Bez zmian w
ShopproOrderMapper/Allegromapperach — to nie jest fix importu adresów (order_addresses.namema zostać tak jak jest, bo trzyma legalne dane firmy JDG). - Bez zmian w
InvoiceService::issue()/ snapshot pattern. - Bez automatycznego splitu
name/company_namepo stronie backendu — fix jest tylko o mapowanie UI po GUS. - Bez nowych eventów automatyzacji.
<success_criteria>
- AC-1, AC-2, AC-3 spełnione manualnym smoke testem.
- Brak regresji w istniejących lookupach NIP (dotychczasowy klucz
company_namezachowany). - Zero zmian w backendzie poza dodaniem 1 pola w JSON response. </success_criteria>