# ECStores Refund Notification Email — Design Spec

## Goal

When a merchant issues a refund through the Filament admin, give them the option to notify the customer by email — with an optional customer-facing message and an optional action-required prompt.

## Context

- **Platform:** Laravel 13, Livewire 4.3, Filament 5.6, stancl/tenancy 3.x
- **Entry point:** `RefundAction` (`app/Filament/Resources/Orders/Actions/RefundAction.php`) — existing modal action on the Orders list
- **Existing mail pattern:** `OrderConfirmationMail`, `AbandonedCartMail` — `Mailable` + `Queueable` + `SerializesModels`, `envelope()` + `content()`, dispatched via `Mail::to()->queue()`
- **Email views:** `resources/views/emails/` — card layout, inline CSS only, null-safe `$settings?->` access

---

## RefundAction Modal Changes

Three new fields added **below** the existing refund fields (`amount`, `type`, `reason_code`, `reason_notes`):

| Field | Type | Label | Notes |
|---|---|---|---|
| `notify_customer` | Toggle | Notify customer by email | Default off; `->live()` to show/hide dependents |
| `customer_message` | Textarea | Message to customer | Optional; hidden unless `notify_customer` is on; placeholder "e.g. We're sorry for the inconvenience." |
| `action_required` | TextInput | Action required | Optional; hidden unless `notify_customer` is on; placeholder "e.g. Please return the product within 14 days." |

**On submit:** if `$data['notify_customer']` is true, dispatch `RefundNotificationMail` to the queue after the refund record is created.

Internal fields (`reason_code`, `reason_notes`) are **never** included in the customer email.

---

## New: `RefundNotificationMail` Mailable

**Location:** `app/Mail/RefundNotificationMail.php`

```php
class RefundNotificationMail extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

    public function __construct(
        public readonly Order $order,
        public readonly Refund $refund,
        public readonly string $customerMessage = '',
        public readonly string $actionRequired = '',
        public readonly ?SiteSettings $settings = null,
    ) {}

    public function envelope(): Envelope
    {
        return new Envelope(subject: 'Refund Issued — Order #' . $this->order->id);
    }

    public function content(): Content
    {
        return new Content(view: 'emails.refund-notification');
    }
}
```

---

## New: `emails.refund-notification` Blade Template

**Location:** `resources/views/emails/refund-notification.blade.php`

Card layout matching existing email templates (white card, max-width 560px, box-shadow, inline CSS only).

Content structure:

```
Subject: Refund Issued — Order #[id]

Hi [contact_name / "there"],

A refund of [formatted amount] has been issued for your order #[id].

[If $customerMessage is not empty]
  [customer message text]

[If $actionRequired is not empty — visually highlighted box]
  Action required: [action_required text]

Questions? Contact us at [settings->contact_email or fallback].

──────────────────────────────────
[settings->company_name] · Powered by ECStores
```

Use `$settings?->company_name`, `$settings?->contact_email`, `$settings?->currency_symbol` with safe fallbacks throughout.

---

## RefundAction Dispatch

In the existing `action()` callback, after the `Refund` record is created:

```php
if ($data['notify_customer'] ?? false) {
    Mail::to($record->contact_email)->queue(
        new RefundNotificationMail(
            order: $record,
            refund: $refund,
            customerMessage: $data['customer_message'] ?? '',
            actionRequired: $data['action_required'] ?? '',
            settings: SiteSettings::current(),
        )
    );
}
```

No new DB tables or models required — the notification is fire-and-forget.

---

## Files Changed

| Action | File |
|---|---|
| Modify | `app/Filament/Resources/Orders/Actions/RefundAction.php` |
| Create | `app/Mail/RefundNotificationMail.php` |
| Create | `resources/views/emails/refund-notification.blade.php` |

---

## Out of Scope

- Logging which refunds triggered a customer notification (no tracking table)
- Resend notification after the fact (separate action)
- Unsubscribe link (merchant-triggered transactional email)
- Automated refund notifications without merchant opt-in
