Skip to content

Commit f93aa0a

Browse files
authored
OmniScript name validation & code cleanup (#31)
1 parent 3910602 commit f93aa0a

File tree

3 files changed

+93
-79
lines changed

3 files changed

+93
-79
lines changed

messages/migrate.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
"invalidNameTypeSubtypeOrLanguage": "Not a valid Name, Type, SubType or Language",
1919
"invalidOrRepeatingOmniscriptElementNames": "Invalid or Repeating Element Names for Same OmniScript",
2020
"invalidDataRaptorName": "Invalid name, can not have special characters",
21-
"duplicatedCardName": "Duplicated card name",
22-
"duplicatedDrName": "Duplicated data raptor name"
21+
"duplicatedCardName": "Duplicated Flex Card name",
22+
"duplicatedDrName": "Duplicated DataRaptor name",
23+
"duplicatedOSName": "Duplicated OmniScript name",
24+
"errorWhileActivatingOs": "Could not activate OmniScript"
2325
}

src/commands/omnistudio/migration/migrate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ export default class Migrate extends OmniStudioBaseCommand {
107107
let allTruncateComplete = true;
108108
for (const cls of migrationObjects.reverse()) {
109109
try {
110-
this.ux.log('Truncating: ' + cls.getName());
111-
debugTimer.lap('Truncating: ' + cls.getName());
110+
this.ux.log('Cleaning: ' + cls.getName());
111+
debugTimer.lap('Cleaning: ' + cls.getName());
112112
await cls.truncate();
113113
} catch (ex: any) {
114114
allTruncateComplete = false;

src/migration/omniscript.ts

Lines changed: 87 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
124124

125125
// Get All Records from OmniScript__c (IP & OS Parent Records)
126126
const omniscripts = await this.getAllOmniScripts();
127+
const duplicatedNames = new Set<string>();
127128

128129
// Variables to be returned After Migration
129130
let done = 0;
@@ -132,60 +133,95 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
132133
const total = omniscripts.length;
133134

134135
for (let omniscript of omniscripts) {
135-
const mappedRecords = [],
136-
originalRecords = new Map<string, AnyJson>();
136+
const mappedRecords = [];
137+
// const originalRecords = new Map<string, AnyJson>();
138+
const recordId = omniscript['Id'];
137139

138140
this.reportProgress(total, done);
139141

140142
// Record is Active, Elements can't be Added, Modified or Deleted for that OS/IP
141143
omniscript[`${this.namespacePrefix}IsActive__c`] = false;
142144

143145
// Create a map of the original OmniScript__c records
144-
originalRecords.set(omniscript['Id'], omniscript);
145-
146-
if (!this.isValidRecord(omniscript)) {
147-
this.setRecordErrors(omniscript, this.messages.getMessage('invalidNameTypeSubtypeOrLanguage'));
148-
originalOsRecords = new Map([...Array.from(originalOsRecords.entries()), ...Array.from(originalRecords.entries())]);
149-
continue;
150-
}
146+
originalOsRecords.set(recordId, omniscript);
151147

152148
// Get All elements for each OmniScript__c record(i.e IP/OS)
153-
const elements = await this.getAllElementsForOmniScript(originalRecords);
149+
const elements = await this.getAllElementsForOmniScript(recordId);
154150

155151
if (!this.areValidElements(elements)) {
156152
this.setRecordErrors(omniscript, this.messages.getMessage('invalidOrRepeatingOmniscriptElementNames'));
157-
originalOsRecords = new Map([...Array.from(originalOsRecords.entries()), ...Array.from(originalRecords.entries())]);
153+
originalOsRecords.set(recordId, omniscript);
158154
continue;
159155
}
160156

161157
// Perform the transformation for OS/IP Parent Record from OmniScript__c
162-
mappedRecords.push(this.mapOmniScriptRecord(omniscript));
158+
const mappedOmniScript = this.mapOmniScriptRecord(omniscript);
159+
160+
// Clean type, subtype
161+
mappedOmniScript[OmniScriptMappings.Type__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.Type__c]);
162+
mappedOmniScript[OmniScriptMappings.SubType__c] = this.cleanName(mappedOmniScript[OmniScriptMappings.SubType__c]);
163+
164+
// Check duplicated name
165+
const mappedOsName = `${mappedOmniScript[OmniScriptMappings.Type__c]}_${mappedOmniScript[OmniScriptMappings.SubType__c]}_${mappedOmniScript[OmniScriptMappings.Language__c]}`;
166+
if (duplicatedNames.has(mappedOsName)) {
167+
this.setRecordErrors(omniscript, this.messages.getMessage('duplicatedOSName'));
168+
originalOsRecords.set(recordId, omniscript)
169+
continue;
170+
}
171+
172+
// Save the mapped record
173+
duplicatedNames.add(mappedOsName);
174+
mappedRecords.push(mappedOmniScript);
163175

164176
// Save the OmniScript__c records to Standard BPO i.e OmniProcess
165-
var osUploadResponse: Map<string, UploadRecordResult> = await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESS_NAME, { mappedRecords, originalRecords });
177+
// const osUploadResponse: Map<string, UploadRecordResult> = await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESS_NAME, { mappedRecords, originalRecords });
178+
const osUploadResponse = await NetUtils.createOne(this.connection, OmniScriptMigrationTool.OMNIPROCESS_NAME, recordId, mappedOmniScript);
166179

167-
// Upload All elements for each OmniScript__c record(i.e IP/OS)
168-
await this.uploadAllElements(originalRecords, osUploadResponse, elements);
180+
if (osUploadResponse.success) {
169181

170-
// Get OmniScript Compiled Definitions for OmniScript Record
171-
const omniscriptsCompiledDefinitions = await this.getOmniScriptCompiledDefinition(originalRecords);
172182

173-
// Upload OmniScript Compiled Definition to OmniProcessCompilation
174-
await this.uploadAllOmniScriptDefinitions(originalRecords, osUploadResponse, omniscriptsCompiledDefinitions);
183+
// Fix errors
184+
if (!osUploadResponse.success) {
185+
osUploadResponse.errors = Array.isArray(osUploadResponse.errors) ? osUploadResponse.errors : [osUploadResponse.errors];
186+
}
187+
188+
const originalOsName = omniscript[this.namespacePrefix + 'Type__c'] + '_' + omniscript[this.namespacePrefix + 'SubType__c'] + '_' + omniscript[this.namespacePrefix + 'Language__c'];
189+
if (originalOsName !== mappedOsName) {
190+
osUploadResponse.errors.unshift('WARNING: OmniScript name has been modified to fit naming rules: ' + mappedOsName);
191+
}
175192

176-
// Update the inserted OS record as it was Active and made InActive to insert.
177-
mappedRecords[0].IsActive = true;
178-
mappedRecords[0].Id = osUploadResponse.entries().next().value[1].id;
193+
// Upload All elements for each OmniScript__c record(i.e IP/OS)
194+
await this.uploadAllElements(osUploadResponse, elements);
179195

180-
if (mappedRecords[0].IsIntegrationProcedure) {
181-
mappedRecords[0].Language = 'Procedure';
182-
}
196+
// Get OmniScript Compiled Definitions for OmniScript Record
197+
const omniscriptsCompiledDefinitions = await this.getOmniScriptCompiledDefinition(recordId);
198+
199+
// Upload OmniScript Compiled Definition to OmniProcessCompilation
200+
await this.uploadAllOmniScriptDefinitions(osUploadResponse, omniscriptsCompiledDefinitions);
201+
202+
// Update the inserted OS record as it was Active and made InActive to insert.
203+
mappedRecords[0].IsActive = true;
204+
mappedRecords[0].Id = osUploadResponse.id;
205+
206+
if (mappedRecords[0].IsIntegrationProcedure) {
207+
mappedRecords[0].Language = 'Procedure';
208+
}
209+
210+
const updateResult = await this.updateData({ mappedRecords, originalRecords: originalOsRecords });
211+
if (updateResult.has(osUploadResponse.id)) {
212+
const res = updateResult.get(osUploadResponse.id);
213+
if (!res.success) {
214+
osUploadResponse.hasErrors = true;
215+
osUploadResponse.errors = osUploadResponse.errors || [];
216+
osUploadResponse.errors.push(this.messages.getMessage('errorWhileActivatingOs'));
217+
}
218+
}
183219

184-
await this.updateData({ mappedRecords, originalRecords });
220+
// Create the return records and response which have been processed
221+
osUploadInfo.set(recordId, osUploadResponse);
222+
}
185223

186-
// Create the return records and response which have been processed
187-
originalOsRecords = new Map([...Array.from(originalOsRecords.entries()), ...Array.from(originalRecords.entries())]);
188-
osUploadInfo = new Map([...Array.from(osUploadInfo.entries()), ...Array.from(osUploadResponse.entries())]);
224+
originalOsRecords.set(recordId, omniscript);
189225

190226
done++;
191227
};
@@ -242,27 +278,27 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
242278
}
243279

244280
// Get All Elements w.r.t OmniScript__c i.e Elements tagged to passed in IP/OS
245-
private async getAllElementsForOmniScript(omniScriptData: Map<string, AnyJson>): Promise<AnyJson[]> {
281+
private async getAllElementsForOmniScript(recordId: string): Promise<AnyJson[]> {
246282
// Query all Elements for an OmniScript
247283
const filters = new Map<string, any>();
248-
filters.set(this.namespacePrefix + 'OmniScriptId__c', omniScriptData.keys().next().value);
284+
filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId);
249285

250286
// const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`;
251287
return await QueryTools.queryWithFilter(this.connection, this.namespace, OmniScriptMigrationTool.ELEMENT_NAME, this.getElementFields(), filters);
252288
}
253289

254290
// Get All Compiled Definitions w.r.t OmniScript__c i.e Definitions tagged to passed in IP/OS
255-
private async getOmniScriptCompiledDefinition(omniScriptData: Map<string, AnyJson>): Promise<AnyJson[]> {
291+
private async getOmniScriptCompiledDefinition(recordId: string): Promise<AnyJson[]> {
256292
// Query all Definitions for an OmniScript
257293
const filters = new Map<string, any>();
258-
filters.set(this.namespacePrefix + 'OmniScriptId__c', omniScriptData.keys().next().value);
294+
filters.set(this.namespacePrefix + 'OmniScriptId__c', recordId);
259295

260296
// const queryFilterStr = ` Where ${this.namespacePrefix}OmniScriptId__c = '${omniScriptData.keys().next().value}'`;
261297
return await QueryTools.queryWithFilter(this.connection, this.namespace, OmniScriptMigrationTool.OMNISCRIPTDEFINITION_NAME, this.getOmniScriptDefinitionFields(), filters);
262298
}
263299

264300
// Upload All the Elements tagged to a OmniScript__c record, after the parent record has been inserted
265-
private async uploadAllElements(omniScriptData: Map<string, AnyJson>, omniScriptUploadResults: Map<string, UploadRecordResult>, elements: AnyJson[]): Promise<Map<string, UploadRecordResult>> {
301+
private async uploadAllElements(omniScriptUploadResults: UploadRecordResult, elements: AnyJson[]): Promise<Map<string, UploadRecordResult>> {
266302
let levelCount = 0; // To define and insert different levels(Parent-Child relationship) at a time
267303
let exit = false; // Counter variable to exit after all parent-child elements inserted
268304
var elementsUploadInfo = new Map<string, UploadRecordResult>(); // Info for Uploaded Elements to be returned
@@ -284,7 +320,7 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
284320
exit = true;
285321
} else {
286322
// Get Transformed Element__c to OmniProcessElement with updated OmniScriptId & ParentElementId
287-
let elementsTransformedData = await this.prepareElementsData(omniScriptData, omniScriptUploadResults, tempElements, elementsUploadInfo);
323+
let elementsTransformedData = await this.prepareElementsData(omniScriptUploadResults, tempElements, elementsUploadInfo);
288324
// Upload the transformed Element__c
289325
let elementsUploadResponse = await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESSELEMENT_NAME, elementsTransformedData);
290326
// Keep appending upload Info for Elements at each level
@@ -299,29 +335,24 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
299335
}
300336

301337
// Upload All the Definitions tagged to a OmniScript__c record, after the parent record has been inserted
302-
private async uploadAllOmniScriptDefinitions(omniScriptData: Map<string, AnyJson>, omniScriptUploadResults: Map<string, UploadRecordResult>, osDefinitions: AnyJson[]): Promise<Map<string, UploadRecordResult>> {
303-
let osDefinitionsData = await this.prepareOsDefinitionsData(omniScriptData, omniScriptUploadResults, osDefinitions);
338+
private async uploadAllOmniScriptDefinitions(omniScriptUploadResults: UploadRecordResult, osDefinitions: AnyJson[]): Promise<Map<string, UploadRecordResult>> {
339+
let osDefinitionsData = await this.prepareOsDefinitionsData(omniScriptUploadResults, osDefinitions);
304340
return await this.uploadTransformedData(OmniScriptMigrationTool.OMNIPROCESSCOMPILATION_NAME, osDefinitionsData);
305341
}
306342

307343
// Prepare Elements Data and Do the neccessary updates, transformation, validations etc.
308-
private async prepareElementsData(omniScriptData: Map<string, AnyJson>, omniScriptUploadResults: Map<string, UploadRecordResult>, elements: AnyJson[], parentElementUploadResponse: Map<string, UploadRecordResult>): Promise<TransformData> {
344+
private async prepareElementsData(osUploadResult: UploadRecordResult, elements: AnyJson[], parentElementUploadResponse: Map<string, UploadRecordResult>): Promise<TransformData> {
309345

310346
const mappedRecords = [],
311347
originalRecords = new Map<string, AnyJson>();
312348

313349
elements.forEach(element => {
314-
// Extract the parent OmniScript__c for the elements
315-
const osRecord = omniScriptData.values().next().value;
316350

317351
// Perform the transformation. We need parent record & must have been migrated before
318-
if (osRecord && omniScriptUploadResults.has(osRecord['Id'])) {
319-
const osUploadResult = omniScriptUploadResults.get(osRecord['Id']);
320-
321-
if (osUploadResult.id) {
322-
mappedRecords.push(this.mapElementData(element, osUploadResult.id, parentElementUploadResponse));
323-
}
352+
if (osUploadResult.id) {
353+
mappedRecords.push(this.mapElementData(element, osUploadResult.id, parentElementUploadResponse));
324354
}
355+
325356
// Create a map of the original records
326357
originalRecords.set(element['Id'], element);
327358
});
@@ -330,22 +361,17 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
330361
}
331362

332363
// Prepare OmniScript Definitions to be uploaded
333-
private async prepareOsDefinitionsData(omniScriptData: Map<string, AnyJson>, omniScriptUploadResults: Map<string, UploadRecordResult>, osDefinitions: AnyJson[]): Promise<TransformData> {
364+
private async prepareOsDefinitionsData(osUploadResult: UploadRecordResult, osDefinitions: AnyJson[]): Promise<TransformData> {
334365
const mappedRecords = [],
335366
originalRecords = new Map<string, AnyJson>();
336367

337368
osDefinitions.forEach(osDefinition => {
338-
// Extract the parent OmniScript__c for the osDefinitions
339-
const osRecord = omniScriptData.values().next().value;
340369

341370
// Perform the transformation. We need parent record & must have been migrated before
342-
if (osRecord && omniScriptUploadResults.has(osRecord['Id'])) {
343-
const osUploadResult = omniScriptUploadResults.get(osRecord['Id']);
344-
345-
if (osUploadResult.id) {
346-
mappedRecords.push(this.mapOsDefinitionsData(osDefinition, osUploadResult.id));
347-
}
371+
if (osUploadResult.id) {
372+
mappedRecords.push(this.mapOsDefinitionsData(osDefinition, osUploadResult.id));
348373
}
374+
349375
// Create a map of the original records
350376
originalRecords.set(osDefinition['Id'], osDefinition);
351377
});
@@ -473,34 +499,20 @@ export class OmniScriptMigrationTool extends BaseMigrationTool implements Migrat
473499
return Object.keys(OmniScriptDefinitionMappings);
474500
}
475501

476-
// Return true/false, if the record is valid/invalid
477-
private isValidRecord(omniscript: AnyJson): boolean {
478-
const nsPrefix = this.namespacePrefix;
479-
480-
return this.validMetaDataName(omniscript[`${nsPrefix}Type__c`]) &&
481-
this.validMetaDataName(omniscript[`${nsPrefix}SubType__c`]) &&
482-
this.validMetaDataName(omniscript[`${nsPrefix}Version__c`]) &&
483-
(
484-
omniscript[`${nsPrefix}Procedure__c`] || (
485-
!omniscript[`${nsPrefix}Procedure__c`] &&
486-
this.validMetaDataName(omniscript[`${nsPrefix}Language__c`])
487-
)
488-
);
489-
}
490-
491502
private areValidElements(elements: AnyJson[]): boolean {
492-
let elementNames = [];
503+
const elementNames = new Set<string>();
493504
for (let element of elements) {
494-
let elementName: string = element['Name'];
505+
let elementName: string = this.cleanName(element['Name']);
495506
if (!elementName) {
496507
return false;
497508
}
498509

499-
if (!this.validMetaDataName(elementName.replace(/\s/g, '')) || elementNames.includes(elementName)) {
510+
if (elementNames.has(elementName)) {
500511
return false;
501-
} else {
502-
elementNames.push(elementName);
503512
}
513+
514+
elementNames.add(elementName);
515+
element['Name'] = elementName;
504516
}
505517
return true;
506518
}

0 commit comments

Comments
 (0)