# Cancellation notification sent to customer

- **Pattern:** `ab-001148` (`ecommerce-order-management.notifications.cancellation-email`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001148
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001148)

## Why it matters

A customer who cancels an order — or whose order is admin-cancelled — and receives no email confirmation is left wondering whether the cancellation actually went through. Without notification, they may place a duplicate order, not monitor their bank account for the refund, or contact support unnecessarily. If the admin cancels an order on behalf of a customer (for a fraud flag, inventory issue, or address problem), the customer deserves immediate notification with context. The iso-25010:2011 reliability dimension: the cancellation event occurred in the system but the customer has no evidence of it.

## Severity rationale

Low because cancellation notification failures inconvenience customers and increase support volume without creating financial or security risk.

## Remediation

Add a cancellation email call to the cancellation handler at `app/api/orders/[id]/cancel/route.ts`, fired after the successful `transitionOrder` call.

```ts
// After transitionOrder(orderId, 'cancelled', ...) in app/api/orders/[id]/cancel/route.ts:
await sendCancellationEmail({
  to: order.user.email,
  orderNumber: order.id,
  refundExpected: order.total > 0,
  refundTimelineDays: REFUND_WINDOW_DAYS,
  supportUrl: 'https://yoursite.com/support',
})
```

Add `sendCancellationEmail` to `lib/email/order-emails.ts` and ensure the admin cancellation path also sends the same notification.

## Detection

- **ID:** `cancellation-email`
- **Severity:** `low`
- **What to look for:** When an order is cancelled, count the email service calls in the cancellation handler (at least 1 required). Enumerate which cancellation paths (customer-initiated and admin-initiated) trigger emails. The cancellation email should communicate at least 2 of: which order was cancelled, whether a refund will be issued, expected refund timeline, or how to contact support. Check both customer-initiated cancellations and admin-initiated cancellations.
- **Pass criteria:** At least 1 cancellation email is sent to the customer when an order is cancelled, regardless of whether the cancellation was customer-initiated or admin-initiated. The email includes at least 2 data fields (order number and refund status or support contact). A cancellation handler with 0 email calls does not count as pass.
- **Fail criteria:** No email is sent on cancellation (0 email calls in cancellation handlers). The customer must check their order status page to discover that their order was cancelled, with no proactive communication.
- **Skip (N/A) when:** The project does not support order cancellation. No cancellation handler exists in the codebase.
- **Detail on fail:** `"The cancellation handler triggers a status update and history entry but makes 0 email service calls. Customers are not notified when their order is cancelled — they only find out by checking their account."`
- **Remediation:** Add cancellation notification to the cancellation handler at `app/api/orders/[id]/cancel/route.ts`:

  ```ts
  // After transitionOrder(orderId, 'cancelled', ...) in app/api/orders/[id]/cancel/route.ts:
  await sendCancellationEmail({
    to: order.user.email,
    orderNumber: order.id,
    refundExpected: order.total > 0,
    refundTimelineDays: REFUND_WINDOW_DAYS,
    supportUrl: 'https://yoursite.com/support',
  })
  ```

## External references

- iso-25010 reliability

Taxons: error-resilience

HTML version: https://auditbuffet.com/patterns/ab-001148
