This commit is contained in:
2026-04-14 20:36:20 +02:00
parent e15b4ccf45
commit 0e8f246d6f
16 changed files with 1234 additions and 54 deletions

View File

@@ -2,6 +2,24 @@
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
@@ -33,6 +51,7 @@ Schemat bazy danych — kluczowe kolumny:
- `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):
@@ -49,7 +68,12 @@ SELECT
oa.email AS buyer_email,
pm.script_name,
pm.output_dir,
pm.requires_photo
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
@@ -61,15 +85,38 @@ WHERE osg.id = 2
AND oi.project_generated = 0
AND oi.personalization IS NOT NULL
AND oi.personalization <> ''
-- {{OPTIONAL_FILTER}}
ORDER BY o.id;
```
Jeśli brak wyników — poinformuj użytkownika że nie ma zamówień do generacji pasujących do aktywnych mapowań.
**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`
- 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"
@@ -255,7 +302,7 @@ Photoshop jako znak łamania linii w warstwach tekstowych rozpoznaje **`\r` (CR)
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`)
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)
3. Jeśli mapowanie ma `output_dir` — skrypt powinien zapisać tam (jeśli obsługuje)
### 8. Oznacz w bazie