# Quotation Send + Payment Flow — Design

**Date:** 2026-02-26
**Status:** Approved

---

## Summary

Wire up the quotation delivery and payment flow end-to-end. When a quotation is created (or manually sent), it is dispatched to the customer via email (Stripe checkout link) and phone (mocked for now). Payment is confirmed automatically via Stripe webhook, with manual recording as a fallback. The tab navigation is simplified to three tabs.

---

## 1. Tab Cleanup

Remove **Deals Pipeline** and **Pipeline Stats** tabs from `tabConfig.tsx`.

The quotation panel shows exactly three tabs:

| Tab            | Purpose                                    |
| -------------- | ------------------------------------------ |
| **Quotations** | Create, list, manage, send quotations      |
| **Recurring**  | Set up recurring billing schedules         |
| **Settings**   | Business defaults + delivery configuration |

Underlying routes/components are not deleted — just removed from tab navigation.

---

## 2. "Send Immediately" Checkbox on the Form

Add a checkbox to `QuotationForm.tsx` just above the Save button:

```
☑  Send to customer immediately
```

- **Default:** checked
- **Checked:** quotation is created with `status = SENT`, delivery fires immediately
- **Unchecked:** quotation is created with `status = DRAFT`, no delivery
- The existing "Send" button on the quotation list row still works for DRAFT quotations, triggering the same delivery logic

The `sendImmediately: boolean` flag is passed in the POST body to `POST /api/dashboard/quotations`.

Bilingual labels:

- EN: "Send to customer immediately"
- AR: "إرسال للعميل فوراً"

---

## 3. Send Flow

Triggered either by `sendImmediately=true` on create, or by the existing `POST /api/dashboard/quotations/[id]/send` endpoint.

**Sequence:**

1. **Generate `portalToken`** — if not already set, generate a unique cuid and persist it on the quotation row
2. **Create Stripe checkout session** — call `createPortalCheckoutSession` (already exists in `quotation-portal.service.ts`), store `stripeCheckoutUrl` + `stripeSessionId`
3. **Enqueue email job** — use `createQuotationSentEmail` template (already exists in `lib/services/email/templates/quotation-templates.ts`), passing:
   - Portal URL: `{NEXTAUTH_URL}/quotation/{portalToken}`
   - Stripe checkout URL embedded in the portal Pay button (portal already handles this)
4. **Phone (mock)** — log `"SMS queued for {phone}"`, return `phoneStatus: "sent"` in the API response. No actual SMS sent.
5. **Update quotation** — `status = SENT`, `sentAt = now()`

**Error handling:**

- If Stripe checkout creation fails → return 502, do not mark as SENT
- If email enqueue fails → log error, still mark as SENT (non-blocking)
- Phone is always "success" (mocked)

---

## 4. Payment Confirmation

### Automatic (Stripe webhook)

- Event: `checkout.session.completed`
- Filter: `metadata.type === 'quotation_payment'`
- Actions:
  - Set `paymentStatus = PAID`
  - Set `status = PAID`
  - Set `paidAt = now()`
  - Set `amountPaid = total`
  - Create `quotation_payments` record for audit trail

Handler lives in `app/api/stripe/webhook/route.ts` — add a new case for this event type.

### Manual (staff)

- Existing flow unchanged
- Staff records cash/bank transfer from the dashboard
- Same payment status update logic applies

---

## 5. Settings Tab Expansion

Add a **Delivery Defaults** section below the existing currency/tax/terms settings in the Settings tab.

| Field                       | Type              | Default                                                 |
| --------------------------- | ----------------- | ------------------------------------------------------- |
| Send immediately by default | Toggle            | On                                                      |
| Reminder schedule           | Multi-select days | 7 days before, 3 days before, on due date, 3 days after |

Stored on the existing `quotation_settings` table (add columns: `defaultSendImmediately: Boolean`, `reminderDays: Json`).

These defaults pre-populate:

- The "Send immediately" checkbox on the form
- The reminder cron job schedule

---

## Files Changed

| File                                                                          | Change                                                             |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `app/[lang]/dashboard/tabConfig.tsx`                                          | Remove Deals Pipeline + Pipeline Stats                             |
| `components/dashboard/quotations/QuotationForm.tsx`                           | Add `sendImmediately` checkbox                                     |
| `app/api/dashboard/quotations/route.ts`                                       | Accept `sendImmediately` flag, call send logic on create           |
| `app/api/dashboard/quotations/[id]/send/route.ts`                             | Wire up portal token + Stripe + email                              |
| `app/api/stripe/webhook/route.ts`                                             | Add `checkout.session.completed` quotation payment handler         |
| `prisma/schema.prisma`                                                        | Add `defaultSendImmediately`, `reminderDays` to quotation_settings |
| `app/[lang]/dashboard/components/QuotationsSettingsTab.tsx` (new or existing) | Delivery defaults UI                                               |

---

## Out of Scope

- Actual SMS/WhatsApp sending (phone is mocked, returns success)
- Partial payments UI changes
- Penalty application
- Reminder cron wiring (schema only, no cron changes)
