Files
orderPRO/.claude/commands/wygeneruj-projekty.md
2026-04-20 23:17:25 +02:00

336 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Generowanie projektów graficznych z zamówień
Jesteś silnikiem generowania projektów graficznych dla zamówień w orderPRO. Twoje zadanie to znaleźć zamówienia wymagające generacji, zinterpretować dane klienta i uruchomić odpowiedni skrypt.
## Opcjonalne parametry filtrowania
Komenda przyjmuje opcjonalny argument (wolnotekstowy) zawężający zakres generacji:
- **Numer zamówienia** — np. `OP000123`, `OP000000385` (pattern: zaczyna się od `OP` + cyfry) → filtr `o.internal_order_number = '<wartość>'`.
- **Klient** — imię/nazwisko lub fragment (np. `Kowalska`, `Anna Kowalska`) → filtr `oa.name LIKE '%<wartość>%'`.
- **Produkt** — fragment nazwy produktu (np. `buteleczka`, `pudelko chrzest`) → filtr `oi.original_name LIKE '%<wartość>%'`.
**Rozpoznanie typu argumentu:**
1. Jeśli pasuje do regex `^OP\d+$` (po znormalizowaniu case) → numer zamówienia.
2. W przeciwnym razie spróbuj jako klient (`oa.name LIKE`). Jeśli wynik pusty → spróbuj jako produkt (`oi.original_name LIKE`).
3. Jeśli użytkownik jawnie napisał `klient:<x>` / `zamowienie:<x>` / `produkt:<x>` — użyj dokładnie tego typu bez zgadywania.
4. Brak argumentu → standardowy tryb (wszystkie pasujące pozycje).
Zawsze raportuj w wstępie: "Filtr: <typ> = <wartość>" albo "Filtr: brak (wszystkie zamówienia)".
**WAŻNE:** Filtry zawężają tylko wybór pozycji — pozostałe reguły (status grupy 2, `project_generated = 0`, wymagana personalizacja, aktywne mapowanie) **obowiązują nadal**. Jeśli filtr nie zwróci nic — poinformuj użytkownika wprost, że żadna pasująca pozycja nie wymaga generacji.
## Przepływ
### 1. Połącz się z bazą danych
Wczytaj dane z pliku `.env` w katalogu projektu:
- `DB_HOST_REMOTE` — host bazy (użyj remote, nie localhost)
- `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `DB_PORT`
Użyj `"C:/xampp/mysql/bin/mysql.exe"` do zapytań (z flagą `--default-character-set=utf8mb4`).
### 2. Pobierz aktywne mapowania
```sql
SELECT id, product_name_pattern, script_name, output_dir, requires_photo
FROM project_mappings
WHERE is_active = 1;
```
Jeśli brak mapowań — poinformuj użytkownika i zakończ.
### 3. Znajdź zamówienia do generacji (z dopasowaniem do mapowań)
Schemat bazy danych — kluczowe kolumny:
- `orders.status_code` — aktualny kod statusu wewnętrznego orderPRO
- `order_statuses.code` — kody statusów, wiązanie: `orders.status_code = order_statuses.code`
- `order_statuses.group_id``order_status_groups.id` — grupy statusów
- `order_items.original_name` — nazwa produktu
- `order_items.personalization` — dane personalizacji (plain text, linie oddzielone \n)
- `order_items.project_generated` — 0 = nie wygenerowano, 1 = wygenerowano
- `order_addresses.address_type` — typ adresu ('customer', 'delivery', 'invoice')
- `order_addresses.name` — pełne imię i nazwisko kupującego
- `order_notes.note_type = 'message'` — wiadomość od klienta do zamówienia (pole `comment`), traktowana jako dodatkowy kontekst do personalizacji
Jedno zapytanie łączy zamówienia z mapowaniami (JOIN eliminuje produkty bez mapowania):
```sql
SELECT
oi.id AS item_id,
oi.original_name AS product_name,
oi.personalization,
oi.quantity,
o.id AS order_id,
o.internal_order_number,
o.status_code AS status_code,
oa.name AS buyer_name,
oa.email AS buyer_email,
pm.script_name,
pm.output_dir,
pm.requires_photo,
(
SELECT GROUP_CONCAT(n.comment SEPARATOR '\n---\n')
FROM order_notes n
WHERE n.order_id = o.id AND n.note_type = 'message'
) AS customer_message
FROM order_items oi
JOIN orders o ON oi.order_id = o.id
JOIN order_statuses os ON o.status_code = os.code
JOIN order_status_groups osg ON os.group_id = osg.id
JOIN project_mappings pm ON pm.is_active = 1
AND oi.original_name = pm.product_name_pattern
LEFT JOIN order_addresses oa ON o.id = oa.order_id AND oa.address_type = 'customer'
WHERE osg.id = 2
AND oi.project_generated = 0
AND oi.personalization IS NOT NULL
AND oi.personalization <> ''
-- {{OPTIONAL_FILTER}}
ORDER BY o.id;
```
**Podstawienie filtra** (patrz sekcja "Opcjonalne parametry filtrowania"):
- Numer zamówienia: `AND o.internal_order_number = '<wartość>'`
- Klient: `AND oa.name LIKE '%<wartość>%'`
- Produkt: `AND oi.original_name LIKE '%<wartość>%'`
- Brak argumentu: usuń marker, nie dodawaj nic.
Escape'uj apostrofy w wartości (zamień `'` na `''`) zanim wstawisz do SQL.
Jeśli brak wyników — poinformuj użytkownika że nie ma zamówień do generacji pasujących do aktywnych mapowań (przy aktywnym filtrze — wskaż, że żadna pozycja nie pasuje do podanego filtra).
### 5. Zinterpretuj dane klienta (AI normalizacja)
Dla każdego pasującego produktu:
- Przeczytaj pole `personalization` z `order_items` **ORAZ** `customer_message` (wiadomość klienta do zamówienia z `order_notes.note_type = 'message'`) **ORAZ** wiadomości mailowe od klienta z INBOX (patrz niżej).
**Sprawdzanie maili od klienta (analogicznie do zdjęć):**
Jeśli zamówienie ma `buyer_email`, przed interpretacją uruchom:
```bash
python tools/generowanie/email_message_fetcher.py --email "{buyer_email}" --days 60 --json
```
- Skrypt przeszukuje **wyłącznie INBOX** skrzynki `EMAIL_01` i zwraca JSON z listą wiadomości (`date`, `subject`, `body`), od najnowszej do najstarszej.
- Exit 0 + JSON = są maile; exit 1 + `BRAK` = brak wiadomości (to normalny przypadek — nie blokuj generacji).
- Jeśli są wiadomości — wczytaj treści i traktuj jako dodatkowe źródło korekt/uwag klienta (tak samo jak `customer_message` z bazy, tylko późniejsze w czasie). Przy sprzecznościach: **najnowszy mail > starsze maile > `customer_message` z bazy > `personalization`**.
- Odfiltruj maile ewidentnie niezwiązane z zamówieniem (np. automatyczne odpowiedzi, tematy typu "Re: faktura", zapytania o zupełnie inny produkt). Zostaw tylko te wyglądające na poprawki/uzupełnienia personalizacji.
- Raportuj w planie w kolumnie "Mail klienta": `BRAK` / `N wiadomości — najnowsza: {krótkie streszczenie}` — żeby użytkownik widział, że sprawdziłaś.
- **Traktuj oba źródła łącznie.** Wiadomość klienta do zamówienia często zawiera doprecyzowania, korekty, dodatkowe życzenia, preferencje zapisu imion, poprawki literówek, prośby typu "zamiast Kasia wpiszcie Kasiu", uzupełnienia brakujących pól (np. data, życzenia). Jeśli wiadomość klienta i personalizacja są **sprzeczne**, preferuj wiadomość klienta (jest późniejsza, bardziej świadoma) — ale zaraportuj konflikt w planie.
- Jeśli `customer_message` zawiera treści niezwiązane z personalizacją (np. "proszę o szybką wysyłkę", "dziękuję") — zignoruj do celów generacji, ale odnotuj w planie w kolumnie "Wiadomość klienta" żeby użytkownik widział że sprawdziłaś.
- Zinterpretuj dane kontekstowo. Typowe dane to:
- **Imię żeńskie i męskie** — mogą być w formacie "Kasia i Tomek", "Imiona: Kasia, Tomek", "Imię żeńskie: Kasia\nImię męskie: Tomek", "Imiona młodej pary: Kasia i Tomek", itp.
- **Data uroczystości** — format DD.MM.YYYY, może być opisana jako "Data: 30.04.2026" lub "Data uroczystości: 30.04.2026" lub po prostu "30.04.2026"
- **Życzenia** — opcjonalny tekst (np. "Na zdrowie!", "Dziękujemy!"). Jeśli brak — zostaw domyślne z szablonu
- Ignoruj pola takie jak "Kolor tekstu", "Zakrętka" — te dotyczą produkcji, nie projektu
- **Imię dziecka — forma zależna od skryptu:**
- **Pudełka, magnesy (`pudelko_*`, `magnes_*`)** — dopełniacz: "Chrzest Święty [kogo?]", "Komunia Święta [kogo?]". Przykłady: Ignacy → Ignacego, Teodor → Teodora, Zosia → Zosi, Maja → Mai, Jakub → Jakuba. Raportuj przekształcenie w planie.
- **Prośby o chrzestnego (`prosba_chrzestny_*`)** — **mianownik**: imię dziecka to podpis na karcie (dziecko „pisze" prośbę). Przekaż dosłownie: Tymon → Tymon, Borysek → Borysek. NIE stosuj dopełniacza.
- **Nazwa klienta** (do nazwy pliku wyjściowego) — z `order_addresses.name` (pole `buyer_name` w zapytaniu)
**WAŻNE — semantyczny podział pola "Kto składa życzenia" na `naglowek` + `od_kogo`:**
Pole `Kto składa życzenia` w personalizacji klienta NIE jest jednoznacznie = `--od-kogo`. Szablony pudełek chrzest/komunia mają dwa osobne teksty nad i pod życzeniami: `naglowek` (fraza życzeniowa, np. "Z najlepszymi życzeniami") oraz `od_kogo` (podpis, np. "Matka Chrzestna"). Klienci często wklejają w jedno pole frazę życzeniową + podpis — trzeba to **semantycznie** rozdzielić, bazując na znajomości języka polskiego.
Zasady:
- **Czysty podpis** (krótki, typu "Twoja chrzestna", "Ciocia Gabi i wujek Filip", "Rodzice Chrzestni") → cały tekst jako `--od-kogo`, `naglowek` domyślny z szablonu.
- **Fraza życzeniowa + podpis** (np. "Z miłością i modlitwą w dniu Chrztu Świętego Matka Chrzestna z rodziną") → podziel:
- Część życzeniowa → `--naglowek` ("Z miłością i modlitwą w dniu Chrztu Świętego")
- Podpis → `--od-kogo` ("Matka Chrzestna z rodziną")
- **Rola rodzinna + konkretne osoby** (np. "Rodzice Chrzestni - Ciocia Ania i Wujek Wojtek") → zostaw jako całość w `--od-kogo`. "Rodzice Chrzestni" to rola, nie fraza życzeniowa.
Separatorem może być myślnik (``, `—`, ` - `), nowa linia, dwukropek, przecinek, **lub nic** — decyduj semantycznie, nie mechanicznie.
Heurystyki rozpoznania frazy życzeniowej (→ `naglowek`):
- zawiera słowa typu: "z miłością", "z modlitwą", "z najlepszymi życzeniami", "w dniu", "błogosławieństwa", "na pamiątkę"
- ma charakter uroczysty, długości >20 znaków
- nie wskazuje konkretnej osoby ani roli rodzinnej
Heurystyki rozpoznania podpisu (→ `od_kogo`):
- role rodzinne: Matka/Ojciec Chrzestny, Rodzice Chrzestni, Ciocia, Wujek, Babcia, Dziadek
- imiona własne, "z rodziną"
**W razie wątpliwości** — pokaż użytkownikowi obie interpretacje w planie (opcja A/B) i zapytaj, zamiast zgadywać.
**WAŻNE — łączenie wielu pozycji jednego zamówienia w jeden plik (prośby o bycie chrzestnym):**
Dla produktów mapujących się na skrypt `prosba_chrzestny_*.py` — szablon ma dwie ścianki (matka + ojciec) i skrypt akceptuje oba zestawy parametrów jednocześnie.
**Kluczowa zasada:** grupowanie po `(order_id, script_name)`, **nie** po nazwie produktu. Produkty w bazie mają różne nazwy dla matki i ojca (np. `"Akrylowa prośba o zostanie Ojcem Chrzestnym lustrzana złota - Dłonie"` i `"Akrylowa prośba o zostanie Matką Chrzestną lustrzana złota - Dłonie"`), ale mapują się **na ten sam skrypt**. Dlatego mapowania w `project_mappings` muszą mieć OSOBNY wpis dla każdej nazwy produktu wskazujący na ten sam `script_name`.
Algorytm dla skryptów `prosba_chrzestny_*`:
1. Po pobraniu listy zamówień **pogrupuj** pozycje po `(order_id, script_name)`.
2. Dla każdej grupy (jedno zamówienie + jeden skrypt):
- Rozpoznaj po nazwie produktu lub treści personalizacji, która pozycja to **ojciec**, a która **matka** (słowa-klucze: "Ojcem Chrzestnym", "Wujku", "moim" → ojciec; "Matką Chrzestną", "Ciociu", "moją" → matka).
- `--imie-dziecka` jest wspólne — wyciągnij z personalizacji (zwykle jedno imię dziecka powtarza się w obu pozycjach).
- `--matka-wolacz` / `--ojciec-wolacz` — z odpowiadających pozycji.
- Uruchom skrypt **raz** z obydwoma parametrami.
3. Wygenerowany zostanie **jeden plik PSD** zawierający obie karty na A3.
4. Oznacz **obie** pozycje `order_items` jako `project_generated = 1` po sukcesie (update po `id IN (item_id_matka, item_id_ojciec)`).
Pozostałe przypadki:
- 1× matka + 1× ojciec → **jeden plik** z obojgiem.
- tylko 1× matka → **jeden plik** z samą matką (DP ukryty).
- tylko 1× ojciec → **jeden plik** z samym ojcem (DL ukryty).
- 2× ta sama strona (np. 2× matka) → **jeden plik** z matką; `quantity` decyduje o liczbie wydruków, nie liczba plików PSD; oznacz obie pozycje jako generowane.
**Przykład** (OP000000385): 2 pozycje — `Akrylowa prośba o zostanie Ojcem Chrzestnym...` (Wujku Adi, Laura) + `Akrylowa prośba o zostanie Matką Chrzestną...` (Ciociu Dario, Laura). Wynik: JEDEN plik `Natalia Kwapisz.psd` z `--imie-dziecka "Laura" --ojciec-wolacz "Wujku Adi" --matka-wolacz "Ciociu Dario"`.
**Rozpoznawanie matka/ojciec — po treści personalizacji, NIE po nazwie produktu:**
Klienci często mylą się przy wyborze produktu i zamawiają np. 2× "Matką Chrzestną", ale w personalizacji jedna z pozycji ma treść męską ("Wujku..."). **Nie sugeruj się nazwą produktu** — analizuj treść personalizacji i rozpoznaj:
- `"Wujku [imię]"`, `"Wujek"`, `"moim Ojcem"`, `"Ojcem Chrzestnym"`**ojciec** (`--ojciec-wolacz`)
- `"Ciociu [imię]"`, `"Ciocia"`, `"moją Matką"`, `"Matką Chrzestną"`**matka** (`--matka-wolacz`)
Jeśli w jednym zamówieniu klient wybrał 2× ten sam produkt, ale personalizacje wskazują na matkę + ojca — zinterpretuj jako 1 plik z obojgiem chrzestnych.
**Normalizacja wołaczy — klient podaje tylko imię w mianowniku:**
Szablon oczekuje formy typu `"Ciociu Kasiu"` / `"Wujku Darku"` (prefiks roli + wołacz imienia). Jeśli klient podał tylko imię w mianowniku (np. `"Imię cioci: Paulina"`, `"Wujek: Dawid"`, `"Ciocia: Julia"`) — **automatycznie przekształć**:
1. Z imienia w mianowniku utwórz **wołacz polski** (Paulina → Paulino, Dawid → Dawidzie, Julia → Julio, Kasia → Kasiu, Darek → Darku, Michał → Michale, Ola → Olu, itd.).
2. Dodaj prefiks roli: `"Ciociu "` dla matki, `"Wujku "` dla ojca.
3. Finalny format: `"Ciociu Paulino"`, `"Wujku Dawidzie"`, `"Ciociu Julio"`.
**Wyjątek:** Jeśli klient **wyraźnie pisze** że ma być bez zwrotu (np. "bez Ciociu", "tylko imię", "samo imię"), wtedy wstawiaj surowe imię bez prefiksu. W każdym innym przypadku — zawsze dodawaj `Ciociu`/`Wujku`.
**Jeśli klient już podał pełną formę** (`"Ciociu Paulino"`, `"Wujku Dawidzie"`) — zostaw dosłownie, nie modyfikuj.
Te reguły (rozpoznawanie płci po treści + auto-wołacz) są domyślne — NIE pytaj użytkownika za każdym razem, tylko raportuj w planie co zrobiono (oryginał → przekształcenie), żeby mógł zweryfikować.
**WAŻNE — zaproszenia akrylowe (skrypt `zaproszenie_chrzest_*.py`):**
Szablon ma 4 ścianki na A3 (DP, DL, GP, GL) — 4 zaproszenia na arkusz. **Wspólne dla wszystkich ścianek:** imię dziecka, miejsce_data, poczęstunek. **Różne:** `od_kogo` (każda ścianka = jedna osoba zapraszana).
**Grupowanie wielu pozycji zamówienia (analogicznie do próśb o chrzestnego):**
W jednym zamówieniu może być kilka pozycji tego samego (lub mapującego się na ten sam skrypt) produktu zaproszeń. **NIE** generuj pliku per pozycja. Zasady:
1. Pogrupuj pozycje po `(order_id, script_name)`.
2. Dla każdej grupy zbierz **wszystkie osoby zapraszane** ze wszystkich pozycji (z `personalization` każdej pozycji, + uwzględnij `quantity` jeśli klient w jednej pozycji podał wiele osób z quantity > 1).
3. Połącz w jedną listę `od_kogo`.
4. Wspólne dane (imię dziecka, miejsce_data, poczęstunek) — wyciągnij raz, z pierwszej pozycji (powinny być identyczne we wszystkich pozycjach grupy, jeśli nie — zapytaj użytkownika).
5. Zastosuj **batching po 4**: podziel listę `od_kogo` na partie po 4 i wywołaj skrypt N razy z numerowanymi nazwami plików.
6. Po sukcesie oznacz **wszystkie** pozycje grupy jako `project_generated = 1`.
**Batching przy quantity > 4:** 1 plik PSD = max 4 zaproszenia. Jeśli klient zamawia więcej osób (np. 17 zaproszeń), silnik dzieli listę na partie po 4 i wywołuje skrypt wielokrotnie z numerowanymi nazwami plików:
- 17 zaproszeń → 5 plików: `Klient 01.psd` (4), `Klient 02.psd` (4), `Klient 03.psd` (4), `Klient 04.psd` (4), `Klient 05.psd` (1).
- 4 zaproszenia → 1 plik `Klient.psd` (bez numeracji).
- 6 zaproszeń → 2 pliki: `Klient 01.psd` (4) + `Klient 02.psd` (2).
Numerowanie nadawane przez silnik (nie przez skrypt). Zderzenia nazw w `_gotowe/` są rozstrzygane normalnym sufiksem.
**Interpretacja skrótowej personalizacji klienta:**
Klienci wpisują dane skrótowo, trzeba je rozwinąć patrząc na oryginalne placeholdery w szablonie. Przykłady:
Wejście klienta:
```
Imię dziecka: Teodor Surma
Imię i nazwisko proszonego gościa: Matkę Chrzestną Wiktorię Igras
na Chrzest Święty w Parafia pw. Świętej Jadwigi Śląskiej w Hedwiżynie 45A
Data i godzina: 18 Kwiecień 2026 Godzina 13.00
Miejsce przyjęcia: "Kresovia Biłgoraj - Sala Balowa, Okrągłe 1C, 23-400 Biłgoraj"
```
Przekształcenie na parametry skryptu:
- `--imie-dziecka "Teodora"` (mianownik "Teodor" → dopełniacz, bo szablon: "uroczystość przyjęcia Sakramentu Chrztu Świętego [kogo?] Teodora")
- `--miejsce-data "W dniu 18.04.2026\ro godzinie 13:00\rParafia pw. Świętej Jadwigi Śląskiej\rw Hedwiżynie 45A"` (format jak w oryginale: "W dniu DD.MM.RRRR o godzinie HH:MM\rParafia...\rulica")
- `--poczestunek "Po uroczystości serdecznie zapraszamy\rna poczęstunek do Kresovia Biłgoraj - Sala Balowa\rOkrągłe 1C, 23-400 Biłgoraj"` (format jak w oryginale)
- `--od-kogo-1 "Matkę Chrzestną Wiktorię Igras"` (poprawiam literówki "Chszestną" → "Chrzestną")
**Zasady rozwijania danych:**
- Daty: `"18 Kwiecień 2026 Godzina 13.00"``"W dniu 18.04.2026\ro godzinie 13:00"` (miesiąc po polsku → numer, "Godzina 13.00" → "o godzinie 13:00", dodany prefiks "W dniu").
- Parafia: `"Parafia pw. X w Y 45A"` → zostaw bez zmian, złącz łamaniem linii w logiczne miejsca.
- Miejsce przyjęcia: osadź w formule "Po uroczystości serdecznie zapraszamy na poczęstunek do [NAZWA]\r[ULICA, KOD MIASTO]".
- Imię dziecka: zawsze dopełniacz (szablon: "Chrztu Świętego [kogo?]").
- Literówki klienta (`"Chszestną"``"Chrzestną"`, `"Chszestnego"``"Chrzestnego"`) — **poprawiaj automatycznie**.
- Nazwisko zapraszanego gościa: zostaw w formie jaką podał klient (nie odmieniaj jeśli nie jesteś pewny).
**Jeśli klient nie podał czegoś** (np. brak miejsca przyjęcia = brak poczęstunku) → `--poczestunek` pomiń, warstwa zostanie ukryta.
**Formatowanie daty — specyficzne dla szablonu:**
Niektóre szablony mają nietypowy format daty (np. `"10 | 05 | 2026"` z pipe'ami). Skrypt przyjmuje datę **dosłownie** — silnik `/wygeneruj-projekty` musi przekształcić standardowy format klienta (`DD.MM.RRRR` lub `DD-MM-RRRR`) na format oczekiwany przez szablon, zanim wywoła skrypt.
Obecne wzorce formatów daty per skrypt:
- `pudelko_komunia_kwiaty_wzor2.py` → format `"DD | MM | RRRR"` (np. `"10 | 05 | 2026"`). Silnik: `"10.05.2026"``"10 | 05 | 2026"`.
- `pudelko_komunia_golabek_uv.py` → format `"DD | MM | RRRR"` (np. `"10 | 05 | 2026"`). Silnik: `"10.05.2026"``"10 | 05 | 2026"`.
- Wszystkie pozostałe `pudelko_komunia_*`, `pudelko_chrzest_*`, `buteleczki_slub_*` → format `"DD.MM.RRRR"` (standardowy).
Dodaj nowe wzory tu, gdy będą tworzone nowe skrypty z nietypowymi formatami.
### 6. Przedstaw plan i generuj
Wyświetl tabelę z planem:
```
Zamówienie | Produkt | Imię żeńskie | Imię męskie | Data | Życzenia | Klient (nazwa pliku)
OP000123 | Buteleczka... | Kinga | Łukasz | 30.04.2026 | (domyślne) | Kinga Klimczak
```
**Autonomia przy generowaniu:**
- Jeśli wszystkie interpretacje są **jasne lub wątpliwości minimalne** (rutynowe przekształcenia: dopełniacz imienia, format daty, auto-wołacz, podział naglowek/od_kogo zgodnie z regułami) → **generuj od razu po wyświetleniu planu**, bez pytania o potwierdzenie. Raportuj w planie co zostało przekształcone, żeby użytkownik mógł zweryfikować po fakcie.
- Jeśli wątpliwość jest **istotna** (np. brakujące imię męskie w buteleczkach ślubnych, niejasne przypisanie matka/ojciec przy próśbach, dwuznaczny podział naglowek/od_kogo, dziwny format daty, klient wyraźnie pomylił produkt, treść zawierająca rażące dubluje lub sprzeczność między polami) → **zatrzymaj się i zapytaj** użytkownika, prezentując opcje.
Kierunkowskaz: "czy jestem pewny że wynik będzie akceptowalny?" Jeśli tak — jedź. Jeśli nie — pytaj.
### 7. Uruchom generowanie
Przed generowaniem sprawdź czy Photoshop jest uruchomiony:
```bash
tasklist //FI "IMAGENAME eq Photoshop.exe" 2>/dev/null | grep -i photoshop
```
Jeśli Photoshop nie jest uruchomiony — poinformuj użytkownika i poczekaj aż go uruchomi.
**Pobranie zdjęcia od klienta (jeśli `requires_photo = 1`):**
Dla mapowań z `requires_photo = 1` przed wywołaniem generatora pobierz zdjęcie z poczty klienta:
```bash
python tools/generowanie/email_photo_fetcher.py --email "{buyer_email}" --out "C:/tmp/orderpro_photos" --days 365
```
- Skrypt zwraca ścieżkę pobranego pliku albo komunikat `BRAK` (exit code 1).
- Jeśli zdjęcie się pobrało — przekaż ścieżkę do generatora przez `--zdjecie`.
- Jeśli zdjęcia **nie znaleziono** — generator i tak ma być wywołany **bez** `--zdjecie` (wstawi zielony placeholder jako sygnał "klient nie przysłał foto"). NIE blokuj generacji.
- Zaraportuj w tabeli planu (kolumna "Zdjęcie") status: ścieżka / `BRAK (zielony placeholder)`.
**WAŻNE — rozpoznawanie płci dziecka (dla skryptów z parametrem `--plec`):**
Niektóre skrypty (np. `akrylowe_podziekowanie_matka_chrzestna_wzor2.py`) mają dwa warianty szablonu (chłopiec/dziewczynka) i wymagają parametru `--plec m` lub `--plec k`. Rozpoznaj płeć na podstawie personalizacji:
- **Imię proste** (Fabian, Wojciech, Kacper → `m`; Blanka, Zosia, Wiktoria → `k`) — standardowa wiedza o polskich imionach.
- **Imię odmienione** (np. "Wojtusia", "Kacpra" → `m`; "Blanki", "Zosi", "Wiktorii" → `k`) — rozpoznaj mianownik i z niego określ płeć.
- **Kontekst** — jeśli w personalizacji pojawia się "mój Chrześniak", "Drogi Synku", "malutki" → `m`; "moja Chrześniaczka", "Droga Córeczko", "malutka" → `k`.
- **W razie wątpliwości** — wyświetl surowe dane klientowi i zapytaj.
**WAŻNE — łamanie linii w tekstach wielolinijkowych (życzenia, podziękowanie, itp.):**
Photoshop jako znak łamania linii w warstwach tekstowych rozpoznaje **`\r` (CR)**, NIE `\n` (LF). Jeśli przekażesz `\n`, Photoshop wyświetli go jako śmieciowy kwadrat z literą "n". W bashu użyj ANSI-C quoting: `$'linia1\rlinia2\rlinia3'` do budowy wartości `--zyczenia` / `--podziekowanie` i przekaż ją w cudzysłowach do skryptu.
Dla każdego potwierdzonego produktu:
1. **Sprawdź kolizję nazwy pliku** w katalogu wyjściowym. Jeśli plik `{klient}.psd` (lub inne rozszerzenie używane przez skrypt) już istnieje — dodaj do nazwy klienta sufiks z indeksem `01`, `02`, ... (np. `Anna Rak``Anna Rak 01`, a jeśli i to zajęte → `Anna Rak 02`). Inkrementuj aż znajdziesz wolną nazwę. Dopiero wtedy przekaż wynik jako `--klient`.
2. Uruchom skrypt: `python tools/generowanie/{script_name} --klient "Imię Nazwisko" ...` (parametry zależne od skryptu — dla buteleczek/pudełek zwykle `--imie/--imiona`, `--data`, opcjonalnie `--zyczenia`/`--podziekowanie`; dla produktów ze zdjęciem dorzuć `--zdjecie /sciezka/do/foto.jpg`; **dla skryptów `magnes_*` dorzuć `--liczba {order_items.quantity}`** — szablony mają N slotów na arkuszu A3, nadmiar ma być ukrywany żeby nie drukować pustych kopii)
**WAŻNE — imię dziecka w skryptach `magnes_chrzest_*`:** Skrypty magnesów chrzestnych konstruują tytuł jako `"Chrzest Święty\r{imie}"` — słowo "Święty" **nie jest odmieniane**, odmienia się **tylko imię** (dopełniacz). Przekaż samo imię w dopełniaczu (np. `--imie "Tymka"`, `--imie "Rozalii"`, `--imie "Jakuba"`). Wynik: "Chrzest Święty↵Tymka" — poprawnie.
3. Jeśli mapowanie ma `output_dir` — skrypt powinien zapisać tam (jeśli obsługuje)
### 8. Oznacz w bazie
Po udanym generowaniu:
```sql
UPDATE order_items
SET project_generated = 1, project_generated_at = NOW()
WHERE id = {item_id};
```
### 9. Raport końcowy
Wyświetl podsumowanie:
- Ile projektów wygenerowano
- Ile pominięto (brak mapowania, brak personalizacji)
- Ewentualne błędy
## Ważne zasady
- **Zawsze pytaj o potwierdzenie** przed generowaniem
- **Photoshop musi być uruchomiony** — sprawdź przed generowaniem
- **Nie oznaczaj jako wygenerowane** jeśli skrypt zwrócił błąd
- **Jeśli nie potrafisz zinterpretować personalizacji** — wyświetl surowe dane i zapytaj użytkownika
- Skrypty generujące znajdują się w `tools/generowanie/` w katalogu projektu orderPRO