---
phase: 97-project-generation
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - database/migrations/20260412_000097_add_project_generation.sql
  - src/Modules/Settings/ProjectMappingController.php
  - src/Modules/Settings/ProjectMappingRepository.php
  - resources/views/settings/project-mappings.php
  - resources/scss/modules/_project-mappings.scss
  - routes/web.php
  - resources/lang/pl.php
  - .claude/commands/wygeneruj-projekty.md
autonomous: false
delegation: off
---

<objective>
## Goal
Półautomat do generowania projektów graficznych (PSD) na podstawie danych klientów z zamówień. Claude Code jest silnikiem generowania — analizuje personalizację produktów, normalizuje dane klienta (rozumiejąc niuanse, literówki, różne formaty zapisu) i uruchamia odpowiedni skrypt Photoshop API.

## Purpose
Eliminacja ręcznej pracy przy tworzeniu projektów graficznych. Claude rozumie kontekst lepiej niż sztywny parser — potrafi zinterpretować "Kasia i Tomek 30 kwietnia", "Imiona: Kasia, Tomek\nData: 30.04.2026" i inne warianty jako te same dane wejściowe.

## Output
- Tabela DB `project_mappings` — mapowanie nazwy produktu → skrypt generujący
- Kolumna `project_generated` w `order_items` — flaga statusu generacji
- Strona w panelu: Ustawienia → Mapowanie projektów (CRUD)
- Komenda Claude Code `/wygeneruj-projekty` — skill uruchamiający cały przepływ
</objective>

<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md

## Source Files
@routes/web.php
@src/Modules/Settings/CompanySettingsController.php (wzorzec CRUD settings)
@src/Modules/Orders/OrdersRepository.php
@resources/views/settings/statuses.php (wzorzec widoku settings)
@tools/generowanie/buteleczki_wzor1.py (istniejący skrypt generujący)

## Technical Context
- Personalizacja produktów w `order_items.personalization` jako plain text (linie \n)
- Klienci piszą dane różnie — Claude interpretuje je kontekstowo
- Skrypty w `tools/generowanie/` przyjmują parametry CLI (--imie_zenskie, --imie_meskie, --data, --klient itd.)
- Skrypty wymagają uruchomionego Photoshopa (COM API)
- DB dostępne przez Medoo (PHP panel) i przez mysql CLI (Claude)
- Dane środowiskowe DB w .env (DB_HOST, DB_NAME, DB_USER, DB_PASS)

## Architektura przepływu
```
Użytkownik: /wygeneruj-projekty
       ↓
Claude: SELECT z DB → zamówienia "w realizacji", project_generated=0
       ↓
Claude: Sprawdź project_mappings → czy jest skrypt dla tego produktu
       ↓
Claude: Przeczytaj personalizację + dane kupującego
       ↓
Claude: Zinterpretuj dane (AI) → imie_zenskie, imie_meskie, data, zyczenia, klient
       ↓
Claude: python tools/generowanie/{skrypt}.py --parametry
       ↓
Claude: UPDATE order_items SET project_generated=1
       ↓
Claude: Raport — co wygenerowano, co się nie udało
```
</context>

<acceptance_criteria>

## AC-1: Tabela mapowań w bazie danych
```gherkin
Given baza danych orderPRO
When uruchomiona migracja 20260412_000097
Then istnieje tabela `project_mappings` z kolumnami: id, product_name_pattern, script_name, output_dir, is_active, created_at, updated_at
And istnieje kolumna `project_generated` (TINYINT DEFAULT 0) w tabeli `order_items`
And istnieje kolumna `project_generated_at` (DATETIME NULL) w tabeli `order_items`
```

## AC-2: CRUD mapowań w panelu ustawień
```gherkin
Given zalogowany użytkownik w panelu
When przechodzi do Ustawienia → Mapowanie projektów
Then widzi listę istniejących mapowań (wzorzec nazwy produktu → skrypt)
And może dodać nowe mapowanie (formularz: wzorzec nazwy, skrypt z dropdown, katalog wyjściowy)
And może edytować i usuwać istniejące mapowania
And może włączyć/wyłączyć mapowanie (is_active)
```

## AC-3: Komenda Claude Code /wygeneruj-projekty
```gherkin
Given komenda /wygeneruj-projekty zdefiniowana jako Claude Code skill
When użytkownik uruchamia /wygeneruj-projekty
Then Claude odpytuje bazę: zamówienia "w realizacji" z produktami gdzie project_generated=0
And dla każdego produktu sprawdza czy istnieje aktywne mapowanie (LIKE match)
And jeśli mapowanie istnieje — pobiera personalizację i dane kupującego
And Claude interpretuje dane kontekstowo (AI normalizacja)
And prezentuje użytkownikowi co zamierza wygenerować (imiona, data, klient) i czeka na potwierdzenie
And po potwierdzeniu uruchamia odpowiedni skrypt Python
And po sukcesie aktualizuje project_generated=1, project_generated_at=NOW()
And na końcu wyświetla raport: ile wygenerowano, ile pominięto, błędy
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Migracja DB — tabela project_mappings + kolumna project_generated</name>
  <files>database/migrations/20260412_000097_add_project_generation.sql</files>
  <action>
    Utwórz migrację SQL:
    
    1. Tabela `project_mappings`:
       - `id` INT AUTO_INCREMENT PRIMARY KEY
       - `product_name_pattern` VARCHAR(255) NOT NULL — wzorzec nazwy produktu (do LIKE match, np. "%buteleczk%")
       - `script_name` VARCHAR(255) NOT NULL — nazwa pliku skryptu w tools/generowanie/ (np. "buteleczki_wzor1.py")
       - `output_dir` VARCHAR(500) NULL — ścieżka do katalogu wyjściowego
       - `is_active` TINYINT(1) DEFAULT 1
       - `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP
       - `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    
    2. ALTER TABLE `order_items`:
       - ADD `project_generated` TINYINT(1) DEFAULT 0 AFTER `payload_json`
       - ADD `project_generated_at` DATETIME NULL AFTER `project_generated`
    
    Wzorzec: CREATE TABLE IF NOT EXISTS, ALTER TABLE z IF NOT EXISTS check
  </action>
  <verify>Migracja wykonuje się bez błędów na stronie /settings/database</verify>
  <done>AC-1 satisfied: tabela project_mappings istnieje, kolumna project_generated dodana do order_items</done>
</task>

<task type="auto">
  <name>Task 2: CRUD Mapowań projektów (backend + widok)</name>
  <files>
    src/Modules/Settings/ProjectMappingController.php,
    src/Modules/Settings/ProjectMappingRepository.php,
    resources/views/settings/project-mappings.php,
    resources/scss/modules/_project-mappings.scss,
    routes/web.php,
    resources/lang/pl.php
  </files>
  <action>
    1. ProjectMappingRepository — klasa final z Medoo:
       - getAll(): array — lista wszystkich mapowań
       - getById(int $id): ?array
       - create(array $data): int
       - update(int $id, array $data): bool
       - delete(int $id): bool
       - toggleActive(int $id): bool
    
    2. ProjectMappingController — wzorzec jak CompanySettingsController:
       - index() — lista mapowań + formularz dodawania
       - store() — zapis nowego mapowania (walidacja: product_name_pattern i script_name wymagane)
       - update() — edycja
       - delete() — usuwanie z potwierdzeniem OrderProAlerts
       - toggleActive() — włącz/wyłącz
       - Skanuj katalog tools/generowanie/*.py i wyświetl jako dropdown w formularzu
    
    3. Widok resources/views/settings/project-mappings.php:
       - Tabela: wzorzec nazwy produktu | skrypt | katalog wyjściowy | aktywny | akcje
       - Formularz dodawania/edycji inline
       - Dropdown ze skryptami z tools/generowanie/
       - Wzorzec UI jak inne strony ustawień (kompaktowy)
    
    4. Routing w web.php:
       - GET /settings/project-mappings → index
       - POST /settings/project-mappings → store
       - POST /settings/project-mappings/{id}/update → update
       - POST /settings/project-mappings/{id}/delete → delete
       - POST /settings/project-mappings/{id}/toggle → toggleActive
    
    5. Dodaj pozycję w menu ustawień
    
    Nie dodawaj natywnych alert()/confirm() — użyj OrderProAlerts.
    Style w SCSS, nie w widoku. CSRF: pole _token.
  </action>
  <verify>Strona /settings/project-mappings wyświetla się, CRUD działa</verify>
  <done>AC-2 satisfied: CRUD mapowań działa w panelu ustawień</done>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <what-built>Migracja DB + CRUD mapowań w panelu ustawień</what-built>
  <how-to-verify>
    1. Uruchom migrację na /settings/database
    2. Przejdź do Ustawienia → Mapowanie projektów
    3. Dodaj mapowanie: wzorzec "%buteleczk%" → skrypt "buteleczki_wzor1.py"
    4. Sprawdź edycję, toggle aktywności, usuwanie
    5. Potwierdź że UI jest spójne z resztą panelu
  </how-to-verify>
  <resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>

<task type="auto">
  <name>Task 3: Komenda Claude Code /wygeneruj-projekty</name>
  <files>.claude/commands/wygeneruj-projekty.md</files>
  <action>
    Utwórz plik `.claude/commands/wygeneruj-projekty.md` — skill Claude Code.
    
    Treść komendy powinna instruować Claude aby:
    
    1. Wczytał dane połączenia DB z .env (DB_HOST, DB_NAME, DB_USER, DB_PASS)
    
    2. Odpytał bazę (mysql CLI):
       - Pobierz aktywne mapowania z project_mappings
       - Pobierz zamówienia "w realizacji": JOIN orders + order_items + order_addresses
         WHERE orders.status IN (kody statusów z grupy "w realizacji")
         AND order_items.project_generated = 0
       - Dla każdego produktu sprawdź LIKE match z product_name_pattern
    
    3. Dla znalezionych produktów:
       - Wyświetl listę: zamówienie, produkt, personalizacja, dane kupującego
       - Zinterpretuj personalizację AI-em (wyciągnij imiona, datę, życzenia)
       - Pokaż co zamierza wygenerować i zapytaj o potwierdzenie
    
    4. Po potwierdzeniu:
       - Uruchom skrypt: python tools/generowanie/{script_name} --parametry
       - Po sukcesie: UPDATE order_items SET project_generated=1, project_generated_at=NOW() WHERE id={item_id}
    
    5. Wyświetl raport końcowy
    
    Ważne w instrukcji:
    - Photoshop musi być uruchomiony — sprawdź przed generowaniem
    - Dane klienta (--klient) to imię i nazwisko z order_addresses (type=customer)
    - Zawsze pytaj o potwierdzenie przed generowaniem
    - Przy błędzie skryptu — nie oznaczaj jako wygenerowane, pokaż błąd
  </action>
  <verify>Komenda /wygeneruj-projekty pojawia się w dostępnych komendach Claude Code</verify>
  <done>AC-3 satisfied: komenda działa, Claude jest silnikiem generowania</done>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <what-built>Pełny przepływ generowania projektów z komendą /wygeneruj-projekty</what-built>
  <how-to-verify>
    1. Upewnij się że Photoshop jest uruchomiony
    2. W panelu dodaj mapowanie: "%buteleczk%" → "buteleczki_wzor1.py"
    3. Upewnij się że jest zamówienie "w realizacji" z produktem "buteleczka" i personalizacją
    4. Uruchom /wygeneruj-projekty w Claude Code
    5. Sprawdź: Claude znalazł zamówienie, poprawnie zinterpretował dane, zapytał o potwierdzenie
    6. Po potwierdzeniu: PSD wygenerowany, project_generated=1 w bazie
  </how-to-verify>
  <resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- tools/generowanie/buteleczki_wzor1.py (istniejący skrypt — nie modyfikuj)
- src/Modules/Orders/OrdersController.php (nie zmieniaj istniejącej logiki)
- Istniejące tabele DB (nie modyfikuj struktury orders, order_addresses)
- Szablony PSD (nie modyfikuj plików projektowych)

## SCOPE LIMITS
- Tylko CRUD mapowań + komenda Claude Code — brak serwisu PHP do generowania
- Generowanie uruchamiane ręcznie komendą — brak crona/automatyzacji
- Brak podglądu wygenerowanych projektów w panelu
- Brak zmian w widoku listy zamówień (project_generated nie wyświetlane)

</boundaries>

<verification>
Before declaring plan complete:
- [ ] Migracja wykonuje się bez błędów
- [ ] CRUD mapowań działa (dodaj, edytuj, usuń, toggle)
- [ ] Komenda /wygeneruj-projekty poprawnie odpytuje DB
- [ ] Claude interpretuje personalizację i prezentuje dane do potwierdzenia
- [ ] Po potwierdzeniu — skrypt generuje PSD z poprawnymi danymi
- [ ] project_generated = 1 po udanej generacji
- [ ] Brak natywnych alert()/confirm() — OrderProAlerts
- [ ] Style w SCSS, nie inline
- [ ] CSRF w formularzach (_token)
</verification>

<success_criteria>
- Wszystkie zadania ukończone
- Wszystkie weryfikacje przechodzą
- Wygenerowany PSD ma poprawne dane i zachowane pozycje warstw
- System gotowy do rozszerzenia o nowe skrypty generujące
</success_criteria>

<output>
After completion, create `.paul/phases/97-project-generation/97-01-SUMMARY.md`
</output>
