agmission/Development/server/scripts/MIGRATION_APPROACH_UPDATED.md

202 lines
6.6 KiB
Markdown

# Customer Migration Script - Simplified Approach (Updated)
## Date: 2025-01-14
## Summary of Changes
The customer migration script has been updated with a **simplified approach** that eliminates username conflicts by simply updating the parent references of sub-accounts instead of trying to move or merge them.
## Previous Approach (Removed)
The old approach attempted to:
1. Move sub-accounts from source to destination customer
2. Detect username conflicts between source and destination sub-accounts
3. Offer a `--merge-conflicts` flag to merge conflicting accounts
4. Mark old accounts as deleted and update all references
**Problem**: Since usernames are globally unique in the system, attempting to move accounts between customers created conflicts.
## New Approach (Current)
The new simplified approach:
1. **Sub-accounts stay in place** with their original usernames
2. Only the `.parent` field is updated to point to the destination customer
3. **No username conflicts** because accounts aren't moving, just being re-parented
4. Much simpler code with no merging logic needed
### Key Changes
#### 1. Conflict Detection Simplified
- **Before**: Checked for username conflicts across all sub-account types
- **After**: Only checks for circular references (migrating a customer to itself)
```javascript
// Old: Complex username conflict checking
// New: Simple validation
async function detectConflicts(sourceCustomers, targetCustomer, migrationRecord) {
const conflicts = [];
// Only check for circular reference
for (const sourceCustomer of sourceCustomers) {
if (sourceCustomer._id.toString() === targetCustomer._id.toString()) {
conflicts.push({
type: 'circular_reference',
message: `Cannot migrate customer ${sourceCustomer.username} to itself`
});
}
}
return conflicts;
}
```
#### 2. Sub-Account Migration Rewritten
- **Before**: `migrateSubAccounts()` with conflict map, merging logic, reference updates
- **After**: `updateSubAccountsParent()` with simple parent field update
```javascript
// Old: ~100 lines of merge/conflict handling
// New: ~40 lines of simple parent update
async function updateSubAccountsParent(sourceId, targetId, session, migrationRecord) {
const subAccounts = await models.User.find({
parent: sourceId,
kind: { $in: [UserTypes.CLIENT, UserTypes.PILOT, UserTypes.DEVICE,
UserTypes.OFFICER, UserTypes.INSPECTOR] }
}).session(session);
for (const account of subAccounts) {
// Simply update the parent reference
account.parent = targetId;
await account.save({ session });
// Track in migration record
migrationRecord.details.changes.push({
action: 'update_parent_reference',
kind: account.kind,
username: account.username,
accountId: account._id,
fromParent: sourceId,
toParent: targetId
});
}
}
```
#### 3. Removed Options
- **Removed**: `--merge-conflicts` flag (no longer needed)
- **Removed**: All conflict merging logic
- **Removed**: Reference update functions for merged accounts
#### 4. Documentation Updates
- Updated header comments to explain the parent-reference approach
- Simplified help text
- Removed merge-related warnings and examples
## Migration Behavior
### What Happens During Migration
1. **Source Customer Account**:
- If `--convert-to-admin` flag: Converted to an admin (kind='2') under destination
- Otherwise: Marked as deleted and inactive
2. **Sub-Accounts (Clients, Pilots, Vehicles, Officers, Inspectors)**:
- **Parent field updated** from sourceCustomerId to targetCustomerId
- **Usernames remain unchanged** (globally unique)
- **All other fields unchanged**
3. **Jobs, Products, Crops**:
- `byPuid` field updated from sourceCustomerId to targetCustomerId
4. **Invoices** (if `--update-invoices` flag):
- `customer` field updated from sourceCustomerId to targetCustomerId
### Example
Before migration:
```
Customer: trungh1@agnav.com (ID: 67ae...)
├─ Client: client1@example.com (parent: 67ae...)
├─ Pilot: pilot1@example.com (parent: 67ae...)
└─ Vehicle: vehicle1 (parent: 67ae...)
Customer: trungh@agnav.com (ID: 6786...)
└─ (existing sub-accounts)
```
After migration:
```
Customer: trungh1@agnav.com (ID: 67ae...) [DELETED]
Customer: trungh@agnav.com (ID: 6786...)
├─ Client: client1@example.com (parent: 6786...) ← Updated
├─ Pilot: pilot1@example.com (parent: 6786...) ← Updated
├─ Vehicle: vehicle1 (parent: 6786...) ← Updated
└─ (existing sub-accounts)
```
## Testing Results
Successfully tested with:
```bash
# Preview mode
node scripts/migrateCustomerData.js \
--sources trungh1@agnav.com \
--destination trungh@agnav.com \
--preview
# Execution
node scripts/migrateCustomerData.js \
--sources trungh1@agnav.com \
--destination trungh@agnav.com
```
**Results**:
- ✅ No conflicts detected
- ✅ 2 clients migrated (parent updated)
- ✅ 1 pilot migrated (parent updated)
- ✅ 5 vehicles migrated (parent updated)
- ✅ 1 job migrated (byPuid updated)
- ✅ 1 product migrated (byPuid updated)
- ✅ 1 crop migrated (byPuid updated)
- ✅ Transaction completed successfully
- ✅ Migration history saved
## Benefits of New Approach
1. **Eliminates Conflicts**: No username conflicts since accounts stay in place
2. **Simpler Code**: Removed ~200 lines of conflict/merge logic
3. **Safer**: No account deletion or reference rewiring
4. **Clearer Intent**: Sub-accounts are "re-parented", not "moved"
5. **Faster Execution**: No conflict checking for thousands of sub-accounts
## Files Modified
- `scripts/migrateCustomerData.js`:
- Simplified `detectConflicts()` function
- Replaced `migrateSubAccounts()` with `updateSubAccountsParent()`
- Removed `updateAccountReferences()` function
- Removed `--merge-conflicts` option parsing
- Updated documentation strings
- Added display name sanitization for corrupt data
## Backward Compatibility
This is a **breaking change** if anyone was using the `--merge-conflicts` flag. However:
- The new approach is the **correct** approach for this data model
- Old approach would have caused data inconsistencies
- Migration history format remains compatible
## Related Files
- `scripts/README_CUSTOMER_MIGRATION.md` - Full documentation (needs minor update)
- `scripts/MIGRATION_QUICK_REFERENCE.md` - Quick reference (needs minor update)
- `MIGRATION_SUMMARY.md` - Implementation overview (needs minor update)
## Next Steps
Consider updating the documentation files to reflect:
1. The simplified conflict detection
2. Removal of merge-conflicts flag
3. Clarification that sub-accounts are "re-parented" not "moved"