feat: Autotask webhook integration, TicketNotes, Datto RMM, workflow engine, Veeam agents/alarms, AI triage, misc improvements
This commit is contained in:
parent
347cf4e298
commit
d7c3dc7168
74 changed files with 37844 additions and 322 deletions
|
|
@ -71,6 +71,15 @@ export class EntitySyncService {
|
|||
if (entity === EntityType.SUB_ISSUE_TYPES) {
|
||||
return await this.syncSubIssueTypes(isIncremental);
|
||||
}
|
||||
if (entity === EntityType.QUEUES) {
|
||||
return await this.syncQueues(isIncremental);
|
||||
}
|
||||
if (entity === EntityType.PRIORITIES) {
|
||||
return await this.syncPriorities(isIncremental);
|
||||
}
|
||||
if (entity === EntityType.TICKET_CATEGORIES) {
|
||||
return await this.syncTicketCategories(isIncremental);
|
||||
}
|
||||
|
||||
const trackingId = syncId || `${entity}_${Date.now()}`;
|
||||
const entityLogger = this.logger.child({ syncId: trackingId, entityType: entity });
|
||||
|
|
@ -889,6 +898,141 @@ export class EntitySyncService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync Queues (Picklist from Ticket field)
|
||||
*/
|
||||
async syncQueues(isIncremental: boolean = false): Promise<EntitySyncStats> {
|
||||
const picklistLogger = this.logger.child({ entityType: EntityType.QUEUES, syncType: 'picklist' });
|
||||
const syncStartTime = picklistLogger.start('Picklist sync');
|
||||
|
||||
try {
|
||||
const picklistValues = await this.autotaskClient.getPicklistValues('Tickets', 'queueID');
|
||||
|
||||
const records = Object.entries(picklistValues).map(([value, label]) => ({
|
||||
value: parseInt(value),
|
||||
label: label,
|
||||
is_active: true,
|
||||
sort_order: parseInt(value),
|
||||
synced_at: new Date(),
|
||||
}));
|
||||
|
||||
picklistLogger.info('Found picklist values', { recordCount: records.length });
|
||||
|
||||
const tableName = getTableName(EntityType.QUEUES);
|
||||
const existingQuery = `SELECT value FROM ${tableName}`;
|
||||
const existingResult = await postgresClient.query<{ value: number }>(existingQuery);
|
||||
const existingValues = new Set(existingResult.rows.map((r: any) => r.value));
|
||||
|
||||
const recordsAdded = records.filter((r: any) => !existingValues.has(r.value)).length;
|
||||
const recordsUpdated = records.filter((r: any) => existingValues.has(r.value)).length;
|
||||
|
||||
await postgresClient.bulkUpsert(tableName, records, ['value']);
|
||||
|
||||
const stats: EntitySyncStats = { recordsAdded, recordsUpdated, recordsDeleted: 0 };
|
||||
|
||||
picklistLogger.complete('Picklist sync', syncStartTime, {
|
||||
recordsAdded: stats.recordsAdded,
|
||||
recordsUpdated: stats.recordsUpdated,
|
||||
});
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
picklistLogger.fail('Picklist sync', syncStartTime, err);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync Priorities (Picklist from Ticket field)
|
||||
*/
|
||||
async syncPriorities(isIncremental: boolean = false): Promise<EntitySyncStats> {
|
||||
const picklistLogger = this.logger.child({ entityType: EntityType.PRIORITIES, syncType: 'picklist' });
|
||||
const syncStartTime = picklistLogger.start('Picklist sync');
|
||||
|
||||
try {
|
||||
const picklistValues = await this.autotaskClient.getPicklistValues('Tickets', 'priority');
|
||||
|
||||
const records = Object.entries(picklistValues).map(([value, label]) => ({
|
||||
value: parseInt(value),
|
||||
label: label,
|
||||
is_active: true,
|
||||
sort_order: parseInt(value),
|
||||
synced_at: new Date(),
|
||||
}));
|
||||
|
||||
picklistLogger.info('Found picklist values', { recordCount: records.length });
|
||||
|
||||
const tableName = getTableName(EntityType.PRIORITIES);
|
||||
const existingQuery = `SELECT value FROM ${tableName}`;
|
||||
const existingResult = await postgresClient.query<{ value: number }>(existingQuery);
|
||||
const existingValues = new Set(existingResult.rows.map((r: any) => r.value));
|
||||
|
||||
const recordsAdded = records.filter((r: any) => !existingValues.has(r.value)).length;
|
||||
const recordsUpdated = records.filter((r: any) => existingValues.has(r.value)).length;
|
||||
|
||||
await postgresClient.bulkUpsert(tableName, records, ['value']);
|
||||
|
||||
const stats: EntitySyncStats = { recordsAdded, recordsUpdated, recordsDeleted: 0 };
|
||||
|
||||
picklistLogger.complete('Picklist sync', syncStartTime, {
|
||||
recordsAdded: stats.recordsAdded,
|
||||
recordsUpdated: stats.recordsUpdated,
|
||||
});
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
picklistLogger.fail('Picklist sync', syncStartTime, err);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync Ticket Categories (Picklist from Ticket field)
|
||||
*/
|
||||
async syncTicketCategories(isIncremental: boolean = false): Promise<EntitySyncStats> {
|
||||
const picklistLogger = this.logger.child({ entityType: EntityType.TICKET_CATEGORIES, syncType: 'picklist' });
|
||||
const syncStartTime = picklistLogger.start('Picklist sync');
|
||||
|
||||
try {
|
||||
const picklistValues = await this.autotaskClient.getPicklistValues('Tickets', 'ticketCategory');
|
||||
|
||||
const records = Object.entries(picklistValues).map(([value, label]) => ({
|
||||
value: parseInt(value),
|
||||
label: label,
|
||||
is_active: true,
|
||||
sort_order: parseInt(value),
|
||||
synced_at: new Date(),
|
||||
}));
|
||||
|
||||
picklistLogger.info('Found picklist values', { recordCount: records.length });
|
||||
|
||||
const tableName = getTableName(EntityType.TICKET_CATEGORIES);
|
||||
const existingQuery = `SELECT value FROM ${tableName}`;
|
||||
const existingResult = await postgresClient.query<{ value: number }>(existingQuery);
|
||||
const existingValues = new Set(existingResult.rows.map((r: any) => r.value));
|
||||
|
||||
const recordsAdded = records.filter((r: any) => !existingValues.has(r.value)).length;
|
||||
const recordsUpdated = records.filter((r: any) => existingValues.has(r.value)).length;
|
||||
|
||||
await postgresClient.bulkUpsert(tableName, records, ['value']);
|
||||
|
||||
const stats: EntitySyncStats = { recordsAdded, recordsUpdated, recordsDeleted: 0 };
|
||||
|
||||
picklistLogger.complete('Picklist sync', syncStartTime, {
|
||||
recordsAdded: stats.recordsAdded,
|
||||
recordsUpdated: stats.recordsUpdated,
|
||||
});
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
picklistLogger.fail('Picklist sync', syncStartTime, err);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync Work Types (Picklist from TimeEntry field)
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue