diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md index accbfc1..3b83814 100644 --- a/.paul/PROJECT.md +++ b/.paul/PROJECT.md @@ -13,7 +13,7 @@ Sprzedawca moĹĽe obsĹ‚ugiwać zamĂłwienia ze wszystkich kanałów | Attribute | Value | |-----------|-------| | Version | 3.7.0-dev | -| Status | v3.7 in progress — Phase 113 (Fakturownia Integration Foundation) shipped | +| Status | v3.7 in progress — Phases 113 (Fakturownia Foundation) + 114 (Accounting Configs Refactor) shipped | | Last Updated | 2026-05-10 | ## Requirements @@ -117,6 +117,7 @@ Sprzedawca moĹĽe obsĹ‚ugiwać zamĂłwienia ze wszystkich kanałów - [x] Re-import zamowienia (Allegro + shopPRO) wykrywa tranzycje payment_status 0/1->2 i emituje `payment.status_changed` (chain reguly #7 zmienia status na `w_realizacji`); naprawa luki dla zamowien zaimportowanych przed potwierdzeniem platnosci (case #864) + backfill CLI — Phase 111 - [x] Re-import istniejacego zamowienia jest delta-only: skip dla pozycji/adresow/notatek (stabilne `order_items.id`, ochrona `project_generated`), zawezony `updateOrderDelta()`, propagacja anulowania ze zrodla, identical-payload no-op guard (case #882) — Phase 112 - [x] Fundament v3.7 Invoices: tabele `invoices`, `invoice_configs`, `invoice_number_counters`, `fakturownia_integration_settings` + `orders.invoice_requested`; CRUD kont Fakturowni z testem polaczenia API (`/settings/integrations/fakturownia`); karta w hubie integracji — Phase 113 +- [x] Ksiegowosc: refaktor `/settings/accounting` na hub-rozdroze + osobne podstrony `/receipts` i `/invoices` + edycja na osobnym widoku; pelen CRUD `invoice_configs` z opcja delegacji do Fakturowni (conditional integration_id, serwerowa walidacja); seed `Domyslny VAT`; globalny modul `confirm-delete.js` — Phase 114 ### Deferred @@ -209,6 +210,10 @@ PHP (XAMPP/Laravel), integracje z API marketplace'Ăłw (Allegro, Erli) oraz API | Faktury: lokalna numeracja domyslna, delegacja przez `invoice_configs.is_delegated` | Pelna kontrola w default; opcja outsourcingu numeracji+PDF do Fakturowni gdy ksiegowy tak chce | 2026-05-10 | Active | | Brak eventu automatyzacji `invoice.created` (na start v3.7) | `receipt.created` pozostaje czysty — regula wysylki paragonu mailem nie zostanie odpalona dla faktury; mozliwe rozszerzenie jako osobny plan w przyszlosci | 2026-05-10 | Active | | Migracje no-op zawsze jako DDL (np. `ALTER TABLE COMMENT`), nigdy `SELECT 1;` | `SELECT` zwraca result set i pod PDO unbuffered blokuje kolejne migracje (SQLSTATE 2014) | 2026-05-10 | Active | +| Ksiegowosc: osobne podstrony `/settings/accounting/{receipts\|invoices}` zamiast tabow/jednej strony | Dlugie listy + rosnacy form faktury (conditional fields delegacji) nie mieszczace sie na jednej stronie | 2026-05-10 | Active | +| Legacy aliasy starych endpointow `/settings/accounting/save\|toggle\|delete` jako duplicate routes | Brak inwentaryzacji zewnetrznych referencji/bookmarkow - zero kosztu utrzymania, pelna wsteczna kompatybilnosc | 2026-05-10 | Active | +| `OrderProAlerts.confirm` to options-object API (`{title, message, onConfirm, danger, confirmLabel}`), nie pozycyjne argumenty | Pozycyjne wywolanie cicho fail'uje - callback ginie. Bug znaleziony w Phase 114-01 podczas smoke testu user. Pattern dla wszystkich przyszlych confirm dialogow | 2026-05-10 | Active | +| Globalny `confirm-delete.js` z `data-confirm-bound='1'` idempotent guard | Stare widoki maja inline scripts robiace to samo - guard zapobiega podwojnemu bindowi gdy modul globalny widzi juz-bound buttony. Mozna stopniowo migrowac stare widoki | 2026-05-10 | Active | ## Success Metrics @@ -240,6 +245,6 @@ Quick Reference: --- *PROJECT.md — Updated when requirements or context change* -*Last updated: 2026-05-10 after Phase 113 (Fakturownia Integration Foundation) completion; v3.7 Invoices milestone in progress* +*Last updated: 2026-05-10 after Phase 114 (Accounting Configs Refactor) completion; v3.7 Invoices milestone in progress* diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index 353b28d..7ac3d9f 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -13,10 +13,10 @@ Wystawianie faktur dla klientow z NIP poprzez integracje z Fakturownia (app.fakt | Phase | Name | Plans | Status | |-------|------|-------|--------| | 113 | Fakturownia Integration Foundation | 1/1 | Complete (2026-05-10) | -| 114 | Receipt Config Edit Refactor + Invoice Configs CRUD | 0/? | Planning | +| 114 | Accounting Configs Refactor (hub + osobne podstrony receipts/invoices) | 1/1 | Complete (2026-05-10) | +| 115 | Wystawianie faktury z zamowienia (lokalne + delegacja Fakturownia) | 0/? | Planning | Planowane kolejne fazy v3.7 (do dokladnego rozplanowania): -- Wystawianie faktury z zamowienia (lokalne + delegacja Fakturownia) - Lista faktur w sekcji Ksiegowosc + podglad/wydruk PDF - `orders.invoice_requested` w importerach Allegro/shopPRO + toggle w UI zamowienia @@ -492,4 +492,4 @@ Archive: `.paul/milestones/v0.1-ROADMAP.md` --- *Roadmap created: 2026-03-12* -*Last updated: 2026-05-10 - Phase 113 (Fakturownia Integration Foundation) complete; v3.7 milestone in progress* +*Last updated: 2026-05-10 - Phase 114 (Accounting Configs Refactor) complete; v3.7 milestone in progress* diff --git a/.paul/STATE.md b/.paul/STATE.md index cba0d7c..576fb74 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -5,46 +5,45 @@ See: .paul/PROJECT.md (updated 2026-05-07) **Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami. -**Current focus:** v3.7 Invoices — Phase 113 (Fakturownia Integration Foundation) shipped; nastepna faza 114 (Receipt Config Edit Refactor + Invoice Configs CRUD) do zaplanowania +**Current focus:** v3.7 Invoices — Phase 113 + 114 shipped; nastepna faza 115 (wystawianie faktury z zamowienia) do zaplanowania ## Current Position Milestone: v3.7 Invoices (Fakturownia integration) — In progress -Phase: 114 of TBD (Receipt Config Edit Refactor + Invoice Configs CRUD) — Not started +Phase: 115 of TBD (Wystawianie faktury z zamowienia) — Not started Plan: pending -Status: Phase 113 complete; ready to plan Phase 114 -Last activity: 2026-05-10 — UNIFY 113-01 complete, Phase 113 closed, transition done +Status: Phase 114 complete (transition done); ready to plan Phase 115 +Last activity: 2026-05-10 — UNIFY 114-01 complete, Phase 114 closed, transition done Progress: -- Milestone v3.7: [██░░░░░░░░] ~15% (Phase 113 z planowanych ~5) -- Phase 113: [██████████] 100% — Complete +- Milestone v3.7: [███░░░░░░░] ~30% (Phase 113 + 114 zamkniete; planowane ~5 faz) +- Phase 114: [██████████] 100% — Complete ## Loop Position Current loop state: ``` v3.7 milestone: - Phase 113 (Fakturownia Integration Foundation): - Plan 113-01: PLAN ✓ → APPLY ✓ → UNIFY ✓ - -> Phase 113 closed (transition complete) - Phase 114 (Receipt Config Edit Refactor + Invoice Configs CRUD): not started + Phase 113 (Fakturownia Integration Foundation): Complete + Phase 114 (Accounting Configs Refactor): Complete + Phase 115 (Wystawianie faktury z zamowienia): not started ``` ``` PLAN ──▶ APPLY ──▶ UNIFY - ✓ ✓ ✓ [Phase 113 closed; ready for Phase 114 plan] + ✓ ✓ ✓ [Phase 114 closed; ready for Phase 115 plan] ``` ## Session Continuity Last session: 2026-05-10 -Stopped at: Phase 113 transition complete (PROJECT.md/ROADMAP.md updated, SUMMARY zapisany) -Next action: /paul:plan dla Phase 114 (Receipt Config Edit Refactor + Invoice Configs CRUD) -Resume file: .paul/phases/113-fakturownia-integration/113-01-SUMMARY.md +Stopped at: Phase 114 transition complete (PROJECT.md + ROADMAP.md updated, SUMMARY zapisany) +Next action: /paul:plan dla Phase 115 (wystawianie faktury z zamowienia, lokalna numeracja + delegacja Fakturownia) +Resume file: .paul/phases/114-accounting-configs-refactor/114-01-SUMMARY.md ## Git State -Last commit: (pending — feat(113): fakturownia integration foundation) +Last commit: 2382018 feat(113): fakturownia integration foundation Branch: main Feature branches merged: none diff --git a/.paul/changelog/2026-05-10.md b/.paul/changelog/2026-05-10.md index 45ad893..8de98c3 100644 --- a/.paul/changelog/2026-05-10.md +++ b/.paul/changelog/2026-05-10.md @@ -2,6 +2,14 @@ ## Co zrobiono +- [Phase 114, Plan 01] Accounting Configs Refactor — `/settings/accounting` jako hub-rozdroze, osobne podstrony Paragony/Faktury, pelen CRUD `invoice_configs` z delegacja do Fakturowni +- Phase 114 Task 1: migracja seed `Domyslny VAT` (idempotentna NOT EXISTS) + `InvoiceConfigRepository` z walidacja delegacji +- Phase 114 Task 2: `InvoiceConfigController` + widoki listy/edycji + `invoice-config-form.js` (conditional integration_id select) + 6 routes +- Phase 114 Task 3: `ReceiptConfigController` refactor (hub/list/edit split) + hub view + 2 widoki paragonow + legacy aliasy + docs +- Auto-fix: globalny `confirm-delete.js` zastapil rozsiane inline scripts (po user feedback "Usuwanie konfiguracji faktur nie dziala") +- Auto-fix: `OrderProAlerts.confirm` poprawiony z pozycyjnych argumentow na options-object API +- Phase 114 transition: PROJECT.md (4 nowe Key Decisions) + ROADMAP.md zaktualizowane + - [Phase 113, Plan 01] Fakturownia Integration Foundation — fundament v3.7 Invoices - Task 1: 3 migracje SQL (invoices, invoice_configs, invoice_number_counters, fakturownia_integration_settings, orders.invoice_requested) - Task 2: FakturowniaIntegrationRepository + FakturowniaApiClient (testConnection + STUB createInvoice/downloadPdf) + IntegrationsRepository::updateTestResult() @@ -13,6 +21,20 @@ ## Zmienione pliki +- `database/migrations/20260511_000107_seed_default_invoice_config.sql` +- `src/Modules/Settings/InvoiceConfigRepository.php` +- `src/Modules/Settings/InvoiceConfigController.php` +- `src/Modules/Settings/ReceiptConfigController.php` +- `resources/views/settings/accounting.php` +- `resources/views/settings/accounting-receipts.php` +- `resources/views/settings/accounting-receipt-edit.php` +- `resources/views/settings/accounting-invoices.php` +- `resources/views/settings/accounting-invoice-edit.php` +- `resources/views/layouts/app.php` +- `public/assets/js/modules/invoice-config-form.js` +- `public/assets/js/modules/confirm-delete.js` +- `.paul/phases/114-accounting-configs-refactor/114-01-PLAN.md` +- `.paul/phases/114-accounting-configs-refactor/114-01-SUMMARY.md` - `database/migrations/20260510_000104_create_invoices_tables.sql` - `database/migrations/20260510_000105_add_invoice_requested_to_orders.sql` - `database/migrations/20260510_000106_seed_fakturownia_integration_type.sql` diff --git a/.paul/codebase/architecture.md b/.paul/codebase/architecture.md index 182ef05..088614e 100644 --- a/.paul/codebase/architecture.md +++ b/.paul/codebase/architecture.md @@ -203,3 +203,32 @@ tests/ ### IntegrationsHubController - Nowy parametr konstruktora `FakturowniaIntegrationRepository $fakturownia` i nowa metoda `buildFakturowniaRow()` agregująca status wszystkich kont (count instancji, configured/active counts, ostatni test). +## Phase 114 — Accounting Configs Refactor + +### Sekcja Ksiegowosc — struktura URL +- `/settings/accounting` — hub-rozdroze z 2 kartami: "Paragony" i "Faktury". `ReceiptConfigController::hub()`. +- `/settings/accounting/receipts` — lista konfiguracji paragonow. `ReceiptConfigController::list()`. +- `/settings/accounting/receipts/new`, `/edit?id=N` — formularz na osobnej podstronie. `ReceiptConfigController::edit()`. +- `/settings/accounting/receipts/save|toggle|delete` — POST actions. +- **Legacy aliasy:** `/settings/accounting/save|toggle|delete` (POST) zostaja jako duplicate routes (wsteczna kompatybilnosc z `
` w starszych szablonach/bookmarkach). +- `/settings/accounting/invoices` + `/new`, `/edit`, `/save`, `/toggle`, `/delete` — analogicznie dla `invoice_configs`. `InvoiceConfigController`. + +### InvoiceConfigRepository (`src/Modules/Settings/InvoiceConfigRepository.php`) +- `listAll()` JOIN `invoice_configs LEFT JOIN integrations` (`type='fakturownia'`) — zwraca `integration_name` gdy `is_delegated=1`. +- `save(array $data): int` — walidacja serwerowa wszystkich pol. Krytyczna regula: gdy `is_delegated=1` musi byc `integration_id > 0` wskazujacy na `integrations.type='fakturownia'`, inaczej rzuca `IntegrationConfigException`. Gdy `is_delegated=0`, ignoruje `integration_id` (NULL). +- `toggleStatus(int $id)` przez `ToggleableRepositoryTrait::toggleActive()`. +- `delete(int $id)` — pre-check `SELECT 1 FROM invoices WHERE config_id` zeby zwrocic czytelny PL komunikat zamiast brzydkiego SQLSTATE z FK RESTRICT. + +### Seed +- Migracja `20260511_000107_seed_default_invoice_config.sql` — idempotentny insert `Domyslny VAT` (NOT EXISTS guard, `invoice_configs.name` nie jest UNIQUE). + +### invoice-config-form.js (`public/assets/js/modules/invoice-config-form.js`) +- Vanilla JS modul ladowany globalnie przez `layouts/app.php`. +- Toggle widocznosci `[data-invoice-delegation]` wrappera w zaleznosci od stanu `[data-invoice-delegated]` checkboxa. +- Ustawia `select[name=integration_id].required` zgodnie ze stanem checkboxa; przy unchecked czysci `value`. + +### Ujednolicony wyglad list paragonow/faktur +- Tabela `table.table` w `table-wrap`, badge `badge--{success,muted}` na statusy. +- Edycja przez ``, toggle/delete przez `` z `_token` i `js-confirm-delete`. +- Wspolny pattern miedzy `accounting-receipts.php` i `accounting-invoices.php` (faktury maja dodatkowe kolumny: Tryb, Konto Fakturowni). + diff --git a/.paul/codebase/db_schema.md b/.paul/codebase/db_schema.md index 8f04dbb..66c40dc 100644 --- a/.paul/codebase/db_schema.md +++ b/.paul/codebase/db_schema.md @@ -624,6 +624,8 @@ UNIQUE: `(config_id, year, month)` ## Invoices (Phase 113-01) +> **Seed (Phase 114-01):** migration `20260511_000107_seed_default_invoice_config.sql` inserts a default `Domyslny VAT` config (format `FV/%N/%M/%Y`, monthly numbering, `is_delegated=0`, `payment_to_days=7`) idempotently via `NOT EXISTS` guard. + **invoice_configs** — Invoice generation configurations (analogous to `receipt_configs` plus delegation flag) | Column | Type | Nullable | Notes | |--------|------|----------|-------| diff --git a/.paul/codebase/tech_changelog.md b/.paul/codebase/tech_changelog.md index 17aa52b..a8b9931 100644 --- a/.paul/codebase/tech_changelog.md +++ b/.paul/codebase/tech_changelog.md @@ -1,5 +1,35 @@ # Technical Changelog +## 2026-05-10 - Phase 114 Plan 01: Accounting Configs Refactor + +**Co zrobiono:** +- Migracja `20260511_000107_seed_default_invoice_config.sql` - idempotentny seed `Domyslny VAT` config (format `FV/%N/%M/%Y`, monthly, lokalna numeracja, payment_to_days=7) przez `NOT EXISTS` guard. +- `InvoiceConfigRepository` - pelne CRUD `invoice_configs` z walidacja serwerowa wszystkich pol + krytyczna regula delegacji: `is_delegated=1` wymaga `integration_id` z `integrations.type='fakturownia'`. `delete()` pre-checkuje `invoices` zeby zwrocic PL komunikat zamiast SQLSTATE. +- `InvoiceConfigController` - index/edit/save/toggle/delete dla `/settings/accounting/invoices`. Flash `accounting.invoices.save/.error`. Edycja na osobnej podstronie. +- `ReceiptConfigController` refactor - rozdzielenie `index()` na `hub()` + `list()` + nowa `edit()`. Save/toggle/delete redirectuja na `/settings/accounting/receipts` (nie hub). +- 4 nowe widoki: + - `accounting.php` (REFAKTOR) - hub-rozdroze z 2 kartami Paragony/Faktury (usunieta lista i formularz inline). + - `accounting-receipts.php` - lista paragonow w stylu spojnym z fakturami (`table.table + badge`). + - `accounting-receipt-edit.php` - formularz paragonu na osobnej podstronie. + - `accounting-invoices.php` - lista faktur (7 kolumn z dodatkami Tryb, Konto Fakturowni). + - `accounting-invoice-edit.php` - formularz faktury z conditional `integration_id` select. +- `invoice-config-form.js` - vanilla JS toggle dla `is_delegated` checkbox -> show/hide `integration_id` select wrapper + dynamiczny `required`. +- `layouts/app.php` - rejestracja nowego modulu JS `invoice-config-form.js` (z cache-busting `?ver=mtime`). +- Routy: 12 nowych endpointow ksiegowosci (6 receipts + 6 invoices) + 3 legacy aliasy starych `/settings/accounting/save|toggle|delete`. +- Docs: `db_schema.md` (notka o seed), `architecture.md` (nowa sekcja "Phase 114"), tech_changelog. + +**Dlaczego:** +- Phase 113 dostarczyl tabele `invoice_configs` - bez UI/CRUD nie da sie operacjonalnie wystawiac faktur. Phase 115 (wystawianie faktury z zamowienia) wymaga gotowych invoice_configs. +- Edycja paragonu pod tabela na `/settings/accounting` (stary uklad) miala 2 problemy: dlugi scroll przy wielu configach + brak miejsca na rosnacy formularz faktury (z conditional fields). Refaktor na osobne podstrony rozwiazuje oba. +- Seed `Domyslny VAT` - operator od razu po deployment moze wystawiac faktury bez recznego skonfigurowania (zerowy onboarding). +- Legacy aliasy `/settings/accounting/save|toggle|delete` - istniejace formularze w cache'u przegladarki / bookmarki / zewnetrzne narzedzia (jesli sa) dalej dzialaja bez 404. +- JS toggle - operator nie zaznaczy delegacji bez wybrania konta (UX + serwerowa walidacja jako backup). + +**BREAKING:** +- Brak. Stare endpointy zachowane jako aliasy. Stary widok `/settings/accounting` to teraz hub z linkami zamiast listy - operator wie ze trzeba kliknac "Zarzadzaj paragonami". + +--- + ## 2026-05-10 - Phase 113 Plan 01: Fakturownia Integration Foundation **Co zrobiono:** diff --git a/.paul/phases/114-accounting-configs-refactor/114-01-PLAN.md b/.paul/phases/114-accounting-configs-refactor/114-01-PLAN.md new file mode 100644 index 0000000..85f3eaf --- /dev/null +++ b/.paul/phases/114-accounting-configs-refactor/114-01-PLAN.md @@ -0,0 +1,363 @@ +--- +phase: 114-accounting-configs-refactor +plan: 01 +type: execute +wave: 1 +depends_on: ["113-01"] +files_modified: + - database/migrations/20260511_000107_seed_default_invoice_config.sql + - src/Modules/Settings/InvoiceConfigRepository.php + - src/Modules/Settings/InvoiceConfigController.php + - src/Modules/Settings/ReceiptConfigController.php + - resources/views/settings/accounting.php + - resources/views/settings/accounting-receipts.php + - resources/views/settings/accounting-receipt-edit.php + - resources/views/settings/accounting-invoices.php + - resources/views/settings/accounting-invoice-edit.php + - public/assets/js/modules/invoice-config-form.js + - resources/views/layouts/app.php + - routes/web.php + - .paul/codebase/db_schema.md + - .paul/codebase/architecture.md + - .paul/codebase/tech_changelog.md +autonomous: true +delegation: off +--- + + +## Goal +Rozdzielic `/settings/accounting` na osobne podstrony `Paragony` (`/settings/accounting/receipts`) i `Faktury` (`/settings/accounting/invoices`). Edycja kazdej konfiguracji na osobnym widoku (zamiast formularza pod tabela). Dorobic pelny CRUD `invoice_configs` z opcja delegacji do Fakturowni (warunkowy select `integration_id` przez JS toggle). Ujednolicic wyglad obu list i formularzy. + +## Purpose +Phase 113 polozyl fundament v3.7 Invoices (schema DB + integracje Fakturownia). Aby Phase 115 (wystawianie faktury z zamowienia) mial sens, operator musi miec UI do zarzadzania `invoice_configs`. Przy okazji porzadkujemy edycje `receipt_configs` na osobna podstrone (request od usera) i ujednolicamy wyglad obu modulow ksiegowosci. + +## Output +- Nowa migracja seed (idempotentny `Domyslny VAT` config) +- `InvoiceConfigRepository` (CRUD `invoice_configs`) +- `InvoiceConfigController` (`/settings/accounting/invoices`, `/edit/{id}`, `/save`, `/toggle`, `/delete`) +- `ReceiptConfigController` rozszerzony o `edit(Request $request)` dla osobnej podstrony (`/settings/accounting/receipts/edit/{id}`) +- 5 nowych widokow + refaktor `/settings/accounting` na hub-rozdroze +- `public/assets/js/modules/invoice-config-form.js` (JS toggle `is_delegated` -> `integration_id` select) +- Routy w `routes/web.php` (15+ nowych endpointow ksiegowosci) + + + +## Project Context +@.paul/PROJECT.md +@.paul/ROADMAP.md +@.paul/STATE.md +@.paul/codebase/architecture.md +@.paul/codebase/db_schema.md + +## Prior Work +@.paul/phases/113-fakturownia-integration/113-01-SUMMARY.md +(Phase 113-01 dostarczyl schema `invoice_configs/invoices/invoice_number_counters` + FakturowniaIntegrationRepository - ten plan implementuje warstwe UI/CRUD nad tym fundamentem.) + +## Reference patterns +@src/Modules/Settings/ReceiptConfigController.php +@src/Modules/Settings/ReceiptConfigRepository.php +@src/Modules/Settings/FakturowniaIntegrationRepository.php +@resources/views/settings/accounting.php +@resources/views/settings/email-mailboxes.php +@resources/views/settings/fakturownia.php + +## Routes +@routes/web.php + + +- **Struktura UI** — Jak ulozyc strone Ksiegowosc po refaktorze? + → Odpowiedź: Osobne podstrony glowne `/settings/accounting/receipts` i `/settings/accounting/invoices`. `/settings/accounting` jako hub-rozdroze (2 karty: Paragony / Faktury). +- **Delegacja** — Walidacja `is_delegated=1` w invoice_config + → Odpowiedź: Wymagaj `integration_id` gdy `is_delegated=1`. Pole `integration_id` (select kont Fakturowni) pokazuje sie warunkowo przez JS toggle. Walidacja serwerowa odrzuca brak gdy is_delegated=1. +- **Seed** — Default invoice_config przy migracji + → Odpowiedź: Tak — idempotentny seed `Domyslny VAT` (format `FV/%N/%M/%Y`, numbering monthly, is_delegated=0, payment_to_days=7). +- **Receipts scope** — Zakres refaktoru `receipt_configs` + → Odpowiedź: Refaktor + ujednolicenie wygladu (te same kolumny tabeli, ten sam style formularza co invoice_configs). + + + + + +## AC-1: Seed + Repository dla invoice_configs +```gherkin +Given pusta tabela `invoice_configs` +When uruchomie `php bin/migrate.php` +Then powstaje wiersz `Domyslny VAT` (number_format='FV/%N/%M/%Y', numbering_type='monthly', is_delegated=0, payment_to_days=7, default_kind='vat', is_active=1) +And kolejne uruchomienie migracji nie tworzy duplikatu (idempotentny INSERT ON DUPLICATE KEY UPDATE / NOT EXISTS) +And `InvoiceConfigRepository::listAll()` zwraca tablice configow z polem `integration_name` (LEFT JOIN integrations gdy `is_delegated=1`) +And `InvoiceConfigRepository::save()` walidacja: gdy `is_delegated=1` musi byc `integration_id != null` i wskazywac na integracje typu 'fakturownia' (rzuca `IntegrationConfigException` w przeciwnym razie) +``` + +## AC-2: CRUD invoice_configs na osobnej podstronie +```gherkin +Given zalogowany operator wchodzi na `/settings/accounting/invoices` +When otwiera liste konfiguracji +Then widzi tabele kolumn `Nazwa | Format numeru | Numerowanie | Tryb (lokalny/delegacja) | Status | Akcje` w stylu `table.table + table-wrap + badge` +And przycisk "Dodaj konfiguracje" prowadzi do `/settings/accounting/invoices/new` +And klikajac "Edytuj" trafia na `/settings/accounting/invoices/edit?id={id}` z formularzem na osobnej podstronie (nie pod tabela) +And formularz zawiera: name, number_format, numbering_type, sale_date_source, order_reference, payment_to_days, default_kind, is_delegated (checkbox), integration_id (select Fakturownia, ukryty gdy is_delegated=0), is_active +And po zaznaczeniu `is_delegated` w UI pojawia sie select integration_id (JS toggle); pre-fill z DB przy edycji +And toggle/delete dziala przez `js-confirm-delete` (window.OrderProAlerts) i POST z `_token` +And zapis bez `integration_id` przy `is_delegated=1` zwraca blad walidacji i flash `accounting.invoices.error` +And delete blokowany gdy istnieje juz wystawiona faktura z tym config_id (FK RESTRICT) - czytelny flash error +``` + +## AC-3: Refaktor receipt_configs + hub +```gherkin +Given zalogowany operator wchodzi na `/settings/accounting` +When otwiera strone glowna ksiegowosci +Then widzi hub-rozdroze: dwie karty `Paragony` (link do `/settings/accounting/receipts`) i `Faktury` (link do `/settings/accounting/invoices`) +And `/settings/accounting/receipts` pokazuje liste paragonow w tym samym ukladzie kolumn co `/settings/accounting/invoices` (z dostosowaniem: brak kolumny Tryb) +And edycja paragonu jest na osobnej podstronie `/settings/accounting/receipts/edit?id={id}` (nie pod tabela) +And istniejace endpointy backend `ReceiptConfigController::save/toggleStatus/delete` dalej dzialaja (nie laduja inline na list view) +And menu sidebar/topbar (jesli zawiera link "Ksiegowosc") wskazuje na `/settings/accounting` (hub) - zachowanie wsteczne kompatybilne +``` + + + + + + + Task 1: Migration seed + InvoiceConfigRepository + walidacja delegacji + database/migrations/20260511_000107_seed_default_invoice_config.sql, src/Modules/Settings/InvoiceConfigRepository.php, .paul/codebase/db_schema.md + + Migracja `20260511_000107_seed_default_invoice_config.sql`: + - Idempotentny insert default configu: + `INSERT INTO invoice_configs (name, number_format, numbering_type, sale_date_source, order_reference, payment_to_days, default_kind, is_delegated, is_active) + SELECT 'Domyslny VAT', 'FV/%N/%M/%Y', 'monthly', 'issue_date', 'none', 7, 'vat', 0, 1 + WHERE NOT EXISTS (SELECT 1 FROM invoice_configs WHERE name = 'Domyslny VAT');` + - Nie ma `ON DUPLICATE KEY` bo `name` nie jest UNIQUE w schema (nie chcemy tego zmieniac, NOT EXISTS jest wystarczajacy). + + `InvoiceConfigRepository` (final class, wzorzec `ReceiptConfigRepository`): + - `__construct(PDO $pdo)`. + - `listAll(): array` — `SELECT ic.*, i.name AS integration_name FROM invoice_configs ic LEFT JOIN integrations i ON i.id = ic.integration_id ORDER BY ic.is_active DESC, ic.name ASC`. Zwroc tablice z polem `integration_name` (NULL gdy nie-delegated). + - `findById(int $id): ?array` — analogicznie z JOIN. + - `save(array $data): int` — insert/update z walidacja: + - `name` required (non-empty, max 128) + - `number_format` required (max 64) + - `numbering_type` in ['monthly', 'yearly'] + - `sale_date_source` in ['order_date', 'payment_date', 'issue_date'] + - `order_reference` in ['none', 'orderpro', 'integration'] + - `payment_to_days` int 0-365 + - `default_kind` non-empty (max 32) + - `is_delegated` cast 0/1 + - **Walidacja delegacji:** gdy `is_delegated=1` musi byc `integration_id > 0` i istniec wpis w `integrations` z `type='fakturownia'` (proste `SELECT 1 FROM integrations WHERE id=? AND type='fakturownia' LIMIT 1`). Gdy `is_delegated=0`, ignoruj `integration_id` (zapisz NULL). + - Niespelnione warunki rzucaja `App\Core\Exceptions\IntegrationConfigException` (lub `\RuntimeException` z czytelnym komunikatem PL). + - Insert zwraca lastInsertId, update zwraca przekazane `id`. + - `toggleStatus(int $id): void` — `UPDATE invoice_configs SET is_active = 1 - is_active, updated_at = NOW() WHERE id = :id`. + - `delete(int $id): void` — pre-check `SELECT 1 FROM invoices WHERE config_id = :id LIMIT 1`. Jesli istnieje, rzuc exception z komunikatem "Nie mozna usunac konfiguracji - istnieja juz wystawione faktury". W przeciwnym razie usun + cascade do `invoice_number_counters`. + + Aktualizacja `.paul/codebase/db_schema.md`: + - W sekcji "Invoices (Phase 113-01)" dodac notke: "Seed: domyslny wiersz `Domyslny VAT` (Phase 114-01)". + + Avoid: + - Walidacji UI-only - musi byc serwerowa (UI moze byc obejsciem). + - Hard-cascade delete inwoice_configs przy istniejacych fakturach (FK juz jest RESTRICT - tu robimy pre-check zeby zwrocic czytelny PL komunikat zamiast brzydkiego SQLSTATE). + + + `php bin/migrate.php` -> migracja przechodzi, `SELECT * FROM invoice_configs` zwraca 1 wiersz `Domyslny VAT`. + Drugie uruchomienie migracji nie tworzy duplikatu. + `php -l src/Modules/Settings/InvoiceConfigRepository.php` -> no syntax errors. + + AC-1 satisfied: seed idempotentny + repo z walidacja delegacji dziala. + + + + Task 2: InvoiceConfigController + widoki (list + edit) + JS toggle + routy + src/Modules/Settings/InvoiceConfigController.php, resources/views/settings/accounting-invoices.php, resources/views/settings/accounting-invoice-edit.php, public/assets/js/modules/invoice-config-form.js, resources/views/layouts/app.php, routes/web.php + + `InvoiceConfigController` (final, wzorzec `ReceiptConfigController`): + - `__construct(Template, Translator, AuthService, InvoiceConfigRepository, FakturowniaIntegrationRepository)`. + - `index(Request $request): Response` — render `settings/accounting-invoices` z `configs = repo->listAll()`, `fakturowniaAccounts = fakturownia->findAll()` (do selectu w edycji), flash. + - `edit(Request $request): Response` — render `settings/accounting-invoice-edit`. Param `id` z `$request->input('id')`. Jesli brak id -> form nowego configu. Inaczej `repo->findById($id)`. Przekaz `fakturowniaAccounts` z `FakturowniaIntegrationRepository::findAll()` (filtruj `is_active=1`). + - `save(Request $request): Response` — CSRF `_token`, zbierz pola, wywolaj `repo->save($data)`. Catch IntegrationConfigException -> Flash `accounting.invoices.error`. Redirect po sukcesie na `/settings/accounting/invoices`, po bledzie na edycje (zachowaj `id` jesli byl). + - `toggleStatus(Request $request): Response` — CSRF, `repo->toggleStatus`, flash, redirect. + - `delete(Request $request): Response` — CSRF, try `repo->delete`. Catch exception -> czytelny flash error. + + Widok `resources/views/settings/accounting-invoices.php` (lista): + - Layout `layouts/app`, `section.card` z tytulem + opis + breadcrumb (`/settings/accounting` > Faktury). + - Flash messages `accounting.invoices.save/.error`. + - Przycisk "Dodaj konfiguracje" -> `/settings/accounting/invoices/new`. + - Tabela `table.table` w `table-wrap`: + Kolumny: Nazwa | Format numeru | Numerowanie | Tryb | Konto Fakturowni | Status | Akcje + - Tryb: badge `success`=delegacja Fakturownia, `muted`=lokalna + - Konto Fakturowni: `integration_name` lub `-` gdy lokalny + - Status: badge success=Aktywna, muted=Nieaktywna + - Akcje: Edytuj (a.btn--sm), Aktywuj/Dezaktywuj (form POST), Usun (form POST z `js-confirm-delete`). + + Widok `resources/views/settings/accounting-invoice-edit.php` (edycja): + - Layout `layouts/app`, breadcrumb, `section.card`. + - Flash messages. + - Form `POST /settings/accounting/invoices/save` z `_token` i (gdy edycja) ``. + - Pola: + - `name` (required, max 128) + - `number_format` (required, max 64, hint: `%N` = numer, `%M` = miesiac, `%Y` = rok) + - `numbering_type` (select: monthly|yearly) + - `sale_date_source` (select: order_date|payment_date|issue_date) + - `order_reference` (select: none|orderpro|integration) + - `payment_to_days` (number 0-365, default 7) + - `default_kind` (select: vat|proforma|invoice_other, hint o znaczeniu) + - `is_delegated` (checkbox + label "Deleguj wystawianie do Fakturowni") + - `integration_id` (select z `$fakturowniaAccounts`, ukryty `style="display:none"` gdy `is_delegated=0`) + - `is_active` (checkbox) + - Przyciski: Zapisz (`btn--primary`), Anuluj (`btn--secondary` -> link do listy) + - `
` wrapper na pole `integration_id` + `` dla JS. + + JS `public/assets/js/modules/invoice-config-form.js`: + - Vanilla JS, IIFE, run on DOMContentLoaded. + - Znajdz `[data-invoice-delegated]` i `[data-invoice-delegation]`. + - Funkcja sync: jesli checkbox checked -> show wrapper (`style.display = ''`), jesli unchecked -> hide (`style.display = 'none'`) oraz `select.required = checked`. + - Bind change event + initial sync. + - Brak zewn deps. + + `resources/views/layouts/app.php`: + - Dodaj `` po istniejacych skryptach modulow (analogicznie do `checkbox-multiselect.js`). + + Routy w `routes/web.php`: + - Import `InvoiceConfigRepository`, `InvoiceConfigController`. + - DI: `$invoiceConfigRepository = new InvoiceConfigRepository($app->db());`, kontroler `new InvoiceConfigController(...)`. + - Routes (pod `AuthMiddleware`): + - `GET /settings/accounting/invoices` -> index + - `GET /settings/accounting/invoices/new` -> edit (bez id) + - `GET /settings/accounting/invoices/edit` -> edit (z id) + - `POST /settings/accounting/invoices/save` -> save + - `POST /settings/accounting/invoices/toggle` -> toggleStatus + - `POST /settings/accounting/invoices/delete` -> delete + + Avoid: + - Walidacji wylacznie po stronie JS (kazde pole musi miec serwerowa walidacje). + - Pozostawiania inline'owych