16 Commits

Author SHA1 Message Date
shawn 07539b683e feat: add script to import machines from Cantaloupe Excel export
Adds scripts/import_from_excel.py that reads Cantaloupe .xlsx exports
and imports missing machines into the canteen-asset-tracker DB.
- Dry-run by default, --write to commit, --prod for production DB
- Maps all 62 spreadsheet columns to assets table schema
- Stores full raw row as JSON in seed_data table
- Backs up DB before import
2026-05-31 11:09:27 -04:00
shawn 064fc43fe3 fix: remove all address-geocoded GPS, keep only original check-ins
All GPS from MSFS account addresses and Cantaloupe seed data removed.
Only 5 authentic app check-in GPS entries remain.
Reverts the bulk restore from earlier commit (gps restore was address-based).
2026-05-31 01:45:53 -04:00
shawn 616769e805 feat: restore GPS data from pre-MSFS backup + MSFS account data
- 221 GPS entries restored via serial_number match from pre-MSFS backup
- 5,730 GPS entries restored via MSFS account address data
- Coverage improved from 1.6% (124) to 80.4% (6,075) of 7,560 assets
- Remaining 1,485 have no GPS in MSFS account records
2026-05-31 01:40:03 -04:00
shawn 474a618f79 UX fixes: fix Map tab crash, remove Edit/Delete buttons, update Help dialog and menu labels 2026-05-30 20:56:28 -04:00
shawn 17b870e4cc feat: wire vision/OCR results back into asset records
- Auto-save photo_path to matched assets when photo uploaded via /api/ocr
- Auto-extract and save serial_number from OCR text to blank-serial matched assets
- Add _extract_serial_from_text helper for serial number pattern matching
- Create scripts/backfill_vision_photos.py for batch-processing unlinked photos
- Add docs/OCR_PIPELINE.md documenting the full OCR/vision pipeline
- Fix test DB schema: add connect_id, equipment_id, barcode, customer_name
- Fix OCR test assertions to match actual endpoint behavior
2026-05-29 10:03:51 -04:00
shawn 99cef94153 Cross-reference photos against assets DB
- Scanned all 15 photos in uploads/photos/ via vision + Tesseract OCR
- Matched keurig_label.jpg → Asset #5144 (machine_id 636671)
- Updated Asset #5144 photo_path in assets.db
- Created scripts/crossref_photos.py for reusable batch matching
- Reported unmatched IDs for coca_cola_label.jpg and telemetry_device.jpg
- Generated crossref_report.md with full findings
2026-05-29 09:56:49 -04:00
shawn b80ed4b483 feat: Ollama vision OCR via Windows PC for label photo matching
- Add persistent SSH tunnel (systemd service) to Windows PC Ollama
- Add _HAS_OLLAMA check at server startup (qwen2.5vl:3b)
- Replace Tesseract-only OCR with Ollama-first strategy
- Ollama (qwen2.5vl:3b) handles dark/complex labels Tesseract can't read
- Keurig serial 2500.0100.0025534 now correctly matched as Asset #5144
- Add ocr_source field to /api/ocr response ('ollama' or 'tesseract')
- Fix match_label_photo.py argparse bug (image_paths -> images)
- Update match_label_photo.py CLI to read vision key from Hermes config
2026-05-29 08:59:53 -04:00
shawn 8022c77b70 feat: add normalized matching for label photos → asset DB lookup
- normalize_identifier() strips dots/dashes/prefixes, keeps alphanumeric
- find_asset_by_normalized_id() searches serial_number, connect_id,
  equipment_id, barcode with normalized comparison
- /api/ocr now returns matched_assets in addition to legacy machine_id
- New /api/match-text endpoint for client-side text matching
- scripts/match_label_photo.py CLI tool for OCR + DB matching
- Vision model fixed (mimo-v2-omni at opencode.ai, was using
  truncated placeholder key)
2026-05-29 08:37:06 -04:00
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
shawn 4f9c0d0b75 feat: populate company/place/customer_name from MSFS extraction DB
- New script: scripts/populate_asset_company_place.py maps connect_id →
  account name (company/customer_name) + city (place) + address via
  extraction DB (msdyn_customerasset + account join)
- 5,743/7,488 assets now have company + customer_name populated
- 5,647/7,488 assets now have place (city) populated
- Fix: SELECT COALESCE(c.name, a.customer_name) so stored customer_name
  isn't overridden to NULL when customer_id FK is missing
- Bump SW v4→v5, version v3.1→v3.2 to force cache refresh
2026-05-29 07:45:01 -04:00
shawn f1eb453a19 fix: keep GUEST/CAST visible in asset names
- clean_customer_name() no longer strips GUEST/CAST suffixes
- Re-ran migration: 967 asset names updated with GUEST/CAST preserved
- Format: '95301 - Animal Kingdom CAST / address / building'
  vs previous: '95301 - Animal Kingdom / address / building'
2026-05-29 00:13:08 -04:00
shawn 1db6475f83 feat: asset naming, location extraction, and location display
- New asset naming: {MID} - {Customer} / {Address} / {Building details}
- Extracted 660 building_names from customer data (Disney resorts, hotels)
- 1,704 assets now have location data (building_name, floor, etc.)
- Location section in detail view now shows building, floor, trailer, room
- Added has_gps filter to API for map loading
- Added location_source column to track GPS origin
2026-05-28 23:58:56 -04:00
shawn faacf0bce9 Rename 'Add Asset' tab to 'Add / Find Asset' across nav + tabs
- Drawer nav: 'Add Asset' → 'Add / Find Asset'
- Bottom tab bar: 'Add Asset' → 'Add / Find Asset'
- Updated e2e_browser_test.py assertions to match
2026-05-25 23:14:52 -04:00
shawn 9fe615c76b clean up asset names: strip addresses/floors/parks/building prefixes from names (353/1848 cleaned) 2026-05-23 20:24:51 -04:00
shawn 76e28614ae feat: tag Disney assets with park/resort codes and display names
- Script: scripts/tag_disney_properties.py (supports dry-run + --apply)
- Maps 112 Disney location IDs to park/resort/office/other codes
- Updated 994 assets: disney_park column + appended display name with emoji
- Added disney_park column to locations table, populated 112 rows
- Covers all 364 locations via case-insensitive substring matching
2026-05-23 19:50:16 -04:00
shawn 13bf61d856 feat: extract floor/building/room/trailer from asset names
Adds scripts/extract_asset_location_data.py which:
- Extracts floor, building_number, room, trailer_number, building_name from names
- Detects and removes duplicated name segments
- Updates both assets (1848) and locations (364) tables
- Dry-run mode by default, --apply to write changes
2026-05-23 19:41:55 -04:00