# WJ classic-ASP import loader (reference implementation) This is **site-specific reference glue**, not product code. It maps West Jefferson's classic-ASP `shopdb` / `cmmc_usb` / `wjf_employees` schema onto the maintained, schema-agnostic import contract in the IMPORT-API wiki page. **Every adopting site has its own source database.** Nobody else runs this loader. Instead, copy the pattern: 1. Point the harness at your source DB(s) (edit `harness.Source`). 2. Write per-entity stages that read your tables and POST to the same the IMPORT-API wiki page endpoints with `Authorization: Bearer ` and `X-Import-Mode: true`. 3. Persist legacy-id -> new-id crosswalks (see `harness.IdMap`) so later stages resolve foreign keys and a crashed run resumes. The import API is the stable contract; loaders are per-site. The mapping itself is the bulk of the work: enumerate the source tables against this contract and write one stage per entity (this loader is the worked example). ## Running (against a THROWAWAY import database) ```bash DATABASE_URL='mysql+pymysql://root:PW@127.0.0.1:3306/shopdb_flask_import?charset=utf8mb4' \ venv/bin/python -m scripts.site_imports.wjf.run --stages reference,employees ``` Prereqs: a fresh target DB built with `flask db upgrade` + `flask plugin upgrade-all` + `flask seed permissions/settings/reference-data`, and the three source dumps loaded into scratch DBs (`shopdb_src`, `cmmc_usb_src`, `wjf_employees_src`). See `scratchpad/IMPORT-PLAN.md` for the full mapping, resolved decisions, and remaining stages. ## Status All 17 stages built: `reference`, `employees`, `catalog`, `assets` (the hub + machineid->assetid crosswalk), `locations`, `printers`, `metrology`, `communications`, `applications` (+ installs), `warranties`, `notifications`, `knowledgebase`, `relationships`, `defaultprinters`, `subnets`, `usb`, `verify`. **The counts below are from the 2026-07-13 run and are STALE.** Two routing changes landed after them - the `isactive=1` filter and the metrology routing rework - so the asset mix has moved substantially. They are kept only as a shape, not as a checklist: re-measure from the next full run before quoting them anywhere, and do not verify a fresh import against them. Last full run (2026-07-13, superseded): 983 assets (computer 663, machine 76, network 58, measuring-tool 136, printer 50), 24 locations, 415 employees, 850 installs, 461 primary IPs, 464 warranties, 261 notifications, 341 KB, 93 relationships, 37 subnets, 18 USB devices + 232 events. Known gaps, none of them blocking a scratch run: - `warranties`, `notifications` and `knowledgebase` POST without a duplicate check on the API side, so resuming ACROSS one of those stages doubles its rows. Resuming at or after them is safe. Re-run into a clean target when in doubt. - There is no `--dry-run` and no guard on the target: the harness mints an admin PAT and sets `setup_complete` in whatever `DATABASE_URL` points at. Check the target before running. - The `verify` stage counts target `assets` against source `machines`, which is apples to oranges - the target also holds printers and synthesized metrology tools. Known follow-ups: general asset `locationid` is null (no source column outside printers); the ~146 duplicate machinenumbers are first-wins-skipped by decision.