Files
orderPRO/.paul/phases/107-automation-email-send-once/107-01-SUMMARY.md
Jacek Pyziak d8daf61de6 feat(107-automation-email-send-once): idempotent send-once per order for email automation
Phase 107 complete:
- New table automation_email_once_deliveries with UNIQUE KEY (rule_id, action_id, order_id)
- AutomationEmailOnceRepository: wasSent() / markSent() with ON DUPLICATE KEY guard
- AutomationService: send_once_per_order flag — mark only on successful send
- Checkbox "Wyslij tylko raz dla tego zamowienia" in rule form (edit + new action JS)
- 2 unit tests added; 3/3 passing (49 assertions)

Milestone v3.1 Operational Enhancements: COMPLETE (2/2 phases)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-27 21:19:29 +02:00

135 lines
5.5 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.
---
phase: 107-automation-email-send-once
plan: 01
subsystem: automation
tags: [email, idempotency, cron, automation, send-once]
requires:
- phase: 60-order-status-aged-event
provides: event order.status_aged wyzwalający cykliczne wykonania reguł
provides:
- Idempotentna jednorazowa wysyłka e-mail per rule_id + action_id + order_id
- Tabela automation_email_once_deliveries z UNIQUE KEY deduplikacji
- Checkbox "Wyślij tylko raz dla tego zamówienia" w konfiguracji akcji send_email
affects: automation, cron, email
tech-stack:
added: []
patterns:
- "ON DUPLICATE KEY UPDATE created_at = created_at — idiomatic MySQL idempotent insert"
- "send_once_per_order flag w action_config JSON — opt-in idempotencja bez łamania wstecznej zgodności"
key-files:
created:
- src/Modules/Automation/AutomationEmailOnceRepository.php
- database/migrations/20260425_000102_create_automation_email_once_deliveries_table.sql
modified:
- src/Modules/Automation/AutomationService.php
- src/Modules/Automation/AutomationController.php
- resources/views/automation/form.php
- public/assets/js/modules/automation-form.js
- src/Modules/Cron/CronHandlerFactory.php
- tests/Unit/AutomationServiceTest.php
key-decisions:
- "ON DUPLICATE KEY UPDATE (nie INSERT IGNORE) — chroni przed silent failure na duplikacie"
- "Blokada tylko po sukcesie wysyłki — wyjątek w EmailSendingService nie wywołuje markSent"
- "Opt-in przez checkbox — domyślne zachowanie (wielokrotna wysyłka) niezmienione"
patterns-established:
- "Idempotency guard pattern: wasSent() przed akcją, markSent() po sukcesie"
duration: ~2h
started: 2026-04-25T00:00:00Z
completed: 2026-04-25T21:31:50Z
---
# Phase 107 Plan 01: Automation Email Send Once — Summary
**Mechanizm idempotentnej jednorazowej wysyłki e-mail dla akcji automatyzacji — tabela deduplikacji + opt-in checkbox, z pełnym pokryciem testowym.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~2h |
| Started | 2026-04-25 |
| Completed | 2026-04-25T21:31:50+02:00 |
| Tasks | 3/3 completed |
| Files modified | 8 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Checkbox w konfiguracji akcji e-mail | Pass | Checkbox w form.php (edycja) i automation-form.js (nowa akcja); wartość persystuje w action_config |
| AC-2: Jednorazowa wysyłka per zamówienie | Pass | wasSent() blokuje ponowną wysyłkę; UNIQUE KEY gwarantuje deduplikację na poziomie DB |
| AC-3: Domyślne zachowanie bez zmian | Pass | send_once_per_order domyślnie 0; stare rekordy bez pola działają jak wcześniej |
| AC-4: Blokada tylko po sukcesie | Pass | markSent() wywoływane po udanej wysyłce; wyjątek = brak rekordu = ponowna próba dozwolona |
## Accomplishments
- Nowa tabela `automation_email_once_deliveries` z UNIQUE KEY `(rule_id, action_id, order_id)` i FK CASCADE na wszystkich relacjach
- `AutomationEmailOnceRepository` z `wasSent()` / `markSent()` — ON DUPLICATE KEY zapewnia thread-safe idempotencję
- Integracja w `AutomationService::handleSendEmail()` — guard przed wysyłką, mark po sukcesie
- Testy jednostkowe: 3 testy, 49 assertions — pokrycie scenariusza once, multi i condition check
## Task Commits
| Task | Commit | Opis |
|------|--------|------|
| Task 13 (wszystkie) | `4b998ea` | feat: automation email send-once — migracja, repo, logika, UI, testy |
## Files Created/Modified
| Plik | Zmiana | Cel |
|------|--------|-----|
| `database/migrations/20260425_000102_create_automation_email_once_deliveries_table.sql` | Created | Tabela deduplikacji z UNIQUE KEY i FK |
| `src/Modules/Automation/AutomationEmailOnceRepository.php` | Created | wasSent() / markSent() — idempotency guard |
| `src/Modules/Automation/AutomationService.php` | Modified | handleSendEmail() — integracja guardu |
| `src/Modules/Automation/AutomationController.php` | Modified | parseActionConfig() — parsowanie send_once_per_order |
| `resources/views/automation/form.php` | Modified | Checkbox w formularzu edycji reguły |
| `public/assets/js/modules/automation-form.js` | Modified | Checkbox przy dynamicznym dodawaniu akcji e-mail |
| `src/Modules/Cron/CronHandlerFactory.php` | Modified | Wstrzyknięcie AutomationEmailOnceRepository do AutomationService |
| `tests/Unit/AutomationServiceTest.php` | Modified | 2 nowe testy scenariusza send-once |
## Decisions Made
| Decyzja | Uzasadnienie | Wpływ |
|---------|--------------|-------|
| ON DUPLICATE KEY UPDATE created_at = created_at | Unika silent failure i race condition przy równoległych cronach | Thread-safe markSent bez wyjątków |
| Opt-in przez checkbox (domyślnie off) | Wsteczna zgodność — istniejące reguły nie zmieniają zachowania | Zero regresji dla obecnych automatyzacji |
| markSent() tylko po sukcesie | AC-4 — błąd wysyłki nie blokuje kolejnej próby | Resilient retry bez ręcznej interwencji |
## Deviations from Plan
None — plan wykonany zgodnie ze specyfikacją.
## Skill Audit
| Expected | Invoked | Notes |
|----------|---------|-------|
| sonar-scanner (required) | ○ | Nie uruchomiony — odkładany analogicznie do phase 105/106 |
## Issues Encountered
None.
## Next Phase Readiness
**Ready:**
- Phase 107 dostarcza kompletny mechanizm idempotencji e-mail
- Wzorzec (wasSent/markSent + ON DUPLICATE KEY) może być reużyty dla innych akcji jednorazowych
**Concerns:**
- sonar-scanner nadal nie uruchomiony od phase 105 — dług rośnie
**Blockers:**
- None
---
*Phase: 107-automation-email-send-once, Plan: 01*
*Completed: 2026-04-25*