# Circuit List Editor Migration ## Goal Migrate legacy row-first consumers into the circuit-first model without deleting legacy data. ## Legacy Mapping Legacy `Consumer` rows map into: - `Circuit` for shared circuit identity and circuit-level technical fields - `CircuitDeviceRow` for per-device load rows Multiple legacy consumers can map into one circuit when they share normalized circuit identity. For one circuit list, all new circuits, device rows, trace mappings and the migration report are committed in one SQLite transaction. A failed run therefore leaves none of those prepared migration writes behind. ## Grouping Strategy (`circuitNumber`) Migration groups legacy rows by normalized `circuitNumber`: - valid/normalizable values become one target circuit per normalized value - duplicates are grouped under that circuit (multiple `CircuitDeviceRow`s) - missing/invalid values trigger generated identifiers and may fall back to `unassigned` section ## Default Section Backfill Before migration, default sections are created/backfilled per circuit list. This guarantees a valid target section space, including `unassigned` when no section can be inferred. ## Migration Commands Run in this order for local database workflows: 1. Backup: - `npm run db:backup` 2. Migrate schema: - `npm run db:migrate` 3. Verify circuit schema: - `npm run db:verify:circuit-schema` 4. Backfill missing sections: - `npm run db:backfill:sections` 5. Migrate legacy consumers: - `npm run db:migrate:legacy-consumers` The migration command finishes with a cutover verification across the complete database. It exits with an error while any legacy consumer lacks a migration mapping, including consumers that cannot be migrated because they have no circuit list assignment. Do not remove or disable the legacy path until this check passes. ## Validation Checks After migration, verify: - tree endpoint returns sections/circuits/rows - grouped duplicate circuit numbers are reported - generated identifiers are reported where expected - migrated rows include `legacyConsumerId` traceability - no duplicate BMKs exist inside one circuit list ## If Tree Endpoint Returns Empty Sections Likely causes: - circuit-first tables missing (migration not run) - sections not backfilled yet - migrated dataset genuinely empty for selected list Actions: 1. Run schema migration and verification commands. 2. Run section backfill command. 3. Run legacy-consumer migration command. 4. Retry tree endpoint. ## Legacy Data Retention Do not delete legacy consumers yet. - legacy endpoints/views remain enabled only until the cutover verification passes - migration trace tables reference old/new mapping - keeping legacy rows allows comparison and rollback validation during transition