# FCM Push Notifications (KiyoHR TimeX)

## Laravel setup

1. Install is already in `composer.json` via `kreait/laravel-firebase`.
2. Download a **Firebase service account JSON** for project `kiyohr-timex` (Firebase Console → Project settings → Service accounts → Generate new private key).
3. Store the file **outside** the web root as `storage/app/firebase/kiyohr-service-account.json` (**exact lowercase** filename on Linux; Windows is case-insensitive). Legacy `Kiyohr-service-account.json` is also resolved by the app.
4. Set in `.env` (absolute path preferred; relative `storage/app/firebase/...` also works):

```env
FIREBASE_CREDENTIALS=C:\KiyoProjects\KiyoHR-Laravel\storage\app\firebase\kiyohr-service-account.json
FIREBASE_PROJECT=app
```

   On Linux production, use e.g. `FIREBASE_CREDENTIALS=/var/www/kiyohr/storage/app/firebase/kiyohr-service-account.json`.

5. Run migrations: `php artisan migrate` (creates `device_tokens` without a hard FK, matching other HRMS tables).
6. Notifications (including FCM) run **after the HTTP response** in the same PHP process via `defer()` — **do not** run `queue:work` for HRMS notifications. Prefer `QUEUE_CONNECTION=sync`.
7. After the mobile app logs in, confirm a row exists in `device_tokens`. Zero rows means the device never registered (permission denied, notifications toggle off, or token sync failed). API logout clears `device_tokens` for that user (or the optional `fcm_token` / `token` body field).

If a partial `device_tokens` table was left from a failed first attempt (FK error), drop it and re-run the migration.

### API

| Method | Path | Auth | Body |
|--------|------|------|------|
| POST | `/api/auth/fcm-token` | Sanctum | `{ "token": "...", "platform": "android\|ios" }` |
| DELETE | `/api/auth/fcm-token` | Sanctum | `{ "token": "..." }` |

### Events that send push

- Leave submitted → approvers (`leave_submitted`) + employee ack (`leave_request_submitted`)
- Leave approved/rejected → employee (`leave_reviewed`)
- Leave cancelled (delete pending) → approvers (`leave_cancelled`)
- Payroll cycle completed → employees with payslips (`payslip_ready`)
- Other `HrmsNotification` subclasses also use FCM when the user has device tokens

## Flutter (TimeX)

- Permissions: requested on init (Android 13+ / iOS).
- Foreground: local notification popup (`high_importance_channel`).
- Background/killed: system tray via FCM.
- Tap opens `/leave` or `/payslip` from payload `route` / `type`.
- Token sync on login unlock and revoke on logout.
- iOS: `UIBackgroundModes` → `remote-notification` in `Info.plist`. `GoogleService-Info.plist` and Push entitlements (`Runner.entitlements` / `aps-environment`) are included for the Runner target. Upload an APNs key in the Firebase Console for project `kiyohr-timex` before testing on a physical iPhone.

## Manual test checklist

- [ ] Login → row appears in `device_tokens`
- [ ] Submit leave (app) → approver device gets pending push; submitter gets confirmation
- [ ] Approve/reject leave → employee push; tap opens Leave
- [ ] Cancel pending leave → approver push
- [ ] Complete payroll cycle → employee payslip push; tap opens Payslip
- [ ] App open → foreground popup
- [ ] App backgrounded/closed → tray notification
- [ ] Logout → token removed from `device_tokens`
