Reguły automatyzacji oparte na zdarzeniach (receipt.created) z warunkami (integracja/kanał sprzedaży, AND logic) i akcjami (wyślij e-mail z 3 trybami odbiorcy: klient / firma / klient+firma). Trigger w ReceiptController po utworzeniu paragonu — błąd automatyzacji nie blokuje sukcesu paragonu. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
308 lines
13 KiB
Markdown
308 lines
13 KiB
Markdown
---
|
|
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
|
|
---
|
|
|
|
<objective>
|
|
## 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
|
|
</objective>
|
|
|
|
<context>
|
|
## 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
|
|
</context>
|
|
|
|
<skills>
|
|
## Required Skills (from SPECIAL-FLOWS.md)
|
|
|
|
No SPECIAL-FLOWS.md found — skills section omitted.
|
|
</skills>
|
|
|
|
<acceptance_criteria>
|
|
|
|
## 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
|
|
```
|
|
|
|
</acceptance_criteria>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Migracja DB — tabele automation</name>
|
|
<files>database/migrations/20260318_000057_create_automation_tables.sql, DOCS/DB_SCHEMA.md</files>
|
|
<action>
|
|
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.
|
|
</action>
|
|
<verify>Migracja wykonuje się bez błędów na lokalnej bazie. Tabele istnieją z poprawnymi FK.</verify>
|
|
<done>AC-1 satisfied: 3 tabele istnieją z poprawnymi relacjami i indeksami</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Backend CRUD — AutomationController + AutomationRepository</name>
|
|
<files>
|
|
src/Modules/Automation/AutomationController.php,
|
|
src/Modules/Automation/AutomationRepository.php,
|
|
src/Core/Application.php,
|
|
DOCS/ARCHITECTURE.md
|
|
</files>
|
|
<action>
|
|
**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ł.
|
|
</action>
|
|
<verify>Routing działa — GET /settings/automation zwraca stronę listy. POST store tworzy regułę w DB.</verify>
|
|
<done>AC-2, AC-3, AC-4 satisfied: CRUD działa end-to-end</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Widoki UI — lista + formularz z dynamicznymi warunkami/akcjami</name>
|
|
<files>
|
|
resources/views/automation/index.php,
|
|
resources/views/automation/form.php,
|
|
resources/scss/modules/_automation.scss,
|
|
public/assets/js/modules/automation-form.js
|
|
</files>
|
|
<action>
|
|
**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.
|
|
</action>
|
|
<verify>Formularz pozwala dodawać/usuwać warunki i akcje dynamicznie. Zapis tworzy regułę z warunkami i akcjami w DB.</verify>
|
|
<done>AC-2, AC-3, AC-4, AC-5 satisfied: UI lista + formularz dynamiczny działają</done>
|
|
</task>
|
|
|
|
<task type="checkpoint:human-verify" gate="blocking">
|
|
<what-built>Moduł Zadania automatyczne — CRUD z dynamicznym formularzem warunków i akcji</what-built>
|
|
<how-to-verify>
|
|
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
|
|
</how-to-verify>
|
|
<resume-signal>Type "approved" to continue to plan 16-02 (watcher/executor), or describe issues to fix</resume-signal>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<boundaries>
|
|
|
|
## 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)
|
|
|
|
</boundaries>
|
|
|
|
<verification>
|
|
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
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Wszystkie taski ukończone
|
|
- Wszystkie verification checks przechodzą
|
|
- Brak błędów PHP / JS w konsoli
|
|
- UI spójne z resztą aplikacji (Ustawienia)
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.paul/phases/16-automated-tasks/16-01-SUMMARY.md`
|
|
</output>
|