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:
203
.paul/phases/08-db-foundation/08-01-PLAN.md
Normal file
203
.paul/phases/08-db-foundation/08-01-PLAN.md
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
phase: 08-db-foundation
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- database/migrations/20260315_000050_create_receipt_configs_table.sql
|
||||
- database/migrations/20260315_000051_create_receipts_table.sql
|
||||
- database/migrations/20260315_000052_create_receipt_number_counters_table.sql
|
||||
- database/migrations/20260315_000053_extend_company_settings_extra_fields.sql
|
||||
- src/Modules/Settings/CompanySettingsRepository.php
|
||||
- resources/views/settings/company.php
|
||||
- DOCS/DB_SCHEMA.md
|
||||
- DOCS/ARCHITECTURE.md
|
||||
autonomous: false
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Wdrożyć migracje bazodanowe dla modułu paragonów (receipt_configs, receipts, receipt_number_counters) oraz rozszerzyć company_settings o pola wymagane na paragonach (BDO, REGON, KRS, logo). Zaktualizować UI danych firmy o nowe pola.
|
||||
|
||||
## Purpose
|
||||
Fundament bazodanowy pod cały moduł paragonów — bez tych tabel nie można przejść do logiki konfiguracji ani wystawiania.
|
||||
|
||||
## Output
|
||||
- 4 pliki migracji SQL (już utworzone, do weryfikacji)
|
||||
- Rozszerzony formularz danych firmy o pola BDO, REGON, KRS, logo
|
||||
- Zaktualizowane DOCS/DB_SCHEMA.md i DOCS/ARCHITECTURE.md
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Source Files
|
||||
@database/migrations/20260315_000050_create_receipt_configs_table.sql
|
||||
@database/migrations/20260315_000051_create_receipts_table.sql
|
||||
@database/migrations/20260315_000052_create_receipt_number_counters_table.sql
|
||||
@database/migrations/20260315_000053_extend_company_settings_extra_fields.sql
|
||||
@src/Modules/Settings/CompanySettingsRepository.php
|
||||
@resources/views/settings/company.php
|
||||
@DOCS/DB_SCHEMA.md
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Required Skills (from SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priority | When to Invoke | Loaded? |
|
||||
|-------|----------|----------------|---------|
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
|
||||
No specialized flows configured for DB migrations.
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Tabele paragonów istnieją po migracji
|
||||
```gherkin
|
||||
Given baza danych jest dostępna i migrator działa
|
||||
When uruchomię migracje pending
|
||||
Then istnieją tabele receipt_configs, receipts, receipt_number_counters z poprawnymi kolumnami, indeksami i FK
|
||||
```
|
||||
|
||||
## AC-2: Company settings rozszerzony o nowe pola
|
||||
```gherkin
|
||||
Given tabela company_settings istnieje
|
||||
When uruchomię migrację 000053
|
||||
Then tabela ma kolumny bdo_number, regon, court_register, logo_path
|
||||
```
|
||||
|
||||
## AC-3: Formularz danych firmy wyświetla i zapisuje nowe pola
|
||||
```gherkin
|
||||
Given użytkownik jest na stronie /settings/company
|
||||
When wypełni pola BDO, REGON, KRS, logo i kliknie Zapisz
|
||||
Then dane są zapisane w company_settings i widoczne po odświeżeniu
|
||||
```
|
||||
|
||||
## AC-4: Dokumentacja zaktualizowana
|
||||
```gherkin
|
||||
Given migracje zostały wdrożone
|
||||
When przeglądam DOCS/DB_SCHEMA.md i DOCS/ARCHITECTURE.md
|
||||
Then widzę opisy nowych tabel receipt_configs, receipts, receipt_number_counters oraz nowych kolumn company_settings
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Weryfikacja i wdrożenie migracji SQL</name>
|
||||
<files>
|
||||
database/migrations/20260315_000050_create_receipt_configs_table.sql,
|
||||
database/migrations/20260315_000051_create_receipts_table.sql,
|
||||
database/migrations/20260315_000052_create_receipt_number_counters_table.sql,
|
||||
database/migrations/20260315_000053_extend_company_settings_extra_fields.sql
|
||||
</files>
|
||||
<action>
|
||||
1. Przejrzeć 4 pliki migracji już utworzonych — zweryfikować poprawność SQL:
|
||||
- receipt_configs: pola name, is_active, number_format, numbering_type, is_named, sale_date_source, order_reference
|
||||
- receipts: FK do orders i receipt_configs, UNIQUE na receipt_number, indeksy, JSON kolumny
|
||||
- receipt_number_counters: UNIQUE na (config_id, year, month), FK do receipt_configs
|
||||
- company_settings: ADD COLUMN IF NOT EXISTS dla bdo_number, regon, court_register, logo_path
|
||||
2. Uruchomić migracje przez UI /settings/database lub bezpośrednio
|
||||
3. Zweryfikować struktury tabel po migracji
|
||||
</action>
|
||||
<verify>Sprawdzić SHOW CREATE TABLE dla receipt_configs, receipts, receipt_number_counters; SHOW COLUMNS FROM company_settings</verify>
|
||||
<done>AC-1 i AC-2 spełnione: tabele istnieją z poprawnymi kolumnami i kluczami</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Rozszerzenie formularza danych firmy o nowe pola</name>
|
||||
<files>
|
||||
src/Modules/Settings/CompanySettingsRepository.php,
|
||||
resources/views/settings/company.php
|
||||
</files>
|
||||
<action>
|
||||
1. W CompanySettingsRepository:
|
||||
- Dodać bdo_number, regon, court_register, logo_path do metody defaults()
|
||||
- Dodać te pola do saveSettings() (mapowanie z POST)
|
||||
- Dodać te pola do getSettings() jeśli nie zwracane automatycznie
|
||||
2. W resources/views/settings/company.php:
|
||||
- Dodać 4 nowe pola formularza (input text) w sekcji danych firmy:
|
||||
- Numer BDO (bdo_number) — varchar 20
|
||||
- REGON (regon) — varchar 14
|
||||
- KRS / Wpis do ewidencji (court_register) — varchar 128
|
||||
- Logo firmy (logo_path) — na razie pole tekstowe ze ścieżką (upload w przyszłości)
|
||||
- Zachować istniejący styl formularza
|
||||
3. Nie zmieniać kontrolera — CompanySettingsController::save() przekazuje wszystkie pola POST do repository
|
||||
</action>
|
||||
<verify>Odwiedzić /settings/company — zobaczyć nowe pola, wypełnić, zapisać, odświeżyć — dane zachowane</verify>
|
||||
<done>AC-3 spełnione: nowe pola widoczne i zapisywalne</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Migracje DB dla modułu paragonów + rozszerzony formularz danych firmy</what-built>
|
||||
<how-to-verify>
|
||||
1. Wejdź na /settings/database — uruchom pending migracje
|
||||
2. Wejdź na /settings/company — sprawdź czy są nowe pola (BDO, REGON, KRS, Logo)
|
||||
3. Wypełnij nowe pola, zapisz, odśwież — dane powinny być zachowane
|
||||
4. Potwierdź że istniejące dane firmy nie zniknęły
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Aktualizacja dokumentacji DB_SCHEMA.md i ARCHITECTURE.md</name>
|
||||
<files>DOCS/DB_SCHEMA.md, DOCS/ARCHITECTURE.md</files>
|
||||
<action>
|
||||
1. W DOCS/DB_SCHEMA.md dodać sekcje:
|
||||
- ### receipt_configs — z opisem kolumn, indeksów
|
||||
- ### receipts — z opisem kolumn, FK, indeksów
|
||||
- ### receipt_number_counters — z opisem kolumn, UNIQUE, FK
|
||||
- Zaktualizować sekcję company_settings o nowe kolumny
|
||||
- Dodać wpis chronologiczny w sekcji Status
|
||||
2. W DOCS/ARCHITECTURE.md:
|
||||
- Dodać moduł App\Modules\Accounting (przygotowanie)
|
||||
- Dodać informację o nowych tabelach w sekcji domen
|
||||
</action>
|
||||
<verify>Przejrzeć oba pliki — sprawdzić kompletność opisów nowych tabel</verify>
|
||||
<done>AC-4 spełnione: dokumentacja odzwierciedla nowy schemat</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Istniejące tabele (orders, order_items, order_activity_log) — żadnych zmian
|
||||
- Istniejące kontrolery i widoki niezwiązane z company settings
|
||||
- Logika istniejących integracji (Allegro, shopPRO, Apaczka, InPost)
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Nie tworzymy jeszcze kontrolera paragonów (Faza 09)
|
||||
- Nie tworzymy widoków konfiguracji paragonów (Faza 09)
|
||||
- Upload logo — na razie tylko pole tekstowe, upload w przyszłości
|
||||
- Nie dodajemy nawigacji do sekcji Księgowość (Faza 12)
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] 4 migracje wykonane bez błędów
|
||||
- [ ] Tabele receipt_configs, receipts, receipt_number_counters istnieją z poprawnymi strukturami
|
||||
- [ ] company_settings ma kolumny bdo_number, regon, court_register, logo_path
|
||||
- [ ] Formularz /settings/company wyświetla i zapisuje nowe pola
|
||||
- [ ] DOCS/DB_SCHEMA.md zaktualizowany
|
||||
- [ ] DOCS/ARCHITECTURE.md zaktualizowany
|
||||
- [ ] Istniejąca funkcjonalność danych firmy niezmieniona
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 4 migracje wykonane pomyślnie
|
||||
- Nowe pola w formularzu danych firmy działają (zapis + odczyt)
|
||||
- Dokumentacja kompletna
|
||||
- Brak regresji w istniejącej funkcjonalności
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/08-db-foundation/08-01-SUMMARY.md`
|
||||
</output>
|
||||
131
.paul/phases/08-db-foundation/08-01-SUMMARY.md
Normal file
131
.paul/phases/08-db-foundation/08-01-SUMMARY.md
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
phase: 08-db-foundation
|
||||
plan: 01
|
||||
subsystem: database
|
||||
tags: [mysql, migrations, receipts, company-settings]
|
||||
|
||||
requires: []
|
||||
provides:
|
||||
- receipt_configs table
|
||||
- receipts table
|
||||
- receipt_number_counters table
|
||||
- company_settings extended fields (bdo, regon, krs, logo)
|
||||
affects: [09-receipt-config, 10-receipt-issue, 11-receipt-print, 12-accounting-list]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [snapshot-json-pattern for receipts]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- database/migrations/20260315_000050_create_receipt_configs_table.sql
|
||||
- database/migrations/20260315_000051_create_receipts_table.sql
|
||||
- database/migrations/20260315_000052_create_receipt_number_counters_table.sql
|
||||
- database/migrations/20260315_000053_extend_company_settings_extra_fields.sql
|
||||
modified:
|
||||
- src/Modules/Settings/CompanySettingsRepository.php
|
||||
- resources/views/settings/company.php
|
||||
- DOCS/DB_SCHEMA.md
|
||||
- DOCS/ARCHITECTURE.md
|
||||
|
||||
key-decisions:
|
||||
- "receipts.order_id as BIGINT UNSIGNED (match orders.id type)"
|
||||
- "receipts uses JSON snapshots for seller/buyer/items data"
|
||||
- "receipt_configs ON DELETE RESTRICT (nie usuwaj konfiguracji z istniejacymi paragonami)"
|
||||
|
||||
patterns-established:
|
||||
- "Snapshot pattern: dane sprzedawcy/nabywcy/pozycji zapisywane jako JSON w momencie wystawienia"
|
||||
|
||||
duration: ~15min
|
||||
completed: 2026-03-15
|
||||
---
|
||||
|
||||
# Phase 8 Plan 01: DB Foundation + Company Settings Summary
|
||||
|
||||
**Migracje bazodanowe dla modulu paragonow (3 nowe tabele) + rozszerzenie company_settings o BDO/REGON/KRS/logo.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~15min |
|
||||
| Completed | 2026-03-15 |
|
||||
| Tasks | 4 completed |
|
||||
| Files modified | 8 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Tabele paragonow istnieja po migracji | Pass | receipt_configs, receipts, receipt_number_counters utworzone |
|
||||
| AC-2: Company settings rozszerzony | Pass | bdo_number, regon, court_register, logo_path dodane |
|
||||
| AC-3: Formularz wyswietla i zapisuje nowe pola | Pass | Zweryfikowane manualnie przez uzytkownika |
|
||||
| AC-4: Dokumentacja zaktualizowana | Pass | DB_SCHEMA.md i ARCHITECTURE.md zaktualizowane |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- 3 nowe tabele bazodanowe dla modulu paragonow (receipt_configs, receipts, receipt_number_counters)
|
||||
- Rozszerzenie company_settings o 4 pola wymagane na dokumentach ksiegowych
|
||||
- Formularz danych firmy zaktualizowany o nowe pola z pelnym zapisem/odczytem
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `database/migrations/20260315_000050_*.sql` | Created | Tabela receipt_configs |
|
||||
| `database/migrations/20260315_000051_*.sql` | Created | Tabela receipts |
|
||||
| `database/migrations/20260315_000052_*.sql` | Created | Tabela receipt_number_counters |
|
||||
| `database/migrations/20260315_000053_*.sql` | Created | Rozszerzenie company_settings |
|
||||
| `src/Modules/Settings/CompanySettingsRepository.php` | Modified | Dodano 4 nowe pola (get/save/defaults) |
|
||||
| `resources/views/settings/company.php` | Modified | Dodano pola REGON, BDO, KRS, Logo |
|
||||
| `DOCS/DB_SCHEMA.md` | Modified | Dokumentacja 3 nowych tabel + nowe kolumny |
|
||||
| `DOCS/ARCHITECTURE.md` | Modified | Dodano modul Accounting (w budowie) |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| receipts.order_id BIGINT UNSIGNED | orders.id jest BIGINT UNSIGNED — FK musi sie zgadzac | Fix bledu errno 150 |
|
||||
| ON DELETE RESTRICT dla receipt_configs | Nie mozna usunac konfiguracji jesli istnieja paragony | Bezpieczenstwo danych |
|
||||
| Logo jako sciezka tekstowa | Upload w przyszlosci, na razie pole tekstowe | Uproszczenie fazy 08 |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 1 | Krytyczny fix typu FK |
|
||||
|
||||
**Total impact:** Jeden fix krytyczny, brak scope creep.
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. FK type mismatch receipts.order_id**
|
||||
- **Found during:** Task 1 (migracje)
|
||||
- **Issue:** receipts.order_id bylo INT UNSIGNED, orders.id jest BIGINT UNSIGNED
|
||||
- **Fix:** Zmieniono na BIGINT UNSIGNED
|
||||
- **Files:** database/migrations/20260315_000051_create_receipts_table.sql
|
||||
- **Verification:** Migracja wykonana pomyslnie po poprawce
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| errno 150 FK constraint | Poprawiono typ order_id z INT na BIGINT UNSIGNED |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Tabele bazodanowe gotowe pod CRUD konfiguracji (faza 09)
|
||||
- Company settings kompletne pod snapshot danych sprzedawcy
|
||||
|
||||
**Concerns:**
|
||||
- Brak
|
||||
|
||||
**Blockers:**
|
||||
- Brak
|
||||
|
||||
---
|
||||
*Phase: 08-db-foundation, Plan: 01*
|
||||
*Completed: 2026-03-15*
|
||||
308
.paul/phases/09-receipt-config/09-01-PLAN.md
Normal file
308
.paul/phases/09-receipt-config/09-01-PLAN.md
Normal 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>
|
||||
126
.paul/phases/09-receipt-config/09-01-SUMMARY.md
Normal file
126
.paul/phases/09-receipt-config/09-01-SUMMARY.md
Normal 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*
|
||||
320
.paul/phases/10-receipt-issue/10-01-PLAN.md
Normal file
320
.paul/phases/10-receipt-issue/10-01-PLAN.md
Normal file
@@ -0,0 +1,320 @@
|
||||
---
|
||||
phase: 10-receipt-issue
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: ["09-01"]
|
||||
files_modified:
|
||||
- src/Modules/Accounting/ReceiptRepository.php
|
||||
- src/Modules/Accounting/ReceiptController.php
|
||||
- src/Modules/Orders/OrdersController.php
|
||||
- resources/views/orders/show.php
|
||||
- resources/views/orders/receipt-create.php
|
||||
- routes/web.php
|
||||
- resources/lang/pl.php
|
||||
- resources/scss/shared/_ui-components.scss
|
||||
- public/assets/css/app.css
|
||||
- DOCS/ARCHITECTURE.md
|
||||
autonomous: false
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Umozliwienie wystawiania paragonow z poziomu widoku zamowienia — przycisk "Wystaw paragon", formularz wyboru konfiguracji z podgladem pozycji, zapis do bazy z atomowym numerowaniem i snapshotem danych.
|
||||
|
||||
## Purpose
|
||||
Kluczowa funkcjonalnosc modulu Ksiegowosci (v0.3) — sprzedawca moze wystawic paragon bezposrednio z zamowienia, bez opuszczania widoku zamowienia.
|
||||
|
||||
## Output
|
||||
- `ReceiptRepository` — CRUD na `receipts` + atomowe numerowanie przez `receipt_number_counters`
|
||||
- `ReceiptController` — formularz tworzenia paragonu + zapis
|
||||
- Przycisk "Wystaw paragon" w widoku zamowienia
|
||||
- Lista wystawionych paragonow w zakladce "Dokumenty"
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
|
||||
## Prior Work
|
||||
@.paul/phases/08-db-foundation/08-01-SUMMARY.md — schemat tabel receipts, receipt_configs, receipt_number_counters
|
||||
@.paul/phases/09-receipt-config/09-01-SUMMARY.md — CRUD konfiguracji, ReceiptConfigRepository, wzorce Request/Csrf
|
||||
|
||||
## Source Files
|
||||
@database/migrations/20260315_000051_create_receipts_table.sql
|
||||
@database/migrations/20260315_000052_create_receipt_number_counters_table.sql
|
||||
@src/Modules/Settings/ReceiptConfigRepository.php
|
||||
@src/Modules/Settings/CompanySettingsRepository.php
|
||||
@src/Modules/Orders/OrdersController.php
|
||||
@resources/views/orders/show.php
|
||||
@routes/web.php
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## Required Skills (from SPECIAL-FLOWS.md)
|
||||
|
||||
| Skill | Priority | When to Invoke | Loaded? |
|
||||
|-------|----------|----------------|---------|
|
||||
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |
|
||||
|
||||
## Skill Invocation Checklist
|
||||
- [ ] sonar-scanner uruchomiony po APPLY
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Przycisk "Wystaw paragon" w widoku zamowienia
|
||||
```gherkin
|
||||
Given uzytkownik jest na stronie szczegulow zamowienia /orders/{id}
|
||||
When sa aktywne konfiguracje paragonow
|
||||
Then widoczny jest przycisk "Wystaw paragon" w sekcji akcji
|
||||
And przycisk prowadzi do formularza /orders/{id}/receipt/create
|
||||
```
|
||||
|
||||
## AC-2: Formularz wystawiania paragonu
|
||||
```gherkin
|
||||
Given uzytkownik otwiera /orders/{id}/receipt/create
|
||||
When formularz sie laduje
|
||||
Then widoczny jest select z aktywnymi konfiguracjami paragonow
|
||||
And wyswietlona jest tabela pozycji zamowienia (nazwa, ilosc, cena, suma)
|
||||
And wyswietlone sa pola: data wystawienia (domyslnie dzis), data sprzedazy (wg konfiguracji)
|
||||
And widoczny jest podglad danych sprzedawcy z company_settings
|
||||
And przycisk "Wystaw paragon" submituje formularz
|
||||
```
|
||||
|
||||
## AC-3: Zapis paragonu z atomowym numerowaniem
|
||||
```gherkin
|
||||
Given uzytkownik wypelnia formularz i klika "Wystaw paragon"
|
||||
When POST /orders/{id}/receipt/store jest wysylany
|
||||
Then tworzony jest rekord w tabeli receipts z:
|
||||
- receipt_number wygenerowanym atomowo z receipt_number_counters (INSERT ON DUPLICATE KEY UPDATE)
|
||||
- seller_data_json jako snapshot company_settings
|
||||
- items_json jako snapshot pozycji zamowienia
|
||||
- total_net i total_gross obliczone z pozycji
|
||||
- sale_date okreslona wg sale_date_source z konfiguracji
|
||||
- order_reference_value wypelnione wg order_reference z konfiguracji
|
||||
And uzytkownik jest przekierowany na /orders/{id} z flash success
|
||||
```
|
||||
|
||||
## AC-4: Lista paragonow w zakladce Dokumenty
|
||||
```gherkin
|
||||
Given zamowienie ma wystawione paragony
|
||||
When uzytkownik klika zakladke "Dokumenty"
|
||||
Then wyswietlona jest tabela paragonow (numer, data wystawienia, kwota brutto, konfiguracja)
|
||||
And kazdy paragon ma link do podgladu (na razie placeholder — faza 11)
|
||||
```
|
||||
|
||||
## AC-5: Walidacja — brak duplikatow i brak pustych konfiguracji
|
||||
```gherkin
|
||||
Given uzytkownik probuje wystawic paragon
|
||||
When nie ma aktywnych konfiguracji
|
||||
Then przycisk "Wystaw paragon" nie jest widoczny w widoku zamowienia
|
||||
|
||||
Given uzytkownik submituje formularz bez wybranej konfiguracji
|
||||
When POST jest wysylany
|
||||
Then zwracany jest blad walidacji i paragon nie jest tworzony
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: ReceiptRepository — CRUD + atomowe numerowanie</name>
|
||||
<files>src/Modules/Accounting/ReceiptRepository.php</files>
|
||||
<action>
|
||||
Utworz nowy modul `src/Modules/Accounting/` z klasa `ReceiptRepository`:
|
||||
|
||||
1. **Konstruktor:** przyjmuje `PDO $pdo`
|
||||
2. **getNextNumber(int $configId, string $numberFormat, string $numberingType): string**
|
||||
- Atomowe numerowanie przez `INSERT INTO receipt_number_counters (config_id, year, month, last_number) VALUES (:config_id, :year, :month, 1) ON DUPLICATE KEY UPDATE last_number = last_number + 1`
|
||||
- Odczyt `last_number` przez `SELECT last_number FROM receipt_number_counters WHERE config_id = :config_id AND year = :year AND month = :month`
|
||||
- Dla `numbering_type = 'yearly'`: month = NULL (w unique key)
|
||||
- Dla `numbering_type = 'monthly'`: month = biezacy miesiac
|
||||
- Podmiana w formacie: `%N` → numer (z zerem wiodacym min 3 cyfry), `%M` → miesiac (2 cyfry), `%Y` → rok (4 cyfry)
|
||||
3. **create(array $data): int**
|
||||
- INSERT do `receipts` ze wszystkimi polami
|
||||
- Zwraca `lastInsertId()`
|
||||
4. **findByOrderId(int $orderId): array**
|
||||
- SELECT receipts + LEFT JOIN receipt_configs (na nazwe konfiguracji)
|
||||
- ORDER BY created_at DESC
|
||||
5. **findById(int $id): ?array**
|
||||
- SELECT * WHERE id = :id
|
||||
|
||||
Wzorzec: analogicznie do ReceiptConfigRepository (PDO, prepared statements, strict types).
|
||||
Namespace: `App\Modules\Accounting`
|
||||
</action>
|
||||
<verify>Klasa parsuje sie bez bledow: `php -l src/Modules/Accounting/ReceiptRepository.php`</verify>
|
||||
<done>AC-3 backend spelnione: atomowe numerowanie i zapis paragonu</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: ReceiptController + routing + widok formularza</name>
|
||||
<files>
|
||||
src/Modules/Accounting/ReceiptController.php,
|
||||
resources/views/orders/receipt-create.php,
|
||||
routes/web.php,
|
||||
resources/lang/pl.php
|
||||
</files>
|
||||
<action>
|
||||
1. **ReceiptController** (`App\Modules\Accounting`):
|
||||
- Konstruktor: `Template, Translator, AuthService, ReceiptRepository, ReceiptConfigRepository, CompanySettingsRepository, OrdersRepository`
|
||||
- **create(Request $request): Response** — GET /orders/{id}/receipt/create
|
||||
- Pobierz zamowienie przez OrdersRepository::findDetails($orderId)
|
||||
- Pobierz aktywne konfiguracje: ReceiptConfigRepository::listAll() + filtruj is_active = 1
|
||||
- Pobierz dane sprzedawcy: CompanySettingsRepository::getSettings()
|
||||
- Renderuj widok `orders/receipt-create`
|
||||
- **store(Request $request): Response** — POST /orders/{id}/receipt/store
|
||||
- Walidacja: config_id wymagane, zamowienie istnieje
|
||||
- CSRF: Csrf::validate()
|
||||
- Pobierz konfiguracje (findById), zamowienie (findDetails), company settings
|
||||
- Oblicz sale_date wg `sale_date_source`: order_date → ordered_at, payment_date → z payments, issue_date → dzis
|
||||
- Oblicz order_reference_value wg `order_reference`: none → NULL, orderpro → internal_order_number, integration → external_order_id
|
||||
- Zbuduj seller_data_json z company_settings (company_name, tax_number, street, city, postal_code, phone, email, bank_account, bdo_number, regon, court_register)
|
||||
- Zbuduj buyer_data_json z address (invoice lub customer)
|
||||
- Zbuduj items_json z pozycji zamowienia (original_name, quantity, original_price_with_tax, sku, ean)
|
||||
- Oblicz total_gross = suma(qty * price), total_net = total_gross (paragony nie rozdzielaja netto/brutto — wartosc taka sama)
|
||||
- Wygeneruj numer przez ReceiptRepository::getNextNumber()
|
||||
- ReceiptRepository::create() ze wszystkimi danymi
|
||||
- Flash::set('order.success', 'Paragon wystawiony: ' . $receiptNumber)
|
||||
- Redirect /orders/{id}
|
||||
|
||||
2. **Widok receipt-create.php:**
|
||||
- Layout z naglowkiem "Wystaw paragon" + link powrotny do zamowienia
|
||||
- Select z aktywnymi konfiguracjami (name + number_format)
|
||||
- Tabela pozycji zamowienia (readonly): nazwa, ilosc, cena, suma
|
||||
- Podsumowanie kwoty brutto
|
||||
- Podglad danych sprzedawcy (readonly z company_settings)
|
||||
- Pole daty wystawienia (input date, domyslnie dzis)
|
||||
- Przycisk "Wystaw paragon" + CSRF token
|
||||
|
||||
3. **routes/web.php:**
|
||||
- Dodaj use statements: `ReceiptController`, `ReceiptRepository` (z `App\Modules\Accounting`)
|
||||
- Utworz instancje: `$receiptRepository = new ReceiptRepository($app->db())`
|
||||
- Utworz kontroler: `$receiptController = new ReceiptController($template, $translator, $auth, $receiptRepository, $receiptConfigRepository, $companySettingsRepository, new OrdersRepository($app->db()))`
|
||||
- Zarejestruj trasy:
|
||||
- `GET /orders/{id}/receipt/create` → `[$receiptController, 'create']`
|
||||
- `POST /orders/{id}/receipt/store` → `[$receiptController, 'store']`
|
||||
|
||||
4. **resources/lang/pl.php:**
|
||||
- Dodaj klucze `receipts.create.title`, `receipts.create.select_config`, `receipts.create.issue_date`, `receipts.create.submit`, `receipts.create.seller_data`, `receipts.create.items`, `receipts.create.total`, `receipts.create.back`
|
||||
|
||||
Wzorzec kontrolera: analogicznie do ReceiptConfigController (Csrf::token(), Csrf::validate(), Flash::set/get, Request::input()).
|
||||
NIE uzywaj natywnych alert()/confirm() — OrderProAlerts juz jest w uzyciu.
|
||||
</action>
|
||||
<verify>
|
||||
- `php -l src/Modules/Accounting/ReceiptController.php`
|
||||
- `php -l resources/views/orders/receipt-create.php`
|
||||
- Otworz /orders/{id}/receipt/create w przegladarce — formularz sie wyswietla
|
||||
</verify>
|
||||
<done>AC-2, AC-3, AC-5 spelnione: formularz, zapis, walidacja</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Integracja z widokiem zamowienia — przycisk + zakladka Dokumenty</name>
|
||||
<files>
|
||||
src/Modules/Orders/OrdersController.php,
|
||||
resources/views/orders/show.php,
|
||||
routes/web.php
|
||||
</files>
|
||||
<action>
|
||||
1. **OrdersController::show():**
|
||||
- Dodaj zaleznosc: `ReceiptConfigRepository` i `ReceiptRepository` (przez konstruktor lub przekazanie w widoku)
|
||||
- UWAGA: OrdersController ma juz 5 parametrow konstruktora. Zamiast rozszerzac konstruktor, przekaz dane przez nowe instancje w routes/web.php:
|
||||
- W web.php: pobierz aktywne configs i receipts w zamknieciu routera GET /orders/{id} LUB
|
||||
- Prostsze: dodaj `?ReceiptRepository` i `?ReceiptConfigRepository` do konstruktora OrdersController
|
||||
- W metodzie show(): pobierz `$receiptConfigs = $this->receiptConfigs->listAll()` (filtruj aktywne)
|
||||
- Pobierz `$receipts = $this->receipts->findByOrderId($orderId)`
|
||||
- Przekaz do widoku: `'receiptConfigs' => $activeConfigs, 'receipts' => $receipts`
|
||||
|
||||
2. **orders/show.php — przycisk "Wystaw paragon":**
|
||||
- W sekcji `.order-details-actions` (linia ~47-54):
|
||||
- Dodaj przycisk miedzy "Przygotuj przesylke" a "Platnosc":
|
||||
```php
|
||||
<?php if (($receiptConfigs ?? []) !== []): ?>
|
||||
<a href="/orders/<?= $e((string) ($orderId ?? 0)) ?>/receipt/create" class="btn btn--secondary">Wystaw paragon</a>
|
||||
<?php endif; ?>
|
||||
```
|
||||
- Przycisk widoczny tylko gdy sa aktywne konfiguracje (AC-1, AC-5)
|
||||
|
||||
3. **orders/show.php — zakladka Dokumenty:**
|
||||
- Zastap pusty placeholder w `data-order-tab-panel="documents"` (linia ~516-521):
|
||||
- Tabela paragonow: Numer, Data wystawienia, Kwota brutto, Konfiguracja, Akcje
|
||||
- Jesli brak paragonow: "Brak dokumentow"
|
||||
- Akcja: link "Podglad" (na razie `#` — placeholder do fazy 11)
|
||||
- Zaktualizuj licznik w zakladce: `Dokumenty (N)` gdzie N = count($receipts)
|
||||
|
||||
4. **routes/web.php:**
|
||||
- Dodaj `use App\Modules\Accounting\ReceiptRepository;` na gorze
|
||||
- Przekaz `$receiptRepository` i `$receiptConfigRepository` do konstruktora `$ordersController`
|
||||
|
||||
5. **DOCS/ARCHITECTURE.md:**
|
||||
- Dodaj modul Accounting z klasami ReceiptRepository, ReceiptController
|
||||
- Dodaj trasy GET/POST /orders/{id}/receipt/*
|
||||
</action>
|
||||
<verify>
|
||||
- Otworz /orders/{id} — przycisk "Wystaw paragon" widoczny (jesli sa aktywne configs)
|
||||
- Kliknij zakladke "Dokumenty" — tabela paragonow wyswietla sie
|
||||
- Po wystawieniu paragonu — pojawia sie na liscie w zakladce Dokumenty
|
||||
</verify>
|
||||
<done>AC-1, AC-4 spelnione: przycisk w widoku zamowienia + lista paragonow w Dokumentach</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Wystawianie paragonow z poziomu zamowienia — pelny flow: przycisk → formularz → zapis → lista w Dokumentach</what-built>
|
||||
<how-to-verify>
|
||||
1. Otworz dowolne zamowienie /orders/{id}
|
||||
2. Sprawdz: przycisk "Wystaw paragon" jest widoczny w akcjach
|
||||
3. Kliknij "Wystaw paragon" — formularz sie otwiera
|
||||
4. Wybierz konfiguracje, sprawdz podglad pozycji i danych sprzedawcy
|
||||
5. Kliknij "Wystaw paragon" w formularzu
|
||||
6. Sprawdz: redirect na zamowienie z flash "Paragon wystawiony: PAR/001/03/2026"
|
||||
7. Kliknij zakladke "Dokumenty" — paragon widoczny na liscie
|
||||
8. Wystaw drugi paragon — numer powinien byc PAR/002/03/2026
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- database/migrations/* (schemat zablokowany — tabele juz istnieja z fazy 08)
|
||||
- src/Modules/Settings/ReceiptConfigRepository.php (gotowe z fazy 09)
|
||||
- src/Modules/Settings/ReceiptConfigController.php (gotowe z fazy 09)
|
||||
- resources/views/settings/accounting.php (gotowe z fazy 09)
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Brak podgladu/wydruku paragonu — to faza 11
|
||||
- Brak edycji/anulowania paragonu — poza zakresem v0.3
|
||||
- Brak generowania PDF — to faza 11
|
||||
- Paragony nie rozdzielaja netto/brutto (total_net = total_gross) — uproszczenie dla paragonow
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `php -l src/Modules/Accounting/ReceiptRepository.php` — brak bledow
|
||||
- [ ] `php -l src/Modules/Accounting/ReceiptController.php` — brak bledow
|
||||
- [ ] Przycisk "Wystaw paragon" widoczny w /orders/{id} gdy sa aktywne konfiguracje
|
||||
- [ ] Formularz /orders/{id}/receipt/create wyswietla pozycje zamowienia i konfiguracje
|
||||
- [ ] Po wystawieniu paragonu: redirect + flash + rekord w bazie
|
||||
- [ ] Numer paragonu generowany atomowo (kolejne numery nie powtarzaja sie)
|
||||
- [ ] Zakladka Dokumenty wyswietla wystawione paragony
|
||||
- [ ] Brak bledow w konsoli PHP
|
||||
- [ ] All acceptance criteria met
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Wszystkie 3 taski auto + 1 checkpoint ukonczone
|
||||
- Wszystkie AC-1 do AC-5 spelnione
|
||||
- Brak bledow PHP (php -l na wszystkich nowych plikach)
|
||||
- Weryfikacja manualna przez uzytkownika (checkpoint)
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/10-receipt-issue/10-01-SUMMARY.md`
|
||||
</output>
|
||||
142
.paul/phases/10-receipt-issue/10-01-SUMMARY.md
Normal file
142
.paul/phases/10-receipt-issue/10-01-SUMMARY.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
phase: 10-receipt-issue
|
||||
plan: 01
|
||||
subsystem: accounting
|
||||
tags: [php, receipts, orders, crud, snapshots, atomic-numbering]
|
||||
|
||||
requires:
|
||||
- phase: 08-db-foundation
|
||||
provides: receipts, receipt_configs, receipt_number_counters tables
|
||||
- phase: 09-receipt-config
|
||||
provides: ReceiptConfigRepository CRUD, active configs
|
||||
provides:
|
||||
- Wystawianie paragonow z poziomu zamowienia
|
||||
- ReceiptRepository (CRUD + atomowe numerowanie)
|
||||
- ReceiptController (formularz + zapis ze snapshotami)
|
||||
- Przycisk "Wystaw paragon" w widoku zamowienia
|
||||
- Lista paragonow + dokumentow zewnetrznych w zakladce Dokumenty
|
||||
- Activity log entry po wystawieniu paragonu
|
||||
affects: [11-receipt-print, 12-accounting-list]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [snapshot-json-pattern for seller/buyer/items, atomic-counter-pattern for receipt numbering]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- src/Modules/Accounting/ReceiptRepository.php
|
||||
- src/Modules/Accounting/ReceiptController.php
|
||||
- resources/views/orders/receipt-create.php
|
||||
modified:
|
||||
- src/Modules/Orders/OrdersController.php
|
||||
- resources/views/orders/show.php
|
||||
- routes/web.php
|
||||
- resources/lang/pl.php
|
||||
- DOCS/ARCHITECTURE.md
|
||||
|
||||
key-decisions:
|
||||
- "ReceiptRepository w App\\Modules\\Accounting (nowy modul, nie w Settings)"
|
||||
- "Snapshot pattern: seller/buyer/items jako JSON w momencie wystawienia"
|
||||
- "Atomowe numerowanie: INSERT ON DUPLICATE KEY UPDATE na receipt_number_counters"
|
||||
- "total_net = total_gross (paragony nie rozdzielaja netto/brutto)"
|
||||
- "OrdersController rozszerzony o opcjonalne ?ReceiptRepository i ?ReceiptConfigRepository"
|
||||
|
||||
patterns-established:
|
||||
- "Modul Accounting: osobny namespace dla funkcjonalnosci ksiegowych"
|
||||
- "Snapshot przy tworzeniu dokumentu: dane zamrazane w JSON, niezalezne od przyszlych zmian zrodla"
|
||||
- "Activity log: recordActivity() po kazdej akcji generujacej dokument"
|
||||
|
||||
duration: ~25min
|
||||
completed: 2026-03-15
|
||||
---
|
||||
|
||||
# Phase 10 Plan 01: Wystawianie paragonow z zamowienia Summary
|
||||
|
||||
**Pelny flow wystawiania paragonow: przycisk w zamowieniu, formularz z podgladem pozycji/sprzedawcy, zapis z atomowym numerowaniem i snapshotami, lista w zakladce Dokumenty + wpis w historii.**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~25min |
|
||||
| Completed | 2026-03-15 |
|
||||
| Tasks | 3 auto + 1 checkpoint |
|
||||
| Files created | 3 |
|
||||
| Files modified | 5 |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Przycisk "Wystaw paragon" w widoku zamowienia | Pass | Widoczny tylko gdy sa aktywne konfiguracje |
|
||||
| AC-2: Formularz wystawiania paragonu | Pass | Select konfiguracji, tabela pozycji, podglad sprzedawcy, data wystawienia |
|
||||
| AC-3: Zapis paragonu z atomowym numerowaniem | Pass | INSERT ON DUPLICATE KEY UPDATE, snapshoty JSON |
|
||||
| AC-4: Lista paragonow w zakladce Dokumenty | Pass | Paragony + dokumenty zewnetrzne w osobnych sekcjach |
|
||||
| AC-5: Walidacja — brak duplikatow i brak pustych konfiguracji | Pass | Przycisk ukryty bez konfiguracji, walidacja config_id |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Nowy modul `App\Modules\Accounting` z ReceiptRepository i ReceiptController
|
||||
- Atomowe numerowanie paragonow przez receipt_number_counters (INSERT ON DUPLICATE KEY UPDATE)
|
||||
- Snapshoty seller/buyer/items jako JSON — dane zamrozone w momencie wystawienia
|
||||
- Zakladka Dokumenty wyswietla zarowno paragony jak i dokumenty zewnetrzne z marketplace
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `src/Modules/Accounting/ReceiptRepository.php` | Created | CRUD na receipts + atomowe numerowanie |
|
||||
| `src/Modules/Accounting/ReceiptController.php` | Created | Formularz tworzenia + zapis paragonu + activity log |
|
||||
| `resources/views/orders/receipt-create.php` | Created | Widok formularza wystawiania paragonu |
|
||||
| `src/Modules/Orders/OrdersController.php` | Modified | Dodano ?ReceiptRepository, ?ReceiptConfigRepository do konstruktora + show() |
|
||||
| `resources/views/orders/show.php` | Modified | Przycisk "Wystaw paragon", zakladka Dokumenty z paragony + dokumenty zewnetrzne |
|
||||
| `routes/web.php` | Modified | Instancje ReceiptRepository/ReceiptController, 2 nowe trasy |
|
||||
| `resources/lang/pl.php` | Modified | Tlumaczenia receipts.create.*, receipts.documents.*, receipt_issued |
|
||||
| `DOCS/ARCHITECTURE.md` | Modified | Klasy Accounting, przeplyw wystawiania paragonu |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Scope additions | 2 | User feedback — activity log + dokumenty zewnetrzne |
|
||||
|
||||
**Total impact:** Dwa uzasadnione rozszerzenia poza planem, poprawiajace UX.
|
||||
|
||||
### Scope Additions
|
||||
|
||||
**1. Activity log po wystawieniu paragonu**
|
||||
- **Source:** User feedback podczas checkpoint
|
||||
- **Issue:** Brak wpisu w historii zmian zamowienia po wystawieniu paragonu
|
||||
- **Fix:** Dodano recordActivity() z typem `receipt_issued` + tlumaczenie
|
||||
- **Files:** ReceiptController.php, resources/lang/pl.php
|
||||
|
||||
**2. Dokumenty zewnetrzne w zakladce Dokumenty**
|
||||
- **Source:** User feedback — licznik Dokumenty(2) ale widoczny tylko 1 paragon
|
||||
- **Issue:** Zakladka wyswietlala tylko paragony, nie dokumenty z order_documents
|
||||
- **Fix:** Dodano sekcje "Dokumenty zewnetrzne" z tabela order_documents
|
||||
- **Files:** resources/views/orders/show.php
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| Duplikacja instancji ReceiptConfigRepository/ReceiptRepository w web.php | Przeniesiono tworzenie przed ordersController, usunieto duplikaty |
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- ReceiptRepository::findById() gotowe pod podglad paragonu (faza 11)
|
||||
- Snapshoty JSON (seller, buyer, items) gotowe do renderowania HTML/PDF
|
||||
- receipt_number unikalne — gotowe do wyswietlania
|
||||
|
||||
**Concerns:**
|
||||
- Brak
|
||||
|
||||
**Blockers:**
|
||||
- Brak
|
||||
|
||||
---
|
||||
*Phase: 10-receipt-issue, Plan: 01*
|
||||
*Completed: 2026-03-15*
|
||||
Reference in New Issue
Block a user