feat(115): wystawianie faktury z zamowienia (lokalne + delegowane Fakturownia)

Phase 115 complete (vertical slice "zamowienie z NIP -> faktura PDF"):
- Task 1: InvoiceRepository + InvoiceService (dual-flow orchestrator) +
  InvoiceIssueException + FakturowniaApiClient::createInvoice + buildPdfUrl
- Task 2: InvoiceController + OrdersController::toggleInvoiceRequested +
  OrdersRepository::setInvoiceRequested + auto-import invoice_requested z
  Allegro (invoice.required) i shopPRO (5-key flexible parser) + show.php
  (toggle w zakladce Platnosci + warunkowy przycisk Wystaw fakture)
- Task 3: Lista wystawionych /settings/accounting/invoices/issued z filtrami
  + invoice_preview + invoice_pdf Dompdf template + hub link
- Task 3b (dodany): NIP lookup przez MF Biala Lista (publiczne API, bez
  rejestracji) — MfWhitelistApiClient w src/Core/Http/ + /api/nip/lookup +
  przycisk "Pobierz z GUS" w formularzu

Auto-fixes podczas smoke testu (5):
- GUS endpoint Fakturowni nie istnial (HTML 404 -> "json is not valid");
  switch na MF Biala Liste
- PHP 8.5 curl_close() deprecation wycieka HTML przed JSON; usuniete z
  MfWhitelistApiClient i FakturowniaApiClient (3 miejsca)
- Fakturownia 422 payment_to_kind_days (nieistniejace pole) -> usuniete
- Generic "error" w 422 -> parser plaskuje errors: {pole: [...]} +
  error_log z 1000 znakow raw body
- Fakturownia security odrzuca seller_*/department_id jako "create new
  department"; usuniete z payloadu (Fakturownia uzywa danych konta)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 23:34:50 +02:00
parent 6129042ff6
commit 33ee1a1cf5
28 changed files with 3228 additions and 45 deletions

View File

@@ -2,6 +2,23 @@
> Lista nieformalnych zadan do zrobienia pozniej. Kazdy wpis ma wlasny tag (np. `STAT-NET`) zeby mozna go bylo zlinkowac z komentarzy w kodzie.
## INVOICE-IDEMP-115 — idempotencja podwojnego POST do Fakturowni (data: 2026-05-10)
### Kontekst
- Phase 115-01 — wystawianie faktury z zamowienia (delegacja Fakturownia).
- Flow: `InvoiceService::issueDelegated()` -> POST do Fakturowni -> on success INSERT do `invoices`.
- Edge case: faktura zostala utworzona w Fakturowni, ale odpowiedz nie dotarla (timeout, network). Operator widzi blad, klika "Wystaw fakture" ponownie -> drugi POST -> Fakturownia tworzy DRUGA fakture.
### Zadania
1. Dorzucic idempotency-key (np. UUID per attempt zachowany w sesji albo w `invoices` ze statusem `pending_external`).
2. Sprawdzic czy Fakturownia API wspiera nag/lowek `Idempotency-Key` lub deduplikacje po referencji.
3. Alternatywa: po bledzie API, przed kolejnym POST, query Fakturowni `GET /invoices.json?q=<order_reference>` zeby sprawdzic czy faktura juz istnieje.
### Status
- Odlozone — operator musi recznie zweryfikowac w panelu Fakturowni przy bledach API.
---
## STAT-NET — netto zamowien w statystykach (data: 2026-04-19)
### Kontekst