# 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 ```