# Yatra — Setup Guide (JWT/DRF + Redis/Channels + Seat Maps + eSewa rebuild)

This covers everything added in this round. Your existing setup steps
(XAMPP MySQL, `yatra_booking` database, Gmail SMTP, Google OAuth) are
unchanged — this guide only covers what's *new*.

## 1. Install Docker Desktop (for Redis)

Redis powers the live seat-map and live Operator/Admin dashboard updates
(Django Channels). You said you already have Docker — good, that's all
you need beyond what you already have installed.

## 2. Start Redis

In the `server/` folder:

```powershell
docker compose up -d
```

This starts a `redis:7-alpine` container on `localhost:6379`. Check it's
running any time with `docker ps`. Stop it with `docker compose down`
(your data doesn't matter here — Redis only holds live, ephemeral
connection state, never bookings or payments).

If you ever run the server on a different machine or port for Redis, set
the `REDIS_URL` environment variable (defaults to `redis://127.0.0.1:6379/0`).

## 3. Install the new Python packages

```powershell
py -m pip install -r requirements.txt
```

New packages: `djangorestframework`, `djangorestframework-simplejwt`,
`channels`, `channels-redis`, `daphne`, `redis`, `qrcode`, `reportlab`.

## 4. Migrate

```powershell
py manage.py migrate
```

This adds: seat-level tables (`bus_seats`, `seat_locks`, `booking_seats`),
payments (`payments`, `payment_webhook_logs`), `operator_documents`,
`ratings`, `device_trust`, plus new fields on `Bus`/`Schedule`/`Booking`.
Nothing existing is dropped or altered destructively — every migration is
additive.

## 5. Run the server — same command as always

```powershell
py manage.py runserver
```

Nothing changes here. Because `daphne` is now the first app in
`INSTALLED_APPS`, Django automatically runs `runserver` through Daphne
(ASGI) instead of its old WSGI dev server, which is what makes WebSockets
(live seat updates, live dashboards) work — you don't need a different
command or a second process for that.

## 6. eSewa payments — already configured for testing

The sandbox (UAT) credentials are wired in and require no setup:

- Test eSewa login: **9711111111** / password **Nepal@123** / OTP token **123456**
- Product code: `EPAYTEST` (in `settings.py` → `ESEWA_SETTINGS`)

**Going live later** is a four-value change in `ESEWA_SETTINGS` in
`yatra_testing/settings.py` — your real merchant code, real secret key, and
the production URLs (commented right below the sandbox ones in that file).
Nothing else in the codebase changes.

## 7. What's real vs. simulated — an honest summary

Everything below is **real**, tested, working code — not mocked:

- JWT authentication (SimpleJWT), device-trust OTP-skip, seat-level
  booking with live locking, Redis/Channels live updates, eSewa's actual
  signed-form + callback + status-check flow (against their sandbox),
  cancellation-fee tiers, document upload/review, trip delays with
  passenger emails, ratings, payment oversight, CSV exports, PDF/QR
  e-tickets.

Two things worth knowing honestly:

- **Concurrency-safe seat locking** (`select_for_update()`) was built
  correctly for MySQL/InnoDB and tested extensively for *business-rule*
  correctness (steal-prevention, expiry, race handling) — but the
  automated tests ran against SQLite, which doesn't provide true
  row-level locking the way MySQL does. The logic is right; if you want
  extra confidence before a live demo under real concurrent load, that's
  the one piece worth a manual double-check on your MySQL setup (e.g. two
  browser tabs racing to grab the same seat).
- **Refunds** are bookkeeping, not a live "send money back" API call —
  eSewa's public merchant API doesn't expose a self-serve refund
  endpoint; refunds are a back-office action in your eSewa merchant
  dashboard in real life, same as with most gateways. The system tracks
  exactly how much is owed and to whom (`Payment` status, cancellation
  fee amounts), which is the correct, honest scope for this endpoint.

## 8. What changed for you day-to-day

- **Operator login**: OTP only the first time on a new browser. After
  that, 7 days with no code needed — then it asks again, matching what
  you asked for.
- **Admin login**: unchanged (password only, 7-day session).
- Both portals' JWT sessions refresh themselves silently in the
  background — you'll never see a random "please login again" mid-task.

## 9. Quick feature map (client)

**Operator portal** — new: Seat map builder (My Buses → 🪑 Seat map),
bus deactivate/delete, per-booking cancel with reason codes, trip delay
marking, Documents (upload for admin review), Ratings, "log out on all
devices" (Profile), live dashboard updates, CSV export.

**Admin portal** — new: Documents (review/reject), Payments (oversight +
live eSewa recheck + webhook log viewer), Ratings/issue queue, CSV
exports, live dashboard updates.

**Passenger website** (unchanged folder structure, `testing_app`) — new:
interactive seat picker with live availability, real eSewa checkout,
payment status on My Bookings, ratings after a completed trip,
PDF/QR e-tickets.
