Docs: add PROJECT_REFERENCE, TESTING_CHECKLIST, update session instructions for Phase 4+5 completion
This commit is contained in:
328
PLANS AND STRATEGIES/TESTING_CHECKLIST.md
Normal file
328
PLANS AND STRATEGIES/TESTING_CHECKLIST.md
Normal file
@@ -0,0 +1,328 @@
|
||||
# POS System — End-to-End Testing Checklist
|
||||
|
||||
Work through this top-to-bottom. Each section depends on the one above it.
|
||||
Mark `[x]` as you go. Note failures with a short comment.
|
||||
|
||||
---
|
||||
|
||||
## 0. Prerequisites
|
||||
|
||||
- [ ] Docker Desktop is running
|
||||
- [ ] You are in the project root: `c:\development\simple-pos-system`
|
||||
- [ ] All `.env` files are filled in correctly (see below)
|
||||
|
||||
### .env quick reference
|
||||
|
||||
**`cloud_backend/.env`**
|
||||
```
|
||||
SECRET_KEY=<long random string>
|
||||
DATABASE_URL=sqlite:////app/data/cloud.db
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=60
|
||||
ADMIN_USERNAME=sysadmin
|
||||
ADMIN_PASSWORD=<your password>
|
||||
```
|
||||
|
||||
**`local_backend/.env`**
|
||||
```
|
||||
SITE_ID=<filled in after step 2.4>
|
||||
SITE_KEY=<filled in after step 2.4>
|
||||
CLOUD_URL=http://cloud_backend:8001
|
||||
SECRET_KEY=<long random string>
|
||||
LICENSE_GRACE_HOURS=24
|
||||
```
|
||||
|
||||
**`sysadmin_panel/.env`**
|
||||
```
|
||||
VITE_CLOUD_URL=http://localhost:8001
|
||||
```
|
||||
|
||||
**`waiter_pwa/.env`**
|
||||
```
|
||||
VITE_API_URL=http://<local-backend-ip>:8000
|
||||
```
|
||||
|
||||
**`manager_dashboard/.env`**
|
||||
```
|
||||
VITE_API_URL=http://<local-backend-ip>:8000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Cloud Backend
|
||||
|
||||
### 1.1 Start
|
||||
```bash
|
||||
docker compose up cloud_backend -d
|
||||
```
|
||||
- [ ] Container starts without errors (`docker compose logs cloud_backend`)
|
||||
|
||||
### 1.2 Health check
|
||||
```
|
||||
GET http://localhost:8001/health
|
||||
```
|
||||
- [ ] Returns `{"status": "ok"}`
|
||||
|
||||
### 1.3 Sysadmin login
|
||||
```
|
||||
POST http://localhost:8001/api/auth/login
|
||||
Body: { "username": "sysadmin", "password": "changeme" }
|
||||
```
|
||||
- [ ] Returns a JWT `access_token`
|
||||
- [ ] Save token for next steps
|
||||
|
||||
### 1.4 List sites (empty)
|
||||
```
|
||||
GET http://localhost:8001/api/sites/
|
||||
Header: Authorization: Bearer <token>
|
||||
```
|
||||
- [ ] Returns `[]` (empty list)
|
||||
|
||||
---
|
||||
|
||||
## 2. Sysadmin Panel
|
||||
|
||||
### 2.1 Start
|
||||
```bash
|
||||
docker compose up sysadmin_panel -d
|
||||
```
|
||||
- [ ] Container starts, `npm install` completes, dev server on port 5175
|
||||
|
||||
### 2.2 Open in browser
|
||||
```
|
||||
http://localhost:5175
|
||||
```
|
||||
- [ ] Redirects to `/login`
|
||||
- [ ] Login form appears (username + password, NOT pin pad)
|
||||
|
||||
### 2.3 Login
|
||||
- [ ] Enter `sysadmin` / `changeme` → redirects to `/sites`
|
||||
- [ ] Sites page shows "0 registered", "Register New Site" button visible
|
||||
- [ ] Summary counts (Active / Locked / Expired) visible
|
||||
|
||||
### 2.4 Register a site
|
||||
- Click "Register New Site"
|
||||
- [ ] Form fields: Restaurant Name, Owner Name, Contact Email, License Expiry
|
||||
- [ ] Fill in test data, set expiry date to at least 1 year from now
|
||||
- [ ] Submit → success screen shows
|
||||
- [ ] **Site ID** and **Secret Key** are displayed
|
||||
- [ ] Warning banner "Copy this secret key now" is visible
|
||||
- [ ] "Copy .env vars" button works (copies to clipboard)
|
||||
- Copy the `SITE_ID` and `SITE_SECRET` values
|
||||
- Paste them into `local_backend/.env` as `SITE_ID=` and `SITE_KEY=`
|
||||
|
||||
### 2.5 Verify site in list
|
||||
- [ ] Navigate to `/sites` → new site card appears
|
||||
- [ ] Status shows yellow "No Heartbeat" (expected — local backend hasn't connected yet)
|
||||
- [ ] Click site card → SiteDetailPage shows correct name, owner, expiry
|
||||
- [ ] Lock/Unlock/Extend License buttons are visible
|
||||
|
||||
---
|
||||
|
||||
## 3. Local Backend
|
||||
|
||||
### 3.1 Start
|
||||
```bash
|
||||
docker compose up backend -d
|
||||
```
|
||||
- [ ] Container starts without errors
|
||||
- [ ] Logs show: `Application startup complete`
|
||||
- [ ] Logs show cloud sync attempt: either `Cloud sync OK` or `Cloud sync failed` (if cloud URL not yet reachable from inside Docker — check `CLOUD_URL=http://cloud_backend:8001`)
|
||||
|
||||
### 3.2 Health check
|
||||
```
|
||||
GET http://localhost:8000/api/system/health
|
||||
```
|
||||
- [ ] Returns `{"status": "ok"}` (this endpoint is exempt from license check)
|
||||
|
||||
### 3.3 Heartbeat appears in sysadmin panel
|
||||
- [ ] In Sysadmin Panel → SiteDetailPage: "Last seen" updates to recent timestamp
|
||||
- [ ] Status indicator turns green "Active"
|
||||
- [ ] Last IP field shows the Docker container IP
|
||||
|
||||
> Note: Cloud sync runs immediately on startup, so this should update within seconds.
|
||||
|
||||
### 3.4 Auth — create initial manager
|
||||
If no manager user exists in the DB yet, seed one via the seed script or direct API call:
|
||||
```bash
|
||||
docker compose exec backend python seed.py
|
||||
```
|
||||
- [ ] Seed runs without errors (or manager already exists)
|
||||
|
||||
### 3.5 Auth — login as manager
|
||||
```
|
||||
POST http://localhost:8000/api/auth/login
|
||||
Body: { "username": "manager", "pin": "1234" }
|
||||
```
|
||||
- [ ] Returns `{ access_token, user: { id, username, role: "manager" } }`
|
||||
|
||||
### 3.6 Auth — login as waiter
|
||||
```
|
||||
POST http://localhost:8000/api/auth/login
|
||||
Body: { "username": "<waiter-username>", "pin": "<pin>" }
|
||||
```
|
||||
- [ ] Returns token with `role: "waiter"`
|
||||
|
||||
### 3.7 Tables endpoint
|
||||
```
|
||||
GET http://localhost:8000/api/tables/
|
||||
Header: Authorization: Bearer <manager-token>
|
||||
```
|
||||
- [ ] Returns list of tables (may be empty if not seeded)
|
||||
|
||||
### 3.8 Products endpoint
|
||||
```
|
||||
GET http://localhost:8000/api/products/
|
||||
Header: Authorization: Bearer <manager-token>
|
||||
```
|
||||
- [ ] Returns list of products and categories
|
||||
|
||||
---
|
||||
|
||||
## 4. Manager Dashboard
|
||||
|
||||
### 4.1 Start
|
||||
```bash
|
||||
docker compose up manager_dashboard -d
|
||||
```
|
||||
- [ ] Dev server starts on port 5174
|
||||
|
||||
### 4.2 Open in browser
|
||||
```
|
||||
http://localhost:5174
|
||||
```
|
||||
- [ ] Redirects to `/login`
|
||||
- [ ] PIN pad + username field visible
|
||||
|
||||
### 4.3 Login
|
||||
- [ ] Enter manager username + PIN → redirects to `/dashboard`
|
||||
- [ ] Dashboard shows table grid (empty or with existing tables)
|
||||
- [ ] No console errors
|
||||
|
||||
### 4.4 Tables page
|
||||
- [ ] Navigate to Tables → existing tables shown
|
||||
- [ ] Create a new table (e.g. Table 10) → appears in list
|
||||
- [ ] Table groups section visible
|
||||
|
||||
### 4.5 Products page
|
||||
- [ ] Navigate to Products → existing products shown
|
||||
- [ ] Create a new category
|
||||
- [ ] Create a new product in that category, assign a price
|
||||
- [ ] Toggle product availability → greyed out when unavailable
|
||||
- [ ] Assign a printer zone to a product (if printer is configured)
|
||||
- [ ] Product image upload works on an existing product
|
||||
|
||||
### 4.6 Waiters page
|
||||
- [ ] Navigate to Waiters → existing waiters shown
|
||||
- [ ] Create a new waiter (username + PIN)
|
||||
- [ ] Block/unblock a waiter works
|
||||
- [ ] Reset PIN works
|
||||
|
||||
### 4.7 Dashboard live grid
|
||||
- [ ] Open an order from the Waiter PWA (step 5 below), then return here
|
||||
- [ ] Table card updates within 30 seconds (polling interval)
|
||||
- [ ] Click table → OrderDetailPage loads with correct items
|
||||
|
||||
### 4.8 Reports page
|
||||
- [ ] Navigate to Reports → no crash
|
||||
- [ ] Date picker works, summary loads (may be empty)
|
||||
|
||||
### 4.9 Settings page
|
||||
- [ ] Navigate to Settings → no crash
|
||||
- [ ] Printer config visible
|
||||
|
||||
---
|
||||
|
||||
## 5. Waiter PWA
|
||||
|
||||
### 5.1 Open on phone (or browser)
|
||||
```
|
||||
http://<local-machine-ip>:5173
|
||||
```
|
||||
- [ ] App loads, redirects to `/login`
|
||||
- [ ] Username field + PIN pad visible
|
||||
|
||||
### 5.2 Login as waiter
|
||||
- [ ] Enter waiter credentials → redirects to table list
|
||||
- [ ] Only active tables visible (not deactivated ones)
|
||||
|
||||
### 5.3 Open a table order
|
||||
- [ ] Tap a table → if no open order, "Open Order" button appears
|
||||
- [ ] Tap "Open Order" → order is created, table turns active
|
||||
|
||||
### 5.4 Add items
|
||||
- [ ] Category tabs visible at top
|
||||
- [ ] Tap a product → added to order
|
||||
- [ ] Products with options show option selector
|
||||
- [ ] Products with removable ingredients show toggle list
|
||||
- [ ] Item with note field → can add freetext note
|
||||
|
||||
### 5.5 Verify print routing
|
||||
- [ ] After adding items: check printer (if connected) received the ticket
|
||||
- [ ] If no physical printer: check `docker compose logs backend` — should show print attempt log (success or failure, NOT a crash)
|
||||
|
||||
### 5.6 View order total
|
||||
- [ ] Order total shows correct sum (base price + selected option deltas)
|
||||
- [ ] Individual item prices shown
|
||||
|
||||
### 5.7 Partial payment
|
||||
- [ ] Select some items → "Mark as Paid" → those items turn grey/paid
|
||||
- [ ] Order status changes to "partially_paid"
|
||||
- [ ] Remaining total updates
|
||||
|
||||
### 5.8 Full payment and close
|
||||
- [ ] Mark all items as paid → order status = "paid"
|
||||
- [ ] "Close Order" button becomes active
|
||||
- [ ] Tap "Close Order" → confirmation prompt
|
||||
- [ ] Confirm → order closes, table returns to "available"
|
||||
|
||||
### 5.9 Multi-waiter scenario
|
||||
- [ ] From Manager Dashboard, add a second waiter to the order
|
||||
- [ ] Second waiter can see and manage the table in their PWA
|
||||
|
||||
### 5.10 Blocked waiter
|
||||
- [ ] From Manager Dashboard, block a waiter
|
||||
- [ ] That waiter is immediately redirected to login on their next PWA request (401 interceptor)
|
||||
|
||||
---
|
||||
|
||||
## 6. License / Lock Testing
|
||||
|
||||
### 6.1 Lock site from sysadmin panel
|
||||
- [ ] In Sysadmin Panel → SiteDetailPage → Lock Site → enter reason → confirm
|
||||
- [ ] Site shows "Locked" status with red indicator
|
||||
- [ ] Within the next sync cycle (or restart local backend to force immediate sync):
|
||||
- Local backend logs show lock status received
|
||||
- All local backend endpoints return HTTP 423 (except `/api/system/health`)
|
||||
- Waiter PWA shows error / cannot load data
|
||||
- Manager Dashboard shows error
|
||||
|
||||
### 6.2 Unlock
|
||||
- [ ] In Sysadmin Panel → Unlock Site
|
||||
- [ ] After next sync: local backend resumes normal operation
|
||||
|
||||
### 6.3 Expired license
|
||||
- [ ] In Sysadmin Panel → Extend License → set expiry date in the PAST → save
|
||||
- [ ] After local backend sync: returns HTTP 402 on all endpoints
|
||||
- [ ] Restore to future date → normal operation resumes
|
||||
|
||||
### 6.4 Cloud unreachable (grace period)
|
||||
- [ ] Stop cloud backend: `docker compose stop cloud_backend`
|
||||
- [ ] Local backend continues to serve requests (last known state + 24h grace)
|
||||
- [ ] Logs show repeated `Cloud sync failed` warnings
|
||||
- [ ] Restart cloud backend → next sync succeeds
|
||||
|
||||
---
|
||||
|
||||
## 7. Known Issues to Watch For
|
||||
|
||||
- Product image upload only works on existing products (not at creation time)
|
||||
- Printer zone must be assigned via Manager Dashboard before items will route to a printer
|
||||
- Some manager/PWA interactions have rough edges (noted in CLAUDE_CODE_INSTRUCTIONS.md)
|
||||
- `SITE_KEY` in `local_backend/.env` must match the secret generated at site registration (copy it immediately, it's shown only once)
|
||||
|
||||
---
|
||||
|
||||
## Done?
|
||||
|
||||
All steps checked → the system is fully operational end-to-end.
|
||||
Log any failures as GitHub issues or in `CLAUDE_CODE_INSTRUCTIONS.md` under a new "Phase 5 Known Issues" section.
|
||||
Reference in New Issue
Block a user