# Customer Data Migration - Quick Reference ## Quick Start ### 1. Preview Migration (Always Do This First!) ```bash # Using usernames (recommended - more readable) node scripts/migrateCustomerData.js \ --preview \ --sources acme_aviation,regional_ag \ --destination consolidated_ag # Using IDs (also supported) node scripts/migrateCustomerData.js \ --preview \ --sources , \ --destination # Mixed: usernames and IDs work together node scripts/migrateCustomerData.js \ --preview \ --sources acme_aviation,507f1f77bcf86cd799439012 \ --destination consolidated_ag ``` ### 2. Execute After Reviewing Preview ```bash # Using usernames node scripts/migrateCustomerData.js \ --sources acme_aviation,regional_ag \ --destination consolidated_ag # Using IDs node scripts/migrateCustomerData.js \ --sources , \ --destination ``` ## Common Scenarios ### Scenario 1: Simple Single Customer Migration **Use Case**: Merge one customer into another ```bash # Step 1: Preview (using usernames - easier to read) node scripts/migrateCustomerData.js \ --preview \ --sources acme_aviation \ --destination consolidated_ag # Step 2: Execute node scripts/migrateCustomerData.js \ --sources acme_aviation \ --destination consolidated_ag # Alternative: Using IDs node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011 \ --destination 507f191e810c19729de860ea ``` **Result**: - Source customer deactivated - All data moved to destination - Aborts if username conflicts detected --- ### Scenario 2: Consolidate Multiple Regional Accounts **Use Case**: Merge multiple regional accounts into corporate account ```bash # Using usernames (recommended) node scripts/migrateCustomerData.js \ --sources acme_west,acme_east,acme_south \ --destination acme_corporate # Using IDs node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011,507f1f77bcf86cd799439012,507f1f77bcf86cd799439013 \ --destination 507f191e810c19729de860ea ``` **Result**: - All 3 regional accounts deactivated - All data consolidated under corporate account - Regional managers can be converted to admins (see Scenario 4) --- ### Scenario 3: Merge with Known Conflicts **Use Case**: Known username overlaps, want to merge accounts ```bash # Preview first to see conflicts (using usernames) node scripts/migrateCustomerData.js \ --preview \ --sources acme_aviation \ --destination consolidated_ag # Execute with merge if conflicts are acceptable node scripts/migrateCustomerData.js \ --sources acme_aviation \ --destination consolidated_ag \ --merge-conflicts ``` **Result**: - Conflicting accounts merged (old accounts marked deleted) - Job/data references updated to existing accounts - Old account data preserved in history ⚠️ **WARNING**: Review conflicts carefully before merging! --- ### Scenario 4: Convert Customers to Admin Accounts **Use Case**: Keep source customer as admin user under destination ```bash # Using usernames node scripts/migrateCustomerData.js \ --sources acme_west,acme_east \ --destination acme_corporate \ --convert-to-admin # Using IDs node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011,507f1f77bcf86cd799439012 \ --destination 507f191e810c19729de860ea \ --convert-to-admin ``` **Result**: - Source customers become admin (kind='2') accounts under destination - All sub-accounts and data moved to destination - Original customer accounts deactivated but admin access preserved **Perfect For**: - Regional managers becoming corporate admins - Acquired companies maintaining some autonomy - Franchise consolidation --- ### Scenario 5: Data Only Migration (Skip Invoices) **Use Case**: Migrate operational data but keep invoices separate ```bash node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011 \ --destination 507f191e810c19729de860ea \ --skip-invoices ``` **Result**: - All data migrated except invoice customer references - Useful for financial separation requirements - Invoices remain linked to original customer --- ### Scenario 6: Custom History File Location **Use Case**: Store migration logs in specific location ```bash node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011 \ --destination 507f191e810c19729de860ea \ --output-file /var/log/agmission/migrations/customer_migration_2025.json ``` **Result**: - Migration history saved to custom location - Useful for compliance/audit requirements --- ## Decision Tree ``` Do you want to migrate customer data? │ ├─ Single source customer? │ ├─ Yes → Use Scenario 1 │ └─ No → Continue │ ├─ Multiple source customers? │ ├─ Yes → Use Scenario 2 │ └─ No → Continue │ ├─ Known username conflicts? │ ├─ Yes → Use Scenario 3 (with --merge-conflicts) │ └─ No → Continue │ ├─ Keep source customers as admins? │ ├─ Yes → Use Scenario 4 (with --convert-to-admin) │ └─ No → Continue │ ├─ Need to preserve invoice separation? │ ├─ Yes → Use Scenario 5 (with --skip-invoices) │ └─ No → Use Scenario 1 or 2 │ └─ Always preview first with --preview! ``` ## Conflict Resolution Strategies ### Strategy 1: Manual Resolution (RECOMMENDED) **Before migration**: 1. Run preview to identify conflicts 2. Manually rename conflicting accounts in source OR destination 3. Run migration without conflicts ```bash # Example: Rename client in source database db.users.updateOne( { _id: ObjectId("507f1f77bcf86cd799439015") }, { $set: { username: "john_farmer_regional" } } ) # Then run migration node scripts/migrateCustomerData.js --sources ... --destination ... ``` ### Strategy 2: Automatic Merge **During migration**: - Use `--merge-conflicts` flag - Old accounts marked as deleted - References updated to existing accounts ```bash node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011 \ --destination 507f191e810c19729de860ea \ --merge-conflicts ``` ### Strategy 3: Selective Migration **Migrate in phases**: 1. Migrate non-conflicting customers first 2. Resolve conflicts for remaining customers 3. Migrate remaining customers ```bash # Phase 1: No conflicts node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439011 \ --destination 507f191e810c19729de860ea # Phase 2: After resolving conflicts node scripts/migrateCustomerData.js \ --sources 507f1f77bcf86cd799439012 \ --destination 507f191e810c19729de860ea ``` ## Verification Steps ### After Migration 1. **Check Migration History** ```bash cat migration_history.json | jq '.[-1]' ``` 2. **Verify Source Customer Deactivated** ```javascript db.users.findOne({ _id: ObjectId("507f1f77bcf86cd799439011"), kind: "1" }) // Should have: markedDelete: true, active: false ``` 3. **Verify Job Migration** ```javascript db.jobs.countDocuments({ byPuid: ObjectId("507f191e810c19729de860ea") }) // Should equal total jobs from source + existing destination jobs ``` 4. **Verify Sub-Account Migration** ```javascript db.users.countDocuments({ parent: ObjectId("507f191e810c19729de860ea"), kind: { $in: ["3", "5", "9"] } }) // Should equal expected count ``` 5. **Check for Errors in History** ```bash cat migration_history.json | jq '.[-1].stats.errors' ``` ## Troubleshooting Common Issues ### Issue: "Source customer(s) not found" ```bash # Verify customer exists mongo > use agmission > db.users.findOne({ _id: ObjectId("YOUR_ID"), kind: "1" }) ``` ### Issue: "Migration aborted due to conflicts" ```bash # View conflicts in detail node scripts/migrateCustomerData.js --preview --sources ... --destination ... # Then use Strategy 1 or 2 above ``` ### Issue: Transaction timeout ```bash # Reduce number of source customers per migration # Instead of migrating 10 at once, do 2-3 at a time ``` ### Issue: Need to rollback ```bash # MongoDB transactions auto-rollback on error # If completed but need to reverse: # 1. Restore from backup # OR # 2. Manually reverse using migration_history.json details ``` ## Environment Variables ```bash # Enable detailed debugging DEBUG=agm:migrate-customer-data,agm:mongo_enhanced \ node scripts/migrateCustomerData.js ... # Custom MongoDB connection MONGODB_URI=mongodb://user:pass@host:port/dbname \ node scripts/migrateCustomerData.js ... ``` ## Data Validation Queries ### Check Job Distribution ```javascript // Count jobs per customer db.jobs.aggregate([ { $match: { markedDelete: { $ne: true } } }, { $group: { _id: "$byPuid", count: { $sum: 1 } } }, { $sort: { count: -1 } } ]) ``` ### Check Sub-Account Distribution ```javascript // Count sub-accounts per parent db.users.aggregate([ { $match: { kind: { $in: ["3", "5", "9"] }, markedDelete: { $ne: true } } }, { $group: { _id: "$parent", count: { $sum: 1 } } }, { $sort: { count: -1 } } ]) ``` ### Find Orphaned Data ```javascript // Jobs without valid customer db.jobs.aggregate([ { $match: { markedDelete: { $ne: true } } }, { $lookup: { from: "users", localField: "byPuid", foreignField: "_id", as: "customer" } }, { $match: { customer: { $size: 0 } } }, { $count: "orphaned_jobs" } ]) ``` ## Checklist Before Migration: - [ ] Database backup completed - [ ] Source and destination customer IDs confirmed - [ ] Preview completed and reviewed - [ ] Conflicts identified and strategy decided - [ ] Stakeholders notified - [ ] Maintenance window scheduled (if applicable) After Migration: - [ ] Migration history file reviewed - [ ] No errors in migration log - [ ] Job counts verified - [ ] Sub-account counts verified - [ ] Invoice references checked (if not skipped) - [ ] Source customer deactivated (if not converted to admin) - [ ] Destination customer has all expected data - [ ] Users notified of changes ## Support For issues or questions: 1. Check `migration_history.json` for details 2. Enable debug logging: `DEBUG=agm:*` 3. Review this guide and main README 4. Contact database administrator ## Related Commands ```bash # View migration history cat migration_history.json | jq '.' # View latest migration cat migration_history.json | jq '.[-1]' # View all failed migrations cat migration_history.json | jq '.[] | select(.status == "failed")' # View all completed migrations cat migration_history.json | jq '.[] | select(.status == "completed")' # Count migrations by status cat migration_history.json | jq 'group_by(.status) | map({status: .[0].status, count: length})' ```