9.2 KiB
Field Map — Canteen Asset Tracker
Every column in assets.db, how each pipeline touches it.
Source Legend
| Source | Pipeline | File(s) | How to Run |
|---|---|---|---|
| MSFS | ADB pull → Dynamics 365 extraction | pull_msfs_data.py → sync_assets_to_canteen.py |
Button on extraction viewer :8910 Manual |
| CANT | Cantaloupe staged import | cantaloupe_sync.py in admin server |
Dashboard upload Manual |
| SEED | Seed Excel import | parser.py → db_writer.py → sync.py |
CLI --mode=seed or --mode=update Manual |
| APP | Main app (technician check-in, photo, GPS) | server.py |
Used by techs in field |
| ADMIN | Admin dashboard edits | admin_server.py |
Dashboard Cleanup/Mass Edit |
Policy Legend
- always — pipeline overwrites this field every run
- if_empty — only filled when currently NULL/empty
- never — pipeline never touches this column
- if_numeric — only overwritten if value is bare number (Cantaloupe default ID)
🔵 MSFS Sync — Field Policy
| Column | Policy | Dynamics 365 Source |
|---|---|---|
serial_number |
always | hsl_serialnumber |
connect_id |
always | hsl_connectid |
equipment_id |
always | hsl_equipmentid |
canteen_connect_guid |
always | hsl_canteenconnectguid |
barcode |
always | hsl_barcode |
manufacturer |
always | hsl_manufacturertext |
model |
always | hsl_modeltext or hsl_modelname |
route_name |
always | hsl_routeidname |
install_date |
always | hsl_opendate |
device |
always | msdyn_deviceid |
name |
if_numeric | msdyn_name or hsl_name |
company |
if_empty | Account name |
customer_name |
if_empty | Account name |
place |
if_empty | Account address1_city |
address |
if_empty | Account address1_line1 + line2 |
make |
never | (uses manufacturer → separate column) |
building_name |
never | — |
floor |
never | — |
room |
never | — |
building_number |
never | — |
trailer_number |
never | — |
location_area |
never | — |
latitude |
never | (mapped but only if NULL in code) |
longitude |
never | (mapped but only if NULL in code) |
photo_path |
never | — |
category |
never | — |
status |
never | — |
description |
never | — |
All other columns (sales data, alerts, disney flags, etc.) are never touched by MSFS sync.
🟡 Cantaloupe Sync — Field Policy
| Column | Policy | Notes |
|---|---|---|
machine_id |
never (match key) | — |
serial_number |
always | — |
name |
always | — |
description |
always | — |
category |
always | Validated against categories table |
status |
always | Validated against statuses |
make |
always | — |
model |
always | — |
address |
always | — |
building_name |
always | — |
building_number |
always | — |
floor |
always | — |
room |
always | — |
trailer_number |
always | — |
walking_directions |
always | — |
map_link |
always | — |
parking_location |
always | — |
photo_path |
always | — |
latitude |
always | — |
longitude |
always | — |
geofence_radius_meters |
always | — |
dex_report_date |
always | — |
deployed |
always | — |
pulled_date |
always | — |
customer_id |
always | Via customer name lookup/creation |
location_id |
always | Via location name lookup/creation |
is_disney |
always | Derived from customer name prefix D- |
No preserve logic. Any non-empty field in the import file overwrites the existing value.
🟢 Seed Import — Field Policy (db_writer.py)
Seed Mode (--mode=seed)
DESTROYS AND RE-INSERTS — DELETE FROM assets first, then inserts all rows fresh.
Update Mode (--mode=update)
Upsert by machine_id. MSFS is primary data source — seed fills gaps only.
ALL fields are treated as ONLY_IF_EMPTY for existing records:
| Column | Policy | Excel Source / Generation |
|---|---|---|
serial_number |
if_empty | Serial Number column + OCR corrections |
name |
if_empty | Generated: {make} @ {place} |
make |
if_empty | Parsed from Type column |
model |
if_empty | Parsed from Type column |
class |
if_empty | Parsed from Type column |
is_glass_front |
if_empty | Parsed from Type column |
company |
if_empty | Parsed from Customer column |
place |
if_empty | Parsed from Place column |
building_name |
if_empty | Parsed from Place column |
suite |
if_empty | Parsed from Place column |
room |
if_empty | Parsed from Place column |
trailer |
if_empty | Parsed from Place column |
floor |
if_empty | Parsed from Place column |
zone |
if_empty | Parsed from Place column |
zone_type |
if_empty | Parsed from Place column |
address |
if_empty | Address column |
location_area |
if_empty | City column |
latitude |
if_empty | Excel (existing GPS preserved) |
longitude |
if_empty | Excel (existing GPS preserved) |
photo_path |
if_empty | Excel (existing photo preserved) |
install_date |
if_empty | Added Date (existing date preserved) |
deployed |
if_empty | Deployed column (existing preserved) |
pulled_date |
if_empty | Pulled Date (existing preserved) |
dex_report_date |
if_empty | Last Dex Report Time |
disney_park |
if_empty | Parsed from Customer column |
disney_area |
if_empty | Derived from disney_park |
remote_pricing_status |
if_empty | Status column |
alerts |
if_empty | Alerts column + Coil/Product Alerts |
telemetry_provider |
if_empty | Parsed from Device column |
card_reader_brand |
if_empty | Parsed from Device column |
priority |
if_empty | Computed from yearly_sales |
yearly_sales |
if_empty | Yearly Sales column |
monthly_sales |
if_empty | Monthly Sales column |
weekly_sales |
if_empty | Weekly Sales column |
days_since_restock |
if_empty | Days Since Restock column |
prepick_group |
if_empty | Prepick Group column |
has_cashless |
if_empty | Has Cashless column |
New assets (not found in DB by machine_id) are inserted with full seed data. Existing assets: only empty/null fields are filled. Any field already populated by MSFS, cleanup, or field use is preserved.
🟠 Seed Import — Sync (sync.py → main app DB)
After db_writer.py, this script pushes the seed DB into the main app's schema.
Now follows ONLY_IF_EMPTY policy for existing assets — same as db_writer update mode.
| Column | Policy |
|---|---|
machine_id |
never (match key) |
serial_number |
if_empty |
name |
if_empty |
description |
if_empty |
category |
if_empty |
status |
if_empty |
make |
if_empty |
model |
if_empty |
address |
if_empty |
building_name |
if_empty |
building_number |
if_empty |
floor |
if_empty |
room |
if_empty |
trailer_number |
if_empty |
walking_directions |
if_empty |
map_link |
if_empty |
parking_location |
if_empty |
photo_path |
if_empty |
latitude |
if_empty |
longitude |
if_empty |
geofence_radius_meters |
if_empty |
disney_park |
if_empty |
is_disney |
if_empty |
dex_report_date |
if_empty |
install_date |
if_empty |
deployed |
if_empty |
pulled_date |
if_empty |
customer_id |
if_empty (via upsert customers table) |
location_id |
if_empty (via upsert locations table) |
Also creates/updates
customersandlocationstables.
⚪ Admin Tools — Policy
Batch Update (Cleanup page)
make,model,name,company,place,building_name,building_number,floor,room,location_area,address,category,status,customer_name- Always overwrites with user-provided value.
Clear GPS
latitude,longitude— set to NULL
Mass Edit (existing tool)
- Same allowed fields as Batch Update.
⚫ Main App (Tech Field) — What Touches What
| Action | Fields Affected |
|---|---|
| Barcode scan check-in | updated_at |
| GPS check-in | latitude, longitude, updated_at |
| Photo upload | photo_path, updated_at |
| OCR scan (name search) | (read-only) |
| Register new asset | All columns with defaults |
Pipeline Activity Status
| Pipeline | Currently Scheduled? | Frequency | Risk to Cleanup |
|---|---|---|---|
| MSFS Sync | 🔴 Manual only | On-demand via extraction viewer | ✅ GPS never touched. Preserves name/company/place/building/floor. Only model overwritten. |
| Cantaloupe Sync | 🔴 No cron | Manual upload on admin dashboard | ⚠️ Preserves GPS now (fixed — none from Cantaloupe). Still overwrites other fields. |
Seed Import --mode=update |
🔴 Manual CLI only | python3 main.py -m update |
✅ GPS never touched (check-in only). Fills gaps only for other fields. |
Seed Import --mode=seed |
🔴 Manual CLI only | python3 main.py -m seed |
🔥 NUCLEAR — DELETE FROM assets. Full re-insert. GPS set to NULL. |