@plusscommunities/pluss-maintenance-aws 2.1.21 → 2.1.22

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.
@@ -1,6 +1,7 @@
1
1
  const getString = require("@plusscommunities/pluss-core-aws/db/strings/getString");
2
2
  const { getRowId, log } = require("@plusscommunities/pluss-core-aws/helper");
3
3
  const ArchibusStrategy = require("./archibus/ArchibusStrategy");
4
+ const SeeStuffStrategy = require("./seestuff/SeeStuffStrategy");
4
5
  const IntegrationStrategy = require("./IntegrationStrategy");
5
6
  const { values } = require("../values.config");
6
7
 
@@ -16,6 +17,8 @@ exports.getStrategy = async (site) => {
16
17
  switch (importConfig.Strategy) {
17
18
  case "Archibus":
18
19
  return new ArchibusStrategy(importConfig);
20
+ case "SeeStuff":
21
+ return new SeeStuffStrategy(importConfig);
19
22
  default:
20
23
  return new IntegrationStrategy();
21
24
  }
@@ -0,0 +1,293 @@
1
+ const axios = require("axios");
2
+ const moment = require("moment");
3
+ const _ = require("lodash");
4
+ const IntegrationStrategy = require("../IntegrationStrategy");
5
+ const { log, getRowId } = require("@plusscommunities/pluss-core-aws/helper");
6
+ const editRef = require("@plusscommunities/pluss-core-aws/db/common/editRef");
7
+ const updateRef = require("@plusscommunities/pluss-core-aws/db/common/updateRef");
8
+ const getRef = require("@plusscommunities/pluss-core-aws/db/common/getRef");
9
+ const indexQuery = require("@plusscommunities/pluss-core-aws/db/common/indexQuery");
10
+ const { values } = require("../../values.config");
11
+
12
+ class SeeStuffStrategy extends IntegrationStrategy {
13
+ constructor(config) {
14
+ super();
15
+ this.baseUrl = config.BaseUrl; // base URL for the API
16
+ this.apiKeyHeader = config.APIKeyHeader; // header to use for API key
17
+ this.apiKey = config.APIKey; // API key
18
+
19
+ const url = new URL(this.baseUrl);
20
+ this.host = url.host;
21
+
22
+ this.siteMap = config.SiteMap ?? {};
23
+ }
24
+
25
+ /**
26
+ * Gets the entity type for the integration
27
+ *
28
+ * @returns {String} The entity type for the integration
29
+ */
30
+ getEntityType = () => {
31
+ return `${values.serviceKey}_SeeStuff`;
32
+ };
33
+
34
+ /**
35
+ * Validates the integration
36
+ *
37
+ * @returns {Boolean} Whether the integration is valid
38
+ */
39
+ isValidIntegration = () => {
40
+ return true;
41
+ };
42
+
43
+ /**
44
+ * Gets the refresh interval for the SeeStuff system
45
+ *
46
+ * @returns {Number} The refresh interval in milliseconds
47
+ */
48
+ getRefreshInterval = () => {
49
+ return Number.MAX_SAFE_INTEGER; // should never refresh
50
+ };
51
+
52
+ /**
53
+ * Creates a request in the SeeStuff system
54
+ *
55
+ * @param {Object} request - Request definition on Pluss
56
+ * @param {Object} mockResponse - Mock response from SeeStuff to simulate response
57
+ * @returns {Boolean} Whether the request was created on SeeStuff
58
+ */
59
+ createRequest = async (request, mockResponse = null) => {
60
+ const logId = log("SeeStuff:CreateRequest", "Start", request);
61
+
62
+ try {
63
+ // Get user details for room/address and CRMID
64
+ let userRoom = request.room || "";
65
+ let crmResidentId = "";
66
+
67
+ // Map site to location code if available
68
+ const location = this.siteMap[request.site];
69
+ if (!location) {
70
+ log("SeeStuff:CreateRequest", "LocationNotFound", request.site, logId);
71
+ return false;
72
+ }
73
+
74
+ if (request.userID) {
75
+ try {
76
+ // Look up user from users table
77
+ const user = await getRef("users", "Id", request.userID);
78
+ log("SeeStuff:CreateRequest", "User", user, logId);
79
+
80
+ if (user) {
81
+ // Get user's address/room
82
+ if (user.unit) {
83
+ userRoom = user.unit;
84
+ }
85
+
86
+ // Get CRMID from user fields
87
+ try {
88
+ const crmIdField = await getRef(
89
+ "userfields",
90
+ "RowId",
91
+ getRowId(request.userID, "CRMID")
92
+ );
93
+ if (crmIdField && crmIdField.Value) {
94
+ crmResidentId = crmIdField.Value;
95
+ }
96
+ log("SeeStuff:CreateRequest", "CRMID", crmResidentId, logId);
97
+ } catch (fieldError) {
98
+ log(
99
+ "SeeStuff:CreateRequest",
100
+ "CRMIDLookupError",
101
+ fieldError,
102
+ logId
103
+ );
104
+ }
105
+ }
106
+ } catch (userError) {
107
+ log("SeeStuff:CreateRequest", "UserLookupError", userError, logId);
108
+ }
109
+ }
110
+
111
+ // Format description similar to Archibus
112
+ const description = `${request.title}${
113
+ _.isEmpty(request.description) ? "" : `\n\n${request.description}`
114
+ }${_.isEmpty(request.room) ? "" : `\n\nLocation: ${request.room}`}${
115
+ _.isEmpty(request.userName) ? "" : `\n\nName: ${request.userName}`
116
+ }${_.isEmpty(request.phone) ? "" : `\n\nPhone: ${request.phone}`}${
117
+ _.isEmpty(request.type) ? "" : `\n\nJob Type: ${request.type}`
118
+ }${
119
+ _.isEmpty(request.images)
120
+ ? ""
121
+ : `\n\nImages: ${request.images.join("\n")}`
122
+ }`;
123
+
124
+ // Format date_reported
125
+ const dateReported = moment().format("YYYY-MM-DD HH:mm:ss");
126
+
127
+ // Build payload
128
+ const data = {
129
+ externalId: request.id,
130
+ description: description,
131
+ priority: "P3",
132
+ location: location,
133
+ room: userRoom,
134
+ date_reported: dateReported,
135
+ crmResidentId: crmResidentId,
136
+ };
137
+
138
+ log("SeeStuff:CreateRequest", "Request", data, logId);
139
+
140
+ const response =
141
+ mockResponse ??
142
+ (await axios({
143
+ method: "POST",
144
+ url: `${this.baseUrl}/assetmgmt/servicerequests`,
145
+ timeout: 30000,
146
+ headers: {
147
+ [this.apiKeyHeader]: this.apiKey,
148
+ "Content-Type": "application/json",
149
+ Host: this.host,
150
+ },
151
+ data,
152
+ }));
153
+
154
+ log("SeeStuff:CreateRequest", "Response", response.data, logId);
155
+
156
+ return true;
157
+ } catch (e) {
158
+ log("SeeStuff:CreateRequest", "Error", e, logId);
159
+
160
+ // Add history entry for failed integration
161
+ try {
162
+ const failedJob = await getRef(
163
+ values.tableNameMaintenance,
164
+ "id",
165
+ request.id
166
+ );
167
+ if (!failedJob.history) failedJob.history = [];
168
+ failedJob.history.push({
169
+ timestamp: moment.utc().valueOf(),
170
+ action: "ExternalIDSetFailed",
171
+ user: {
172
+ displayName: "SeeStuff Integration",
173
+ id: "system",
174
+ },
175
+ });
176
+
177
+ await editRef(values.tableNameMaintenance, "id", request.id, {
178
+ history: failedJob.history,
179
+ });
180
+ } catch (historyError) {
181
+ log("SeeStuff:CreateRequest", "HistoryError", historyError, logId);
182
+ }
183
+ }
184
+ return false;
185
+ };
186
+
187
+ /**
188
+ * Fetches a request from the SeeStuff system
189
+ * Not implemented yet
190
+ *
191
+ * @param {String} externalId - Id of the request on SeeStuff
192
+ * @returns {Object} The request as it exists on SeeStuff
193
+ */
194
+ getRequest = async (externalId) => {
195
+ return null;
196
+ };
197
+
198
+ /**
199
+ * Refreshes a request from the SeeStuff system
200
+ * Not implemented yet
201
+ *
202
+ * @param {String} requestId - Id of the request on Pluss
203
+ * @param {String} externalId - Id of the request on SeeStuff
204
+ * @param {Object} trackedData - The set of fields tracked
205
+ * @returns {Boolean} Whether the request had any changes on SeeStuff
206
+ */
207
+ refreshFromSource = async (requestId, externalId, trackedData) => {
208
+ return false;
209
+ };
210
+
211
+ /**
212
+ * Get SeeStuff Id of the request
213
+ * Queries externalentities table to find the external ID
214
+ *
215
+ * @param {Object} request - Request definition on Pluss
216
+ * @returns {String} Id of the request on SeeStuff
217
+ */
218
+ getExternalId = async (request) => {
219
+ const logId = log("SeeStuff:GetExternalId", "Start", { Id: request.id });
220
+
221
+ // get external id
222
+ const externalEntityQuery = await indexQuery("externalentities", {
223
+ IndexName: "InternalIdIndex",
224
+ KeyConditionExpression:
225
+ "EntityType = :entityType AND InternalId = :internalId",
226
+ ExpressionAttributeValues: {
227
+ ":entityType": this.getEntityType(),
228
+ ":internalId": request.id,
229
+ },
230
+ });
231
+
232
+ log(
233
+ "SeeStuff:GetExternalId",
234
+ "ExternalLength",
235
+ externalEntityQuery.Items.length,
236
+ logId
237
+ );
238
+ if (_.isEmpty(externalEntityQuery.Items)) {
239
+ return null;
240
+ }
241
+
242
+ const externalId = externalEntityQuery.Items[0].ExternalId;
243
+ log("SeeStuff:GetExternalId", "ExternalId", externalId, logId);
244
+
245
+ return externalId;
246
+ };
247
+
248
+ /**
249
+ * Perform actions when a task's status has changed
250
+ * Not implemented yet
251
+ *
252
+ * @param {Object} request - Request definition on Pluss
253
+ * @returns {Boolean} Represents whether the actions were successful
254
+ */
255
+ onStatusChanged = async (request) => {
256
+ return true;
257
+ };
258
+
259
+ /**
260
+ * Perform actions when a comment has been added to a task
261
+ * Not implemented yet
262
+ *
263
+ * @param {Object} request - Request definition on Pluss
264
+ * @returns {Boolean} Represents whether the actions were successful
265
+ */
266
+ onCommentAdded = async (request) => {
267
+ return true;
268
+ };
269
+
270
+ /**
271
+ * Perform actions when a note has been added to a task
272
+ * Not implemented yet
273
+ *
274
+ * @param {Object} request - Request definition on Pluss
275
+ * @returns {Boolean} Represents whether the actions were successful
276
+ */
277
+ onNotesAdded = async (request) => {
278
+ return true;
279
+ };
280
+
281
+ /**
282
+ * Perform completion actions when a task is completed
283
+ * Not implemented yet
284
+ *
285
+ * @param {Object} request - Request definition on Pluss
286
+ * @returns {Boolean} Represents whether the actions were successful
287
+ */
288
+ onCompleteRequest = async (request) => {
289
+ return true;
290
+ };
291
+ }
292
+
293
+ module.exports = SeeStuffStrategy;
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-maintenance-aws",
3
- "version": "2.1.21",
3
+ "version": "2.1.22",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plusscommunities/pluss-maintenance-aws",
3
- "version": "2.1.21",
3
+ "version": "2.1.22",
4
4
  "description": "Extension package to enable maintenance on Pluss Communities Platform",
5
5
  "scripts": {
6
6
  "gc": "node ../../tools/gc ./",