Files
orderPRO/.paul/phases/125-invoice-requested-import-fix/125-01-SUMMARY.md
Jacek Pyziak 2ab461aaae feat(125): invoice_requested import fix + drop legacy is_invoice column
- shopPRO: ShopproOrderMapper jako jedyne zrodlo heurystyki detekcji faktury;
  mapOrderAggregate() zwraca top-level invoice_detected (transient).
- ShopproOrdersSyncService: usunieta wlasna shouldRequestInvoice(); propagacja
  aggregate['invoice_detected'] do setInvoiceRequested() tylko przy created=true.
- Allegro: nowa shouldRequestInvoice(payload) z 4 wzorcami (invoice.required,
  naturalPerson=false, address.taxId, companyName/address.company.name).
  Wczesniej tylko invoice.required -> analogiczna luka jak shopPRO.
- Migracja 20260513_000113: idempotentny backfill (UPDATE invoice_requested=1
  WHERE is_invoice=1 AND invoice_requested=0) + DROP COLUMN orders.is_invoice.
  Guard przez information_schema.COLUMNS + PREPARE/EXECUTE z ALTER TABLE COMMENT
  no-op fallbackiem (portable MySQL/MariaDB).
- Cleanup is_invoice z OrderImportRepository (INSERT cols/values/params,
  docstring Phase 112) i OrdersRepository (paginate SELECT, transformOrderRow
  hydrate). AllegroOrderImportService mapping w mapCheckoutFormPayload tez
  usuniety (wymuszone konsekwencja DROP COLUMN).
- Bugfix #1089: zamowienie shopPRO z firm_nip (bez wants_invoice/invoice.required)
  ustawia teraz invoice_requested=1 -> UI w zakladce Platnosci zaznacza checkbox,
  przycisk "Wystaw fakture" widoczny.

Pending operator: php bin/migrate.php (XAMPP MySQL online) -> backfill 7 zamowien.
Smoke test: re-import shopPRO + nowe Allegro z NIP.
2026-05-12 22:11:49 +02:00

11 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, duration, started, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established duration started completed
125-invoice-requested-import-fix 01 orders-import
shoppro
allegro
invoices
import
migration
fakturownia
phase provides
115-invoice-from-order orders.invoice_requested column + setInvoiceRequested API + UI toggle
phase provides
113-fakturownia-integration-foundation invoice_requested schema baseline
Bugfix shopPRO/Allegro
invoice_requested auto-set ujednolicony z heurystyka mappera
DROP COLUMN orders.is_invoice (legacy z Phase 115) + backfill 7 zamowien
Wspolny kontrakt detekcji
ShopproOrderMapper.invoice_detected (aggregate top-level) + AllegroOrderImportService::shouldRequestInvoice()
future invoice automation
invoice.created event
fakturownia idempotency
added patterns
Mapper jako jedyne zrodlo heurystyki detekcji (sync service propaguje, nie duplikuje)
Migracje DROP COLUMN idempotentne przez information_schema.COLUMNS guard + prepared statement
created modified
database/migrations/20260513_000113_drop_orders_is_invoice_and_backfill_invoice_requested.sql
src/Modules/Settings/ShopproOrderMapper.php
src/Modules/Settings/ShopproOrdersSyncService.php
src/Modules/Settings/AllegroOrderImportService.php
src/Modules/Orders/OrderImportRepository.php
src/Modules/Orders/OrdersRepository.php
.paul/codebase/db_schema.md
.paul/codebase/architecture.md
.paul/codebase/tech_changelog.md
Mapper jako jedyne zrodlo heurystyki shopPRO — sync service propaguje aggregate['invoice_detected'] zamiast wlasnej listy kluczy
Allegro shouldRequestInvoice rozszerzony o invoice.naturalPerson=false / invoice.address.taxId / invoice.companyName
DROP COLUMN orders.is_invoice w tej samej migracji co backfill (eliminacja dryftu architekturalnego, nie tylko fixu objawowego)
Migracja idempotentna przez information_schema guard zamiast DROP COLUMN IF EXISTS (portable MySQL/MariaDB)
Top-level klucz 'invoice_detected' w mapOrderAggregate() — pattern dla transient flag detection (nie pisanej do DB ale konsumowanej przez sync service)
Idempotentny DROP COLUMN: SET @col_exists := (SELECT COUNT(*) FROM information_schema.COLUMNS...) + PREPARE/EXECUTE z fallbackiem ALTER TABLE COMMENT no-op
~30min 2026-05-13T00:45:00Z 2026-05-13T01:15:00Z

Phase 125 Plan 01: invoice_requested Import Fix Summary

shopPRO order z firm_nip (bez explicit invoice.required flagi) ustawia teraz invoice_requested=1 przy imporcie; Allegro rozszerzony o detekcje NIP/naturalPerson/companyName; legacy orders.is_invoice usunieta z DB i kodu (eliminacja dryftu architekturalnego z Phase 115).

Performance

Metric Value
Duration ~30 min
Started 2026-05-13T00:45:00Z
Completed 2026-05-13T01:15:00Z
Tasks 4/4 completed
Files modified 8 (5 PHP + 1 SQL + 3 docs)

Acceptance Criteria Results

Criterion Status Notes
AC-1: Import shopPRO z firm_nip ustawia invoice_requested Pass (kod) / Pending UAT Kod: ShopproOrdersSyncService::importOne propaguje aggregate['invoice_detected']; mapper heurystyka obejmuje firm_name/firm_nip. UAT: smoke test po migracji.
AC-2: Import Allegro z NIP ustawia invoice_requested Pass (kod) / Pending UAT AllegroOrderImportService::shouldRequestInvoice sprawdza required/naturalPerson=false/taxId/companyName. UAT: brak aktywnego zamowienia Allegro z samym NIP do potwierdzenia w tej sesji.
AC-3: Re-import nie nadpisuje manualnego toggla Pass (kod) Guard wasCreated=true zachowany w obu importerach (kontrakt Phase 115/112).
AC-4: Backfill istniejących zamówień Pass (migracja gotowa) / Pending operator Migracja idempotentna; 7 zamowien czeka na php bin/migrate.php (operator + XAMPP MySQL online).
AC-5: Kolumna is_invoice nie istnieje w runtime Pass (kod, czeka migracji) Grep is_invoice w src/: tylko 1 trafienie (ShopproOrderMapper:388 — klucz payloadu, nie kolumna DB). Aplikacja nie referencuje juz kolumny orders.is_invoice — gotowa na DROP COLUMN.

Accomplishments

  • Bugfix #1089: shopPRO order z firm_nip (klient firmowy bez wants_invoice/invoice_required/invoice.required flag) ustawia teraz invoice_requested=1 przy pierwszym imporcie. UI w zakladce Platnosci pokazuje zaznaczony checkbox, przycisk "Wystaw fakture" jest dostepny.
  • Fix architekturalny: dwie kolumny dla tej samej semantyki (is_invoice + invoice_requested) i dwie sciezki detekcji (mapper + sync service) ujednolicone do jednego zrodla prawdy. Mapper jest jedyna heurystyka, sync service propaguje wynik.
  • Allegro symmetric fix: detekcja faktury rozszerzona o invoice.naturalPerson=false, invoice.address.taxId, invoice.companyName/invoice.address.company.name (wczesniej tylko invoice.required).
  • Idempotentna migracja: pattern information_schema.COLUMNS + PREPARE/EXECUTE z fallbackiem ALTER TABLE COMMENT no-op — portable na czysty MySQL (nie wymaga DROP COLUMN IF EXISTS MariaDB-only).

Task Commits

Atomic commits zaplanowane na transition (delegation: off, inline execution; brak commitow w trakcie APPLY). Wszystkie zmiany w roboczym tree, gotowe do feat(125): invoice_requested import fix commit.

Task Status Description
Task 1: Mapper exposes detection, importers propagate Done ShopproOrderMapper.invoice_detected aggregate key + propagacja w sync service + Allegro shouldRequestInvoice
Task 2: Migration backfill + DROP COLUMN Done 20260513_000113 idempotent SQL
Task 3: Remove is_invoice from PHP Done OrderImportRepository INSERT + OrdersRepository SELECT/hydrate
Task 4: Update docs Done db_schema.md note + architecture.md sekcja invoice_requested + tech_changelog.md wpis

Files Created/Modified

File Change Purpose
src/Modules/Settings/ShopproOrderMapper.php Modified Usuniety klucz is_invoice z order; dodany top-level invoice_detected w mapOrderAggregate()
src/Modules/Settings/ShopproOrdersSyncService.php Modified shouldRequestInvoice() usunieta; propagacja !empty($aggregate['invoice_detected']) w importOne()
src/Modules/Settings/AllegroOrderImportService.php Modified shouldRequestInvoice($payload) (nowa) z 4 wzorcami heurystyki; mapping is_invoice w mapCheckoutFormPayload() usuniety
src/Modules/Orders/OrderImportRepository.php Modified Usuniety is_invoice z INSERT (kolumny + values + orderParams); docstring updateOrderDelta() (Phase 112) zaktualizowany
src/Modules/Orders/OrdersRepository.php Modified Usuniety o.is_invoice z SELECT (paginate query); usuniety is_invoice klucz z transformOrderRow() hydrate
database/migrations/20260513_000113_drop_orders_is_invoice_and_backfill_invoice_requested.sql Created Idempotentny backfill + DROP COLUMN przez information_schema guard
.paul/codebase/db_schema.md Modified Updated date + note pod tabela orders o usunieciu is_invoice
.paul/codebase/architecture.md Modified Sekcja "Auto-import flagi invoice_requested" rozszerzona o Phase 125 zmiany (shopPRO mapper-driven + Allegro heurystyka NIP)
.paul/codebase/tech_changelog.md Modified Prepend wpis Phase 125-01 z Co/Dlaczego/BREAKING

Decisions Made

Decision Rationale Impact
Mapper jako jedyne zrodlo heurystyki (top-level invoice_detected w aggregate) Eliminuje dryft sync service vs. mapper. Sync service propaguje, nie duplikuje listy kluczy Pattern dla przyszlych detection-flag (gdy mapper juz robi heurystyka, sync service czyta wynik)
DROP COLUMN is_invoice razem z fixem detekcji Korzen buga to dwie kolumny dla tej samej semantyki. Naprawa objawu (UI sync) bez usuwania struktury zostawia dryftowy potential dla kolejnych fix'ow Cleaner architecture, +1 BREAKING (legacy column gone)
Migracja idempotentna przez information_schema.COLUMNS guard DROP COLUMN IF EXISTS to MariaDB only; portable MySQL pattern + idempotencja dla re-runow Pattern dla przyszlych migracji DROP COLUMN
Allegro shouldRequestInvoice z 4 wzorcami (required / naturalPerson / taxId / companyName) Allegro miala analogiczna luke: klient firmowy z NIP ale bez required=true (np. checkout-form gdzie NIP zapisany w invoice.address ale invoice.required niewymaganie zaznaczony) Symmetric fix shopPRO + Allegro w jednej fazie zamiast osobnego ticketu
AllegroOrderImportService: usuniecie is_invoice z mapCheckoutFormPayload() poza scope Task 1 Bez tego INSERT by sie wywalil po migracji (kolumna znika) — wymuszone przez DROP COLUMN, zalogowane w deviations Scope addition wymuszony konsekwencja DROP COLUMN; bez ryzyka

Deviations from Plan

Summary

Type Count Impact
Auto-fixed 1 Niezbedny side-effect DROP COLUMN
Scope additions 0
Deferred 0

Total impact: Niezbedna korekta w AllegroOrderImportService nieuwzgledniona explicite w PLAN.md Task 1; logiczny side-effect DROP COLUMN.

Auto-fixed Issues

1. AllegroOrderImportService::mapCheckoutFormPayload: usuniecie 'is_invoice' => !empty($invoice['required']) (linia 235)

  • Found during: Task 1 (inspekcja AllegroOrderImportService przy dodawaniu shouldRequestInvoice)
  • Issue: PLAN Task 1 opisuje tylko zmiany w importSingleOrder (linie 99-103) dla Allegro. PLAN Task 3 dotyczy OrderImportRepository/OrdersRepository. Mapping is_invoice w Allegro pozostalby pisany do $mapped['order'], ktore potem OrderImportRepository::insertOrder wstawia do DB — po DROP COLUMN to powodowaloby SQL error.
  • Fix: Usuniety klucz is_invoice z mapowania w mapCheckoutFormPayload() (linia 235).
  • Files: src/Modules/Settings/AllegroOrderImportService.php
  • Verification: grep is_invoice src/Modules/Settings/AllegroOrderImportService.php → 0 trafien po edit; lint pass.
  • Commit: w zakresie wspolnego commitu phase-125.

Deferred Items

Brak — plan wykonany pelnie.

Issues Encountered

Issue Resolution
Allegro is_invoice mapping w mapCheckoutFormPayload poza explicite scope PLAN Self-fix w Task 1 (logiczny side-effect DROP COLUMN); zalogowane w Deviations.Auto-fixed

Next Phase Readiness

Ready:

  • Bugfix #1089 wdrozony w kodzie; gotowe do smoke testu po migracji.
  • Allegro symmetric fix — eliminacja analogicznej luki bez czekania na osobny ticket.
  • Migracja idempotentna — pattern do reuse w przyszlych DROP COLUMN.

Concerns:

  • AC-1/AC-2 wymagaja UAT na zywej bazie po php bin/migrate.php — operator musi potwierdzic na shopPRO 1089 i nowym Allegro zamowieniu z NIP.
  • Brak PHPUnit testow dla shouldRequestInvoice (Allegro) i invoice_detected (shopPRO mapper). Boundary explicit; mozliwe follow-up plan.

Blockers: None.


Phase: 125-invoice-requested-import-fix, Plan: 01 Completed: 2026-05-13