mirror of
https://git.meshkee.com/BaloutPastry/backend.git
synced 2026-08-11 22:31:00 +04:30
197 lines
7.4 KiB
Markdown
197 lines
7.4 KiB
Markdown
# Balout Pastry — Backend (setup context)
|
|
|
|
NestJS API for شیرینیفروشی بلوط. Serves the admin Dashboards SPA (and future customer apps).
|
|
|
|
Repo: `https://git.meshkee.com/BaloutPastry/backend.git`
|
|
Dashboards repo: `https://git.meshkee.com/BaloutPastry/dashboards.git`
|
|
|
|
## Stack
|
|
|
|
- NestJS 11 / TypeScript
|
|
- Prisma 6 + PostgreSQL 16 (Docker Compose)
|
|
- JWT access + refresh tokens (bcrypt password hashes)
|
|
- Parspack S3-compatible object storage (prefix `balout/`)
|
|
|
|
## Prerequisites
|
|
|
|
- Node.js **20+** (LTS recommended)
|
|
- npm
|
|
- Docker + Docker Compose (for local Postgres)
|
|
- S3 credentials if you need media upload (can leave blank for auth/users-only local work)
|
|
|
|
## Setup on a new device
|
|
|
|
```bash
|
|
git clone https://git.meshkee.com/BaloutPastry/backend.git
|
|
cd backend
|
|
|
|
cp .env.example .env
|
|
# Fill S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY if you need uploads
|
|
# Change JWT_* secrets before any shared/staging use
|
|
|
|
npm install
|
|
npm run db:up # Postgres on 127.0.0.1:5434
|
|
npx prisma migrate deploy # apply migrations
|
|
npx prisma generate # if client missing after install
|
|
|
|
npm run create-super-admin -- --phone 09120000000 --password secret123
|
|
# optional: --first علی --last رضایی --title "جناب آقای"
|
|
|
|
npm run start:dev # http://localhost:3100/api/v1
|
|
```
|
|
|
|
Health check: `GET http://localhost:3100/api/v1/auth/me` → `401` without token is expected (server is up).
|
|
|
|
### Pair with Dashboards
|
|
|
|
1. Keep this API on **3100**
|
|
2. In dashboards: `VITE_API_BASE_URL=http://localhost:3100/api/v1`
|
|
3. Backend `CORS_ORIGIN` must include local dashboard origins, e.g.
|
|
`http://baloutpastry.com:5173,http://admin.baloutpastry.com:5173,http://customer.baloutpastry.com:5173,http://localhost:5173`
|
|
4. Add local DNS in `/etc/hosts` for `baloutpastry.com`, `admin.baloutpastry.com`, `customer.baloutpastry.com` → `127.0.0.1`
|
|
5. Log in with the super-admin phone/password you created
|
|
- Admin: `http://admin.baloutpastry.com:5173`
|
|
- Customer: `http://customer.baloutpastry.com:5173`
|
|
|
|
## Scripts
|
|
|
|
| Command | What it does |
|
|
|---------|----------------|
|
|
| `npm run start:dev` | Nest watch mode → `http://localhost:3100/api/v1` |
|
|
| `npm run start:prod` | Run compiled `dist/main` |
|
|
| `npm run build` | Compile Nest → `dist/` |
|
|
| `npm run db:up` | `docker compose up -d` (Postgres) |
|
|
| `npm run db:down` | Stop Postgres container |
|
|
| `npm run prisma:migrate` | Create/apply migrations in dev |
|
|
| `npm run prisma:deploy` | Apply existing migrations (CI / new device) |
|
|
| `npm run prisma:generate` | Regenerate Prisma Client |
|
|
| `npm run create-super-admin` | Create first `superAdmin` user |
|
|
| `npm run send-sms` | Send SMS via Meshkee (`--to` / `--message`) |
|
|
| `npm run lint` | ESLint |
|
|
|
|
## Environment
|
|
|
|
Copy from `.env.example`. Do **not** commit `.env`.
|
|
|
|
| Variable | Notes |
|
|
|----------|--------|
|
|
| `DATABASE_URL` | Prisma connection string (default → local Docker on **5434**) |
|
|
| `POSTGRES_*` | Used by Docker Compose |
|
|
| `PORT` | API port, default **3100** |
|
|
| `CORS_ORIGIN` | Comma-separated origins; include dashboard URL |
|
|
| `JWT_ACCESS_SECRET` / `JWT_REFRESH_SECRET` | Change from example values |
|
|
| `JWT_ACCESS_EXPIRES_IN` / `JWT_REFRESH_EXPIRES_IN` | e.g. `15m` / `7d` |
|
|
| `STORAGE_DISK` | `s3` for Parspack |
|
|
| `S3_*` | Endpoint, bucket, public URL, keys |
|
|
| `MEDIA_MAX_FILE_SIZE_MB` | Upload size cap |
|
|
| `MESHKEE_SMS_URL` | Meshkee public SMS send endpoint |
|
|
| `MESHKEE_SMS_API_KEY` | Partner API key (`X-Api-Key`) — server only |
|
|
| `MESHKEE_SMS_DOMAIN` | Partner domain, e.g. `baloutpastry.com` |
|
|
|
|
Inject `SmsService` from `SmsModule` to send SMS from the backend (never from the frontend). Limits: 30/partner/min, 5/destination/min.
|
|
|
|
```bash
|
|
npm run send-sms -- --to 09127004945 --message "متن پیام"
|
|
```
|
|
|
|
Ports are intentional vs Meshkee: API **3100**, Postgres host **5434** (Meshkee uses 3000 / 5432).
|
|
|
|
## Auth rules
|
|
|
|
- Login: `POST /auth/login` with `{ "cellNumber": "09…", "password": "…" }`
|
|
- Login with SMS: `POST /auth/login/send-code` then `POST /auth/login/verify`
|
|
- Forgot password: `POST /auth/forgot-password/send-code` → `/verify` → `/reset`
|
|
- Register: `POST /auth/register/send-code` then `POST /auth/register/verify` (SMS OTP → create `customer`)
|
|
- Only `admin` and `superAdmin` can log in to the admin API/dashboard
|
|
- Only `superAdmin` can assign `admin` or `superAdmin` roles
|
|
- `customer` users exist for orders / future customer UI
|
|
- Access token in `Authorization: Bearer …`; refresh via `POST /auth/refresh`
|
|
|
|
## Main routes (`/api/v1`)
|
|
|
|
| Area | Methods |
|
|
|------|---------|
|
|
| Auth | `POST /auth/login`, `/auth/login/send-code`, `/auth/login/verify`, `/auth/forgot-password/send-code`, `/auth/forgot-password/verify`, `/auth/forgot-password/reset`, `/auth/register/send-code`, `/auth/register/verify`, `/auth/refresh`, `/auth/logout`, `GET /auth/me` |
|
|
| Users | CRUD + `PATCH /users/:id/role`, `/password` + addresses under `/users/:id/addresses` |
|
|
| Flavors | CRUD |
|
|
| Categories | tree CRUD + `GET\|PUT /categories/:id/options` |
|
|
| Products | CRUD (options must match category templates); list filters `q`, `categoryId`, `minPrice`, `maxPrice` |
|
|
| Orders | `GET /orders`, `GET /orders/:id`, `POST /orders`, `PATCH /orders/:id/status` |
|
|
| Media | `POST /media/upload?kind=main\|gallery\|temp` |
|
|
| Settings | districts, shipping exceptions, branches |
|
|
|
|
Guards: most routes require JWT + `admin`/`superAdmin`. Role changes require `superAdmin`.
|
|
|
|
## Orders
|
|
|
|
Create body example:
|
|
|
|
```json
|
|
{
|
|
"customerId": "...",
|
|
"deliveryType": "pickup",
|
|
"branchId": "...",
|
|
"note": "optional",
|
|
"items": [
|
|
{ "productId": "...", "quantity": 2, "optionIds": ["..."] }
|
|
]
|
|
}
|
|
```
|
|
|
|
For shipping: `deliveryType: "shipping"` + `shippingAddressId` (from user addresses). Prices/names are snapshotted. Display code: `BL-{number}`.
|
|
|
|
## Domain notes
|
|
|
|
- Prices are integer **تومان**
|
|
- Phone numbers: `09` + 9 digits (English digits)
|
|
- User titles/categories are fixed Persian enums in `src/users/users.constants.ts`
|
|
|
|
## Project layout
|
|
|
|
```
|
|
prisma/ schema + migrations
|
|
scripts/ create-super-admin.ts
|
|
src/
|
|
auth/ JWT login, refresh, guards, roles
|
|
users/ users + addresses
|
|
flavors/
|
|
categories/
|
|
products/
|
|
orders/
|
|
media/ uploads
|
|
settings/ districts, shipping, branches
|
|
storage/ S3 driver
|
|
prisma/ PrismaModule / PrismaService
|
|
main.ts global prefix api/v1, CORS, ValidationPipe
|
|
docker-compose.yml local Postgres
|
|
```
|
|
|
|
## Production sketch
|
|
|
|
```bash
|
|
cp .env.example .env # real secrets, DB, CORS, S3
|
|
npm ci
|
|
npx prisma migrate deploy
|
|
npm run build
|
|
npm run start:prod
|
|
```
|
|
|
|
Ensure Postgres is reachable via `DATABASE_URL` and `CORS_ORIGIN` lists the real dashboard origin(s).
|
|
|
|
## Common issues
|
|
|
|
| Symptom | Likely cause |
|
|
|---------|----------------|
|
|
| `ECONNREFUSED` / Prisma errors | Postgres not up → `npm run db:up`, check `DATABASE_URL` / port **5434** |
|
|
| Port already in use | Another process on 3100 or 5434 |
|
|
| Login rejected for valid user | Role is `customer`, or wrong phone format |
|
|
| CORS errors from dashboard | `CORS_ORIGIN` missing `http://localhost:5173` |
|
|
| Upload fails | Missing/invalid `S3_*` keys or endpoint |
|
|
| `User already exists` on create-super-admin | That phone is already in DB |
|
|
|
|
## Related
|
|
|
|
- Dashboards setup: clone `BaloutPastry/dashboards` and read `CONTEXT.md`
|
|
- Website (storefront): clone `BaloutPastry/website` and read `CONTEXT.md` (dev port **5174**)
|
|
- Short API overview also in `README.md`
|