# Canteen Asset Geolocation Tool

Mobile-friendly webapp for tracking physical assets with barcode scanning, OCR sticker reading, and GPS check-ins. Built with FastAPI + SQLite + vanilla JS.

## Quick Start

```bash
cd ~/projects/canteen-asset-tracker
./start.sh
```

Then open `https://canteen.ourpad.casa` on your phone. HTTPS via NPMPlus reverse proxy → backend on :8901.

## Default Login

The server seeds a default admin account on first startup:

| Field    | Value        |
|----------|-------------|
| Username | `admin`     |
| Password | `Brett85!@` |

**Change this password on first login** via the Settings → Users tab.

## Features

- **Add Asset tab** — Three entry modes:
  - **Barcode** — Live camera scanning via ZXing. Uses 1D-only format hints (Code 128, Code 39, EAN/UPC, ITF, Codabar) with `decodeFromVideoDevice` for fast, accurate detection. Auto-looks up assets or offers to create new ones.
  - **OCR** — Snap a photo of the Connect ID sticker. Extracts the last 5 digits from the `XXXXX-XXXXXX` pattern (e.g., `05912-095330` → `95330`).
  - **Manual** — Full form with photo capture, customer/location assignment, keys, and badges.
- **Auto check-in** — Every new asset (from any entry mode) gets an automatic GPS check-in on creation. If GPS isn't available yet, the manual check-in button remains.
- **Assets tab** — Browse, search, filter, create, edit, delete assets. View check-in history per asset with map.
- **Dashboard tab** — Stats: total assets, check-ins, breakdown by category and status. CSV export.
- **Activity tab** — Full activity feed with user filtering.
- **Map tab** — View all assets and check-ins on an interactive Leaflet map.
- GPS auto-acquired on page load for location-tagged check-ins.

## Tech Stack

| Layer    | Tech                          |
|----------|-------------------------------|
| Backend  | FastAPI + SQLite (WAL mode)   |
| Frontend | Vanilla HTML/CSS/JS (single file, ~280KB) |
| Scanner  | @zxing/library 0.20.0 (CDN)   |
| OCR      | Tesseract (pytesseract + PIL) |
| Maps     | Leaflet + Leaflet.Draw + Leaflet.Heat |
| TLS      | Self-signed cert, port 8901, proxied via NPMPlus |

## API

Base URL: `https://canteen.ourpad.casa`

Auth: Bearer token (obtained via `/api/auth/login`)

| Method | Endpoint                        | Description                         |
|--------|---------------------------------|-------------------------------------|
| POST   | `/api/auth/login`               | Login, returns token                |
| GET    | `/api/auth/me`                  | Current user info                   |
| POST   | `/api/assets`                   | Create asset                        |
| GET    | `/api/assets`                   | List assets (filterable)            |
| GET    | `/api/assets/search?machine_id=`| Lookup by machine ID                |
| GET    | `/api/assets/{id}`              | Get single asset                    |
| PUT    | `/api/assets/{id}`              | Update asset                        |
| DELETE | `/api/assets/{id}`              | Delete asset + check-ins            |
| POST   | `/api/checkins`                 | Create check-in (GPS + photo)       |
| GET    | `/api/checkins`                 | List check-ins (filterable)         |
| POST   | `/api/ocr`                      | OCR sticker image → machine_id      |
| GET    | `/api/stats`                    | Dashboard stats                     |
| GET    | `/api/export/assets`            | Export assets CSV                   |
| GET    | `/api/export/checkins`          | Export check-ins CSV                |
| GET    | `/api/activity`                 | Activity feed                       |
| *      | `/api/settings/{entity}`        | Dynamic CRUD for 6 entity types     |
| *      | `/api/customers`                | Customer CRUD                       |
| *      | `/api/locations`                | Location CRUD + rooms               |
| *      | `/api/users`                    | User CRUD                           |
| *      | `/api/geofences`                | Geofence CRUD + user assignment     |
| *      | `/api/visits`                   | Visit CRUD + stats                  |
| *      | `/api/proximity`                | Find assets near GPS point          |
| POST   | `/api/upload/photo`             | Upload asset photo                  |
| POST   | `/api/upload/icon`              | Upload icon                         |

### OCR endpoint

`POST /api/ocr` — Upload a sticker image (multipart form, field `file`). Extracts machine ID from `XXXXX-XXXXXX` Connect ID pattern, returning only the last 5 digits.

```json
{
  "machine_id": "95330",
  "raw_text": "CONNECT ...",
  "raw_match": "05912-095330",
  "confidence": "high"
}
```

### Asset fields

`machine_id` (unique, required), `name` (required), `serial_number`, `description`, `category` (Furniture/Appliances/Utensils & Serveware/Equipment/Other), `status` (active/maintenance/retired), `make`, `model`, `address`, `building_name`, `building_number`, `floor`, `room`, `trailer_number`, `walking_directions`, `map_link`, `parking_location`, `photo_path`, `customer_id`, `location_id`, `assigned_to`, `created_at`, `updated_at`.

### Check-in fields

`asset_id` (required), `latitude`, `longitude`, `accuracy`, `photo_path`, `notes`, `created_at`.

## Environment Variables

| Variable           | Default                  | Description              |
|--------------------|--------------------------|--------------------------|
| `CANTEEN_PORT`     | `8901`                   | Listen port              |
| `CANTEEN_DB_PATH`  | `./assets.db`            | SQLite database path     |
| `CANTEEN_WIPE_DB`  | (empty)                  | Set to `1` to clear DB   |
| `CANTEEN_SKIP_AUTH`| (empty)                  | Set to `1` for tests     |

## Running Tests

```bash
pip install -r requirements.txt
python -m pytest tests/ -v
```

## Project Structure

```
canteen-asset-tracker/
├── server.py              # FastAPI app (all routes, DB, auth, OCR)
├── openapi.yaml           # API contract (source of truth)
├── start.sh               # One-command startup with cert gen
├── static/
│   └── index.html         # SPA frontend (vanilla JS, self-contained)
├── tests/                 # pytest test suite
├── docs/                  # Documentation
├── uploads/               # Photo/OCR storage (gitignored)
├── cert.pem               # Self-signed TLS cert (auto-generated)
├── key.pem                # TLS private key (auto-generated)
├── requirements.txt       # Python deps
├── PROJECT.md             # Detailed project structure
└── README.md
```
