stand_socotra_policy_transformer 3.0.1 → 3.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stand_socotra_policy_transformer",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Stands internal javascript module for executing underwriting",
5
5
  "main": "dist/stand_underwriter.js",
6
6
  "scripts": {
@@ -1,4 +1,4 @@
1
- const {SocotraEntry} = require("./socotra_structure_helper");
1
+ const {SocotraEntry, SocotraGroupEntry} = require("./socotra_structure_helper");
2
2
  class SocotraPayloadConverter {
3
3
  constructor(entries) {
4
4
  this.entries = entries
@@ -79,7 +79,11 @@ class SocotraPayloadConverter {
79
79
  let payload = SocotraEntry.socotra_create_update_template(dwelling_exposure_locator)
80
80
  this.entries.forEach(entry => {
81
81
  if (Object.keys(retool_payload).includes(entry.retool_id)) {
82
- entry.socotra_update(retool_payload, payload)
82
+ if(entry instanceof SocotraGroupEntry){
83
+ entry.socotra_update(retool_payload, payload, old_payload)
84
+ } else{
85
+ entry.socotra_update(retool_payload, payload)
86
+ }
83
87
  }
84
88
  })
85
89
 
@@ -133,4 +137,4 @@ class SocotraPayloadConverter {
133
137
  }
134
138
  }
135
139
 
136
- module.exports = {SocotraPayloadConverter}
140
+ module.exports = {SocotraPayloadConverter}
@@ -3,6 +3,7 @@ const { DateTime } = require('luxon');
3
3
  const socotra_locations = Object.freeze([
4
4
  'policy.fields',
5
5
  'policy.fields.array',
6
+ 'policy.fields.group',
6
7
  'exposure.dwelling.fields',
7
8
  'policy.group',
8
9
  'policy',
@@ -236,6 +237,246 @@ class SocotraEntry {
236
237
  }
237
238
  }
238
239
 
240
+ class SocotraGroupEntry extends SocotraEntry {
241
+ constructor(retool_id, socotra_id, socotra_location, socotra_schema = {}, retool_schema = {}) {
242
+ super(retool_id, socotra_id, socotra_location);
243
+ this.socotra_schema = socotra_schema;
244
+ this.retool_schema = retool_schema;
245
+ }
246
+
247
+ socotra_create_response(json_payload, socotra_response) {
248
+ // Handle nested data structure
249
+ const path = this.retool_id.split('.');
250
+ let data = json_payload;
251
+
252
+ // Navigate through the nested structure
253
+ for (const key of path) {
254
+ if (data && data[key] !== undefined) {
255
+ data = data[key];
256
+ } else {
257
+ // If the path doesn't exist, return
258
+ return;
259
+ }
260
+ }
261
+
262
+ // If data is an array, process each item
263
+ if (Array.isArray(data)) {
264
+ // Initialize fieldGroups if it doesn't exist
265
+ if (!socotra_response.fieldGroups) {
266
+ socotra_response.fieldGroups = [];
267
+ }
268
+
269
+ // Transform each item according to the schemas
270
+ const transformedData = data.map(item => {
271
+ const fieldValues = {};
272
+
273
+ // Map fields from retool schema to socotra schema
274
+ for (const [socotraField, retoolField] of Object.entries(this.socotra_schema)) {
275
+ // If the retool field starts with ':', it's a direct mapping
276
+ if (retoolField.startsWith(':')) {
277
+ const actualRetoolField = retoolField.substring(1);
278
+ if (item[actualRetoolField] !== undefined) {
279
+ fieldValues[socotraField] = item[actualRetoolField];
280
+ }
281
+ }
282
+ }
283
+
284
+ return {
285
+ fieldName: this.socotra_id,
286
+ fieldValues: fieldValues
287
+ };
288
+ });
289
+
290
+ // Add the transformed data to the response
291
+ socotra_response.fieldGroups = transformedData;
292
+ }
293
+ }
294
+
295
+ retool_response(socotra_payload, retool_response) {
296
+ // Handle group entities for Socotra to Retool transformation
297
+ if (this.socotra_location === 'policy.fields.group') {
298
+ // Get the field values from the Socotra payload
299
+ const fieldValues = socotra_payload.characteristics.fieldValues;
300
+ const fieldGroupsByLocator = socotra_payload.characteristics.fieldGroupsByLocator;
301
+
302
+ // Check if the field exists and has values
303
+ if (fieldValues && fieldValues[this.socotra_id] && fieldGroupsByLocator) {
304
+ // Initialize the nested structure in the retool response
305
+ const path = this.retool_id.split('.');
306
+ let current = retool_response;
307
+
308
+ // Create the nested structure
309
+ for (let i = 0; i < path.length - 1; i++) {
310
+ if (!current[path[i]]) {
311
+ current[path[i]] = {};
312
+ }
313
+ current = current[path[i]];
314
+ }
315
+
316
+ // Get the locators for the group entities
317
+ const locators = fieldValues[this.socotra_id];
318
+
319
+ // Initialize the array for the group entities
320
+ current[path[path.length - 1]] = [];
321
+
322
+ // Transform each group entity
323
+ for (const locator of locators) {
324
+ if (fieldGroupsByLocator[locator]) {
325
+ const groupData = fieldGroupsByLocator[locator];
326
+ const retoolItem = {};
327
+
328
+ // Map fields from socotra schema to retool schema
329
+ for (const [socotraField, retoolField] of Object.entries(this.retool_schema)) {
330
+ // If the retool field starts with ':', it's a direct mapping
331
+ if (retoolField.startsWith(':')) {
332
+ const actualRetoolField = retoolField.substring(1);
333
+ if (groupData[socotraField] && groupData[socotraField][0] !== undefined) {
334
+ retoolItem[actualRetoolField] = groupData[socotraField][0];
335
+ }
336
+ }
337
+ }
338
+
339
+ // Add the socotra field locator
340
+ retoolItem.socotra_field_locator = locator;
341
+
342
+ // Add the transformed item to the array
343
+ current[path[path.length - 1]].push(retoolItem);
344
+ }
345
+ }
346
+ }
347
+ return;
348
+ }
349
+
350
+ // Fall back to the parent class implementation for non-group fields
351
+ return super.retool_response(socotra_payload, retool_response);
352
+ }
353
+
354
+ // Helper function to navigate through nested structure
355
+ _navigateNestedStructure(obj, path) {
356
+ let result = obj;
357
+ for (const key of path) {
358
+ if (result && result[key] !== undefined) {
359
+ result = result[key];
360
+ } else {
361
+ // If the path doesn't exist, return empty array
362
+ return [];
363
+ }
364
+ }
365
+ return result;
366
+ }
367
+
368
+ // Helper function to create field values from an item
369
+ _createFieldValues(item) {
370
+ const fieldValues = {};
239
371
 
372
+ // Map fields from retool schema to socotra schema
373
+ for (const [socotraField, retoolField] of Object.entries(this.socotra_schema)) {
374
+ // If the retool field starts with ':', it's a direct mapping
375
+ if (retoolField.startsWith(':')) {
376
+ const actualRetoolField = retoolField.substring(1);
377
+ if (item[actualRetoolField] !== undefined) {
378
+ fieldValues[socotraField] = item[actualRetoolField];
379
+ }
380
+ }
381
+ }
382
+
383
+ return fieldValues;
384
+ }
385
+
386
+ // Helper function to add an item to addFieldGroups
387
+ _addItemToFieldGroups(item, socotra_response) {
388
+ // Skip explicit remove operations
389
+ if (item.remove === true) return;
390
+
391
+ // Transform the item for add
392
+ const fieldValues = this._createFieldValues(item);
393
+
394
+ // Add to addFieldGroups
395
+ socotra_response.addFieldGroups.push({
396
+ fieldName: this.socotra_id,
397
+ fieldValues: fieldValues
398
+ });
399
+ }
400
+
401
+ // Helper function to process explicit remove operations
402
+ _processRemoveOperations(data, socotra_response) {
403
+ for (const item of data) {
404
+ if (item.remove === true && item.locator) {
405
+ // Add to removeFieldGroups
406
+ socotra_response.removeFieldGroups.push(item.locator);
407
+ }
408
+ }
409
+ }
410
+
411
+ // Helper function to create a comparison key for an item
412
+ _createComparisonKey(item) {
413
+ const itemCopy = { ...item };
414
+ delete itemCopy.socotra_field_locator;
415
+ return JSON.stringify(itemCopy);
416
+ }
417
+
418
+ socotra_update(retool_payload, socotra_response, old_payload) {
419
+ // Handle nested data structure
420
+ const path = this.retool_id.split('.');
421
+ let data = this._navigateNestedStructure(retool_payload, path);
422
+ let oldData = old_payload ? this._navigateNestedStructure(old_payload, path) : [];
423
+
424
+ // Initialize arrays for different operations if they don't exist
425
+ if (!socotra_response.addFieldGroups) {
426
+ socotra_response.addFieldGroups = [];
427
+ }
428
+ if (!socotra_response.removeFieldGroups) {
429
+ socotra_response.removeFieldGroups = [];
430
+ }
431
+
432
+ // Process explicit remove operations first
433
+ this._processRemoveOperations(data, socotra_response);
434
+
435
+ // If old_payload is provided, compare new and old data
436
+ if (old_payload && Array.isArray(oldData) && Array.isArray(data)) {
437
+ // Create a map of new items for easier comparison
438
+ const newItemsMap = new Map();
439
+ for (const item of data) {
440
+ // Create a key for comparison (excluding socotra_field_locator)
441
+ const key = this._createComparisonKey(item);
442
+ newItemsMap.set(key, item);
443
+ }
444
+
445
+ // Check old items
446
+ for (const oldItem of oldData) {
447
+ // Create a key for comparison (excluding socotra_field_locator)
448
+ const key = this._createComparisonKey(oldItem);
449
+
450
+ // If the item exists in both old and new, it's a match - skip it
451
+ if (newItemsMap.has(key)) {
452
+ newItemsMap.delete(key);
453
+ }
454
+ // If the item only exists in old, remove it
455
+ else if (oldItem.socotra_field_locator) {
456
+ socotra_response.removeFieldGroups.push(oldItem.socotra_field_locator);
457
+ }
458
+ }
459
+
460
+ // Add items that only exist in new
461
+ for (const item of newItemsMap.values()) {
462
+ this._addItemToFieldGroups(item, socotra_response);
463
+ }
464
+ }
465
+ // If no old_payload, process as before
466
+ else {
467
+ for (const item of data) {
468
+ this._addItemToFieldGroups(item, socotra_response);
469
+ }
470
+ }
471
+
472
+ // Remove empty arrays
473
+ if (socotra_response.addFieldGroups.length === 0) {
474
+ delete socotra_response.addFieldGroups;
475
+ }
476
+ if (socotra_response.removeFieldGroups.length === 0) {
477
+ delete socotra_response.removeFieldGroups;
478
+ }
479
+ }
480
+ }
240
481
 
241
- module.exports = {SocotraEntry}
482
+ module.exports = {SocotraEntry, SocotraGroupEntry}
@@ -1,4 +1,4 @@
1
- const {SocotraEntry} = require("../socotra_structure_helper");
1
+ const {SocotraEntry, SocotraGroupEntry} = require("../socotra_structure_helper");
2
2
 
3
3
  function solar_panel_functions() {
4
4
  let to_socotra_map = {0: "No", "1+": "Yes"}
@@ -204,8 +204,44 @@ entries_v3 = [
204
204
 
205
205
  ]
206
206
 
207
-
208
-
209
-
210
-
211
- module.exports = {entries_v3}
207
+ // Define schemas for Groups
208
+ const additional_insured_socotra_schema = {
209
+ type: ":type",
210
+ name: ":name",
211
+ street_address: ":street_address",
212
+ street_address2: ":street_address2",
213
+ city: ":city",
214
+ state: ":state",
215
+ zip: ":zip",
216
+ description: ":description",
217
+ loan_number: ":loan_number"
218
+ };
219
+
220
+ const additional_insured_retool_schema = {
221
+ zip: ":zip",
222
+ street_address: ":street_address",
223
+ loan_number: ":loan_number",
224
+ city: ":city",
225
+ street_address2: ":street_address2",
226
+ state: ":state",
227
+ type: ":type",
228
+ name: ":name",
229
+ description: ":description"
230
+ };
231
+
232
+ // Add additional insured to entries_v3
233
+ entries_v3.push(
234
+ new SocotraGroupEntry(
235
+ "additional_insured_data.additionalInterest",
236
+ "additional_insured",
237
+ "policy.fields.group",
238
+ additional_insured_socotra_schema,
239
+ additional_insured_retool_schema
240
+ )
241
+ );
242
+
243
+
244
+
245
+
246
+
247
+ module.exports = {entries_v3}