diff --git a/.claude/memory/MEMORY.md b/.claude/memory/MEMORY.md index 3d9b267..bee85e5 100644 --- a/.claude/memory/MEMORY.md +++ b/.claude/memory/MEMORY.md @@ -4,3 +4,5 @@ - [feedback_edit_icon_pattern.md](feedback_edit_icon_pattern.md) — Ikonka ✎ na hover z dropdown menu — reuse pattern - [feedback_generowanie_imie_dziecka.md](feedback_generowanie_imie_dziecka.md) — Imię dziecka do skryptów generowania musi być w dopełniaczu (Ignacy → Ignacego) - [feedback_generowanie_pythonutf8.md](feedback_generowanie_pythonutf8.md) — Skrypty generowania uruchamiaj z PYTHONUTF8=1 (emoji/Unicode w od_kogo/życzeniach) +- [feedback_generowanie_widocznosc_warstw.md](feedback_generowanie_widocznosc_warstw.md) — Przy eksploracji PSD sprawdzaj visible warstw — niewidoczne grupy mylą wybór celu edycji +- [feedback_mysql_polskie_znaki.md](feedback_mysql_polskie_znaki.md) — LIKE z polskimi znakami (ł) przez shell→mysql może fałszywie zwracać 0 — użyj hex-encoded CONCAT diff --git a/.claude/memory/feedback_generowanie_widocznosc_warstw.md b/.claude/memory/feedback_generowanie_widocznosc_warstw.md new file mode 100644 index 0000000..b14e506 --- /dev/null +++ b/.claude/memory/feedback_generowanie_widocznosc_warstw.md @@ -0,0 +1,11 @@ +--- +name: Widocznosc warstw przy eksploracji PSD +description: Przy eksplorowaniu struktury szablonu PSD sprawdzaj visible, nie tylko strukturę — niewidoczne grupy mogą zmylić, którą grupę edytować +type: feedback +originSessionId: 6b490a59-53d2-4351-8049-2be9d065ec83 +--- +Przy pisaniu skryptów generowania z szablonu PSD — eksplorator warstw MUSI raportować `visible` dla każdej grupy i warstwy. Sama struktura nazw nie wystarczy. + +**Why:** W szablonie Łabędzie były dwie grupy o tej samej funkcji — `dane` (semantyczne nazwy: imiona, data, podziekowanie — ale `visible=False`, niedokończony eksperyment) oraz `Warstwa 1` (literalne nazwy: "Przemek", "Ania", "17.08.2024" — `visible=True`, aktywny design). Skrypt edytował `dane` (lepiej nazwane), ale render pokazywał `Warstwa 1`. Plik wychodził "nietknięty" mimo że log pokazywał podmianę. + +**How to apply:** W `_tmp_explore_*.py` zawsze drukuj `visible` dla `layerSets` i `artLayers`. Przy wyborze grupy docelowej — preferuj `visible=True`. Jeśli są dwie kandydatki (widoczna z dziwnymi nazwami + ukryta z ładnymi) — najpierw przemianuj warstwy w widocznej na czytelne semantyczne nazwy, potem pisz skrypt. diff --git a/.claude/memory/feedback_mysql_polskie_znaki.md b/.claude/memory/feedback_mysql_polskie_znaki.md new file mode 100644 index 0000000..dec397b --- /dev/null +++ b/.claude/memory/feedback_mysql_polskie_znaki.md @@ -0,0 +1,21 @@ +--- +name: Polskie znaki w mysql LIKE przez shell +description: LIKE z polskimi znakami (szczególnie ł) w zapytaniach mysql uruchamianych z git-bash nie zawsze dopasowuje — użyj hex-encoded pattern w CONCAT +type: feedback +originSessionId: 6b490a59-53d2-4351-8049-2be9d065ec83 +--- +Przy filtrowaniu klientów w `/wygeneruj-projekty` — jeśli imię/nazwisko zawiera polskie znaki (szczególnie `ł`, ale też `ę`/`ń` w niektórych kombinacjach), LIKE w postaci `WHERE oa.name LIKE '%Małgorzata%'` przekazane przez `mysql.exe -e "..."` z git-bash może zwracać **zero wyników**, mimo że rekord istnieje w bazie. + +**Why:** shell/terminal/console transkoduje polskie znaki niespójnie między git-bash a mysql.exe (ConvertTo z UTF-8 na code page Windows i z powrotem). Charset kliencki `--default-character-set=utf8mb4` nie zawsze to naprawia. Rekord w bazie jest poprawnie UTF-8, ale pattern LIKE po przejściu przez shell zawiera inne bajty. + +**How to apply:** Jeśli zapytanie dopasowania klienta po nazwisku zwraca 0 wyników, a jesteś pewny że rekord istnieje — ponów z hex-encoded wzorcem: + +```sql +-- Zamiast: WHERE oa.name LIKE '%Stępińska%' +-- Użyj: +WHERE oa.name LIKE CONCAT('%', 0x5374C4997069C584736B61, '%') +``` + +Hex wygenerować w shell: `printf 'Stępińska' | od -An -tx1 | tr -d ' \n'` → `5374C4997069C584736B61`. + +Lub użyj samego fragmentu bez polskich znaków (np. tylko nazwisko `%tarnowska%`, `%fundakowska%`) gdy to wystarcza do jednoznacznego dopasowania. diff --git a/.paul/governance/governance_2026-04-22.jsonl b/.paul/governance/governance_2026-04-22.jsonl new file mode 100644 index 0000000..375c297 --- /dev/null +++ b/.paul/governance/governance_2026-04-22.jsonl @@ -0,0 +1,71 @@ +{"ts":"2026-04-21T22:42:24Z","tool":"Bash","cmd":"cmd //c start \"\" \"C:\\\\Program Files\\\\Adobe\\\\Adobe Photoshop 2026\\\\Photoshop.exe\"\",\"description\":\"Launch Photoshop 2026\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupt","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T07:27:22Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -i photoshop\",\"description\":\"Check if Photoshop is running\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":fal","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T07:29:27Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -i photoshop\",\"description\":\"Verify Photoshop is running\"},\"tool_response\":{\"stdout\":\"Binary file (standard input) matches\",\","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T07:51:04Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -i photoshop || echo \"Photoshop NIE jest uruchomiony\"\",\"description\":\"Check if Photoshop is running\"},\"tool_response\":{\"stdout","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T07:53:14Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_tmp_explore_wzor3.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:20:18Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && php -r \"require 'config/bootstrap.php'; \\\\$db = \\\\$GLOBALS['db'] ?? null; if(!\\\\$db){ \\\\$db = (require 'config/database.php'); } \\\\$rows = ","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:20:45Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:20:55Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:21:07Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:21:15Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:21:52Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_mapping.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:22:02Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:22:12Z","tool":"Bash","cmd":"rm \"C:/visual studio code/projekty/orderPRO/_tmp_mapping.sql\" && echo OK\",\"description\":\"Remove temp SQL file\"},\"tool_response\":{\"stdout\":\"OK\",\"stderr\":\"\",\"interrupted\":false,\"isIm","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:23:00Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_query.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:23:06Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -ci photoshop || echo \"0\"\",\"description\":\"Check if Photoshop is running\"},\"tool_response\":{\"stdout\":\"1\",\"stderr\":\"\",\"i","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:23:15Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:23:27Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && python tools/generowanie/email_message_fetcher.py --email \"leszek.krzem@wp.pl\" --days 60 --json 2>&1 | head -20\",\"timeout\":60000,\"description\":","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:23:55Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/buteleczki_urodziny_wzor3.py --imie \"Agnieszki\" --wiek \"50\" --klient \"Agnieszka Krzemińska\" 2>&1\",\"time","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:24:09Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_mark.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:24:17Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:26:06Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_query.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:26:15Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:26:27Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && python tools/generowanie/email_message_fetcher.py --email \"oliwia.mowinska.06@wp.pl\" --days 60 --json 2>&1 | head -5\",\"timeout\":60000,\"descripti","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:27:00Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/buteleczki_slub_wzor4.py --imie_zenskie \"Oliwia\" --imie_meskie \"Dominik\" --data \"20.06.2026\" --klient \"Ol","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:27:07Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_mark.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:27:17Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:35:02Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_query.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:35:11Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:35:27Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && python tools/generowanie/email_message_fetcher.py --email \"aleksandrazuchniarz@wp.pl\" --days 60 --json 2>&1 | head -3\",\"timeout\":60000,\"descript","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:36:00Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/buteleczki_slub_mloda_para.py --imiona \"Aleksandra i Piotr\" --data \"15.08.2026\" --klient \"Aleksandra Zuchni","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:36:07Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_mark.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:36:22Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:37:37Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_query.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:37:46Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:37:57Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && python tools/generowanie/email_message_fetcher.py --email \"aniapilarczyk@onet.pl\" --days 60 --json 2>&1 | head -3\",\"timeout\":60000,\"description\","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:38:19Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/buteleczki_slub_mloda_para.py --imiona \"Ania i Maciek\" --data \"09.05.2026\" --klient \"Ania Pilarczyk\" 2>&1\","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:38:25Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_mark.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:38:33Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:39:31Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\_tmp_query.sql","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:39:43Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && source <(grep -E '^(DB_HOST_REMOTE|DB_HOST|DB_PORT|DB_DATABASE|DB_USERNAME|DB_PASSWORD)=' .env | sed 's/=\\\\(.*\\\\)/=\"\\\\1\"/') && HOST=${DB_HOST_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:40:09Z","tool":"Bash","cmd":"rm \"C:/visual studio code/projekty/orderPRO/_tmp_query.sql\" 2>/dev/null && echo OK\",\"description\":\"Cleanup temp SQL file\"},\"tool_response\":{\"stdout\":\"OK\",\"stderr\":\"\",\"interrupted\":f","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:41:25Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_tmp_explore_labedzie.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:42:23Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/buteleczki_slub_labedzie.py --imiona \"Ania i Maciek\" --data \"09.05.2026\" --klient \"TEST_Ania_Pilarczyk\" 2>","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:46:45Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -i photoshop || echo \"Photoshop NIE jest uruchomiony\"\",\"description\":\"Check if Photoshop is running\"},\"tool_response\":{\"stdout","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:47:42Z","tool":"Bash","cmd":"where python 2>/dev/null; where python3 2>/dev/null; where py 2>/dev/null\",\"description\":\"Find Python installation\"},\"tool_response\":{\"stdout\":\"C:\\\\Users\\\\jacek\\\\AppData\\\\Local\\\\Pr","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T08:54:20Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\buteleczki_slub_labedzie.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:05:38Z","tool":"Bash","cmd":"rm \"C:/visual studio code/projekty/orderPRO/tools/generowanie/_tmp_explore_labedzie.py\" && echo \"Usunięto\"\",\"description\":\"Remove temporary explorer file\"},\"tool_response\":{\"stdout\":\"Us","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:11:26Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\buteleczki_slub_labedzie.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:11:36Z","tool":"Bash","cmd":"rm \"d:/pomysloweprezenty.pl/projekty/ślub - buteleczki/Podziękowanie dla gości weselnych buteleczka z nadrukiem UV - Łabędzie/_gotowe/Ania Pilarczyk.psd\" && echo \"usunieto stary plik\"\",\"des","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:11:53Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\buteleczki_slub_labedzie.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:15:07Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\buteleczki_slub_labedzie.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:16:05Z","tool":"Write","file":"C:\\\\Users\\\\jacek\\\\.claude\\\\projects\\\\C--visual-studio-code-projekty-orderPRO\\\\memory\\\\feedback_generowanie_widocznosc_warstw.md","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T09:16:14Z","tool":"Edit","file":"C:\\\\Users\\\\jacek\\\\.claude\\\\projects\\\\C--visual-studio-code-projekty-orderPRO\\\\memory\\\\MEMORY.md","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T10:27:54Z","tool":"Write","file":"C:\\\\Users\\\\jacek\\\\.claude\\\\projects\\\\C--visual-studio-code-projekty-orderPRO\\\\memory\\\\feedback_mysql_polskie_znaki.md","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T10:28:01Z","tool":"Edit","file":"C:\\\\Users\\\\jacek\\\\.claude\\\\projects\\\\C--visual-studio-code-projekty-orderPRO\\\\memory\\\\MEMORY.md","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T10:56:16Z","tool":"Bash","cmd":"tasklist //FI \"IMAGENAME eq Photoshop.exe\" 2>/dev/null | grep -i photoshop; ls -la \"d:/pomysloweprezenty.pl/projekty/ślub - magnesy/Magnes podziękowanie dla gości weselnych na plastrze brzozy - ","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T10:56:34Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_explore_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T10:56:42Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/_explore_tmp.py 2>&1 | head -200\",\"description\":\"Explore PSD structure\"},\"tool_response\":{\"stdout\":\"==","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:12:09Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_explore_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:12:16Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/_explore_tmp.py 2>&1 | tail -10\",\"description\":\"Check layer bounds\"},\"tool_response\":{\"stdout\":\"\"Sewe","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:12:26Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\_rename_tmp.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:12:34Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/_rename_tmp.py 2>&1 | tail -5\",\"description\":\"Rename layers in PSD\"},\"tool_response\":{\"stdout\":\"OK ren","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:13:03Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\magnes_slub_plaster_brzozy_kwiaty_wzor8.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:13:11Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\orderPRO\\\\tools\\\\generowanie\\\\magnes_slub_plaster_brzozy_kwiaty_wzor8.py","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:13:24Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && PYTHONUTF8=1 python tools/generowanie/magnes_slub_plaster_brzozy_kwiaty_wzor8.py --klient \"test_ania_maciek\" --imie_zenskie \"Ania\" --imie_meskie \","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:13:30Z","tool":"Bash","cmd":"rm \"C:/visual studio code/projekty/orderPRO/tools/generowanie/_explore_tmp.py\" \"C:/visual studio code/projekty/orderPRO/tools/generowanie/_rename_tmp.py\"\",\"description\":\"Remove temp scripts\"}","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:15:19Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && grep -E \"^(DB_HOST_REMOTE|DB_DATABASE|DB_USERNAME|DB_PASSWORD|DB_PORT)=\" .env\",\"description\":\"Read DB env\"},\"tool_response\":{\"stdout\":\"DB_","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:15:30Z","tool":"Bash","cmd":"\"C:/xampp/mysql/bin/mysql.exe\" -h host700513.hostido.net.pl -P 3306 -u host700513_orderpro -phrDNtUBg9grwZ7syN77S host700513_orderpro --default-character-set=utf8mb4 -e \"SELECT oi.id AS item_id, oi","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:15:40Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/orderPRO\" && python tools/generowanie/email_message_fetcher.py --email \"edyta1407@op.pl\" --days 60 --json 2>&1 | tail -20\",\"description\":\"Check client emails","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:16:09Z","tool":"Bash","cmd":"rm -f \"d:/pomysloweprezenty.pl/projekty/ślub - magnesy/Magnes podziękowanie dla gości weselnych na plastrze brzozy - Kwiaty Wzór 8/_gotowe/test_ania_maciek.psd\" && cd \"C:/visual studio code/pro","cwd":"/c/visual studio code/projekty/orderPRO"} +{"ts":"2026-04-22T11:16:17Z","tool":"Bash","cmd":"\"C:/xampp/mysql/bin/mysql.exe\" -h host700513.hostido.net.pl -P 3306 -u host700513_orderpro -phrDNtUBg9grwZ7syN77S host700513_orderpro --default-character-set=utf8mb4 -e \"UPDATE order_items SET proj","cwd":"/c/visual studio code/projekty/orderPRO"} diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index f762174..a9f70d8 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -5739,6 +5739,12 @@ "lmtime": 0, "modified": false }, + "buteleczki_slub_wzor3.py": { + "type": "-", + "size": 5701, + "lmtime": 0, + "modified": false + }, "buteleczki_slub_wzor4.py": { "type": "-", "size": 5304, @@ -5781,11 +5787,17 @@ "lmtime": 1776018627219, "modified": false }, + "_explore_psd.py": { + "type": "-", + "size": 1571, + "lmtime": 0, + "modified": false + }, "_explore_temp.py": { "type": "-", - "size": 1681, + "size": 3438, "lmtime": 1776017342215, - "modified": false + "modified": true }, "_explore_tmp.py": { "type": "-", @@ -5793,6 +5805,12 @@ "lmtime": 0, "modified": false }, + "_explore_wzor3.py": { + "type": "-", + "size": 3585, + "lmtime": 0, + "modified": false + }, "magnes_babcia_kocham_babciu.py": { "type": "-", "size": 2208, @@ -5817,6 +5835,12 @@ "lmtime": 1776029394137, "modified": false }, + "magnes_wieczor_panienski_pierscionek.py": { + "type": "-", + "size": 2896, + "lmtime": 0, + "modified": false + }, "magnes_wieczor_panienski_szampan.py": { "type": "-", "size": 2807, @@ -5829,6 +5853,12 @@ "lmtime": 1776031123643, "modified": false }, + "pudelko_chrzest_aniolek_chlopak_hdf_uv.py": { + "type": "-", + "size": 3588, + "lmtime": 0, + "modified": false + }, "pudelko_chrzest_dlonie_uv.py": { "type": "-", "size": 3483, @@ -5921,11 +5951,17 @@ "modified": false } }, + "_rename_psd.py": { + "type": "-", + "size": 1978, + "lmtime": 0, + "modified": false + }, "_rename_temp.py": { "type": "-", - "size": 1394, + "size": 1700, "lmtime": 1776017830161, - "modified": false + "modified": true }, "_rename_tmp.py": { "type": "-", @@ -5933,6 +5969,12 @@ "lmtime": 0, "modified": false }, + "_rename_wzor3.py": { + "type": "-", + "size": 2723, + "lmtime": 0, + "modified": false + }, "_tmp_photos": { "01_IMG_7330.jpeg": { "type": "-", @@ -5958,6 +6000,12 @@ "size": 5328, "lmtime": 1776032317220, "modified": false + }, + "pudelko_chrzest_spiacy_aniolek_chlopak_hdf_uv.py": { + "type": "-", + "size": 3588, + "lmtime": 1776763857067, + "modified": false } } }, diff --git a/tools/generowanie/buteleczki_slub_labedzie.py b/tools/generowanie/buteleczki_slub_labedzie.py new file mode 100644 index 0000000..4cf2159 --- /dev/null +++ b/tools/generowanie/buteleczki_slub_labedzie.py @@ -0,0 +1,173 @@ +""" +Generator PSD — Podziękowanie dla gości weselnych (buteleczka, Łabędzie). + +Szablon 370x300 to layout 8-up: 8 instancji Smart Object linkujących do +jednego źródła (Warstwa 1.psb). Edycja zawartości jednej warstwy SO +propaguje się na wszystkie 8 kopii w arkuszu. + +Wewnątrz SO warstwy tekstowe są w grupie "Warstwa 1": + imie_zenskie, imie_meskie, data, zyczenia +(separator "&" zostaje bez zmian) + +Wymaga: uruchomiony Adobe Photoshop, pakiet photoshop-python-api. + +Użycie: + python buteleczki_slub_labedzie.py --klient "Ania Pilarczyk" \ + --imie_zenskie "Ania" --imie_meskie "Maciek" --data "09.05.2026" + + python buteleczki_slub_labedzie.py --klient "Ania Pilarczyk" \ + --imie_zenskie "Ania" --imie_meskie "Maciek" --data "09.05.2026" \ + --zyczenia "DZIĘKUJEMY!" +""" + +import argparse +import os +import photoshop.api as ps + + +# --- Ścieżki --- +PROJEKT_DIR = os.path.join( + r"d:\pomysloweprezenty.pl\projekty\ślub - buteleczki", + "Podziękowanie dla gości weselnych buteleczka z nadrukiem UV - Łabędzie", +) +SZABLON_PATH = os.path.join(PROJEKT_DIR, "szablon 370x300.psd") +GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") + +# Grupa z tekstami wewnątrz Smart Object (Warstwa 1.psb) +TEKST_GROUP = "Warstwa 1" + +# Kind code dla Smart Object w photoshop-python-api +SMART_OBJECT_KIND = 17 + + +def open_smart_object(app): + """Otwiera zawartość aktywnej warstwy Smart Object do edycji.""" + desc = ps.ActionDescriptor() + ref = ps.ActionReference() + ref.putEnumerated( + app.stringIDToTypeID("layer"), + app.stringIDToTypeID("ordinal"), + app.stringIDToTypeID("targetEnum"), + ) + desc.putReference(app.stringIDToTypeID("null"), ref) + app.executeAction(app.stringIDToTypeID("placedLayerEditContents"), desc) + + +def change_text_preserve_position(layer, new_text): + """Zmienia tekst warstwy zachowując środek bounding boxa + (kompensacja dla warstw z wyśrodkowaną justyfikacją).""" + b = [float(x) for x in layer.bounds] + cx_before, cy_before = (b[0] + b[2]) / 2, (b[1] + b[3]) / 2 + + layer.textItem.contents = new_text + + b2 = [float(x) for x in layer.bounds] + cx_after, cy_after = (b2[0] + b2[2]) / 2, (b2[1] + b2[3]) / 2 + + dx, dy = cx_before - cx_after, cy_before - cy_after + if dx or dy: + layer.translate(dx, dy) + + +def find_first_smart_object(doc): + """Zwraca pierwszą warstwę Smart Object w dokumencie. + + Wszystkie 8 kopii linkuje do jednego .psb, więc edycja jednej + propaguje zmiany na pozostałe. + """ + for layer in doc.artLayers: + if layer.kind == SMART_OBJECT_KIND: + return layer + raise RuntimeError("Nie znaleziono warstwy Smart Object w szablonie") + + +def close_all_without_saving(app): + """Zamyka wszystkie otwarte dokumenty bez zapisu (awaryjne sprzątanie).""" + while app.documents.length > 0: + app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) + + +def generate(klient, imie_zenskie, imie_meskie, data, zyczenia=None): + """Generuje PSD z podmienionymi danymi.""" + os.makedirs(GOTOWE_DIR, exist_ok=True) + output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") + + app = ps.Application() + doc = app.open(SZABLON_PATH) + print(f"Otwarto szablon: {doc.name}") + + try: + so_layer = find_first_smart_object(doc) + app.activeDocument.activeLayer = so_layer + open_smart_object(app) + so_doc = app.activeDocument + print(f"Wszedłem do Smart Object: {so_doc.name}") + + tekst = so_doc.layerSets[TEKST_GROUP] + + replacements = { + "imie_zenskie": imie_zenskie, + "imie_meskie": imie_meskie, + "data": data, + } + if zyczenia is not None: + replacements["zyczenia"] = zyczenia + + print("Podmiana tekstów:") + for layer_name, new_text in replacements.items(): + layer = tekst.artLayers[layer_name] + old_text = layer.textItem.contents + change_text_preserve_position(layer, new_text) + print(f' {layer_name}: "{old_text}" -> "{new_text}"') + + so_doc.save() + so_doc.close() + print("Smart Object zapisany") + + # Wymus odswiezenie cache wszystkich Smart Objectow w glownym dokumencie + # — bez tego saveAs zapisze stary composite, mimo ze warstwy tekstowe + # wewnatrz SO maja nowe wartosci. + app.executeAction( + app.stringIDToTypeID("placedLayerUpdateAllModified"), + ps.ActionDescriptor(), + ) + + psd_opts = ps.PhotoshopSaveOptions() + app.activeDocument.saveAs(output_path, psd_opts, True) + print(f"Zapisano: {output_path}") + + app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) + except Exception: + close_all_without_saving(app) + raise + + print("Gotowe!") + return output_path + + +def main(): + parser = argparse.ArgumentParser( + description="Generator PSD - buteleczki ślubne (Łabędzie) 370x300 8-up" + ) + parser.add_argument("--klient", required=True, help="Nazwa pliku wyjściowego (bez rozszerzenia)") + parser.add_argument("--imie_zenskie", required=True, help="Imię żeńskie (np. Ania)") + parser.add_argument("--imie_meskie", required=True, help="Imię męskie (np. Maciek)") + parser.add_argument("--data", required=True, help="Data uroczystości (DD.MM.YYYY)") + parser.add_argument( + "--zyczenia", + default=None, + help='Tekst życzeń (opcjonalnie, domyślnie "NA ZDROWIE!" z szablonu)', + ) + + args = parser.parse_args() + generate( + klient=args.klient, + imie_zenskie=args.imie_zenskie, + imie_meskie=args.imie_meskie, + data=args.data, + zyczenia=args.zyczenia, + ) + + +if __name__ == "__main__": + main() diff --git a/tools/generowanie/buteleczki_urodziny_wzor3.py b/tools/generowanie/buteleczki_urodziny_wzor3.py new file mode 100644 index 0000000..656126b --- /dev/null +++ b/tools/generowanie/buteleczki_urodziny_wzor3.py @@ -0,0 +1,160 @@ +""" +Generator PSD — Podziękowanie dla gości buteleczka urodziny (Wzór 3). + +Otwiera szablon PSD, podmienia teksty w Smart Object z zachowaniem pozycji warstw, +zapisuje jako nowy PSD w folderze _gotowe. + +Szablon zawiera 8 linked instancji tego samego Smart Object (arkusz drukarski) — +edycja jednego SO propaguje się do wszystkich 8 kopii. + +Wymaga: uruchomiony Adobe Photoshop, pakiet photoshop-python-api. + +Użycie: + python buteleczki_urodziny_wzor3.py --imie "Agnieszki" --wiek "25" --klient "Agnieszka Kowalska" + + python buteleczki_urodziny_wzor3.py --imie "Agnieszki" --wiek "25" \ + --naglowek "urodziny" --klient "Agnieszka Kowalska" +""" + +import argparse +import os +import photoshop.api as ps + + +# --- Ścieżki --- +PROJEKT_DIR = os.path.join( + r"d:\pomysloweprezenty.pl\projekty\urodziny - buteleczki", + "Podziękowanie dla gości buteleczka z nadrukiem UV - Wzór 3", +) +SZABLON_PATH = os.path.join(PROJEKT_DIR, "szablon 370x300.psd") +GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") + +# Nazwa warstwy Smart Object w głównym PSD. +# W szablonie jest 8 linked kopii tego samego SO ("Warstwa 2", "Warstwa 2 kopia", ...). +# Wystarczy wejść w dowolną — zmiana propaguje się do wszystkich. +SMART_OBJECT_LAYER = "Warstwa 2" + +# Grupa w Smart Object, w której leżą warstwy tekstowe. +TEKST_GROUP = "Warstwa 1" + + +def open_smart_object(app): + """Otwiera zawartość aktywnej warstwy Smart Object do edycji.""" + desc = ps.ActionDescriptor() + ref = ps.ActionReference() + ref.putEnumerated( + app.stringIDToTypeID("layer"), + app.stringIDToTypeID("ordinal"), + app.stringIDToTypeID("targetEnum"), + ) + desc.putReference(app.stringIDToTypeID("null"), ref) + app.executeAction(app.stringIDToTypeID("placedLayerEditContents"), desc) + + +def change_text_preserve_position(layer, new_text): + """Zmienia tekst warstwy z zachowaniem jej oryginalnej pozycji. + + Uwzglednia justowanie: + - center (2): zachowuje srodek poziomy + - right (3): zachowuje prawa krawedz + - left (1): zachowuje lewa krawedz + W pionie zawsze zachowuje gora (pierwsza linia bazowa). + """ + bounds_before = [float(b) for b in layer.bounds] + + try: + just_int = int(layer.textItem.justification) + except Exception: + just_int = 1 + + layer.textItem.contents = new_text + bounds_after = [float(b) for b in layer.bounds] + + if just_int == 2: + cx_before = (bounds_before[0] + bounds_before[2]) / 2 + cx_after = (bounds_after[0] + bounds_after[2]) / 2 + dx = cx_before - cx_after + elif just_int == 3: + dx = bounds_before[2] - bounds_after[2] + else: + dx = bounds_before[0] - bounds_after[0] + + dy = bounds_before[1] - bounds_after[1] + + if dx != 0 or dy != 0: + layer.translate(dx, dy) + + +def generate(imie, wiek, klient, naglowek=None): + """Generuje PSD z podmienionymi danymi.""" + os.makedirs(GOTOWE_DIR, exist_ok=True) + output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") + + app = ps.Application() + doc = app.open(SZABLON_PATH) + print(f"Otwarto szablon: {doc.name}") + + # Znajdź i otwórz Smart Object + try: + target = doc.artLayers[SMART_OBJECT_LAYER] + except Exception: + doc.close(ps.SaveOptions.DoNotSaveChanges) + raise RuntimeError(f"Nie znaleziono warstwy '{SMART_OBJECT_LAYER}'") + + app.activeDocument.activeLayer = target + open_smart_object(app) + so_doc = app.activeDocument + + # Nawigacja do grupy z tekstami + grupa = so_doc.layerSets[TEKST_GROUP] + + # Podmiana tekstów + replacements = { + "imie": imie, + "wiek": str(wiek), + } + if naglowek is not None: + replacements["naglowek"] = naglowek + + for layer_name, new_text in replacements.items(): + layer = grupa.artLayers[layer_name] + old_text = layer.textItem.contents + change_text_preserve_position(layer, new_text) + print(f" {layer_name}: \"{old_text}\" -> \"{new_text}\"") + + # Zapisz Smart Object (propaguje do wszystkich 8 linked instancji) + so_doc.save() + so_doc.close() + print("Smart Object zapisany") + + # Zapisz jako nowy PSD + psd_opts = ps.PhotoshopSaveOptions() + app.activeDocument.saveAs(output_path, psd_opts, True) + print(f"Zapisano: {output_path}") + + # Zamknij oryginał bez zapisu + app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) + print("Gotowe!") + return output_path + + +def main(): + parser = argparse.ArgumentParser( + description="Generator PSD - buteleczki urodziny Wzór 3" + ) + parser.add_argument("--imie", required=True, help="Imię w dopełniaczu (np. Agnieszki)") + parser.add_argument("--wiek", required=True, help="Wiek jubilata (np. 25)") + parser.add_argument("--klient", required=True, help="Imię i nazwisko klienta (nazwa pliku wyjściowego)") + parser.add_argument("--naglowek", default=None, help="Tekst nagłówka (domyślnie: 'urodziny' z szablonu)") + + args = parser.parse_args() + generate( + imie=args.imie, + wiek=args.wiek, + klient=args.klient, + naglowek=args.naglowek, + ) + + +if __name__ == "__main__": + main() diff --git a/tools/generowanie/magnes_slub_plaster_brzozy_kwiaty_wzor8.py b/tools/generowanie/magnes_slub_plaster_brzozy_kwiaty_wzor8.py new file mode 100644 index 0000000..4c67209 --- /dev/null +++ b/tools/generowanie/magnes_slub_plaster_brzozy_kwiaty_wzor8.py @@ -0,0 +1,110 @@ +""" +Generator PSD — Magnes podziekowanie na plastrze brzozy (Kwiaty, Wzor 8). + +Szablon jest plaski (bez Smart Object). Warstwy tekstowe: + doc."data" — data uroczystosci + doc.""."Dane"."imie_zenskie" — imie panny mlodej (lewa) + doc.""."Dane"."imie_meskie" — imie pana mlodego (prawa) + +Wymaga: uruchomiony Adobe Photoshop, pakiet photoshop-python-api. + +Uzycie: + python magnes_slub_plaster_brzozy_kwiaty_wzor8.py --klient "Nowak" \\ + --imie_zenskie "Kasia" --imie_meskie "Jakub" --data "31.07.2025" +""" + +import argparse +import os +import photoshop.api as ps + + +PROJEKT_DIR = os.path.join( + "d:\\pomysloweprezenty.pl\\projekty\\ślub - magnesy", + "Magnes podziękowanie dla gości weselnych na plastrze brzozy - Kwiaty Wzór 8", +) +SZABLON_PATH = os.path.join( + PROJEKT_DIR, + "Magnes podziękowanie dla gości weselnych na plastrze brzozy - Kwiaty Wzór 8.psd", +) +GOTOWE_DIR = os.path.join(PROJEKT_DIR, "_gotowe") + +GRUPA_TOP = "" +GRUPA_DANE = "Dane" + + +def change_text_preserve_position(layer, new_text): + """Zmienia tekst warstwy zachowujac srodek bounding boxa.""" + b = [float(x) for x in layer.bounds] + cx_before, cy_before = (b[0] + b[2]) / 2, (b[1] + b[3]) / 2 + + layer.textItem.contents = new_text + + b2 = [float(x) for x in layer.bounds] + cx_after, cy_after = (b2[0] + b2[2]) / 2, (b2[1] + b2[3]) / 2 + + dx, dy = cx_before - cx_after, cy_before - cy_after + if dx or dy: + layer.translate(dx, dy) + + +def close_all_without_saving(app): + while app.documents.length > 0: + app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) + + +def generate(klient, imie_zenskie, imie_meskie, data): + os.makedirs(GOTOWE_DIR, exist_ok=True) + output_path = os.path.join(GOTOWE_DIR, f"{klient}.psd") + + app = ps.Application() + doc = app.open(SZABLON_PATH) + print(f"Otwarto szablon: {doc.name}") + + try: + dane = doc.layerSets[GRUPA_TOP].layerSets[GRUPA_DANE] + + replacements = [ + (doc.artLayers["data"], data, "data"), + (dane.artLayers["imie_zenskie"], imie_zenskie, "imie_zenskie"), + (dane.artLayers["imie_meskie"], imie_meskie, "imie_meskie"), + ] + + print("Podmiana tekstow:") + for layer, new_text, label in replacements: + old = layer.textItem.contents + change_text_preserve_position(layer, new_text) + print(f' {label}: "{old}" -> "{new_text}"') + + psd_opts = ps.PhotoshopSaveOptions() + app.activeDocument.saveAs(output_path, psd_opts, True) + print(f"Zapisano: {output_path}") + + app.activeDocument.close(ps.SaveOptions.DoNotSaveChanges) + except Exception: + close_all_without_saving(app) + raise + + print("Gotowe!") + return output_path + + +def main(): + parser = argparse.ArgumentParser( + description="Generator PSD - Magnes slubny na plastrze brzozy (Kwiaty Wzor 8)" + ) + parser.add_argument("--klient", required=True, help="Nazwa pliku wyjsciowego (bez rozszerzenia)") + parser.add_argument("--imie_zenskie", required=True, help="Imie panny mlodej (lewa strona)") + parser.add_argument("--imie_meskie", required=True, help="Imie pana mlodego (prawa strona)") + parser.add_argument("--data", required=True, help="Data uroczystosci (DD.MM.YYYY)") + + args = parser.parse_args() + generate( + klient=args.klient, + imie_zenskie=args.imie_zenskie, + imie_meskie=args.imie_meskie, + data=args.data, + ) + + +if __name__ == "__main__": + main()