tango-app-api-trax 3.7.77 → 3.7.80

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": "tango-app-api-trax",
3
- "version": "3.7.77",
3
+ "version": "3.7.80",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,19 +1,137 @@
1
- import { logger, signedUrl, sendMessageToQueue } from 'tango-app-api-middleware';
1
+ import { logger, signedUrl, sendMessageToQueue, fileUpload } from 'tango-app-api-middleware';
2
2
  import dayjs from 'dayjs';
3
3
  import * as downloadService from '../services/download.services.js';
4
4
  import * as processedchecklistService from '../services/processedchecklist.services.js';
5
5
  import * as processedTaskService from '../services/processedTaskList.service.js';
6
6
  import * as taskConfigService from '../services/taskConfig.service.js';
7
7
  import * as checklistService from '../services/checklist.service.js';
8
+ import { buildVisitChecklistTemplateData, generateVisitChecklistPDF } from '../utils/visitChecklistPdf.utils.js';
9
+ import archiver from 'archiver';
8
10
  // import * as processedTaskconfigService from '../services/processedTaskConfig.service.js';
9
11
  import * as processedcheklistconfigService from '../services/processedchecklistconfig.services.js';
10
12
  import * as clientService from '../services/clients.services.js';
11
13
  import * as storeService from '../services/store.service.js';
14
+ import * as processedchecklist from '../services/processedchecklist.services.js';
15
+ import * as processedTask from '../services/processedTaskList.service.js';
12
16
 
13
17
 
14
18
  import utc from 'dayjs/plugin/utc.js';
15
19
  dayjs.extend( utc );
16
20
  import mongoose from 'mongoose';
21
+ import { PassThrough } from 'stream';
22
+
23
+ function sanitizeFilenamePart( value, fallback = 'checklist' ) {
24
+ const cleaned = String( value || fallback )
25
+ .replace( /[<>:"/\\|?*\x00-\x1F]/g, '_' )
26
+ .replace( /\s+/g, ' ' )
27
+ .trim();
28
+
29
+ return cleaned || fallback;
30
+ }
31
+
32
+ async function getBrandInfo( clientId ) {
33
+ const brandInfo = { clientName: 'lenskart', brandLogo: '' };
34
+
35
+ if ( !clientId ) return brandInfo;
36
+
37
+ const clientDetails = await clientService.findOne( { clientId }, { clientName: 1, profileDetails: 1 } );
38
+ if ( !clientDetails?.clientName ) return brandInfo;
39
+
40
+ if ( clientDetails?.profileDetails?.logo ) {
41
+ const bucketpath = clientId + '/logo';
42
+ const params = {
43
+ Bucket: JSON.parse( process.env.BUCKET )?.assets,
44
+ file_path: `${bucketpath}/${clientDetails?.profileDetails?.logo}`,
45
+ };
46
+ const brandImage = await signedUrl( params );
47
+ if ( brandImage ) {
48
+ brandInfo.brandLogo = brandImage;
49
+ }
50
+ }
51
+
52
+ brandInfo.clientName = clientDetails.clientName;
53
+ return brandInfo;
54
+ }
55
+
56
+ async function streamChecklistZip( res, checklistList, brandInfo, zipBaseName ) {
57
+ const zipName = `${sanitizeFilenamePart( zipBaseName, 'visit-checklists' )}_${dayjs().format( 'YYYY-MM-DD_HH-mm' )}.zip`;
58
+
59
+ res.status( 200 );
60
+ res.setHeader( 'Content-Type', 'application/zip' );
61
+ res.setHeader( 'Content-Disposition', `attachment; filename="${zipName.replace( /"/g, '\\"' )}"` );
62
+ res.setHeader( 'Cache-Control', 'private, no-cache' );
63
+
64
+ const archive = archiver( 'zip', { zlib: { level: 9 } } );
65
+
66
+ archive.on( 'error', ( err ) => {
67
+ throw err;
68
+ } );
69
+
70
+ archive.pipe( res );
71
+
72
+ for ( const checklistDetails of checklistList ) {
73
+ const templateData = buildVisitChecklistTemplateData( checklistDetails, brandInfo );
74
+ const pdfBuffer = await generateVisitChecklistPDF( templateData );
75
+ const pdfName = `${sanitizeFilenamePart( checklistDetails.storeName || checklistDetails.store_id || checklistDetails._id, 'store' )}_${sanitizeFilenamePart( checklistDetails.checkListName || 'Visit Checklist' )}.pdf`;
76
+ archive.append( Buffer.isBuffer( pdfBuffer ) ? pdfBuffer : Buffer.from( pdfBuffer ), { name: pdfName } );
77
+ }
78
+
79
+ await archive.finalize();
80
+ }
81
+
82
+ async function createChecklistZipBuffer( checklistList, brandInfo ) {
83
+ const output = new PassThrough();
84
+ const chunks = [];
85
+
86
+ output.on( 'data', ( chunk ) => {
87
+ chunks.push( chunk );
88
+ } );
89
+
90
+ const archive = archiver( 'zip', { zlib: { level: 9 } } );
91
+ archive.on( 'error', ( err ) => {
92
+ throw err;
93
+ } );
94
+ archive.pipe( output );
95
+
96
+ for ( const checklistDetails of checklistList ) {
97
+ const templateData = buildVisitChecklistTemplateData( checklistDetails, brandInfo );
98
+ const pdfBuffer = await generateVisitChecklistPDF( templateData );
99
+ const pdfName = `${sanitizeFilenamePart( checklistDetails.storeName || checklistDetails.store_id || checklistDetails._id, 'store' )}_${sanitizeFilenamePart( checklistDetails.checkListName || 'Visit Checklist' )}.pdf`;
100
+ archive.append( Buffer.isBuffer( pdfBuffer ) ? pdfBuffer : Buffer.from( pdfBuffer ), { name: pdfName } );
101
+ }
102
+
103
+ await archive.finalize();
104
+
105
+ return await new Promise( ( resolve, reject ) => {
106
+ output.on( 'end', () => resolve( Buffer.concat( chunks ) ) );
107
+ output.on( 'error', reject );
108
+ archive.on( 'error', reject );
109
+ } );
110
+ }
111
+
112
+ async function uploadGeneratedFile( { sourceId, fileName, body, contentType } ) {
113
+ const bucket = JSON.parse( process.env.BUCKET );
114
+ const folderDate = dayjs().format( 'YYYY-MM-DD' );
115
+ const folderSource = sanitizeFilenamePart( sourceId || 'adhoc-download', 'adhoc-download' );
116
+ const keyPrefix = `downloads/${folderSource}/${folderDate}/`;
117
+
118
+ const uploadResult = await fileUpload( {
119
+ fileName,
120
+ Key: keyPrefix,
121
+ Bucket: bucket.sop,
122
+ body,
123
+ ContentType: contentType,
124
+ } );
125
+
126
+ if ( uploadResult?.errors?.length ) {
127
+ throw new Error( uploadResult.errors[0].message || 'File upload failed' );
128
+ }
129
+
130
+ return {
131
+ bucketName: bucket.sop,
132
+ key: uploadResult.Key,
133
+ };
134
+ }
17
135
 
18
136
  export const downloadInsert = async ( req, res ) => {
19
137
  try {
@@ -173,6 +291,262 @@ export const downloadInsert = async ( req, res ) => {
173
291
  return res.sendError( e, 500 );
174
292
  }
175
293
  };
294
+
295
+ export const downloadInsertNew = async ( req, res ) => {
296
+ try {
297
+ let requestData = req.body;
298
+ let name;
299
+ let fileType = requestData?.fileType || 'pdfzip';
300
+ let checklistDetails = null;
301
+ let checklistDetailsList = [];
302
+
303
+ if ( requestData.searchValue && requestData.searchValue != '' ) {
304
+ let storeList = requestData.searchValue.split( ',' ).map( ( item ) => item.trim().toLowerCase() );
305
+ let getStoreIDQuery = [];
306
+ if ( storeList.length > 0 ) {
307
+ getStoreIDQuery.push( { $project: { storeName: 1, storeId: 1 } } );
308
+ getStoreIDQuery.push( { $addFields: { store: { $toLower: '$storeName' } } } );
309
+ getStoreIDQuery.push( { $match: { store: { $in: storeList } } } );
310
+ getStoreIDQuery.push( { $group: { _id: null, storeId: { $push: '$storeId' } } } );
311
+ getStoreIDQuery.push( { $project: { storeId: 1, _id: 0 } } );
312
+ }
313
+ let getStoreId = await storeService.aggregate( getStoreIDQuery );
314
+ if ( getStoreId.length > 0 ) {
315
+ if ( getStoreId[0].storeId && getStoreId[0].storeId.length > 0 ) {
316
+ requestData.storeIds = getStoreId[0].storeId;
317
+ }
318
+ }
319
+ }
320
+
321
+ const sourceId = requestData.sourceCheckList_id;
322
+ // Gallery / download API sends insertType; legacy may send type — both must be honored
323
+ const isChecklistDownload = requestData.insertType === 'checklist' || requestData.type === 'checklist';
324
+ if ( sourceId && mongoose.isValidObjectId( sourceId ) ) {
325
+ const sourceOid = new mongoose.Types.ObjectId( sourceId );
326
+ const submitMatch = { sourceCheckList_id: sourceOid, checklistStatus: 'submit' };
327
+ if ( Array.isArray( requestData.storeIds ) && requestData.storeIds.length > 0 ) {
328
+ submitMatch.store_id = { $in: requestData.storeIds };
329
+ }
330
+ if ( Array.isArray( requestData.checklistId ) && requestData.checklistId.length > 0 ) {
331
+ submitMatch._id = {
332
+ $in: requestData.checklistId
333
+ .filter( ( id ) => mongoose.isValidObjectId( id ) )
334
+ .map( ( id ) => new mongoose.Types.ObjectId( id ) ),
335
+ };
336
+ }
337
+ if ( isChecklistDownload ) {
338
+ checklistDetailsList = await processedchecklist.find( submitMatch );
339
+ } else {
340
+ checklistDetailsList = await processedTask.find( submitMatch );
341
+ }
342
+ checklistDetails = checklistDetailsList[0] || null;
343
+ }
344
+
345
+ if ( requestData.fileType === 'pdf' ) {
346
+ if ( !checklistDetails && !( Array.isArray( checklistDetailsList ) && checklistDetailsList.length ) ) {
347
+ return res.sendError( 'Checklist not found', 400 );
348
+ }
349
+ try {
350
+ const pdfChecklistList = Array.isArray( checklistDetailsList ) && checklistDetailsList.length ? checklistDetailsList : [ checklistDetails ];
351
+ const brandInfo = await getBrandInfo( checklistDetails?.client_id || pdfChecklistList[0]?.client_id );
352
+ const uploadSourceId = sourceId || checklistDetails?.sourceCheckList_id || checklistDetails?._id;
353
+
354
+ if ( sourceId && pdfChecklistList.length ) {
355
+ const zipBaseName = checklistDetails?.checkListName || requestData.checklistName || 'visit-checklists';
356
+ const zipBuffer = await createChecklistZipBuffer( pdfChecklistList, brandInfo );
357
+ const zipName = `${sanitizeFilenamePart( zipBaseName, 'visit-checklists' )}_${dayjs().format( 'YYYY-MM-DD_HH-mm' )}.zip`;
358
+ const uploadResult = await uploadGeneratedFile( {
359
+ sourceId: uploadSourceId,
360
+ fileName: zipName,
361
+ body: zipBuffer,
362
+ contentType: 'application/zip',
363
+ } );
364
+
365
+ return res.sendSuccess( {
366
+ key: uploadResult.key,
367
+ bucketName: uploadResult.bucketName,
368
+ fileType: 'zip',
369
+ totalFiles: pdfChecklistList.length,
370
+ } );
371
+ }
372
+
373
+ const templateData = buildVisitChecklistTemplateData( checklistDetails, brandInfo );
374
+ const pdfBuffer = await generateVisitChecklistPDF( templateData );
375
+ const filename = `${checklistDetails.checkListName}_${dayjs().format( 'YYYY-MM-DD_HH-mm' )}.pdf`;
376
+ const uploadResult = await uploadGeneratedFile( {
377
+ sourceId: uploadSourceId,
378
+ fileName: filename,
379
+ body: Buffer.isBuffer( pdfBuffer ) ? pdfBuffer : Buffer.from( pdfBuffer ),
380
+ contentType: 'application/pdf',
381
+ } );
382
+
383
+ return res.sendSuccess( {
384
+ key: uploadResult.key,
385
+ bucketName: uploadResult.bucketName,
386
+ fileType: 'pdf',
387
+ totalFiles: 1,
388
+ } );
389
+ } catch ( pdfErr ) {
390
+ logger.error( { functionName: 'downloadInsert', error: pdfErr, message: 'PDF generation failed' } );
391
+ return res.sendError( 'PDF generation failed', 500 );
392
+ }
393
+ }
394
+
395
+ if ( requestData.searchValue && requestData.searchValue != '' ) {
396
+ let storeList = requestData.searchValue.split( ',' ).map( ( item ) => item.trim().toLowerCase() );
397
+ let getStoreIDQuery = [];
398
+ if ( storeList.length > 0 ) {
399
+ getStoreIDQuery.push( { $project: { storeName: 1, storeId: 1 } } );
400
+ getStoreIDQuery.push( { $addFields: { store: { $toLower: '$storeName' } } } );
401
+ getStoreIDQuery.push( { $match: { store: { $in: storeList } } } );
402
+ getStoreIDQuery.push( { $group: { _id: null, storeId: { $push: '$storeId' } } } );
403
+ getStoreIDQuery.push( { $project: { storeId: 1, _id: 0 } } );
404
+ }
405
+ let getStoreId = await storeService.aggregate( getStoreIDQuery );
406
+ if ( getStoreId.length > 0 ) {
407
+ if ( getStoreId[0].storeId && getStoreId[0].storeId.length > 0 ) {
408
+ requestData.storeIds = getStoreId[0].storeId;
409
+ }
410
+ }
411
+ }
412
+ // console.log( requestData );
413
+ // // No Need to Check
414
+ // let fromDate = new Date( requestData.fromDate );
415
+ // let toDate = new Date( requestData.toDate );
416
+ // let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
417
+ // toDate = new Date( toDate.getTime() - userTimezoneOffset );
418
+ // toDate.setUTCHours( 23, 59, 59, 59 );
419
+ // if ( requestData.sourceCheckList_id && requestData.sourceCheckList_id != '' ) {
420
+ // let getChecklistQuery = [];
421
+ // getChecklistQuery.push( { $project: { sourceCheckList_id: 1, date_iso: 1, store_id: 1, userEmail: 1, checklistStatus: 1, redoStatus: 1 } } );
422
+
423
+ // if ( requestData.filtertype ==='Clusters' ) {
424
+ // getChecklistQuery.push( {
425
+ // $match: {
426
+ // $and: [
427
+ // { sourceCheckList_id: new mongoose.Types.ObjectId( requestData.sourceCheckList_id ) },
428
+ // { date_iso: { $gte: fromDate, $lte: toDate } },
429
+ // { store_id: { $in: requestData.storeIds } },
430
+ // ],
431
+ // $or: [
432
+ // { checklistStatus: 'submit' },
433
+ // { redoStatus: true },
434
+ // ],
435
+ // },
436
+ // } );
437
+ // } else {
438
+ // // console.log( requestData );
439
+ // getChecklistQuery.push( {
440
+ // $match: {
441
+ // $and: [
442
+ // { sourceCheckList_id: new mongoose.Types.ObjectId( requestData.sourceCheckList_id ) },
443
+ // { date_iso: { $gte: fromDate, $lte: toDate } },
444
+ // { userEmail: { $in: requestData.userEmailList } },
445
+ // ],
446
+ // $or: [
447
+ // { checklistStatus: 'submit' },
448
+ // { redoStatus: true },
449
+ // ],
450
+ // },
451
+ // } );
452
+ // }
453
+ // // getChecklistQuery.push( { $count: 'totalCount' } );
454
+
455
+ // let getChecklistCount = await processedchecklistService.aggregate( getChecklistQuery );
456
+ // // console.log( getChecklistCount );
457
+ // if ( requestData.insertType === 'task' ) {
458
+ // getChecklistCount = await processedTaskService.aggregate( getChecklistQuery );
459
+ // }
460
+ // if ( getChecklistCount && getChecklistCount.length > 0 ) {
461
+ // // console.log( 'if' );
462
+ // // console.log( 'getChecklistCountgetChecklistCount[0].totalCount =>', getChecklistCount[0]?.totalCount );
463
+ // } else {
464
+ // return res.sendError( { error: 'No Data Found' }, 400 );
465
+ // }
466
+ // }
467
+
468
+ if ( requestData.fileType == 'pdf' ) {
469
+ if ( requestData?.sourceCheckList_id && requestData?.sourceCheckList_id != '' ) {
470
+ fileType = 'pdfzip';
471
+ }
472
+ if ( requestData?.checklistId && requestData?.checklistId.length > 1 ) {
473
+ fileType = 'pdfzip';
474
+ }
475
+ }
476
+
477
+
478
+ if ( requestData.checklistName != '' ) {
479
+ name = requestData.checklistName + '_' + dayjs( requestData.fromDate ).format( 'DD/MM/YYYY' );
480
+ if ( requestData?.toDate ) {
481
+ name = name + '-' + dayjs( requestData?.toDate ).format( 'DD/MM/YYYY' );
482
+ }
483
+ let regexName = new RegExp( `^${name.split( '(' )[0]} \\(.*\\)$`, 'i' );
484
+ let type = requestData.fileType || 'pdfzip';
485
+ let downloadDetails = await downloadService.getCount( { $and: [ { $or: [ { name: { $regex: regexName } }, { name: name } ] }, { fileType: type } ] } );
486
+ if ( downloadDetails ) {
487
+ name = name + ' (' + downloadDetails + ')';
488
+ }
489
+ } else {
490
+ name = requestData?.checklistName;
491
+ }
492
+
493
+ name = name + '-' + requestData.fileType;
494
+ let insertData = {
495
+ 'date_string': requestData.fromDate || '',
496
+ 'sourceCheckList_id': requestData?.sourceCheckList_id || '',
497
+ 'checklistIdList': requestData?.checklistId || [],
498
+ 'status': 'inprogress',
499
+ 'client_id': requestData.clientId || '',
500
+ 'date_iso': new Date( requestData.fromDate ) || '',
501
+ 'createdBy': req.user._id || '',
502
+ 'name': name,
503
+ 'fileType': fileType,
504
+ 'storeIds': requestData.storeIds || [],
505
+ 'questions': requestData.questions || [],
506
+ 'fromDate': requestData.fromDate || '',
507
+ 'toDate': requestData.toDate || '',
508
+ 'previewType': requestData.previewType || '',
509
+ 'viewFlag': requestData.viewFlag || false,
510
+ 'userEmail': req.user.email || '',
511
+ 'createdBy': req.user._id || '',
512
+ 'downloadInsertFrom': requestData.downloadInsertFrom || '',
513
+ 'answerType': requestData.answerType || '',
514
+ 'searchValue': requestData.searchValue || '',
515
+ 'insertType': requestData.insertType || '',
516
+ 'viewRedo': requestData.viewRedo || false,
517
+ 'userEmailList': requestData.userEmailList || [],
518
+ 'filtertype': requestData.filtertype || 'Clusters',
519
+ 'checkListType': requestData.checkListType,
520
+ };
521
+ console.log( 'downloadInsert insertData =>', insertData );
522
+ let resultData = await downloadService.insert( insertData );
523
+ if ( resultData ) {
524
+ let sqsMessageRequestData = {
525
+ 'zipId': resultData._id,
526
+ 'fileType': fileType || 'zip',
527
+ 'storeId': requestData.storeIds || [],
528
+ };
529
+ if ( fileType === 'csv' || fileType === 'pdf' || fileType === 'csvzip' || fileType === 'pdfzip' || fileType === 'zipfiles' ) {
530
+ const msg = await sendMessageToQueue( `${JSON.parse( process.env.SQS ).url}${JSON.parse( process.env.SQS ).new_sqs_sop}`, JSON.stringify( sqsMessageRequestData ) );
531
+ console.log( 'Send SQS Message CSV/PDF=>', msg );
532
+ }
533
+
534
+ if ( fileType === 'ppt' || fileType === 'pptzip' ) {
535
+ const msg = await sendMessageToQueue( `${JSON.parse( process.env.SQS ).url}${JSON.parse( process.env.SQS ).new_sqs_sop_ppt}`, JSON.stringify( sqsMessageRequestData ) );
536
+ console.log( 'Send SQS Message PPT=>', msg );
537
+ }
538
+
539
+ res.sendSuccess( 'Success' );
540
+ } else {
541
+ return res.sendError( 'something went wrong, please try again', 500 );
542
+ }
543
+ } catch ( e ) {
544
+ console.log( 'insertdownloadRequest =>', e );
545
+ return res.sendError( e, 500 );
546
+ }
547
+ };
548
+
549
+
176
550
  export const downloadInsertAI = async ( req, res ) => {
177
551
  try {
178
552
  let requestData = req.body;
@@ -1,4 +1,18 @@
1
1
  import Handlebars from 'handlebars';
2
+ import fs from 'fs';
3
+
4
+ import path from 'path';
5
+
6
+ import { fileURLToPath } from 'url';
7
+
8
+ const __dirname = path.dirname( fileURLToPath( import.meta.url ) );
9
+
10
+ const tangoyeFooterLogoPartial = fs.readFileSync(
11
+ path.join( __dirname, '../hbs/partials/tangoye-footer-logo.hbs' ),
12
+ 'utf8',
13
+ );
14
+
15
+ Handlebars.registerPartial( 'tangoyeFooterLogo', tangoyeFooterLogoPartial );
2
16
 
3
17
  Handlebars.registerHelper( 'eq', function( arg1, arg2, options ) {
4
18
  return ( arg1 == arg2 ) ? options.fn( this ) : options.inverse( this );
@@ -28,4 +42,8 @@ Handlebars.registerHelper( 'add', function( a, b ) {
28
42
  return ( a || 0 ) + ( b || 0 );
29
43
  } );
30
44
 
45
+ Handlebars.registerHelper( 'strConcat', function( a, b ) {
46
+ return String( a ?? '' ) + String( b ?? '' );
47
+ } );
48
+
31
49
  export default Handlebars;
@@ -18,7 +18,7 @@ import timeZone from 'dayjs/plugin/timezone.js';
18
18
  import utc from 'dayjs/plugin/utc.js';
19
19
  import { logger } from 'tango-app-api-middleware';
20
20
  import mongoose from 'mongoose';
21
- import { sendPushNotification, sendAiPushNotification } from 'tango-app-api-middleware';
21
+ import { sendPushNotification, sendAiPushNotification, sendEmailWithSES } from 'tango-app-api-middleware';
22
22
  // import * as planoService from '../services/planogram.service.js';
23
23
  import * as clusterServices from '../services/cluster.service.js';
24
24
  import * as teamsServices from '../services/teams.service.js';
@@ -26,6 +26,10 @@ import * as notificationModel from '../services/notification.service.js';
26
26
  import * as runAIRequestServices from '../services/runAIRequest.services.js';
27
27
  import * as traxApprover from '../services/approver.service.js';
28
28
  import { insertSingleProcessData } from '../controllers/trax.controller.js';
29
+ import handlebars from './handlebar-helper.js';
30
+ import fs from 'fs';
31
+ import path from 'path';
32
+
29
33
 
30
34
  const ObjectId = mongoose.Types.ObjectId;
31
35
  dayjs.extend( customParseFormat );
@@ -3370,31 +3374,32 @@ export async function getStoreTaskDetails( req, res ) {
3370
3374
 
3371
3375
  export async function runAIFlag( req, res ) {
3372
3376
  try {
3373
- let checklistDetails = await CLconfig.find( { publish: true, $expr: { $ne: [ { $size: '$notifyFlags.notifyType' }, 0 ] }, runAIQuestionCount: { $ne: 0 } }, { _id: 1 } );
3377
+ let checklistDetails = await CLconfig.find( { publish: true, $expr: { $ne: [ { $size: '$notifyFlags.notifyType' }, 0 ] }, runAIQuestionCount: { $ne: 0 } }, { _id: 1, notifyFlags: 1, approver: 1 } );
3378
+ console.log( checklistDetails, 'checklistDetails' );
3374
3379
  if ( checklistDetails.length ) {
3375
3380
  await Promise.all( checklistDetails.map( async ( ele ) => {
3376
3381
  let submitDetails = await processedchecklist.find( { sourceCheckList_id: ele._id, checklistStatus: 'submit' }, { storeName: 1, checkListName: 1, questionAnswers: 1 } );
3377
3382
  await Promise.all( submitDetails.map( ( store ) => {
3378
- if ( questionAnswers.length ) {
3383
+ if ( store.questionAnswers.length ) {
3379
3384
  let runAIFlag = 0;
3380
- questionAnswers.forEach( ( section ) => {
3385
+ store.questionAnswers.forEach( ( section ) => {
3381
3386
  section.questions.forEach( ( question ) => {
3382
- if ( question.answerType == 'image' && ( question?.userAnswer?.[0]?.runAIDate.value == 'false' || !question?.userAnswer?.[0]?.runAIDate.value ) ) {
3387
+ if ( question.answerType == 'image' && ( question?.userAnswer?.[0]?.runAIData.value == 'false' || !question?.userAnswer?.[0]?.runAIData.value ) ) {
3383
3388
  runAIFlag++;
3384
3389
  }
3385
3390
  } );
3386
3391
  } );
3387
3392
 
3388
3393
  if ( runAIFlag ) {
3389
- let emailList = checklistDetails?.notifyFlags?.notifyType.includes( 'approver' ) ? checklistDetails.approver.map( ( ele ) => ele?.value ): [];
3390
- emailList = [ ...emailList, ...checklistDetails?.notifyFlags?.users?.map( ( ele ) => ele?.value ) ];
3394
+ let emailList = ele?.notifyFlags?.notifyType.includes( 'approver' ) ? ele.approver.map( ( approver ) => approver?.value ): [];
3395
+ emailList = [ ...emailList, ...ele?.notifyFlags?.users?.map( ( user ) => user?.value ) ];
3391
3396
  let data = {
3392
3397
  storeName: store.storeName,
3393
3398
  flagCount: 1,
3394
3399
  checklistName: store.checkListName?.trim(),
3395
3400
  submittedBy: '--',
3396
3401
  time: '--',
3397
- domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags`,
3402
+ domain: `${JSON.parse( process.env.URL ).domain}/manage/trax/flags?date=${dayjs().format( 'YYYY-MM-DD' )}`,
3398
3403
  type: 'delay',
3399
3404
  };
3400
3405
  const fileContent = fs.readFileSync( path.resolve( path.dirname( '' ) ) + '/src/hbs/flag.hbs', 'utf8' );
@@ -3415,6 +3420,7 @@ export async function runAIFlag( req, res ) {
3415
3420
  } ) );
3416
3421
  } ) );
3417
3422
  }
3423
+ return res.sendSuccess( 'Message send successfully' );
3418
3424
  } catch ( e ) {
3419
3425
  logger.error( { functionName: 'runAIFlag', error: e } );
3420
3426
  return res.sendError( e, 500 );
@@ -664,12 +664,14 @@ export async function sopMobilechecklistQuestionValidatorv1( req, res, next ) {
664
664
  section.questions.forEach( ( question ) => {
665
665
  // question.answers.forEach( ( answer ) => {
666
666
  let sectionQuestion = requestSection.filter( ( secQuestion ) => secQuestion.qname == question.oldQname || secQuestion.qname == question.qname );
667
- if ( sectionQuestion.length && requestData.submittype == 'submit' ) {
668
- if ( ( question.answerType == 'multiplechoicemultiple' || ( question.answerType =='dropdown' && question.allowMultiple ) ) && ( sectionQuestion[0].Multianswer == null || sectionQuestion[0].Multianswer == '' || !sectionQuestion[0].Multianswer.length ) ) {
669
- validationCount++;
670
- } else {
671
- if ( ![ 'multiplechoicemultiple', 'multipleImage' ].includes( question.answerType ) && ( question.answerType =='dropdown' && !question.allowMultiple ) && ( ( !sectionQuestion[0].linkType && ( sectionQuestion[0].answer == null || sectionQuestion[0].answer == '' ) ) || ( sectionQuestion[0].linkType && sectionQuestion[0].linkquestionenabled && ( sectionQuestion[0].answer == null || sectionQuestion[0].answer == '' ) ) ) ) {
667
+ if ( sectionQuestion.length ) {
668
+ if ( requestData.submittype == 'submit' ) {
669
+ if ( ( question.answerType == 'multiplechoicemultiple' || ( question.answerType =='dropdown' && question.allowMultiple ) ) && ( sectionQuestion[0].Multianswer == null || sectionQuestion[0].Multianswer == '' || !sectionQuestion[0].Multianswer.length ) ) {
672
670
  validationCount++;
671
+ } else {
672
+ if ( ![ 'multiplechoicemultiple', 'multipleImage' ].includes( question.answerType ) && ( question.answerType =='dropdown' && !question.allowMultiple ) && ( ( !sectionQuestion[0].linkType && ( sectionQuestion[0].answer == null || sectionQuestion[0].answer == '' ) ) || ( sectionQuestion[0].linkType && sectionQuestion[0].linkquestionenabled && ( sectionQuestion[0].answer == null || sectionQuestion[0].answer == '' ) ) ) ) {
673
+ validationCount++;
674
+ }
673
675
  }
674
676
  }
675
677
  } else {
@@ -1457,11 +1459,11 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1457
1459
  if ( ansArray.includes( '-' ) ) {
1458
1460
  ansArray = requestSection[i].answer.split( '-' );
1459
1461
  }
1460
- if ( ansArray.length > 1 && ansArray.some( ( date ) => dayjs( date, 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate || dayjs( date, 'DD MMM YYYY' ) <= qaAnswers[j]?.answers[0]?.endDate ) ) {
1462
+ if ( ansArray.length > 1 && ansArray.some( ( date ) => dayjs( date, 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate && dayjs( date, 'DD MMM YYYY' ) <= qaAnswers[j]?.answers[0]?.endDate ) ) {
1461
1463
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.matchedCount;
1462
- } else if ( ansArray.length > 1 && ( dayjs( ansArray?.[0], 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate || dayjs( ansArray?.[1], 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) <= qaAnswers[j]?.answers[0]?.endDate ) ) {
1464
+ } else if ( ansArray.length > 1 && ( dayjs( ansArray?.[0], 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate && dayjs( ansArray?.[1], 'DD MMM YYYY' ).format( 'DD-MM-YYYY' ) <= qaAnswers[j]?.answers[0]?.endDate ) ) {
1463
1465
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.matchedCount;
1464
- } else if ( dayjs( requestSection[i].answer, 'DD MMM YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate || dayjs( requestSection[i].answer, 'DD MMM YYYY' ) <= qaAnswers[j]?.answers[0]?.startDate ) {
1466
+ } else if ( dayjs( requestSection[i].answer, 'DD MMM YYYY' ) >= qaAnswers[j]?.answers[0]?.startDate && dayjs( requestSection[i].answer, 'DD MMM YYYY' ) <= qaAnswers[j]?.answers[0]?.endDate ) {
1465
1467
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.matchedCount;
1466
1468
  } else {
1467
1469
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.notMatchedCount;
@@ -1472,7 +1474,7 @@ export async function sopMobilechecklistMultiSectionFormatterv1( req, res, next
1472
1474
  if ( qaAnswers[j].answerType == 'linearscale' ) {
1473
1475
  if ( qaAnswers[j].compliance ) {
1474
1476
  let linearAnswer = requestSection[i].answer.split( 'to' );
1475
- if ( parseInt( linearAnswer?.[0] ) >= qaAnswers[j]?.answers[0]?.minValue || parseInt( linearAnswer?.[1] ) <= qaAnswers[j]?.answers[0]?.maxValue ) {
1477
+ if ( parseInt( linearAnswer?.[0] ) >= qaAnswers[j]?.answers[0]?.minValue && parseInt( linearAnswer?.[1] ) <= qaAnswers[j]?.answers[0]?.maxValue ) {
1476
1478
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.matchedCount;
1477
1479
  } else {
1478
1480
  ansstructure.complianceScore = qaAnswers[j]?.answers[0]?.notMatchedCount;
@@ -192,11 +192,16 @@ export const create = async ( req, res ) => {
192
192
  if ( element?.questions?.length ) {
193
193
  questionCount = questionCount + element?.questions?.length;
194
194
  }
195
+ let answerCount = 0;
195
196
  element.questions.forEach( ( question ) => {
196
197
  complianceCount += Math.max( ...question.answers.map( ( o ) => o?.complianceScore ?? Math.max( o?.matchedCount ?? 0, o?.notMatched ?? 0 ) ) );
198
+ if ( question.answers.some( ( a ) => a.runAI ) ) {
199
+ answerCount += 1;
200
+ }
197
201
  } );
198
202
  let runAiQuestions = element?.questions.filter( ( qn ) => qn.runAI );
199
- runAIQuestionCount += runAiQuestions.length;
203
+
204
+ runAIQuestionCount = runAIQuestionCount + runAiQuestions.length + answerCount;
200
205
  } );
201
206
 
202
207
  let checkListDetails = {
@@ -996,11 +1001,15 @@ export const update = async ( req, res ) => {
996
1001
  if ( element.questions.length ) {
997
1002
  questionCount = questionCount + element.questions.length;
998
1003
  }
1004
+ let answerCount=0;
999
1005
  element.questions.forEach( ( question ) => {
1000
1006
  complianceCount += Math.max( ...question.answers.map( ( o ) => o?.complianceScore ?? Math.max( o?.matchedCount ?? 0, o?.notMatched ?? 0 ) ) );
1007
+ if ( question.answers.some( ( a ) => a.runAI ) ) {
1008
+ answerCount += 1;
1009
+ }
1001
1010
  } );
1002
1011
  let runAiQuestions = element?.questions.filter( ( qn ) => qn.runAI );
1003
- runAIQuestionCount += runAiQuestions.length;
1012
+ runAIQuestionCount = runAIQuestionCount + runAiQuestions.length + answerCount;
1004
1013
  } );
1005
1014
 
1006
1015
 
@@ -0,0 +1,18 @@
1
+ <svg class="footer-tangoye-logo" width="95" height="25" viewBox="0 0 95 25" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
2
+ <path d="M23.0988 0.796875H2.32668C1.70831 0.796875 1.20703 1.3062 1.20703 1.93449V23.0401C1.20703 23.6684 1.70831 24.1777 2.32668 24.1777H23.0988C23.7172 24.1777 24.2185 23.6684 24.2185 23.0401V1.93449C24.2185 1.3062 23.7172 0.796875 23.0988 0.796875Z" fill="url(#te-grad-{{gid}})"/>
3
+ <path d="M20.2597 18.5753L19.6797 17.9861L13.4306 11.6366L15.2844 9.75302L15.7286 9.30082C15.7709 9.25715 15.7948 9.19837 15.7952 9.13704C15.795 9.10671 15.789 9.07671 15.7774 9.04876C15.7658 9.02081 15.7489 8.99545 15.7277 8.97414L15.2826 8.52194L13.3167 6.52087L12.8716 6.06867C12.8506 6.04693 12.8255 6.02965 12.7978 6.01786C12.7702 6.00607 12.7404 6 12.7104 6C12.6804 6 12.6507 6.00607 12.623 6.01786C12.5954 6.02965 12.5703 6.04693 12.5492 6.06867L12.1042 6.52176L9.69492 8.96969C9.67354 8.99099 9.65656 9.0164 9.64497 9.04445C9.63337 9.0725 9.6274 9.10261 9.6274 9.13303C9.6274 9.16345 9.63337 9.19357 9.64497 9.22161C9.65656 9.24966 9.67354 9.27508 9.69492 9.29637L11.9964 11.6357L5.74637 17.9861L5.16902 18.5753C5.12621 18.6184 5.10196 18.677 5.10156 18.7382C5.10181 18.7974 5.12403 18.8543 5.16377 18.8976C5.18498 18.9206 5.21062 18.939 5.23911 18.9515C5.26759 18.9641 5.2983 18.9706 5.32935 18.9706H10.9512C11.0116 18.9703 11.0694 18.9459 11.112 18.9025C11.1547 18.8592 11.1788 18.8004 11.179 18.7391V18.1712C11.179 18.1098 11.155 18.0508 11.1124 18.0073C11.0697 17.9637 11.0117 17.9391 10.9512 17.9389H7.22784L12.7131 12.3656L18.1983 17.9389H14.4425C14.382 17.9391 14.324 17.9637 14.2813 18.0073C14.2387 18.0508 14.2147 18.1098 14.2147 18.1712V18.7391C14.2146 18.7696 14.2205 18.7998 14.2321 18.828C14.2437 18.8561 14.2607 18.8816 14.2821 18.9029C14.3247 18.9461 14.3823 18.9704 14.4425 18.9706H20.0985C20.1297 18.9707 20.1606 18.9643 20.1892 18.9517C20.2179 18.9391 20.2437 18.9207 20.265 18.8976C20.3059 18.8539 20.3283 18.7957 20.3273 18.7354C20.3263 18.6751 20.3021 18.6176 20.2597 18.5753ZM12.7096 7.36385L14.4556 9.13793L12.7139 10.9076L10.9679 9.13348L12.7096 7.36385Z" fill="white"/>
4
+ <path d="M29.9727 6.27139V5.375H37.7865V6.27139H34.3698V16.3239H33.3877V6.27139H29.9727Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
5
+ <path d="M40.4434 16.503C39.9823 16.5087 39.5257 16.4093 39.1074 16.2119C38.715 16.0269 38.3813 15.7344 38.1437 15.3671C37.8965 14.9645 37.7721 14.4965 37.7863 14.0221C37.7748 13.6661 37.8526 13.3129 38.0123 12.9957C38.1651 12.7154 38.3862 12.4797 38.6545 12.3112C38.9596 12.121 39.2913 11.9788 39.6383 11.8893C40.0498 11.779 40.4685 11.6984 40.8911 11.6481C41.3432 11.5887 41.7263 11.5389 42.0406 11.4985C42.29 11.4749 42.5333 11.4061 42.759 11.2956C42.8384 11.2527 42.9039 11.1875 42.9477 11.1078C42.9915 11.0281 43.0118 10.9372 43.006 10.846V10.6538C43.006 10.0947 42.8422 9.65381 42.5145 9.33098C42.1869 9.00815 41.7158 8.84674 41.1014 8.84674C40.5173 8.84674 40.0428 8.9767 39.6777 9.23662C39.3398 9.46266 39.0723 9.78196 38.9068 10.157L38.0219 9.83036C38.1806 9.41228 38.4396 9.04112 38.7754 8.7506C39.0951 8.48448 39.4647 8.28704 39.8617 8.17022C40.2566 8.05202 40.6661 7.99206 41.0777 7.99219C41.4026 7.99443 41.7261 8.03566 42.0414 8.11503C42.3761 8.19663 42.6928 8.34093 42.9753 8.54052C43.2752 8.75551 43.5163 9.04434 43.6762 9.37994C43.8549 9.736 43.9443 10.1894 43.9443 10.7401V16.3169H43.006V15.0173H42.9482C42.8223 15.2799 42.6531 15.5186 42.4479 15.7232C42.2092 15.9633 41.9268 16.154 41.6165 16.2849C41.2443 16.4382 40.845 16.5124 40.4434 16.503ZM40.5696 15.6315C41.0236 15.6433 41.4718 15.5268 41.8645 15.295C42.2206 15.0793 42.5124 14.7695 42.709 14.3986C42.9087 14.02 43.0108 13.5962 43.006 13.1667V11.9801C42.903 12.0641 42.7835 12.1248 42.6556 12.1581C42.4708 12.217 42.2827 12.2642 42.0923 12.2996C41.8802 12.3406 41.6688 12.3753 41.458 12.4038L40.8902 12.4786C40.4919 12.5216 40.0997 12.6112 39.7215 12.7456C39.435 12.8423 39.1789 13.0146 38.9795 13.245C38.8009 13.4786 38.7099 13.7692 38.7228 14.0648C38.7228 14.5645 38.898 14.9502 39.2485 15.222C39.5989 15.4938 40.0393 15.6303 40.5696 15.6315Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
6
+ <path d="M46.5537 11.1874V16.321H45.6172V8.10751H46.5274V9.39646H46.6151C46.8043 8.97612 47.1131 8.62299 47.5017 8.38257C47.9041 8.12799 48.4005 8.00069 48.991 8.00069C49.4898 7.98976 49.9832 8.10833 50.4243 8.34518C50.8384 8.57725 51.1742 8.93052 51.388 9.35907C51.6175 9.80415 51.7323 10.3513 51.7323 11.0005V16.321H50.7949V11.0602C50.7949 10.3866 50.6097 9.85251 50.2395 9.45788C49.8692 9.06324 49.3727 8.86711 48.7501 8.86949C48.3556 8.86199 47.9658 8.95762 47.6182 9.14721C47.2882 9.3336 47.0172 9.61144 46.8367 9.94835C46.6389 10.3297 46.5414 10.7565 46.5537 11.1874Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
7
+ <path d="M56.4726 19.571C55.9821 19.5802 55.4934 19.5071 55.0262 19.3546C54.6415 19.2284 54.2845 19.0277 53.9749 18.7636C53.7032 18.5298 53.4784 18.2451 53.3126 17.9251L54.0809 17.4114C54.2092 17.6344 54.3656 17.8394 54.5461 18.0212C54.7654 18.2367 55.0248 18.4056 55.3092 18.5179C55.6795 18.6601 56.0735 18.7275 56.4691 18.7164C57.1846 18.7164 57.7625 18.5345 58.2029 18.1707C58.6433 17.807 58.8635 17.2432 58.8635 16.4794V14.6306H58.7759C58.6546 14.9 58.4972 15.1511 58.3081 15.3765C58.0878 15.6367 57.8162 15.8469 57.5108 15.9934C57.1301 16.1659 56.7157 16.2478 56.2992 16.2329C55.6921 16.2445 55.0948 16.0762 54.5803 15.7486C54.0656 15.407 53.657 14.9239 53.4019 14.3555C53.1157 13.752 52.9727 13.0313 52.9727 12.1933C52.9727 11.3554 53.1125 10.6249 53.3923 10.0018C53.6406 9.40956 54.0458 8.89896 54.5628 8.5268C55.0778 8.1677 55.6904 7.98098 56.3149 7.99271C56.8102 7.99271 57.2208 8.08172 57.5467 8.25975C57.8522 8.41901 58.121 8.64231 58.3352 8.91491C58.5177 9.1496 58.6737 9.40428 58.8004 9.67421H58.895V8.10754H59.8106V16.5337C59.8106 17.2293 59.6645 17.8013 59.3725 18.25C59.0839 18.6965 58.6692 19.0441 58.1828 19.2469C57.64 19.4707 57.0583 19.5809 56.4726 19.571ZM56.4096 15.3641C56.8815 15.3776 57.3462 15.2441 57.7412 14.9813C58.124 14.708 58.4187 14.3258 58.5884 13.8829C58.7964 13.3397 58.8964 12.76 58.8828 12.1773C58.8931 11.5945 58.795 11.0149 58.5937 10.4691C58.4261 10.005 58.1356 9.59683 57.7544 9.28966C57.3559 9.00621 56.8807 8.85527 56.3943 8.85767C55.9079 8.86006 55.4342 9.01565 55.0385 9.30302C54.6547 9.61463 54.3633 10.0281 54.1966 10.4976C54.0009 11.0337 53.9044 11.602 53.9118 12.1738C53.9009 12.7411 53.9995 13.3051 54.2018 13.8339C54.3716 14.2833 54.6658 14.6732 55.049 14.9564C55.4482 15.236 55.9249 15.3788 56.4096 15.3641Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
8
+ <path d="M64.6186 16.4927C63.9624 16.5053 63.3177 16.317 62.7683 15.9524C62.2232 15.5804 61.7892 15.0634 61.5137 14.4578C61.2129 13.8223 61.0625 13.0873 61.0625 12.2529C61.0625 11.4186 61.2135 10.6768 61.5154 10.0275C61.7897 9.42067 62.2239 8.90277 62.77 8.5312C63.3243 8.17897 63.9648 7.99219 64.6186 7.99219C65.2723 7.99219 65.9129 8.17897 66.4671 8.5312C67.0121 8.90649 67.4456 9.4261 67.7208 10.0338C68.0251 10.6723 68.177 11.412 68.1764 12.2529C68.1758 13.0938 68.0239 13.8288 67.7208 14.4578C67.4453 15.0634 67.0113 15.5804 66.4662 15.9524C65.9175 16.3166 65.2738 16.5048 64.6186 16.4927ZM64.6186 15.6213C65.1309 15.6385 65.6337 15.4778 66.044 15.1655C66.4444 14.8457 66.7515 14.421 66.9323 13.9371C67.3365 12.85 67.3365 11.6505 66.9323 10.5634C66.7515 10.0783 66.4452 9.6518 66.0457 9.32878C65.6305 9.02603 65.1323 8.8632 64.6212 8.8632C64.1101 8.8632 63.6119 9.02603 63.1967 9.32878C62.7959 9.65114 62.4886 10.0778 62.3074 10.5634C61.9044 11.6507 61.9044 12.8498 62.3074 13.9371C62.4872 14.4206 62.7931 14.8452 63.1923 15.1655C63.583 15.47 64.0584 15.6219 64.6186 15.6213Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
9
+ <path d="M69.5312 16.3239V5.375H75.7839V6.27139H70.5151V10.3937H75.4501V11.2919H70.5151V15.4248H75.8873V16.3239H69.5312Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
10
+ <path d="M78.2602 19.401C78.0853 19.4021 77.9109 19.3842 77.7398 19.3476C77.6081 19.3214 77.4793 19.282 77.3552 19.2301L77.6075 18.3907C77.8815 18.4848 78.1714 18.5221 78.4599 18.5002C78.7143 18.471 78.9497 18.3496 79.1231 18.1583C79.3159 17.9572 79.4879 17.6498 79.6392 17.2361L79.9335 16.4021L76.9609 8.10938H77.9763L80.3759 15.065H80.4495L82.8492 8.10938H83.8645L80.4478 17.6207C80.3246 17.9783 80.145 18.3132 79.916 18.6123C79.7219 18.8653 79.4723 19.0686 79.1871 19.206C78.8961 19.3398 78.5795 19.4063 78.2602 19.401Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
11
+ <path d="M88.141 16.4936C87.387 16.4936 86.7346 16.3155 86.1838 15.9595C85.6279 15.5956 85.1855 15.0785 84.9082 14.4685C84.6074 13.8317 84.4573 13.0982 84.4579 12.268C84.4439 11.5078 84.5978 10.754 84.9082 10.0622C85.1803 9.4518 85.6114 8.92853 86.1549 8.54895C86.7001 8.17908 87.3437 7.98772 87.9991 8.00061C88.4345 7.99834 88.8665 8.07989 89.272 8.24095C89.6849 8.40781 90.0586 8.66106 90.3689 8.98423C90.7095 9.34384 90.9722 9.77202 91.1399 10.2411C91.3406 10.8148 91.4368 11.4208 91.4237 12.0295V12.4959H85.1097V11.6565H90.4662C90.4737 11.1633 90.3666 10.6753 90.1534 10.2322C89.9574 9.825 89.6576 9.47858 89.2852 9.22903C88.8877 8.98 88.4282 8.85223 87.9613 8.86091C87.4945 8.86959 87.0399 9.01436 86.6516 9.27798C86.2591 9.55898 85.9446 9.93828 85.7388 10.3791C85.5167 10.8455 85.4022 11.3573 85.4041 11.8755V12.3784C85.391 12.9658 85.5052 13.549 85.7388 14.0866C85.9407 14.5491 86.2706 14.9419 86.6884 15.2171C87.058 15.436 87.4707 15.5693 87.8969 15.6073C88.3231 15.6453 88.7523 15.5871 89.1538 15.437C89.4275 15.3259 89.6762 15.1593 89.8844 14.9474C90.0761 14.7535 90.229 14.5238 90.3347 14.2709L91.224 14.5655C91.0929 14.9247 90.8874 15.2511 90.6212 15.5224C90.3248 15.8265 89.9703 16.0658 89.5796 16.2256C89.1224 16.4114 88.6333 16.5025 88.141 16.4936Z" fill="#0066CC" stroke="#0066CC" stroke-width="0.158784" stroke-miterlimit="10"/>
12
+ <defs>
13
+ <linearGradient id="te-grad-{{gid}}" x1="6.02116" y1="3.53321" x2="22.0732" y2="24.3409" gradientUnits="userSpaceOnUse">
14
+ <stop stop-color="#794FD9"/>
15
+ <stop offset="1" stop-color="#33B1F7"/>
16
+ </linearGradient>
17
+ </defs>
18
+ </svg>