10 KiB
10 KiB
Customer Data Migration - Quick Reference
Quick Start
1. Preview Migration (Always Do This First!)
# 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 <SOURCE_ID1>,<SOURCE_ID2> \
--destination <DEST_ID>
# Mixed: usernames and IDs work together
node scripts/migrateCustomerData.js \
--preview \
--sources acme_aviation,507f1f77bcf86cd799439012 \
--destination consolidated_ag
2. Execute After Reviewing Preview
# Using usernames
node scripts/migrateCustomerData.js \
--sources acme_aviation,regional_ag \
--destination consolidated_ag
# Using IDs
node scripts/migrateCustomerData.js \
--sources <SOURCE_ID1>,<SOURCE_ID2> \
--destination <DEST_ID>
Common Scenarios
Scenario 1: Simple Single Customer Migration
Use Case: Merge one customer into another
# 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
# 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
# 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
# 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
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
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:
- Run preview to identify conflicts
- Manually rename conflicting accounts in source OR destination
- Run migration without conflicts
# 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-conflictsflag - Old accounts marked as deleted
- References updated to existing accounts
node scripts/migrateCustomerData.js \
--sources 507f1f77bcf86cd799439011 \
--destination 507f191e810c19729de860ea \
--merge-conflicts
Strategy 3: Selective Migration
Migrate in phases:
- Migrate non-conflicting customers first
- Resolve conflicts for remaining customers
- Migrate remaining customers
# 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
-
Check Migration History
cat migration_history.json | jq '.[-1]' -
Verify Source Customer Deactivated
db.users.findOne({ _id: ObjectId("507f1f77bcf86cd799439011"), kind: "1" }) // Should have: markedDelete: true, active: false -
Verify Job Migration
db.jobs.countDocuments({ byPuid: ObjectId("507f191e810c19729de860ea") }) // Should equal total jobs from source + existing destination jobs -
Verify Sub-Account Migration
db.users.countDocuments({ parent: ObjectId("507f191e810c19729de860ea"), kind: { $in: ["3", "5", "9"] } }) // Should equal expected count -
Check for Errors in History
cat migration_history.json | jq '.[-1].stats.errors'
Troubleshooting Common Issues
Issue: "Source customer(s) not found"
# Verify customer exists
mongo
> use agmission
> db.users.findOne({ _id: ObjectId("YOUR_ID"), kind: "1" })
Issue: "Migration aborted due to conflicts"
# View conflicts in detail
node scripts/migrateCustomerData.js --preview --sources ... --destination ...
# Then use Strategy 1 or 2 above
Issue: Transaction timeout
# Reduce number of source customers per migration
# Instead of migrating 10 at once, do 2-3 at a time
Issue: Need to rollback
# 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
# 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
// Count jobs per customer
db.jobs.aggregate([
{ $match: { markedDelete: { $ne: true } } },
{ $group: { _id: "$byPuid", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
Check Sub-Account Distribution
// 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
// 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:
- Check
migration_history.jsonfor details - Enable debug logging:
DEBUG=agm:* - Review this guide and main README
- Contact database administrator
Related Commands
# 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})'