feat(08-10-receipt-module): phases 08-10 complete — receipt issuing from orders

Phase 08 — DB Foundation:
- 3 new tables: receipt_configs, receipts, receipt_number_counters
- company_settings extended with BDO, REGON, KRS, logo fields

Phase 09 — Receipt Config:
- CRUD for receipt configurations (Settings > Accounting)
- ReceiptConfigController + ReceiptConfigRepository

Phase 10 — Receipt Issuing:
- ReceiptRepository with atomic numbering (INSERT ON DUPLICATE KEY UPDATE)
- ReceiptController with snapshot pattern (seller/buyer/items as JSON)
- "Wystaw paragon" button in order view
- Documents tab showing both receipts and marketplace documents
- Activity log entry on receipt creation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 19:49:06 +01:00
parent 3bccc7a533
commit ed057fc304
31 changed files with 2539 additions and 39 deletions

View File

@@ -0,0 +1,308 @@
---
phase: 09-receipt-config
plan: 01
type: execute
wave: 1
depends_on: ["08-01"]
files_modified:
- src/Modules/Settings/ReceiptConfigController.php
- src/Modules/Settings/ReceiptConfigRepository.php
- resources/views/settings/accounting.php
- resources/views/layouts/app.php
- resources/lang/pl.php
- routes/web.php
- DOCS/ARCHITECTURE.md
autonomous: false
---
<objective>
## Goal
Wdrozyc CRUD konfiguracji paragonow w sekcji Ustawienia > Ksiegowosc: lista konfiguracji, tworzenie, edycja, aktywacja/dezaktywacja, usuwanie. Dodac sublinek "Ksiegowosc" do nawigacji ustawien.
## Purpose
Umozliwienie zarzadzania szablonami paragonow (numeracja, imiennosc, zrodlo daty sprzedazy) — fundament pod wystawianie paragonow w fazie 10.
## Output
- ReceiptConfigController (index, save, toggleStatus, delete)
- ReceiptConfigRepository (CRUD na receipt_configs)
- Widok settings/accounting.php z lista i formularzem
- Sublinek w sidebarze Ustawienia
- Tlumaczenia PL
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Prior Work
@.paul/phases/08-db-foundation/08-01-SUMMARY.md
## Source Files (wzorce)
@src/Modules/Settings/CompanySettingsController.php
@src/Modules/Settings/CompanySettingsRepository.php
@resources/views/settings/company.php
@resources/views/layouts/app.php
@routes/web.php
@resources/lang/pl.php
</context>
<skills>
## Required Skills (from SPECIAL-FLOWS.md)
| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
</skills>
<acceptance_criteria>
## AC-1: Lista konfiguracji paragonow
```gherkin
Given uzytkownik jest zalogowany
When wchodzi na /settings/accounting
Then widzi liste wszystkich konfiguracji paragonow (nazwa, status, format numeracji, typ)
And widzi przycisk "Dodaj konfiguracje"
```
## AC-2: Tworzenie nowej konfiguracji
```gherkin
Given uzytkownik jest na /settings/accounting
When wypelnia formularz (nazwa, format numeracji, typ numeracji, imiennosc, zrodlo daty, referencja zamowienia) i klika Zapisz
Then konfiguracja jest zapisana w receipt_configs
And pojawia sie na liscie z flash message sukcesu
```
## AC-3: Edycja istniejącej konfiguracji
```gherkin
Given istnieje konfiguracja paragonow
When uzytkownik klika "Edytuj" przy konfiguracji
Then formularz jest wypelniony danymi konfiguracji
When zmienia dane i klika Zapisz
Then zmiany sa zapisane i widoczne na liscie
```
## AC-4: Aktywacja/dezaktywacja konfiguracji
```gherkin
Given istnieje konfiguracja paragonow
When uzytkownik klika przycisk aktywuj/dezaktywuj
Then status konfiguracji zmienia sie (is_active toggle)
And lista odswiezja sie z nowym statusem
```
## AC-5: Usuwanie konfiguracji
```gherkin
Given istnieje konfiguracja paragonow bez wystawionych paragonow
When uzytkownik klika "Usun" i potwierdza w OrderProAlerts.confirm()
Then konfiguracja jest usunieta z bazy
And znika z listy
```
## AC-6: Nawigacja — sublinek Ksiegowosc
```gherkin
Given uzytkownik jest zalogowany
When patrzy na sidebar w sekcji Ustawienia
Then widzi sublinek "Ksiegowosc" prowadzacy do /settings/accounting
And sublinek jest podswietlony gdy jest na stronie konfiguracji
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: ReceiptConfigRepository — CRUD na receipt_configs</name>
<files>src/Modules/Settings/ReceiptConfigRepository.php</files>
<action>
Utworzyc klase `App\Modules\Settings\ReceiptConfigRepository` wzorowana na CompanySettingsRepository:
- Konstruktor: `private readonly PDO $pdo`
- `listAll(): array` — SELECT * FROM receipt_configs ORDER BY created_at DESC
- `findById(int $id): ?array` — SELECT * WHERE id = :id
- `save(array $data): void` — INSERT lub UPDATE (jesli data['id'] istnieje):
- pola: name, is_active, number_format, numbering_type, is_named, sale_date_source, order_reference
- INSERT: prepared statement z VALUES
- UPDATE: prepared statement z WHERE id = :id
- `toggleStatus(int $id): void` — UPDATE receipt_configs SET is_active = NOT is_active WHERE id = :id
- `delete(int $id): bool` — DELETE FROM receipt_configs WHERE id = :id (zwraca false jesli FK RESTRICT zablokuje)
- Wszystko przez prepared statements (wzorzec z CompanySettingsRepository)
- Klasa final
</action>
<verify>Sprawdzic syntax PHP: php -l src/Modules/Settings/ReceiptConfigRepository.php</verify>
<done>AC-2, AC-3, AC-4, AC-5 (backend) spelnione</done>
</task>
<task type="auto">
<name>Task 2: ReceiptConfigController — kontroler CRUD</name>
<files>src/Modules/Settings/ReceiptConfigController.php</files>
<action>
Utworzyc klase `App\Modules\Settings\ReceiptConfigController` wzorowana na CompanySettingsController:
- Konstruktor: Template, Translator, AuthService, ReceiptConfigRepository (readonly)
- `index(Request $request): Response`:
- Pobiera liste konfiguracji z repository->listAll()
- Jesli query param `edit` — laduje konfiguracje do edycji (findById)
- Renderuje 'settings/accounting' z layout 'layouts/app'
- Przekazuje: activeMenu='settings', activeSettings='accounting', csrfToken, configs, editConfig, flash messages
- `save(Request $request): Response`:
- Waliduje CSRF (Csrf::validate)
- Waliduje: name wymagane, number_format wymagane i zawiera %N
- Wywoluje repository->save([...]) z danymi z $request->input(...)
- Flash::set('settings.accounting.flash.saved/save_failed')
- Redirect do /settings/accounting
- `toggleStatus(Request $request): Response`:
- Waliduje CSRF i id
- Wywoluje repository->toggleStatus((int) $request->input('id'))
- Redirect do /settings/accounting
- `delete(Request $request): Response`:
- Waliduje CSRF i id
- try: repository->delete((int) $request->input('id'))
- catch (Throwable): flash error (konfiguracja ma powiazane paragony)
- Redirect do /settings/accounting
- Klasa final
- Uzyc Flash::set/get wzorca, walidacja CSRF przez Csrf::validate($request->input('_token'))
</action>
<verify>Sprawdzic syntax PHP: php -l src/Modules/Settings/ReceiptConfigController.php</verify>
<done>AC-1, AC-2, AC-3, AC-4, AC-5 (kontroler) spelnione</done>
</task>
<task type="auto">
<name>Task 3: Widok settings/accounting.php, routing, nawigacja, tlumaczenia</name>
<files>
resources/views/settings/accounting.php,
resources/views/layouts/app.php,
routes/web.php,
resources/lang/pl.php
</files>
<action>
1. Utworzyc `resources/views/settings/accounting.php`:
- Sekcja .card z tytulem "Ksiegowosc — Konfiguracje paragonow"
- Flash messages (error/success)
- Tabela lista konfiguracji:
- Kolumny: Nazwa, Format numeracji, Typ, Imienny, Data sprzedazy, Ref. zamowienia, Status, Akcje
- Status: badge aktywny/nieaktywny
- Akcje: Edytuj (link z ?edit=ID), Aktywuj/Dezaktywuj (form POST), Usun (form POST z OrderProAlerts.confirm)
- Formularz dodawania/edycji (pod tabelą lub w osobnej sekcji):
- hidden: _token, id (jesli edycja)
- Nazwa (text, required)
- Format numeracji (text, required, placeholder: PAR/%N/%M/%Y)
- Typ numeracji (select: miesięczny/roczny)
- Imienny (checkbox)
- Domyslna data sprzedazy (select: wg daty zamowienia/oplacenia/wystawienia)
- Informacja o zamowieniu (select: brak/numer orderPRO/numer integracji)
- Przycisk Zapisz
- Styl: uzyc istniejacych klas .card, .form-control, .form-field, .btn, .form-grid-2, table.data-table
- Usun potwierdzenie: window.OrderProAlerts.confirm() (NIE natywny confirm())
2. W `resources/views/layouts/app.php`:
- Dodac sublinek "Ksiegowosc" po "Dane firmy" w sekcji settings:
```php
<a class="sidebar__sublink<?= $currentMenu === 'settings' && $currentSettings === 'accounting' ? ' is-active' : '' ?>" href="/settings/accounting">
<?= $e($t('navigation.accounting')) ?>
</a>
```
3. W `routes/web.php`:
- Instantiacja: new ReceiptConfigRepository($app->db()), new ReceiptConfigController($template, $translator, $auth, $receiptConfigRepository)
- Trasy:
- GET /settings/accounting -> [$receiptConfigController, 'index'], [$authMiddleware]
- POST /settings/accounting/save -> [$receiptConfigController, 'save'], [$authMiddleware]
- POST /settings/accounting/toggle -> [$receiptConfigController, 'toggleStatus'], [$authMiddleware]
- POST /settings/accounting/delete -> [$receiptConfigController, 'delete'], [$authMiddleware]
- Dodac use statement dla nowych klas
4. W `resources/lang/pl.php`:
- navigation.accounting => 'Ksiegowosc'
- settings.accounting.title => 'Konfiguracje paragonow'
- settings.accounting.description => 'Zarzadzaj szablonami numeracji i ustawieniami paragonow'
- settings.accounting.fields.* => tlumaczenia pol formularza
- settings.accounting.flash.saved => 'Konfiguracja zapisana'
- settings.accounting.flash.save_failed => 'Blad zapisu konfiguracji'
- settings.accounting.flash.deleted => 'Konfiguracja usunieta'
- settings.accounting.flash.delete_failed => 'Nie mozna usunac — konfiguracja ma powiazane paragony'
- settings.accounting.flash.toggled => 'Status zmieniony'
- settings.accounting.actions.* => etykiety przyciskow
- settings.accounting.table.* => naglowki kolumn tabeli
- settings.accounting.options.* => opcje selectow (miesięczny/roczny, daty, referencje)
</action>
<verify>
Sprawdzic syntax: php -l resources/views/settings/accounting.php
Sprawdzic syntax routes: php -l routes/web.php
</verify>
<done>AC-1, AC-6 spelnione</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>CRUD konfiguracji paragonow w Ustawienia > Ksiegowosc</what-built>
<how-to-verify>
1. Wejdz na strone — w sidebarze Ustawienia powinien byc sublinek "Ksiegowosc"
2. Kliknij — powinna wyswietlic sie strona /settings/accounting z pusta lista i formularzem
3. Dodaj nowa konfiguracje: nazwa "Paragony standardowe", format "PAR/%N/%M/%Y", typ miesięczny
4. Sprawdz czy pojawila sie na liscie
5. Kliknij Edytuj — formularz powinien sie wypelnic danymi
6. Zmien nazwe i zapisz — sprawdz aktualizacje
7. Kliknij Dezaktywuj — status powinien sie zmienic
8. Kliknij Usun — powinien pojawic sie modal potwierdzenia (OrderProAlerts)
9. Potwierdz — konfiguracja powinna zniknac z listy
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
<task type="auto">
<name>Task 4: Aktualizacja ARCHITECTURE.md</name>
<files>DOCS/ARCHITECTURE.md</files>
<action>
Dodac w ARCHITECTURE.md:
1. W sekcji "Kluczowe klasy":
- App\Modules\Settings\ReceiptConfigController
- App\Modules\Settings\ReceiptConfigRepository
2. W sekcji "Routing" nowe trasy:
- GET /settings/accounting
- POST /settings/accounting/save
- POST /settings/accounting/toggle
- POST /settings/accounting/delete
3. Nowa sekcja "Przeplyw Ustawienia > Ksiegowosc" opisujaca CRUD konfiguracji
4. W sekcji "Nawigacja ustawien" dodac sublinek Ksiegowosc
</action>
<verify>Przejrzec ARCHITECTURE.md pod katem kompletnosci</verify>
<done>AC-1 do AC-6 udokumentowane</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- database/migrations/* — schemat zablokowany (migracje z fazy 08)
- Istniejace kontrolery i widoki niezwiazane z accounting
- src/Modules/Settings/CompanySettingsController.php
- src/Modules/Settings/CompanySettingsRepository.php
## SCOPE LIMITS
- Nie tworzymy sekcji glownej Ksiegowosc w sidebarze (to faza 12)
- Nie tworzymy logiki wystawiania paragonow (faza 10)
- Nie dodajemy walidacji unikalnosci nazwy konfiguracji (nice-to-have)
- Nie dodajemy sortowania/filtrowania listy konfiguracji (prostota)
</boundaries>
<verification>
Before declaring plan complete:
- [ ] ReceiptConfigRepository — CRUD dziala (list, find, save, toggle, delete)
- [ ] ReceiptConfigController — 4 endpointy dzialaja
- [ ] Widok accounting.php renderuje liste i formularz
- [ ] Sublinek "Ksiegowosc" widoczny w sidebarze ustawien
- [ ] Tlumaczenia PL kompletne
- [ ] Routing zarejestrowany i dziala
- [ ] OrderProAlerts.confirm() dla usuwania
- [ ] ARCHITECTURE.md zaktualizowany
</verification>
<success_criteria>
- Uzytkownik moze tworzyc, edytowac, aktywowac/dezaktywowac i usuwac konfiguracje paragonow
- Nawigacja w sidebarze dziala poprawnie
- Brak regresji w istniejacych ustawieniach
</success_criteria>
<output>
After completion, create `.paul/phases/09-receipt-config/09-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,126 @@
---
phase: 09-receipt-config
plan: 01
subsystem: ui
tags: [php, settings, receipts, crud, scss]
requires:
- phase: 08-db-foundation
provides: receipt_configs table
provides:
- CRUD konfiguracji paragonow (Ustawienia > Ksiegowosc)
- ReceiptConfigController + ReceiptConfigRepository
affects: [10-receipt-issue, 11-receipt-print, 12-accounting-list]
tech-stack:
added: []
patterns: [settings-controller-pattern for new modules]
key-files:
created:
- src/Modules/Settings/ReceiptConfigController.php
- src/Modules/Settings/ReceiptConfigRepository.php
- resources/views/settings/accounting.php
modified:
- resources/views/layouts/app.php
- routes/web.php
- resources/lang/pl.php
- resources/scss/shared/_ui-components.scss
- resources/scss/app.scss
- public/assets/css/app.css
- DOCS/ARCHITECTURE.md
key-decisions:
- "Request::input() zamiast query() — klasa Request nie ma metody query()"
- "Csrf::token() i Csrf::validate() jako bool — nie rzuca wyjatkow"
- "Tabela .table zamiast .data-table — data-table nie istnieje w SCSS"
- "form-grid align-items: start — zapobiega rozciaganiu pol przez hint/small"
patterns-established:
- "Nowe strony ustawien: wzorzec ReceiptConfigController (index+save+toggle+delete)"
duration: ~30min
completed: 2026-03-15
---
# Phase 9 Plan 01: Konfiguracja paragonow (Ustawienia > Ksiegowosc) Summary
**CRUD konfiguracji paragonow z nawigacja, tlumaczeniami i poprawkami globalnymi CSS (form-control, form-grid align).**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~30min |
| Completed | 2026-03-15 |
| Tasks | 5 completed |
| Files modified | 10 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Lista konfiguracji | Pass | Tabela z kolumnami Nazwa/Format/Typ/Status/Akcje |
| AC-2: Tworzenie konfiguracji | Pass | Formularz z walidacja nazwy i formatu |
| AC-3: Edycja konfiguracji | Pass | Link ?edit=ID wypelnia formularz |
| AC-4: Toggle aktywnosci | Pass | POST /settings/accounting/toggle |
| AC-5: Usuwanie z potwierdzeniem | Pass | OrderProAlerts.confirm() |
| AC-6: Sublinek Ksiegowosc | Pass | Widoczny i aktywny w sidebarze |
## Accomplishments
- Pelny CRUD konfiguracji paragonow z walidacja i flash messages
- Sublinek "Ksiegowosc" w nawigacji ustawien
- Globalne poprawki CSS: form-control kompaktniejszy, form-grid align-items: start
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `src/Modules/Settings/ReceiptConfigRepository.php` | Created | CRUD na receipt_configs |
| `src/Modules/Settings/ReceiptConfigController.php` | Created | 4 endpointy (index/save/toggle/delete) |
| `resources/views/settings/accounting.php` | Created | Lista + formularz konfiguracji |
| `resources/views/layouts/app.php` | Modified | Sublinek Ksiegowosc w sidebarze |
| `routes/web.php` | Modified | 4 trasy + use statements |
| `resources/lang/pl.php` | Modified | Tlumaczenia settings.accounting.* |
| `resources/scss/shared/_ui-components.scss` | Modified | form-control: min-height 30px, border-radius 6px |
| `resources/scss/app.scss` | Modified | form-grid-2/3/4: align-items start |
| `public/assets/css/app.css` | Modified | Build CSS |
| `DOCS/ARCHITECTURE.md` | Modified | Nowe trasy, klasy, przeplyw |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 4 | Krytyczne fixy API kontrolera + CSS |
### Auto-fixed Issues
**1. Request::query() nie istnieje**
- **Fix:** Zamieniono na Request::input() ktory obsluguje tez query params
**2. Csrf::generate() nie istnieje**
- **Fix:** Zamieniono na Csrf::token()
**3. Csrf::validate() zwraca bool, nie rzuca wyjatku**
- **Fix:** Zamieniono try/catch na if(!Csrf::validate())
**4. Klasa CSS data-table nie istnieje**
- **Fix:** Zamieniono na .table (istniejaca w _ui-components.scss)
## Next Phase Readiness
**Ready:**
- CRUD konfiguracji dziala — faza 10 moze pobierac aktywne konfiguracje do wystawiania paragonow
**Concerns:**
- Brak
**Blockers:**
- Brak
---
*Phase: 09-receipt-config, Plan: 01*
*Completed: 2026-03-15*