@manyos/smileconnect-api 1.43.1 → 1.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/app.js CHANGED
@@ -337,6 +337,7 @@ app.use('/v1/:requestType/:parentId/tasks', function(req, res, next) {
337
337
  const parentId = req.params.parentId;
338
338
  const allowedTypes = ['incidents', 'problems', 'workorders', 'changes'];
339
339
  if (allowedTypes.includes(requestType)) {
340
+ req.ticketConfig = config.ticketConfig['tasks'];
340
341
  req.parentId = parentId;
341
342
  req.requestType = requestType;
342
343
  setParentForm(req);
package/conf/clients.json CHANGED
@@ -587,7 +587,8 @@
587
587
  "Support Company",
588
588
  "Assignee Organization",
589
589
  "Assignee Group",
590
- "Phase GUID"
590
+ "Phase GUID",
591
+ "InstanceId"
591
592
  ],
592
593
  "constants": [
593
594
  {
@@ -8,19 +8,21 @@ const CONSTANTS = require('../util/constants');
8
8
  const relationUtil = require('../util/relationUtil');
9
9
  const mappingUtil = require('../util/mappingUtil');
10
10
  const scriptController = require('./scriptController');
11
+ const {getIncludeArray} = require("../util/paramHelper");
12
+ const ticketCIRelationController = require("./ticketCIRelationController");
11
13
 
12
14
  const taskCache = new CacheService(process.env.CACHETTL_TASK || 0); // Create a new cache service instance
13
15
 
14
- function getTasks(config, category, globalScriptParams) {
16
+ function getTasks(config, category, globalScriptParams, includeString) {
15
17
  let query = '1=1';
16
18
  if (category)
17
19
  query = `'Category' = \"${category}\"`;
18
20
  return queryTasks(config, query, globalScriptParams);
19
21
  }
20
22
 
21
- function getTasksByRootRequest(config, rootRequestId, rootRequestForm, globalScriptParams) {
23
+ function getTasksByRootRequest(config, rootRequestId, rootRequestForm, globalScriptParams, includeString) {
22
24
  const query = `'RootRequestID' = \"${rootRequestId}\" AND 'RootRequestFormName' = \"${rootRequestForm}\"`;
23
- return queryTasks(config, query, globalScriptParams);
25
+ return queryTasks(config, query, globalScriptParams, includeString);
24
26
  }
25
27
 
26
28
  async function createTask(clientConfig, rootForm, rootRequestId, taskData, createTaskFlow, globalScriptParams) {
@@ -171,8 +173,9 @@ async function createWorklog(clientConfig, taskId, data, globalScriptParams) {
171
173
  //todo add attachment handling
172
174
  }
173
175
 
174
- function queryTasks(clientConfig, query, globalScriptParams) {
176
+ function queryTasks(clientConfig, query, globalScriptParams, includeString) {
175
177
  const scripts = clientConfig.task.scripts.GET;
178
+ const includeArray = getIncludeArray(includeString);
176
179
 
177
180
  const key = clientConfig.task.basequery + clientConfig.task.fields.toString() + query;
178
181
  log.debug('Cachekey is', key);
@@ -209,6 +212,12 @@ function queryTasks(clientConfig, query, globalScriptParams) {
209
212
  await scriptController.runScripts(scripts.preMapping, element, clientConfig.clientId, globalScriptParams);
210
213
  }
211
214
 
215
+ element.relations = {};
216
+ if (includeArray.includes('ciRelations')) {
217
+ const relations = await ticketCIRelationController.getTicketCIRelations(element['InstanceId']);
218
+ element.relations.ciRelations = relations;
219
+ }
220
+
212
221
  //Apply mapping
213
222
  mapping.forEach(function (mappingEntry) {
214
223
  try {
@@ -220,7 +229,7 @@ function queryTasks(clientConfig, query, globalScriptParams) {
220
229
  });
221
230
  delete element['Request ID'];
222
231
 
223
- //run preScripts
232
+ //run postScripts
224
233
  if (scripts && scripts.postMapping) {
225
234
  await scriptController.runScripts(scripts.postMapping, element, clientConfig.clientId, globalScriptParams);
226
235
  }
@@ -296,9 +305,9 @@ async function getTask(clientConfig, id, globalScriptParams) {
296
305
  return tasks.data[0];
297
306
  }
298
307
 
299
- async function getTaskByRootRequest(config, rootRequestId, taskId, globalScriptParams) {
308
+ async function getTaskByRootRequest(config, rootRequestId, taskId, globalScriptParams, includeString) {
300
309
  const query = `'Task ID'=\"${taskId}\" AND 'RootRequestID' = \"${rootRequestId}\"`;
301
- const returnValue = await queryTasks(config, query, globalScriptParams);
310
+ const returnValue = await queryTasks(config, query, globalScriptParams, includeString);
302
311
  const task = returnValue.data[0];
303
312
  return {data: task, included: returnValue.included};
304
313
  }
@@ -381,6 +390,13 @@ function getAttachmentFieldId(attachmentId) {
381
390
  return attachmentFieldId;
382
391
  }
383
392
 
393
+ async function lookupInstanceId(taskId) {
394
+ const result = await arquery.executeARQuery('TMS:Task', undefined, `'1' = "${taskId}"`, 'InstanceId')
395
+ if (result && result.data && Array.isArray(result.data)) {
396
+ return (result.data[0].InstanceId)
397
+ }
398
+ }
399
+
384
400
  module.exports = {
385
401
  getTaskByRootRequest,
386
402
  getTasks,
@@ -391,5 +407,6 @@ module.exports = {
391
407
  getTasksByRootRequest,
392
408
  createWorklog,
393
409
  setWorklogAttachment,
394
- getWorklogAttachment
410
+ getWorklogAttachment,
411
+ lookupInstanceId
395
412
  };
@@ -135,28 +135,45 @@ async function createTicketCIRelation(ticketConfig, ticketId, ciInstanceId, asso
135
135
  throw new Error(`CI ${ciInstanceId} not found.`);
136
136
  }
137
137
  const schemaName = await getSchemaName(ciData.ClassId);
138
- const ticketRelationFormData = {
138
+ let ticketRelationFormData = {
139
139
  "Form Name01" : schemaName,
140
- "Request ID01" : ciData.ReconciliationIdentity,
141
140
  "Request Type01" : 6000,
142
141
  "Form Name02" : ticketForm,
143
142
  "Association Type01": assocLookup.assocCode,
144
143
  "Request Description01": ciData.Name,
145
- "Request ID02": ticketId,
146
144
  "Lookup Keyword": ciData.ClassId
147
145
  };
148
146
  const assetRelationFormData = {
149
147
  "Form Name01" : ticketForm,
150
- "Request ID01" : ticketId,
151
148
  "Request Type01" : ticketType,
152
149
  "Form Name02" : schemaName,
153
150
  "Lookup Keyword01": ticketKeyword,
154
151
  "Association Type01": assocLookup.oppositeCode,
155
152
  "Request Description01": ticketSummary,
156
- "Request ID02": ciData.ReconciliationIdentity,
157
153
  "Lookup Keyword": ciData.ClassId,
158
- "Parent_DataSet_ID01": "BMC.ASSET"
154
+ "Parent_DataSet_ID01": "BMC.ASSET",
155
+ "Request ID01" : ticketId,
156
+ "Request ID02": ciData.ReconciliationIdentity
159
157
  };
158
+
159
+ if (ticketConfig.assocTicketType === 'Task') {
160
+ ticketRelationFormData = {
161
+ ...ticketRelationFormData,
162
+ ...{
163
+ "ID01" : ciData.ReconciliationIdentity,
164
+ "ID02": ticketId
165
+ }
166
+ }
167
+ } else {
168
+ ticketRelationFormData = {
169
+ ...ticketRelationFormData,
170
+ ...{
171
+ "Request ID01" : ciData.ReconciliationIdentity,
172
+ "Request ID02": ticketId,
173
+ }
174
+ }
175
+ }
176
+
160
177
  log.debug('Create CI Ticket Relation', ticketRelationFormData);
161
178
  //todo: implement impersonate
162
179
  const ticketRelation = await arquery.createEntry(ticketRelationForm, ticketRelationFormData);
@@ -208,7 +225,10 @@ async function createTicket2TicketRelation(ticketConfig, ticketId1, ticketConfig
208
225
  async function deleteTicketCIRelation(ticketConfig, ticketId, ciInstanceId) {
209
226
  const ticketRelationForm = ticketConfig.forms.assoc;
210
227
  const ciData = await getCIData(ciInstanceId);
211
- const ticketRelationQuery = `'Request ID02'= "${ticketId}" AND 'Request ID01' = "${ciData.ReconciliationIdentity}"`;
228
+ let ticketRelationQuery = `'Request ID02'= "${ticketId}" AND 'Request ID01' = "${ciData.ReconciliationIdentity}"`;
229
+ if (ticketConfig.assocTicketType === 'Task') {
230
+ ticketRelationQuery = `'ID02'= "${ticketId}" AND 'ID01' = "${ciData.ReconciliationIdentity}"`;
231
+ }
212
232
  const assetRelationQuery = `'Request ID02'= "${ciData.ReconciliationIdentity}" AND 'Request ID01' = "${ticketId}"`;
213
233
  log.debug('Delete Ticket2CI Relation', ticketRelationQuery);
214
234
  log.debug('Delete CI2Ticket Relation', assetRelationQuery);
@@ -483,7 +503,7 @@ function getTicketConfigByTicketType(ticketType) {
483
503
  function getCIData(instanceId) {
484
504
  log.debug('Search for CI', instanceId);
485
505
  //get only CIs with recon
486
- const query = `'InstanceId'="${instanceId}" AND 'ReconciliationIdentity' != $NULL$ AND 'ReconciliationIdentity' != "0"`;
506
+ const query = `('InstanceId'="${instanceId}" OR ('ReconciliationIdentity' = "${instanceId}" AND 'DatasetId' = "BMC.ASSET")) AND 'ReconciliationIdentity' != $NULL$ AND 'ReconciliationIdentity' != "0"`;
487
507
  const form = CONSTANTS.FORM_CMDB_CI_BASE;
488
508
  return utilCache.get(form + ':' + query, function () {
489
509
  return new Promise((resolve, reject) => {
package/docs/releases.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## API
4
4
 
5
+ ### 1.45.0 - 27.09.21
6
+ Add ciRelation Handling for Tasks
7
+
8
+ ### 1.44.0 - 27.09.21
9
+ Also allow CI RecondId for Ticket2CI Relations.
10
+
5
11
  ### 1.43.1 - 23.09.21
6
12
  Allow also "isPublic": "true" instead of "isPublic": true for Ticket Worklogs
7
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@manyos/smileconnect-api",
3
- "version": "1.43.1",
3
+ "version": "1.45.0",
4
4
  "description": "A proxy and abstraction layer for BMCs IT Service Management Suite",
5
5
  "main": "app.js",
6
6
  "scripts": {
@@ -4,6 +4,7 @@ const {body, validationResult, oneOf} = require('express-validator/check');
4
4
  const task = require('../controller/taskController');
5
5
  const eventLog = require('../controller/eventLogController');
6
6
  const CONSTANTS = require('../util/constants');
7
+ const ticketCIRelationController = require("../controller/ticketCIRelationController");
7
8
 
8
9
  module.exports = (function () {
9
10
  const taskRoutes = require('express').Router();
@@ -15,6 +16,7 @@ module.exports = (function () {
15
16
 
16
17
  taskRoutes.get('/', async function (req, res, next) {
17
18
  const id = req.parentId;
19
+ const includeString = req.query.include;
18
20
  //todo customize eventbase
19
21
  eventLog.setEventData(
20
22
  req,
@@ -24,7 +26,7 @@ module.exports = (function () {
24
26
  id
25
27
  );
26
28
 
27
- const result = await task.getTasksByRootRequest(req.user.config, id, req.parentForm, req.globalScriptParams);
29
+ const result = await task.getTasksByRootRequest(req.user.config, id, req.parentForm, req.globalScriptParams, includeString);
28
30
  req.includeObjectsList = result.included;
29
31
  req.result = {data:result.data || {}};
30
32
 
@@ -33,6 +35,8 @@ module.exports = (function () {
33
35
 
34
36
  taskRoutes.post('/', function (req, res, next) {
35
37
  const origData = JSON.parse(JSON.stringify(req.body));
38
+ const includeString = req.query.include;
39
+ const relations = req.body.data.relations;
36
40
  eventLog.setEventData(
37
41
  req,
38
42
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -56,10 +60,9 @@ module.exports = (function () {
56
60
  let taskResult = {};
57
61
  if (resultKeys.length > 1 || Array.isArray(req.body.data)) {
58
62
  taskResult = [];
59
- let x=0;
60
- for (x=0; x<resultKeys.length; x++) {
63
+ for (let x=0; x<resultKeys.length; x++) {
61
64
  const taskId = createResult[resultKeys[x]];
62
- const result = await task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams);
65
+ const result = await task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams, includeString);
63
66
  taskResult.push(result.data);
64
67
  }
65
68
  //todo fix included objects
@@ -68,7 +71,12 @@ module.exports = (function () {
68
71
  next();
69
72
  } else {
70
73
  const taskId = createResult['0'];
71
- task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams).then(function (result) {
74
+ if (relations && relations.ciRelations) {
75
+ const taskInstanceId = await task.lookupInstanceId(taskId)
76
+ log.debug('Add ciRelations to task', taskId, taskInstanceId, relations)
77
+ await ticketCIRelationController.updateRelations(req.ticketConfig, req.user.config, taskInstanceId, relations);
78
+ }
79
+ task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams, includeString).then(function (result) {
72
80
  req.includeObjectsList = result.included;
73
81
  req.result = {data:result.data || {}};
74
82
  next();
@@ -87,6 +95,7 @@ module.exports = (function () {
87
95
  const taskId = req.params.taskId;
88
96
  req.globalScriptParams.id = parentId
89
97
  req.globalScriptParams.id2 = taskId
98
+ const includeString = req.query.include;
90
99
  eventLog.setEventData(
91
100
  req,
92
101
  req.parentEventBase + '_' + CONSTANTS.EVENT_BASE_TAS,
@@ -97,16 +106,18 @@ module.exports = (function () {
97
106
  taskId
98
107
  );
99
108
 
100
- const result = await task.getTaskByRootRequest(req.user.config, parentId, taskId, req.globalScriptParams);
109
+ const result = await task.getTaskByRootRequest(req.user.config, parentId, taskId, req.globalScriptParams, includeString);
101
110
  req.includeObjectsList = result.included;
102
111
  req.result = {data:result.data || {}};
103
112
  next();
104
113
  });
105
114
 
106
- taskRoutes.put('/:taskId', function (req, res, next) {
115
+ taskRoutes.put('/:taskId', async function (req, res, next) {
107
116
  const taskId = req.params.taskId;
108
117
  req.globalScriptParams.id = req.parentId;
109
118
  req.globalScriptParams.id2 = taskId
119
+ const relations = req.body.data.relations;
120
+ const includeString = req.query.include;
110
121
  const origData = JSON.parse(JSON.stringify(req.body));
111
122
  eventLog.setEventData(
112
123
  req,
@@ -122,8 +133,13 @@ module.exports = (function () {
122
133
  req.errorStatus = 422;
123
134
  next(errors.array());
124
135
  } else {
125
- task.updateTask(req.user.config, taskId, req.body.data, req.globalScriptParams).then(function (updateResult) {
126
- task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams).then(function (result) {
136
+ task.updateTask(req.user.config, taskId, req.body.data, req.globalScriptParams).then(async function (updateResult) {
137
+ if (relations && relations.ciRelations) {
138
+ const taskInstanceId = await task.lookupInstanceId(taskId)
139
+ log.debug('Add ciRelations to task', taskId, taskInstanceId, relations)
140
+ await ticketCIRelationController.updateRelations(req.ticketConfig, req.user.config, taskInstanceId, relations);
141
+ }
142
+ task.getTaskByRootRequest(req.user.config, req.parentId, taskId, req.globalScriptParams, includeString).then(function (result) {
127
143
  req.includeObjectsList = result.included;
128
144
  req.result = {data:result.data || {}};
129
145
  next();
package/util/config.js CHANGED
@@ -387,10 +387,14 @@ const ticketConfig = {
387
387
  },
388
388
  "tasks": {
389
389
  "forms": {
390
- "template": CONSTANTS.FORM_TASK_TEMPLATE
390
+ "template": CONSTANTS.FORM_TASK_TEMPLATE,
391
+ "regular": CONSTANTS.FORM_TASK,
392
+ "assoc": CONSTANTS.FORM_TASK_ASSOC,
391
393
  },
392
394
  "requestTemplate": "taskTemplate",
393
- "templateRequestId": "Template ID"
395
+ "templateRequestId": "Template ID",
396
+ "assocTicketKeyword": "TMSTASK",
397
+ "assocTicketType": "Task",
394
398
  }
395
399
  };
396
400
 
package/util/constants.js CHANGED
@@ -14,6 +14,7 @@ module.exports = {
14
14
  FORM_TASK: "TMS:Task",
15
15
  FORM_TASK_WORKLOG: "TMS:WorkInfo",
16
16
  FORM_TASK_TEMPLATE: "TMS:TaskTemplate",
17
+ FORM_TASK_ASSOC: "TMS:Relationships",
17
18
  FORM_WORKORDER: "WOI:WorkOrder",
18
19
  FORM_WORKORDER_CREATE: "WOI:WorkOrderInterface_Create",
19
20
  FORM_WORKORDER_ASSOC: "WOI:Associations",