ba6921eade
- Replaced loadSettingsCache() with hardcoded seed data (categories, makes, keys, badges) - Removed tabActivity lifecycle hook (activity log moved to admin app) - Updated version to v3.0 + Admin Panel link in drawer footer - Updated PROJECT.md with v3 project structure (3 repos, admin server docs) - Removed backup files (.bak, .orig) - Main index.html reduced from 7645 to 4228 lines
7.2 KiB
7.2 KiB
Canteen Asset Tracker — Project Structure (v3)
Three projects, shared DB.
Repositories
~/projects/canteen-asset-tracker/ ← Main app (technician-facing: scan, check-in, assets, map, nav)
~/projects/canteen-asset-tracker-android/ ← Android app (Kotlin, Jetpack Compose)
~/projects/canteen-admin-server/ ← Admin app (users, customers, settings, exports, activity)
Web App (canteen-asset-tracker)
canteen-asset-tracker/
├── server.py FastAPI backend — core technician API routes (assets, checkins, visits, auth, OCR, upload)
├── openapi.yaml **Shared API contract** — source of truth for both projects
├── assets.db SQLite database (WAL mode, foreign keys on)
├── static/
│ └── index.html Single-page frontend (technician UI: scan, assets, map, nav)
├── tests/ pytest test suite
├── uploads/ User-uploaded photos
├── cert.pem / key.pem Self-signed TLS certs
├── requirements.txt Python deps (fastapi, uvicorn, pytesseract, pillow)
├── start.sh Launch script (production)
└── smoke_test.sh Smoke test suite
- Port: 8901 (HTTPS)
- URL: https://canteen.ourpad.casa (NPMPlus reverse proxy → backend :8901)
- Frontend: Single HTML file — no build step, no npm (~200KB, technician-focused).
- Backend: FastAPI with SQLite (WAL mode). Auth via Bearer tokens. OCR via Tesseract. EXIF GPS extraction via PIL.
Admin App (canteen-admin-server)
canteen-admin-server/
├── admin_server.py FastAPI backend — admin-only API routes (users, customers, locations, rooms, settings, activity, stats, exports, geofences)
├── static/
│ └── index.html Single-page admin frontend (settings, user mgmt, activity, reports)
├── requirements.txt Python deps (fastapi, uvicorn)
└── run.sh Launch script (port 8900)
Admin functions separated into their own project:
- Port: 8900
- URL: https://admin.canteen.ourpad.casa (NPMPlus proxy → backend)
- Shared DB: Uses same
assets.dbviaCANTEEN_DB_PATHenv var - Auth: Same login system as main app (admin role required for admin endpoints)
- Frontend: Standalone SPA with Dashboard, Settings, Users, Customers/Locations, Activity Log, CSV Exports, DB Reset
Android App (canteen-asset-tracker-android)
canteen-asset-tracker-android/
├── app/
│ ├── src/main/java/com/canteen/assettracker/
│ │ ├── network/
│ │ │ └── RetrofitModule.kt API client config (points to web app URL)
│ │ ├── ui/
│ │ │ ├── login/ Login screen + ViewModel
│ │ │ ├── dashboard/ Dashboard screen + ViewModel
│ │ │ └── settings/ Settings screen + ViewModel
│ │ └── location/
│ │ └── ProximityEngine.kt GPS proximity logic
│ └── build/ Build outputs (APK, test reports)
├── build.gradle.kts Root build config
├── settings.gradle.kts
├── gradlew / gradlew.bat Gradle wrapper
└── keystore.properties Signing keys
- Package:
com.canteen.assettracker - API Base URL:
https://canteen.ourpad.casa:8901/(hardcoded inRetrofitModule.kt) - Tests: 3 ViewModel/engine test classes, all passing (debug + release)
- Built APK: run
./gradlew assembleRelease
API Contract
openapi.yaml is the single source of truth. When you change the backend:
- Update
server.py - Update
openapi.yamlto match - Android team (or future-you) can see exactly what changed
The spec covers:
- 48 named routes across assets, check-ins, customers, locations, rooms, users, auth, geofences, visits, activity, stats, exports, uploads, and OCR
- 30 dynamic settings routes (
/api/settings/{entity}for 6 entity types) - All request/response schemas
- Query parameters and path parameters
Quick reference — main route groups
| Group | Routes |
|---|---|
| Auth | login, me |
| Assets | CRUD + search by machine ID |
| Check-ins | CRUD (GPS + photo + notes) |
| Customers | CRUD with contacts |
| Locations | CRUD + child rooms |
| Rooms | CRUD (nested under locations) |
| Users | CRUD |
| Geofences | CRUD + user assignment (service areas) |
| Visits | CRUD + stats |
| Stats | Dashboard aggregates |
| Exports | Assets CSV, Check-ins CSV, Service Summary CSV |
| Uploads | Icon + Photo upload |
| OCR | Extract machine ID from sticker image |
| Settings | Dynamic CRUD for 6 entity types |
| Proximity | Find assets near GPS point |
| Activity | Activity feed |
Working with both projects
Adding a feature to BOTH web + Android
- Design the endpoint in
openapi.yamlfirst - Implement in
server.py - Run backend tests
- Implement Android client code + run Android tests
Adding a feature to web ONLY
- Add endpoint to
server.py - Update
openapi.yaml - Android app ignores the new endpoint — no changes needed
Adding a feature to Android ONLY
- Plan the endpoint in
openapi.yaml(even if backend isn't ready) - Build Android client against the planned contract
- Backend implements later
Running
# Web app
cd ~/projects/canteen-asset-tracker
./start.sh # production
# or: uvicorn server:app --reload # development
# Tests
cd ~/projects/canteen-asset-tracker
python -m pytest tests/ -v
# Android
cd ~/projects/canteen-asset-tracker-android
./gradlew assembleRelease # build APK
./gradlew test # run unit tests
Recent Changes (May 2026 — v3)
- v3 admin separation — Admin functionality extracted to separate project
~/projects/canteen-admin-server/(port 8900). Mainserver.pyreduced from 3005→1946 lines by removing admin routes. Mainindex.htmlreduced from 7645→4228 lines by removing admin UI panels. Admin app live at https://admin.canteen.ourpad.casa. - EXIF GPS extraction —
/api/ocrand/api/upload/photonow extract GPS coordinates from image EXIF data server-side (PIL getexif()) and return{exif_gps: {lat, lng}}alongside results. Raw file bytes preserved — no re-compression, no EXIF stripping. - OCR fix — Now extracts only the last 5 digits from Connect ID (e.g.,
05912-095330→95330). Addedraw_matchfield to response for debugging. - Barcode scanner fix — Switched from
decodeFromVideoElementtodecodeFromVideoDevicewith 1D-only format hints (Code 128, Code 39, EAN/UPC, ITF, Codabar). AddedTRY_HARDERhint and 50ms scan interval for fast, reliable detection. - Auto check-in — New assets automatically check in with GPS on creation (all three entry modes: barcode, OCR, manual). Best-effort: silently skips if GPS unavailable.
- Service stability — Added NPMPlus reverse proxy. Service runs as background process on port 8901.