--- phase: 16-automated-tasks plan: 01 type: execute wave: 1 depends_on: [] files_modified: - database/migrations/20260318_000057_create_automation_tables.sql - src/Modules/Automation/AutomationController.php - src/Modules/Automation/AutomationRepository.php - resources/views/automation/index.php - resources/views/automation/form.php - resources/scss/modules/_automation.scss - public/assets/js/modules/automation-form.js - src/Core/Application.php autonomous: false --- ## Goal Stworzyć moduł "Zadania automatyczne" — tabele DB, backend CRUD i widoki UI do zarządzania regułami automatyzacji (tworzenie, edycja, lista, usuwanie). Reguły składają się z: zdarzenia wyzwalającego, warunków (AND) i akcji do wykonania. ## Purpose Użytkownik może definiować reguły automatyzacji, np. "Gdy utworzono paragon dla zamówienia z Allegro → wyślij e-mail z szablonu X do klienta". To fundament pod automatyzację procesów sprzedażowych. ## Output - 3 nowe tabele DB: `automation_rules`, `automation_conditions`, `automation_actions` - Moduł `App\Modules\Automation` z kontrolerem i repozytorium - Widoki: lista reguł + formularz tworzenia/edycji z dynamicznym dodawaniem warunków i akcji - Nowa sekcja w menu nawigacji ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Prior Work @.paul/phases/15-email-sending/15-01-SUMMARY.md — EmailSendingService (reuse w akcji "wyślij e-mail") @.paul/phases/14-email-templates/14-02-SUMMARY.md — Szablony e-mail (wybór szablonu w akcji) ## Source Files @src/Modules/Email/EmailSendingService.php — send(orderId, templateId, ?mailboxId, ?actorName) @src/Modules/Accounting/ReceiptController.php — trigger point (receipt.created) @src/Core/Application.php — routing registration @DOCS/DB_SCHEMA.md — existing schema reference @DOCS/ARCHITECTURE.md — module patterns ## Required Skills (from SPECIAL-FLOWS.md) No SPECIAL-FLOWS.md found — skills section omitted. ## AC-1: Tabele DB istnieją z poprawnymi relacjami ```gherkin Given migracja 000057 uruchomiona When sprawdzam strukturę bazy Then tabele automation_rules, automation_conditions, automation_actions istnieją And automation_conditions.rule_id ma FK do automation_rules.id z ON DELETE CASCADE And automation_actions.rule_id ma FK do automation_rules.id z ON DELETE CASCADE ``` ## AC-2: Lista reguł automatyzacji ```gherkin Given istnieją reguły automatyzacji w DB When użytkownik wchodzi na stronę Ustawienia > Zadania automatyczne Then widzi listę reguł z kolumnami: nazwa, zdarzenie, status, akcje (edytuj/usuń) And może przełączać status (aktywna/nieaktywna) przyciskiem toggle ``` ## AC-3: Tworzenie reguły z warunkami i akcjami ```gherkin Given użytkownik jest na formularzu tworzenia reguły When wypełnia nazwę, wybiera zdarzenie "Utworzono paragon" And dodaje warunek "Integracja" z wybranym kanałem sprzedaży And dodaje akcję "Wyślij e-mail" z wybranym szablonem i odbiorcą And zapisuje formularz Then reguła zostaje zapisana w DB z powiązanymi warunkami i akcjami And użytkownik wraca na listę z komunikatem sukcesu ``` ## AC-4: Edycja i usuwanie reguły ```gherkin Given istnieje reguła automatyzacji When użytkownik edytuje regułę (zmienia warunki/akcje) i zapisuje Then zmiany są zapisane w DB (stare warunki/akcje usunięte, nowe wstawione) When użytkownik klika usuń i potwierdza Then reguła i powiązane warunki/akcje są usunięte z DB ``` ## AC-5: Dynamiczny formularz — warunki i akcje ```gherkin Given użytkownik jest na formularzu reguły When klika "Dodaj warunek" Then pojawia się nowy wiersz z wyborem typu warunku i wartości When klika "Dodaj akcję" Then pojawia się nowy wiersz z wyborem typu akcji i konfiguracji When klika X przy warunku/akcji Then wiersz jest usuwany z formularza ``` Task 1: Migracja DB — tabele automation database/migrations/20260318_000057_create_automation_tables.sql, DOCS/DB_SCHEMA.md Utworzyć migrację z 3 tabelami: **automation_rules:** - `id` int unsigned PK AI - `name` varchar(128) NOT NULL - `event_type` varchar(64) NOT NULL (na razie: 'receipt.created') - `is_active` tinyint(1) NOT NULL DEFAULT 1 - `created_at` datetime DEFAULT CURRENT_TIMESTAMP - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP **automation_conditions:** - `id` int unsigned PK AI - `rule_id` int unsigned NOT NULL, FK → automation_rules.id ON DELETE CASCADE - `condition_type` varchar(64) NOT NULL (na razie: 'integration') - `condition_value` json NOT NULL (np. {"integration_ids": [1, 3]}) - `sort_order` smallint unsigned NOT NULL DEFAULT 0 - Indeks: `auto_cond_rule_idx` (rule_id) **automation_actions:** - `id` int unsigned PK AI - `rule_id` int unsigned NOT NULL, FK → automation_rules.id ON DELETE CASCADE - `action_type` varchar(64) NOT NULL (na razie: 'send_email') - `action_config` json NOT NULL (np. {"template_id": 5, "recipient": "client"}) - `sort_order` smallint unsigned NOT NULL DEFAULT 0 - Indeks: `auto_act_rule_idx` (rule_id) Zaktualizować DOCS/DB_SCHEMA.md o nowe tabele. Używać InnoDB, utf8mb4_unicode_ci — jak istniejące tabele. Migracja wykonuje się bez błędów na lokalnej bazie. Tabele istnieją z poprawnymi FK. AC-1 satisfied: 3 tabele istnieją z poprawnymi relacjami i indeksami Task 2: Backend CRUD — AutomationController + AutomationRepository src/Modules/Automation/AutomationController.php, src/Modules/Automation/AutomationRepository.php, src/Core/Application.php, DOCS/ARCHITECTURE.md **AutomationRepository:** - `findAll(): array` — lista reguł z count warunków/akcji - `findById(int $id): ?array` — reguła + warunki + akcje (eager load) - `create(array $data, array $conditions, array $actions): int` — INSERT rule + conditions + actions w jednej transakcji - `update(int $id, array $data, array $conditions, array $actions): bool` — UPDATE rule, DELETE old conditions/actions, INSERT new (transakcja) - `delete(int $id): bool` — DELETE rule (CASCADE usunie warunki/akcje) - `toggleActive(int $id): bool` — przełącz is_active - `findActiveByEvent(string $eventType): array` — pobierz aktywne reguły dla danego zdarzenia (z warunkami i akcjami) — potrzebne w planie 16-02 **AutomationController:** - `index()` — lista reguł - `create()` — formularz nowej reguły - `store(Request)` — walidacja + zapis, Flash sukces, redirect do index - `edit(Request)` — formularz edycji (load istniejącej reguły) - `update(Request)` — walidacja + update, Flash sukces, redirect - `destroy(Request)` — usunięcie z potwierdzeniem CSRF - `toggleStatus(Request)` — AJAX toggle is_active Walidacja w store/update: - Nazwa wymagana (1-128 znaków) - Event type wymagany (whitelist: ['receipt.created']) - Min 1 warunek, min 1 akcja - Walidacja typów warunków i akcji (whitelist) - CSRF Dane do formularza (getFormData helper): - Lista integracji z `integrations` (id, type, name) WHERE type IN ('allegro', 'shoppro') AND is_active = 1 - Lista szablonów e-mail z `email_templates` (id, name) Routing w Application.php: - GET /settings/automation → index - GET /settings/automation/create → create - POST /settings/automation/store → store - GET /settings/automation/edit/{id} → edit - POST /settings/automation/update/{id} → update - POST /settings/automation/delete/{id} → destroy - POST /settings/automation/toggle/{id} → toggleStatus (AJAX) Zaktualizować DOCS/ARCHITECTURE.md o nowy moduł. Routing działa — GET /settings/automation zwraca stronę listy. POST store tworzy regułę w DB. AC-2, AC-3, AC-4 satisfied: CRUD działa end-to-end Task 3: Widoki UI — lista + formularz z dynamicznymi warunkami/akcjami resources/views/automation/index.php, resources/views/automation/form.php, resources/scss/modules/_automation.scss, public/assets/js/modules/automation-form.js **index.php — lista reguł:** - Tabela: nazwa, zdarzenie (label), liczba warunków, liczba akcji, status (toggle switch), akcje (edytuj/usuń) - Toggle switch zmienia status via AJAX POST /settings/automation/toggle/{id} - Przycisk "Dodaj zadanie automatyczne" → /settings/automation/create - Usuwanie przez OrderProAlerts.confirm() + POST - Layout spójny z innymi listami w Ustawienia (email_mailboxes, email_templates, receipt_configs) **form.php — formularz tworzenia/edycji:** - Pola: nazwa (input text), zdarzenie (select — na razie 1 opcja "Utworzono paragon") - Sekcja "Warunki" z przyciskiem "Dodaj warunek": - Typ warunku: select (na razie "Integracja / kanał sprzedaży") - Wartość: multi-select z listą aktywnych integracji allegro/shoppro (checkbox dropdown lub multi-select) - Przycisk X do usunięcia warunku - Sekcja "Akcje" z przyciskiem "Dodaj akcję": - Typ akcji: select (na razie "Wyślij e-mail") - Konfiguracja "Wyślij e-mail": - Szablon: select z listy email_templates - Wyślij do: select z opcjami: "Klient", "Klient + e-mail z danych firmy", "E-mail z danych firmy" - Przycisk X do usunięcia akcji - Przyciski: Zapisz / Anuluj - Formularz POST z CSRF (_token) **automation-form.js:** - Dodawanie/usuwanie wierszy warunków (template clone) - Dodawanie/usuwanie wierszy akcji (template clone) - Nazewnictwo pól: conditions[0][type], conditions[0][value], actions[0][type], actions[0][config][template_id], actions[0][config][recipient] - Numeracja indeksów po dodaniu/usunięciu **_automation.scss:** - Style dla formularza dynamicznego (warunki/akcje bloki) - Kompaktowy layout (jak reszta aplikacji) - Importować w głównym pliku SCSS Nie używać natywnych alert()/confirm() — tylko OrderProAlerts. Nie pisać CSS w widokach — tylko SCSS. Formularz pozwala dodawać/usuwać warunki i akcje dynamicznie. Zapis tworzy regułę z warunkami i akcjami w DB. AC-2, AC-3, AC-4, AC-5 satisfied: UI lista + formularz dynamiczny działają Moduł Zadania automatyczne — CRUD z dynamicznym formularzem warunków i akcji 1. Uruchom migrację 000057 na lokalnej bazie 2. Wejdź na /settings/automation — powinna być pusta lista 3. Kliknij "Dodaj zadanie automatyczne" 4. Wypełnij nazwę, wybierz zdarzenie "Utworzono paragon" 5. Dodaj warunek "Integracja" → wybierz kanały sprzedaży 6. Dodaj akcję "Wyślij e-mail" → wybierz szablon i odbiorcę 7. Zapisz — powinna pojawić się na liście 8. Edytuj regułę — warunki i akcje powinny się załadować 9. Przełącz status toggle — powinien się zmienić 10. Usuń regułę — potwierdzenie + usunięcie Type "approved" to continue to plan 16-02 (watcher/executor), or describe issues to fix ## DO NOT CHANGE - src/Modules/Email/* (reuse, nie modyfikuj) - src/Modules/Accounting/* (trigger point będzie w planie 16-02) - database/migrations/000001-000056 (istniejące migracje) - src/Modules/Cron/* (integracja w planie 16-02) ## SCOPE LIMITS - Ten plan to tylko CRUD (zarządzanie regułami) — BEZ wykonywania reguł - Watcher/executor będzie w planie 16-02 - Nie dodawać nowych typów zdarzeń/warunków/akcji poza zdefiniowanymi - Nie modyfikować ReceiptController (trigger w planie 16-02) Before declaring plan complete: - [ ] Migracja 000057 wykonuje się bez błędów - [ ] GET /settings/automation wyświetla listę reguł - [ ] Tworzenie reguły z warunkami i akcjami zapisuje do DB poprawnie - [ ] Edycja ładuje istniejące warunki/akcje i zapisuje zmiany - [ ] Usunięcie reguły usuwa kaskadowo warunki i akcje - [ ] Toggle status zmienia is_active via AJAX - [ ] Formularz dynamicznie dodaje/usuwa warunki i akcje - [ ] CSRF walidacja działa - [ ] DOCS/DB_SCHEMA.md i DOCS/ARCHITECTURE.md zaktualizowane - Wszystkie taski ukończone - Wszystkie verification checks przechodzą - Brak błędów PHP / JS w konsoli - UI spójne z resztą aplikacji (Ustawienia) After completion, create `.paul/phases/16-automated-tasks/16-01-SUMMARY.md`