Files
shawn 2bdcfe0bae feat: branch fallback for assets without account linkage
- 1,606 more assets now get company from branch/territory name
  (e.g. 'Canteen Corp/Orlando, FL') when the connect_id exists
  in extraction DB but has no linked account name
- Coverage: 7,349/7,488 (98.1%) have company + customer_name
- Only 139 remain empty (4 prefixes not in branch cache)
- Updated AGENTS.md with data population docs
2026-05-29 07:51:02 -04:00

3.5 KiB

Canteen Asset Tracker

Mobile-friendly webapp for tracking physical assets with barcode scanning, OCR sticker reading, and GPS check-ins. The main technician-facing application.

...

Company & Place Data

Asset company, customer_name, and place fields are populated from the MSFS Dynamics 365 extraction DB. The migration script scripts/populate_asset_company_place.py maps each asset's connect_idmsdyn_customerassetaccount table to get:

  • company = account name (e.g. "Jeremy B - 1960 Broadway")
  • place = city name (e.g. "Orlando")
  • customer_name = account name (same as company, for search/filter)

5,743/7,488 assets (~77%) have company data; remaining 1,745 have connect_ids with no account linkage in the extraction DB.

Stack

  • Python 3.11+, FastAPI, uvicorn
  • SQLite (WAL mode, foreign keys)
  • pytesseract — OCR for ConnectID stickers
  • Pillow, piexif — image processing
  • Frontend: vanilla HTML/CSS/JS (~200KB SPA), Leaflet maps, ZXing barcode scanner
  • Tests: pytest

Project Structure

server.py                 # ~2.5K lines — ALL backend routes, DB, auth, OCR in one file
openapi.yaml              # Shared API contract (source of truth for frontend)
requirements.txt

static/
  index.html              # SPA frontend (~200KB, no build step)
  sw.js                   # Service worker for offline support
  app-release.apk         # Companion Android APK

docs/
  ADMIN_GUIDE.md          # Admin operations guide
  USER_GUIDE.md           # End-user operations
  FEATURES.md             # Feature catalog
  images/                 # Screenshots for docs

scripts/                  # Data migration and helper scripts
PROJECT.md                # v3 project structure doc
TEST_PLAN.md              # Test plan
TEST_PLAN_MAP.md          # Map test plan

How to Run

# Production (generates self-signed TLS cert, auto-installs deps, backs up DB)
./start.sh

# Quick restart
./restart_server.sh

Key Architecture

  • Single-file backendserver.py contains routes, DB models, auth, OCR, and geolocation
  • OCR: Extracts last 5 digits from XXXXX-XXXXXX Connect ID sticker format via Tesseract
  • Auth: Bearer token system, role-based (technician + admin)
  • DB: assets.db — SQLite with WAL mode, foreign keys enabled
  • Frontend: Pure vanilla JS SPA — no build step, no npm dependencies

Production

  • URL: https://canteen.ourpad.casa
  • Port: 8901 (HTTPS, self-signed cert → NPMPlus reverse proxy)
  • Startup: start.sh generates self-signed cert, backs up DB, starts uvicorn
  • No systemd — runs via nohup from start/restart scripts

Environment Variables

Var Description
CANTEEN_DB_PATH Path to assets.db (default: ./assets.db)
Project What it does
canteen-admin-server Admin CRUD API, shares same SQLite DB
canteen-seed-import Seed data import from Cantaloupe CSVs
exif-test EXIF/OCR validation against this DB
cantaloupe-downloader CLI to export machine data from Cantaloupe

Pitfalls

  • Single-file backend — server.py is ~2.5K lines; routes, DB, and OCR all in one file
  • DB shared across canteen-admin-server, seed-import, exif-test — schema changes must be coordinated
  • HTTPS — start.sh generates self-signed cert every restart; ports 8901 (production) vs 8904 (dev)
  • OCR requires Tesseract installed system-wide (apt install tesseract-ocr)