| name | maintainx-migration-deep-dive |
| description | Execute complete platform migrations to or from MaintainX.
Use when migrating from legacy CMMS systems, performing major re-platforming,
or transitioning to MaintainX from spreadsheets or other tools.
Trigger with phrases like "migrate to maintainx", "maintainx migration",
"cmms migration", "switch to maintainx", "maintainx data migration".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Bash(node:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX Migration Deep Dive
Overview
Comprehensive guide for migrating to MaintainX from legacy CMMS systems, spreadsheets, or other maintenance management tools.
Prerequisites
- MaintainX account with API access
- Access to source system data
- Understanding of both systems' data models
Migration Strategy
┌─────────────────────────────────────────────────────────────────────┐
│ Migration Strategy Overview │
│ │
│ Phase 1 Phase 2 Phase 3 Phase 4 │
│ ASSESS PREPARE MIGRATE VALIDATE │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Inventory │ │Data │ │Parallel │ │Testing │ │
│ │data │───▶│cleansing │───▶│run │───▶│& cutover │ │
│ │ │ │& mapping │ │ │ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ Week 1-2 Week 3-4 Week 5-6 Week 7-8 │
└─────────────────────────────────────────────────────────────────────┘
Instructions
Step 1: Source System Assessment
interface SourceSystemAssessment {
system: string;
dataVolume: {
workOrders: number;
assets: number;
locations: number;
users: number;
procedures: number;
};
dataQuality: {
completeness: number;
duplicates: number;
invalidRecords: number;
};
customizations: string[];
integrations: string[];
risks: string[];
}
async function assessSourceSystem(sourceData: any): Promise<SourceSystemAssessment> {
console.log('=== Migration Assessment ===\n');
const assessment: SourceSystemAssessment = {
system: sourceData.systemName || 'Unknown',
dataVolume: {
workOrders: 0,
assets: 0,
: ,
: ,
: ,
},
: {
: ,
: ,
: ,
},
: [],
: [],
: [],
};
.();
assessment.. = sourceData.?. || ;
assessment.. = sourceData.?. || ;
assessment.. = sourceData.?. || ;
assessment.. = sourceData.?. || ;
assessment.. = sourceData.?. || ;
.();
workOrders = sourceData. || [];
requiredFields = [, ];
completeRecords = ;
workOrders.( {
hasAllRequired = requiredFields.( wo[f]);
(hasAllRequired) completeRecords++;
});
assessment.. = workOrders. >
? (completeRecords / workOrders.) *
: ;
titles = workOrders.( wo.);
uniqueTitles = (titles);
assessment.. = titles. - uniqueTitles.;
(assessment.. > ) {
assessment..();
}
(assessment.. < ) {
assessment..();
}
(assessment.. > ) {
assessment..();
}
assessment;
}
(): {
.();
.();
.();
.();
.();
.();
.();
.();
.();
.();
.();
(assessment.. > ) {
.();
assessment..( .());
}
}
Step 2: Data Mapping
interface FieldMapping {
sourceField: string;
targetField: string;
transform?: (value: any) => any;
required: boolean;
defaultValue?: any;
}
interface DataMapping {
workOrders: FieldMapping[];
assets: FieldMapping[];
locations: FieldMapping[];
users: FieldMapping[];
}
const legacyCmmsToMaintainX: DataMapping = {
workOrders: [
{ sourceField: 'wo_number', targetField: 'externalId', required: false },
{ sourceField: 'wo_title', targetField: 'title', required: true },
{ sourceField: 'wo_description', targetField: 'description', required: false },
{
sourceField: 'wo_priority',
: ,
: ,
: ,
: {
: <, > = {
: , : , : ,
: , : , : ,
: , : , : ,
};
map[(value).()] || ;
},
},
{
: ,
: ,
: ,
: ,
: {
: <, > = {
: , : , : ,
: , : , : ,
: , : , : ,
: , : , : , : ,
};
map[(value).()] || ;
},
},
{ : , : , : },
{ : , : , : },
{ : , : , : },
{ : , : , : },
],
: [
{ : , : , : },
{ : , : , : },
{ : , : , : },
{ : , : , : },
{ : , : , : },
{
: ,
: ,
: ,
: ,
: {
: <, > = {
: , : , : ,
: , : , : ,
: , : ,
};
map[(value).()] || ;
},
},
],
: [
{ : , : , : },
{ : , : , : },
{ : , : , : },
{ : , : , : },
],
: [
{ : , : , : },
{ : , : , : },
{ : , : , : },
{ : , : , : },
],
};
applyMapping<T>(
: [],
: []
): T[] {
sourceRecords.( {
: = {};
mappings.( {
value = source[mapping.];
(mapping. && value !== && value !== ) {
value = mapping.(value);
}
((value === || value === ) && mapping. !== ) {
value = mapping.;
}
(value === || value === ) {
(mapping.) {
();
}
;
}
target[mapping.] = value;
});
target T;
});
}
Step 3: Migration Execution
interface MigrationPlan {
phases: MigrationPhase[];
rollbackPlan: RollbackStep[];
validationRules: ValidationRule[];
}
interface MigrationPhase {
name: string;
order: number;
resource: 'locations' | 'assets' | 'users' | 'workOrders';
batchSize: number;
dependsOn?: string[];
}
interface MigrationResult {
phase: string;
status: 'success' | 'partial' | 'failed';
processed: number;
succeeded: number;
failed: number;
errors: MigrationError[];
duration: number;
}
class MaintainXMigrator {
private client: MaintainXClient;
private idMapping: Map<string, string> = new ();
(
: ,
:
): <[]> {
: [] = [];
sortedPhases = .(plan.);
( phase sortedPhases) {
.();
result = .(
phase,
sourceData[phase.],
plan.
);
results.(result);
(result. === ) {
.();
;
}
}
results;
}
(
: ,
: [],
: []
): <> {
startTime = .();
: = {
: phase.,
: ,
: ,
: ,
: ,
: [],
: ,
};
mappings = legacyCmmsToMaintainX[phase.];
: [];
{
transformedRecords = (sourceRecords, mappings);
} (: ) {
result. = ;
result..({ : , : error. });
result. = .() - startTime;
result;
}
( i = ; i < transformedRecords.; i += phase.) {
batch = transformedRecords.(i, i + phase.);
( record batch) {
result.++;
{
(record. && ..(record.)) {
record. = ..(record.);
}
(record. && ..(record.)) {
record. = ..(record.);
}
(record. && ..(record.)) {
record. = ..(record.);
}
created = .(phase., record);
(record.) {
..(record., created.);
}
result.++;
} (: ) {
result.++;
result..({
record,
: error.,
});
}
}
.();
( (r, ));
}
result. = result. === ? :
result. > ? : ;
result. = .() - startTime;
result;
}
(: , : ): <> {
(resource) {
:
..(data);
:
();
}
}
}
Step 4: Validation & Verification
interface ValidationReport {
phase: string;
totalRecords: number;
passed: number;
failed: number;
failures: ValidationFailure[];
}
interface ValidationFailure {
sourceId: string;
targetId?: string;
issues: string[];
}
class MigrationValidator {
async validateMigration(
sourceData: any[],
targetData: any[]
): Promise<ValidationReport> {
const report: ValidationReport = {
phase: 'post-migration',
totalRecords: sourceData.length,
passed: 0,
failed: 0,
failures: [],
};
const sourceMap = new Map(sourceData.map(s => [s.externalId || s.id, s]));
targetMap = (targetData.( [t., t]));
( [sourceId, source] sourceMap) {
target = targetMap.(sourceId);
: [] = [];
(!target) {
issues.();
} {
(source. !== target.) {
issues.();
}
}
(issues. === ) {
report.++;
} {
report.++;
report..({
sourceId,
: target?.,
issues,
});
}
}
report;
}
(
: [],
:
): <> {
.();
woResponse = maintainxClient.({ : });
assetResponse = maintainxClient.({ : });
locationResponse = maintainxClient.({ : });
.();
.();
.();
.();
.();
.();
.();
.();
.();
}
}
Step 5: Rollback Procedures
interface RollbackPlan {
steps: RollbackStep[];
checkpoint: Date;
}
interface RollbackStep {
order: number;
description: string;
execute: () => Promise<void>;
}
class MigrationRollback {
private client: MaintainXClient;
private migratedIds: Map<string, string[]> = new Map();
trackMigrated(resource: string, id: string): void {
if (!this.migratedIds.has(resource)) {
this.migratedIds.set(resource, []);
}
this.migratedIds.get(resource)!.push(id);
}
generateRollbackPlan(): {
: = {
: [],
: (),
};
plan..({
: ,
: ,
: () => {
report = {
: ().(),
: .(.),
};
fs.(
,
.(report, , )
);
.();
},
});
plan..({
: ,
: ,
: () => {
.();
.();
.();
.();
},
});
plan..({
: ,
: ,
: () => {
.();
},
});
plan;
}
(: ): <> {
.();
( step plan..( a. - b.)) {
.();
step.();
.();
}
.();
}
}
Migration Checklist
Output
- Assessment report
- Data mapping configuration
- Migration results
- Validation report
- Rollback plan
Timeline Template
| Week | Phase | Activities |
|---|
| 1-2 | Assessment | Data inventory, quality analysis |
| 3-4 | Preparation | Mapping, test migration |
| 5-6 | Migration | Parallel run, data migration |
| 7-8 | Validation | Testing, cutover, decommission |
Resources
Next Steps
Congratulations! You have completed the MaintainX skill pack. For additional support, contact MaintainX at support@getmaintainx.com.