# Phase 7: Cross-cutting Concerns — DONE

**Completed:** 2026-03-13

## What was delivered

### Migration (1)

- `database/migrations/2026_08_01_000013_add_reminded_at_to_restaurant_reservations_table.php` — Adds `reminded_at` timestamp to `restaurant_reservations` for deduplicating reminder notifications

### Enum Updates (1)

- `app/Enums/NotificationType.php` — Added 6 new cases: `RESTAURANT_RESERVATION_CONFIRMED`, `RESTAURANT_RESERVATION_REMINDER`, `RESTAURANT_RESERVATION_CANCELLED`, `RESTAURANT_PREORDER_CONFIRMED`, `RESTAURANT_NEW_RESERVATION`, `RESTAURANT_DAILY_SUMMARY` with correct `isEmailSupported()` and `isPushSupported()` mappings

### Notifications (6)

- `app/Notifications/Restaurant/CustomerReservationConfirmedNotification.php` — Email + push to customer when reservation is confirmed
- `app/Notifications/Restaurant/CustomerReservationReminderNotification.php` — Push only to customer 2 hours before reservation
- `app/Notifications/Restaurant/CustomerReservationCancelledNotification.php` — Email + push to customer when reservation is cancelled
- `app/Notifications/Restaurant/CustomerPreorderConfirmedNotification.php` — Email + push to customer when pre-order is paid
- `app/Notifications/Restaurant/ManagerNewReservationNotification.php` — Push to restaurant managers when new reservation is created
- `app/Notifications/Restaurant/ManagerDailySummaryNotification.php` — Email to managers with previous day's stats (revenue, covers, reservations, no-shows, orders)

### Pusher Events (4)

- `app/Events/Restaurant/TableStatusChanged.php` — Broadcasts on `restaurant.{public_id}` channel when a table status changes (available/occupied/reserved/maintenance)
- `app/Events/Restaurant/NewReservationCreated.php` — Broadcasts on `restaurant.{public_id}` when a new reservation is created
- `app/Events/Restaurant/ReservationStatusUpdated.php` — Broadcasts on `restaurant.{public_id}` when a reservation status changes
- `app/Events/Restaurant/RestaurantOrderPaid.php` — Broadcasts on `restaurant.{public_id}` when a restaurant order is paid

### Scheduled Commands (4)

- `app/Console/Commands/SendRestaurantReservationRemindersCommand.php` — `restaurant:reservation:remind` — Sends push reminders for confirmed/pending reservations within 2 hours, marks `reminded_at` to prevent duplicates. Scheduled every 15 minutes
- `app/Console/Commands/CleanupExpiredRestaurantCartsCommand.php` — `restaurant:carts:cleanup` — Deletes abandoned restaurant carts (WAITING_PAYMENT) older than 24 hours. Scheduled daily at 03:00
- `app/Console/Commands/SendRestaurantDailySummaryCommand.php` — `restaurant:daily-summary` — Sends summary email to restaurant managers with previous day stats. Scheduled daily at 06:00
- `app/Console/Commands/WarmRestaurantDashboardCacheCommand.php` — `restaurant:dashboard:warm-cache` — Invalidates and re-warms dashboard cache for all active restaurants. Scheduled daily at 00:05

### Listeners (2)

- `app/Listeners/BroadcastRestaurantOrderPaid.php` — Listens to `OrderPaid` event, broadcasts `RestaurantOrderPaid` for restaurant orders, invalidates dashboard cache
- `app/Listeners/NotifyManagersOfNewReservation.php` — Listens to `NewReservationCreated` event, notifies all restaurant managers at the place via push notification

### Observer (1)

- `app/Observers/RestaurantReservationObserver.php` — Registered in `RestaurantReservation::boot()`. Handles:
  - `created`: dispatches `NewReservationCreated` event, sends confirmation notification if auto-confirmed, invalidates dashboard cache
  - `updated`: detects status changes, dispatches `ReservationStatusUpdated` event, sends confirmed/cancelled notifications to customer, invalidates dashboard cache
  - `deleted`: invalidates dashboard cache

### Translations (4 languages)

- `lang/en.json`, `lang/fr.json`, `lang/es.json`, `lang/zh.json` — Added:
  - 10 push notification translation keys (`notifications.push.restaurant_*`)
  - Admin labels for Restaurant, RestaurantTable, RestaurantMenuCategory, RestaurantMenuItem, RestaurantMenu, RestaurantReservation
  - Enum labels for RestaurantTableZone (6), RestaurantTableStatus (4), RestaurantReservationStatus (6), RestaurantServicePeriod (6), RestaurantMenuCategoryType (2), Allergen (14), DietaryLabel (10)

### Modified Files

- `app/Models/RestaurantReservation.php` — Added `reminded_at` to `$fillable` and `$casts`, registered `RestaurantReservationObserver` in `boot()`
- `app/Services/RestaurantManager/RestaurantDashboardCacheService.php` — Added `warmCache()` method
- `app/Console/Kernel.php` — Added 4 scheduled commands (reservation remind every 15min, cart cleanup daily 03:00, daily summary 06:00, dashboard warm 00:05)

### Tests

- `tests/Feature/Controllers/RestaurantManager/CrossCuttingTest.php` — 20 test cases covering:
  - Observer dispatches NewReservationCreated event on creation
  - Observer dispatches ReservationStatusUpdated event on status change
  - Customer notified when reservation confirmed
  - Customer notified when reservation cancelled
  - Managers notified of new reservation via listener
  - Restaurant order paid broadcasts RestaurantOrderPaid event
  - Non-restaurant orders do not broadcast RestaurantOrderPaid
  - Reservation reminder command sends reminders for upcoming reservations
  - Reservation reminder command prevents duplicate reminders (reminded_at)
  - Reservation reminder command ignores far-future reservations
  - Cart cleanup deletes expired restaurant carts
  - Cart cleanup does not delete non-restaurant carts
  - Dashboard cache warm runs for active restaurants
  - Dashboard cache warm runs for specific restaurant by public_id
  - TableStatusChanged broadcasts correct payload
  - NewReservationCreated broadcasts correct payload with public_id
  - ReservationStatusUpdated broadcasts correct payload
  - Translation keys exist in en
  - Translation keys exist in fr
  - NotificationType enum has correct email/push support for all 6 new cases

## Quality Checks

- `vendor/bin/pint` — PASS (23 files, 11 auto-fixed style issues)
- `vendor/bin/phpstan --level=7` — PASS (0 errors after fixing 5 initial issues)

## Files Summary

| Type | Count |
|---|---|
| Migration | 1 |
| Notifications | 6 |
| Pusher Events | 4 |
| Scheduled Commands | 4 |
| Listeners | 2 |
| Observer | 1 |
| Tests | 1 (20 test cases) |
| Modified files | 7 (RestaurantReservation.php, DashboardCacheService.php, Kernel.php, NotificationType.php, en.json, fr.json, es.json, zh.json) |
| **Total new files** | **19** |
