tango-app-api-audit 3.6.22 → 3.6.24

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-audit",
3
- "version": "3.6.22",
3
+ "version": "3.6.24",
4
4
  "description": "audit & audit metrics apis",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -13,7 +13,6 @@
13
13
  "author": "praveenraj",
14
14
  "license": "ISC",
15
15
  "dependencies": {
16
- "@aws-sdk/client-ses": "^3.918.0",
17
16
  "adm-zip": "^0.5.15",
18
17
  "aws-sdk": "^2.1643.0",
19
18
  "axios": "^1.7.9",
@@ -25,7 +24,6 @@
25
24
  "joi-to-swagger": "^6.2.0",
26
25
  "lodash": "^4.17.21",
27
26
  "mongodb": "^6.7.0",
28
- "nodemailer": "^7.0.10",
29
27
  "nodemon": "^3.1.3",
30
28
  "swagger-ui-express": "^5.0.1",
31
29
  "tango-api-schema": "^2.3.28",
@@ -609,7 +609,7 @@ export async function getAuditFile( req, res ) {
609
609
  const getQuery = msg.audit_type =='ReAudit'?
610
610
  {
611
611
  size: inputData?.limit || 500,
612
- _source: [ 'module', 'status', 'date', 'store_id', 'outputCluster', 'personPath', 'REIDCluster', 'isEmployee', 'isJunk', 'EmployeeStatusFinal' ], // Only fetch necessary fields
612
+ _source: [ 'module', 'status', 'date', 'store_id', 'outputCluster', 'personPath', 'REIDCluster', 'isEmployee', 'isJunk', 'EmployeeStatusFinal', 'entry_timestamp' ], // Only fetch necessary fields
613
613
 
614
614
  query: {
615
615
  bool: {
@@ -638,13 +638,13 @@ export async function getAuditFile( req, res ) {
638
638
  },
639
639
  },
640
640
  sort: [
641
- { timestamp: { order: 'desc' } },
641
+ { entry_timestamp: { order: 'desc' } },
642
642
  ],
643
643
 
644
644
  }:
645
645
  {
646
646
  size: inputData?.limit || 500,
647
- _source: [ 'module', 'status', 'date', 'store_id', 'personPath', 'REIDCluster', 'EmployeeStatusProposed', 'isJunk', 'EmployeeStatusFinal' ], // Only fetch necessary fields
647
+ _source: [ 'module', 'status', 'date', 'store_id', 'personPath', 'REIDCluster', 'EmployeeStatusProposed', 'isJunk', 'EmployeeStatusFinal', 'entry_timestamp' ], // Only fetch necessary fields
648
648
 
649
649
  query: {
650
650
  bool: {
@@ -668,7 +668,7 @@ export async function getAuditFile( req, res ) {
668
668
  },
669
669
  },
670
670
  sort: [
671
- { timestamp: { order: 'desc' } },
671
+ { entry_timestamp: { order: 'desc' } },
672
672
  ],
673
673
 
674
674
  };
@@ -4490,7 +4490,7 @@ export async function auditImages( req, res ) {
4490
4490
  case 'BC':
4491
4491
  const getQuery = {
4492
4492
  size: 10000,
4493
- _source: [ 'module', 'status', 'date', 'store_id', 'personPath', 'REIDCluster', 'EmployeeStatusProposed', 'isJunk', 'EmployeeStatusFinal' ], // Only fetch necessary fields
4493
+ _source: [ 'module', 'status', 'date', 'store_id', 'personPath', 'REIDCluster', 'EmployeeStatusProposed', 'isJunk', 'EmployeeStatusFinal', 'entry_timestamp' ], // Only fetch necessary fields
4494
4494
 
4495
4495
  query: {
4496
4496
  bool: {
@@ -4515,7 +4515,7 @@ export async function auditImages( req, res ) {
4515
4515
  },
4516
4516
 
4517
4517
  sort: [
4518
- { timestamp: { order: 'desc' } },
4518
+ { entry_timestamp: { order: 'desc' } },
4519
4519
  ],
4520
4520
  };
4521
4521
  const files = [];
@@ -4565,7 +4565,7 @@ export async function auditImages( req, res ) {
4565
4565
 
4566
4566
  const getACQuery = {
4567
4567
  size: 10000,
4568
- _source: [ 'module', 'status', 'date', 'store_id', 'outputCluster', 'personPath', 'REIDCluster', 'isEmployee', 'isJunk', 'EmployeeStatusFinal' ], // Only fetch necessary fields
4568
+ _source: [ 'module', 'status', 'date', 'store_id', 'outputCluster', 'personPath', 'REIDCluster', 'isEmployee', 'isJunk', 'EmployeeStatusFinal', 'entry_timestamp' ], // Only fetch necessary fields
4569
4569
 
4570
4570
  query: {
4571
4571
  bool: {
@@ -4594,7 +4594,7 @@ export async function auditImages( req, res ) {
4594
4594
  },
4595
4595
  },
4596
4596
  sort: [
4597
- { timestamp: { order: 'desc' } },
4597
+ { entry_timestamp: { order: 'desc' } },
4598
4598
  ],
4599
4599
 
4600
4600
  };
@@ -811,6 +811,7 @@ export async function save( req, res ) {
811
811
  },
812
812
  };
813
813
  const getOutput = await getOpenSearchData( openSearch.EyeTestOutput, searchQuery );
814
+ logger.info( { getOutput: getOutput } );
814
815
  const output = getOutput?.body?.hits?.hits?.length > 0 ? getOutput?.body?.hits?.hits[0] : null;
815
816
  if ( !output ) {
816
817
  return res.sendError( 'This file is currently being audited by another user. Any actions you perform will not be saved.', 400 );
@@ -844,27 +845,19 @@ export async function save( req, res ) {
844
845
 
845
846
  const getEyetestConfig = await findOneEyeTestConfig( { clientId: req?.user.userType == 'tango'? inputData?.clientId : req.user.clientId, configureType: 'email' }, { complianceThreshold: 1 } );
846
847
 
847
- if ( getEyetestConfig &&( inputData.auditStatus == 'Audited' ||inputData.auditStatus == 'ReAudited' ) && inputUpdatedData && inputData.type === 'physical' && inputData?.isReSend !== false ) {
848
+ if ( getEyetestConfig && inputData.auditStatus == 'Audited' && inputUpdatedData ) {
848
849
  const trustScore = Math.round( 100-( ( inputData?.overRides / inputData?.steps?.length ) * 100 ) );
849
850
  const value = Number( getEyetestConfig?.complianceThreshold?.value?.split( '%' )[0] );
850
851
  const condition = getEyetestConfig?.complianceThreshold?.condition;
851
- const id= inputData?.isReSend === true ?`${inputData.id}_${inputUpdatedData?._source?.optumId}_${inputData?.fileId}_${Date.now()}` : `${inputData.id}_${inputUpdatedData?._source?.optumId}_${inputData?.fileId}`;
852
- const humanScore = Math.round( ( inputUpdatedData?._source?.auditedSteps /inputUpdatedData?._source?.totalSteps ) * 100 );
853
- const userName = await findOneUser( { _id: new mongoose.Types.ObjectId( inputUpdatedData?._source?.userId ) }, { userName: 1 } );
854
-
855
-
852
+ const id= `${inputData?.RMEmail}_${inputData?.cluster}_${inputUpdatedData?._source?.optumId}_${inputData?.fileId}`;
856
853
  switch ( condition ) {
857
854
  case '>': if ( trustScore > value ) {
858
855
  const record1 = {
859
856
  RMEmail: inputData.RMEmail,
860
- RMName: inputData.RMEmail,
861
857
  cluster: inputData.cluster,
862
858
  optumId: inputUpdatedData?._source?.optumId,
863
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
864
859
  storeName: inputUpdatedData?._source?.storeName,
865
860
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
866
- humanScore: humanScore,
867
- auditedBy: userName?.userName || '',
868
861
  trustScore: inputUpdatedData?._source?.trustScore,
869
862
  auditedId: inputUpdatedData?._id,
870
863
  queueId: inputUpdatedData?._source?.queueId,
@@ -878,14 +871,10 @@ export async function save( req, res ) {
878
871
  case '<': if ( trustScore < value ) {
879
872
  const record2 = {
880
873
  RMEmail: inputData.RMEmail,
881
- RMName: inputData.RMEmail,
882
874
  cluster: inputData.cluster,
883
875
  optumId: inputUpdatedData?._source?.optumId,
884
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
885
876
  storeName: inputUpdatedData?._source?.storeName,
886
877
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
887
- humanScore: humanScore,
888
- auditedBy: userName?.userName || '',
889
878
  trustScore: inputUpdatedData?._source?.trustScore,
890
879
  auditedId: inputUpdatedData?._id,
891
880
  queueId: inputUpdatedData?._source?.queueId,
@@ -899,14 +888,10 @@ export async function save( req, res ) {
899
888
  case '>=': if ( trustScore >= value ) {
900
889
  const record3 = {
901
890
  RMEmail: inputData.RMEmail,
902
- RMName: inputData.RMEmail,
903
891
  cluster: inputData.cluster,
904
892
  optumId: inputUpdatedData?._source?.optumId,
905
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
906
893
  storeName: inputUpdatedData?._source?.storeName,
907
894
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
908
- humanScore: humanScore,
909
- auditedBy: userName?.userName || '',
910
895
  trustScore: inputUpdatedData?._source?.trustScore,
911
896
  auditedId: inputUpdatedData?._id,
912
897
  queueId: inputUpdatedData?._source?.queueId,
@@ -920,14 +905,10 @@ export async function save( req, res ) {
920
905
  case '<=': if ( trustScore <= value ) {
921
906
  const record4 = {
922
907
  RMEmail: inputData.RMEmail,
923
- RMName: inputData.RMEmail,
924
908
  cluster: inputData.cluster,
925
909
  optumId: inputUpdatedData?._source?.optumId,
926
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
927
910
  storeName: inputUpdatedData?._source?.storeName,
928
911
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
929
- humanScore: humanScore,
930
- auditedBy: userName?.userName || '',
931
912
  trustScore: inputUpdatedData?._source?.trustScore,
932
913
  auditedId: inputUpdatedData?._id,
933
914
  queueId: inputUpdatedData?._source?.queueId,
@@ -942,14 +923,10 @@ export async function save( req, res ) {
942
923
  case '==': if ( trustScore == value ) {
943
924
  const record5 = {
944
925
  RMEmail: inputData.RMEmail,
945
- RMName: inputData.RMEmail,
946
926
  cluster: inputData.cluster,
947
927
  optumId: inputUpdatedData?._source?.optumId,
948
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
949
928
  storeName: inputUpdatedData?._source?.storeName,
950
929
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
951
- humanScore: humanScore,
952
- auditedBy: userName?.userName || '',
953
930
  trustScore: inputUpdatedData?._source?.trustScore,
954
931
  auditedId: inputUpdatedData?._id,
955
932
  queueId: inputUpdatedData?._source?.queueId,
@@ -963,14 +940,10 @@ export async function save( req, res ) {
963
940
  case '===': if ( trustScore === value ) {
964
941
  const record6 = {
965
942
  RMEmail: inputData.RMEmail,
966
- RMName: inputData.RMEmail,
967
943
  cluster: inputData.cluster,
968
944
  optumId: inputUpdatedData?._source?.optumId,
969
- optomEmailId: inputUpdatedData?._source?.salesmanEmailId,
970
945
  storeName: inputUpdatedData?._source?.storeName,
971
946
  complianceScore: inputUpdatedData?._source?.ComplianceScore,
972
- humanScore: humanScore,
973
- auditedBy: userName?.userName || '',
974
947
  trustScore: inputUpdatedData?._source?.trustScore,
975
948
  auditedId: inputUpdatedData?._id,
976
949
  queueId: inputUpdatedData?._source?.queueId,
@@ -983,7 +956,7 @@ export async function save( req, res ) {
983
956
  default: throw new Error( `Unknown condition: ${condition}` );
984
957
  }
985
958
  }
986
- return res.sendSuccess( 'The file has been submitted successfully' );
959
+ return res.sendSuccess( 'The file has been submited successfully' );
987
960
  } catch ( error ) {
988
961
  const err = error.message || 'Internal Server Error';
989
962
  logger.error( { message: error, data: req.params, function: 'eyetestAudit-controller-save' } );
@@ -1225,25 +1198,18 @@ export async function userAuditedData( req, res ) {
1225
1198
 
1226
1199
  export async function summaryList( req, res ) {
1227
1200
  try {
1228
- // declare inputData and get request body
1229
1201
  const inputData = req.body;
1230
-
1231
- // throw 204 if client id is not 11
1232
1202
  if ( inputData.clientId !== '11' ) {
1233
1203
  return res.sendError( 'No data found', 204 );
1234
1204
  }
1235
1205
 
1236
- // declare openSearch and get data form the .env/secret manager
1237
1206
  const openSearch = JSON.parse( process.env.OPENSEARCH );
1238
-
1239
- // set limit, offset, sortBy, sortOrder value if not set default value
1240
1207
  const limit = inputData.limit || 10;
1241
1208
  const offset = inputData.offset ? ( inputData.offset - 1 ) * limit : 0;
1242
1209
 
1243
1210
  const sortBy = inputData?.sortBy ? [ 'coveredStepsAI', 'trustScore', 'date', 'ComplianceScore', 'auditedSteps' ].includes( inputData.sortBy ) ? inputData.sortBy :`${inputData.sortBy}.keyword` : 'storeName.keyword';
1244
1211
  const order = inputData?.sortOrder || -1;
1245
1212
 
1246
- // declare filter and assign range values from inputData
1247
1213
  let filter= [
1248
1214
  {
1249
1215
  'range': {
@@ -1256,7 +1222,6 @@ export async function summaryList( req, res ) {
1256
1222
 
1257
1223
  ];
1258
1224
 
1259
- // filter by Audit Status if key has minimum one element
1260
1225
  if ( inputData?.auditStatus && inputData?.auditStatus?.length > 0 ) {
1261
1226
  filter.push( {
1262
1227
  'terms': {
@@ -1264,8 +1229,6 @@ export async function summaryList( req, res ) {
1264
1229
  },
1265
1230
  } );
1266
1231
  }
1267
-
1268
- // filter by Visitors Type if key has minimum one element
1269
1232
  if ( inputData?.demographics && inputData?.demographics?.length > 0 ) {
1270
1233
  filter.push( {
1271
1234
  'terms': {
@@ -1273,8 +1236,6 @@ export async function summaryList( req, res ) {
1273
1236
  },
1274
1237
  } );
1275
1238
  }
1276
-
1277
- // filter by Eye test Type if key has string value one element
1278
1239
  if ( inputData.type && inputData.type!='' ) {
1279
1240
  filter.push( {
1280
1241
  'term': {
@@ -1284,17 +1245,6 @@ export async function summaryList( req, res ) {
1284
1245
  } );
1285
1246
  }
1286
1247
 
1287
- // filter by near addition if value != "" and eye test must be a physical
1288
- if ( inputData.nearAddition && inputData.nearAddition!='' && inputData.type ==='physical' ) {
1289
- filter.push( {
1290
- 'term': {
1291
- 'nearAddition.keyword': inputData.nearAddition,
1292
- },
1293
-
1294
- } );
1295
- }
1296
-
1297
- // filter by stores if key has minimum one element else throw an error
1298
1248
  if ( inputData.storeId && inputData.storeId.length > 0 ) {
1299
1249
  filter.push( {
1300
1250
 
@@ -1307,14 +1257,11 @@ export async function summaryList( req, res ) {
1307
1257
  return res.sendError( 'No data found', 204 );
1308
1258
  }
1309
1259
 
1310
- // Declare mustQuery as an array and include all elements from the filter array
1311
1260
  let mustQuery = [
1312
1261
  ...filter,
1313
1262
  ];
1314
1263
 
1315
- // filter by complianceScore/tango score if key has minimum one element
1316
- if ( inputData.complianceScore && inputData.complianceScore?.length > 0 ) {
1317
- // If the key type is not 'store', split the compliance score ranges
1264
+ if ( inputData.complianceScore && inputData.complianceScore?.length > null ) {
1318
1265
  if ( inputData.keyType !== 'store' ) {
1319
1266
  const rangeShould = inputData?.complianceScore?.map( ( r ) => {
1320
1267
  const [ gte, lte ] = r.split( '-' ).map( Number );
@@ -1324,7 +1271,7 @@ export async function summaryList( req, res ) {
1324
1271
  },
1325
1272
  };
1326
1273
  } );
1327
- // Add the range conditions to mustQuery (any one of the ranges should match)
1274
+
1328
1275
  mustQuery.push(
1329
1276
  {
1330
1277
  bool: {
@@ -1333,7 +1280,7 @@ export async function summaryList( req, res ) {
1333
1280
  },
1334
1281
  },
1335
1282
  );
1336
- } else { // If-else condition: use 'terms' filter to match records by Compliance Score / Tango Score
1283
+ } else {
1337
1284
  const values = Array.isArray( inputData.complianceScore ) ?
1338
1285
  inputData.complianceScore.map( Number ) :
1339
1286
  [ Number( inputData.complianceScore ) ];
@@ -1346,7 +1293,6 @@ export async function summaryList( req, res ) {
1346
1293
  }
1347
1294
  }
1348
1295
 
1349
- // filter by category if key exist allow "fake, genuine" else throw valid category
1350
1296
  if ( inputData?.category ) {
1351
1297
  switch ( inputData?.category ) {
1352
1298
  case 'fake':
@@ -2172,15 +2118,6 @@ export async function summaryCard( req, res ) {
2172
2118
  },
2173
2119
  } );
2174
2120
  }
2175
-
2176
- if ( inputData.nearAddition && inputData.nearAddition!='' && inputData.type ==='physical' ) {
2177
- filter.push( {
2178
- 'term': {
2179
- 'nearAddition.keyword': inputData.nearAddition,
2180
- },
2181
-
2182
- } );
2183
- }
2184
2121
  let mustQuery = [
2185
2122
  ...filter,
2186
2123
  ];
@@ -2449,7 +2386,7 @@ export async function emailAlertLog( req, res ) {
2449
2386
  inputData.clientId = req.user.userType == 'tango'? inputData?.clientId : req?.user?.clientId;
2450
2387
  // get openserach name form the env file
2451
2388
  const openSearch = JSON.parse( process.env.OPENSEARCH );
2452
- const sortBy = inputData?.sortBy ? [ 'complianceScore', 'humanScore', 'trustScore', 'updatedAt', 'createdAt' ].includes( inputData.sortBy ) ? inputData.sortBy :`${inputData.sortBy}.keyword` : 'RMName.keyword';
2389
+
2453
2390
 
2454
2391
  let filter =[
2455
2392
  {
@@ -2462,7 +2399,7 @@ export async function emailAlertLog( req, res ) {
2462
2399
  },
2463
2400
  ];
2464
2401
  let sort =[
2465
- { [sortBy]: { order: inputData.sortOrder === 1 ? 'asc' : 'desc' } },
2402
+ { [inputData?.sortBy]: { order: inputData.sortOrder === 1 ? 'asc' : 'desc' } },
2466
2403
  ];
2467
2404
  if ( inputData.RmList && inputData.RmList?.lenght > 0 ) {
2468
2405
  filter.push( {
@@ -2479,86 +2416,19 @@ export async function emailAlertLog( req, res ) {
2479
2416
  },
2480
2417
  } );
2481
2418
  }
2482
- let search = {
2483
- must: filter,
2484
- };
2485
- if ( inputData.searchValue && inputData.searchValue !== '' ) {
2486
- search ={
2487
- 'must': filter,
2488
- 'should': [
2489
- {
2490
- 'wildcard': {
2491
- 'RMEmail.keyword': {
2492
- 'value': `*${inputData.searchValue}*`,
2493
- },
2494
- },
2495
- },
2496
- {
2497
- 'wildcard': {
2498
- 'RMName.keyword': {
2499
- 'value': `*${inputData.searchValue}*`,
2500
- },
2501
- },
2502
- },
2503
- {
2504
- 'wildcard': {
2505
- 'cluster.keyword': {
2506
- 'value': `*${inputData.searchValue}*`,
2507
- },
2508
- },
2509
- },
2510
- {
2511
- 'wildcard': {
2512
- 'optumId.keyword': {
2513
- 'value': `*${inputData.searchValue}*`,
2514
- },
2515
- },
2516
- },
2517
- {
2518
- 'wildcard': {
2519
- 'queueId.keyword': {
2520
- 'value': `*${inputData.searchValue}*`,
2521
- },
2522
- },
2523
- },
2524
- {
2525
- 'wildcard': {
2526
- 'storeName.keyword': {
2527
- 'value': `*${inputData.searchValue}*`,
2528
- },
2529
- },
2530
- },
2531
- {
2532
- 'wildcard': {
2533
- 'auditedBy.keyword': {
2534
- 'value': `*${inputData.searchValue}*`,
2535
- },
2536
- },
2537
- },
2538
- {
2539
- 'wildcard': {
2540
- 'optomEmailId.keyword': {
2541
- 'value': `*${inputData.searchValue}*`,
2542
- },
2543
- },
2544
- },
2545
- ],
2546
- 'minimum_should_match': 1,
2547
- };
2548
- }
2549
2419
  const getQuery = {
2550
2420
  'size': inputData.isExport == true? 50000 : inputData?.limit || 10,
2551
2421
  'from': offset || 0,
2552
2422
  'query': {
2553
- 'bool': search,
2423
+ 'bool': {
2424
+ 'must': filter,
2425
+ },
2554
2426
  },
2555
2427
  'sort': sort,
2556
2428
  };
2557
2429
 
2558
-
2559
2430
  // get query result from the open saerch
2560
2431
  const getData= await getOpenSearchData( openSearch.eyeTestEmailAlert, getQuery );
2561
- const count = getData?.body?.hits?.total?.value;
2562
2432
  // throw error if got null or empty array
2563
2433
  if ( !getData || getData?.body?.hits?.hits?.length == 0 ) {
2564
2434
  return res.sendError( 'No records found', 204 );
@@ -2566,18 +2436,14 @@ export async function emailAlertLog( req, res ) {
2566
2436
  let response =[];
2567
2437
  for ( let item of getData?.body?.hits?.hits ) {
2568
2438
  response.push( {
2569
- RMEmail: item?._source?.RMEmail || '',
2570
- RMName: item?._source?.RMName || '',
2439
+ RMEmail: item?._source?.RMEmail,
2571
2440
  cluster: item?._source?.cluster,
2572
2441
  optumId: item?._source?.optumId,
2573
- optomEmailId: item?._source?.optomEmailId,
2574
2442
  storeName: item?._source?.storeName,
2575
2443
  complianceScore: item?._source?.complianceScore,
2576
- humanScore: item?._source?.humanScore,
2577
2444
  trustScore: item?._source?.trustScore,
2578
2445
  auditedId: item?._source?.auditedId,
2579
2446
  queueId: item?._source?.queueId,
2580
- auditedBy: item?._source?.auditedBy,
2581
2447
 
2582
2448
  } );
2583
2449
  }
@@ -2611,7 +2477,7 @@ export async function emailAlertLog( req, res ) {
2611
2477
 
2612
2478
 
2613
2479
  logger.info( { inputData: inputData, getData: response } );
2614
- return res.sendSuccess( { result: response, count: count } );
2480
+ return res.sendSuccess( { result: response, count: response.length } );
2615
2481
  } catch ( error ) {
2616
2482
  const err = error.message || 'Internal Server Error';
2617
2483
  logger.error( { message: error, data: req.body, function: 'eyetestAudit-controller-emailAlertLog' } );
@@ -2771,6 +2637,10 @@ export async function getEmailConfig( req, res ) {
2771
2637
  configureType: 'email',
2772
2638
  };
2773
2639
  const getOne = await findOneEyeTestConfig( query, { complianceThreshold: 1, _id: 1 } );
2640
+ logger.info( { getOne: getOne, message: 'getEmailConfig' } );
2641
+ // if ( !getOne?.complianceThreshold ) {
2642
+ // return res.sendError( 'No data found', 204 );
2643
+ // }
2774
2644
  if ( !getOne ) {
2775
2645
  return res.sendError( ' No data found', 204 );
2776
2646
  }
@@ -64,7 +64,6 @@ export const saveSchema = joi.object( {
64
64
  spokenLanguage: joi.string().optional(),
65
65
  cluster: joi.string().required().allow( '' ),
66
66
  RMEmail: joi.string().required().allow( '' ),
67
- isReSend: joi.boolean().optional(),
68
67
  } );
69
68
 
70
69
  export const saveValid = {
@@ -157,7 +156,7 @@ export const summaryListSchema = joi.object( {
157
156
  ).optional(),
158
157
  storeId: joi.array().items( joi.string().required() ).required(),
159
158
  complianceScore: joi.array().items( joi.string().required() ).optional(),
160
- nearAddition: joi.string().optional().allow( '', 'true', 'false' ),
159
+ nearAddition: joi.string().optional().allow( '' ),
161
160
  isExport: joi.boolean().optional(),
162
161
  searchValue: joi.string().optional().allow( '' ),
163
162
  sortBy: joi.string().optional(),
@@ -235,7 +234,7 @@ export const summaryCardSchema = joi.object( {
235
234
  ).optional(),
236
235
  storeId: joi.array().items( joi.string().required() ).required(),
237
236
  complianceScore: joi.array().items( joi.string().required() ).optional(),
238
- nearAddition: joi.string().optional().allow( '', 'true', 'false' ),
237
+ nearAddition: joi.string().optional().allow( '' ),
239
238
  category: joi.string().optional() .valid( 'fake', 'genuine' ),
240
239
  } );
241
240
 
@@ -280,8 +279,12 @@ export const emailAlertLogSchema = joi.object( {
280
279
 
281
280
  return value;
282
281
  } ),
282
+ type: joi.string().required().messages( {
283
+ 'any.required': 'Type is required',
284
+ 'string.empty': 'Type cannot be empty',
285
+ } ),
283
286
  RMList: joi.array().items(
284
- joi.string().required(),
287
+ joi.string().optional(),
285
288
  ).optional(),
286
289
  clientId: joi.string().when( '$userType', {
287
290
  is: 'tango',
@@ -291,7 +294,7 @@ export const emailAlertLogSchema = joi.object( {
291
294
  } ),
292
295
  otherwise: joi.optional(),
293
296
  } ),
294
- cluster: joi.array().items( joi.string().required() ).optional(),
297
+ cluster: joi.array().items( joi.string().required() ).required(),
295
298
  isExport: joi.boolean().optional(),
296
299
  searchValue: joi.string().optional().allow( '' ),
297
300
  sortBy: joi.string().optional(),
@@ -410,7 +413,6 @@ export const getEmailConfigSchema = joi.object( {
410
413
  } ),
411
414
  otherwise: joi.optional(),
412
415
  } ),
413
-
414
416
  } );
415
417
 
416
418
  export const getEmailConfigValid = {
@@ -3,14 +3,14 @@ import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
3
3
  import { accessVerification } from 'tango-app-api-middleware';
4
4
  import { cancelValid, clusterListValid, emailAlertLogValid, getEmailConfigValid, getFileHistoryValid, getFileValid, getListValid, getUserConfigValid, rmListValid, saveValid, summaryCardValid, summaryListValid, updateEmailConfigValid, updateUserConfigValid, userAuditedDataValid, viewFileValid } from '../dtos/eyeTestAudit.dtos.js';
5
5
  import { addUserConfig, cancel, clusterList, emailAlertLog, getEmailConfig, getFile, getFileHistory, getList, getUserConfig, rmList, save, summaryCard, summaryList, updateEmailConfig, updateEmailConfig1, updateUserConfig, userAuditedData, viewFile } from '../controllers/eyeTestAudit.controllers.js';
6
- import { isSuperAdmin, roleValidation, sendAlert } from '../validation/eyeTest.validation.js';
6
+ import { isSuperAdmin, roleValidation } from '../validation/eyeTest.validation.js';
7
7
 
8
8
  export const eyeTestAuditRouter = Router();
9
9
 
10
10
  eyeTestAuditRouter.post( '/get-list', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( getListValid ), getList );
11
11
  eyeTestAuditRouter.get( '/view-file/:id', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( viewFileValid ), viewFile );
12
12
  eyeTestAuditRouter.get( '/get-file/:id', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( getFileValid ), getFile );
13
- eyeTestAuditRouter.post( '/save', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( saveValid ), sendAlert, save );
13
+ eyeTestAuditRouter.post( '/save', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( saveValid ), save );
14
14
  eyeTestAuditRouter.post( '/cancel', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( cancelValid ), cancel );
15
15
  eyeTestAuditRouter.get( '/get-file-history/:id/:type', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( getFileHistoryValid ), getFileHistory );
16
16
  eyeTestAuditRouter.get( '/user-audited-data/:id', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ] } ), validate( userAuditedDataValid ), userAuditedData );
@@ -1,5 +1,4 @@
1
- import { getOpenSearchById, logger } from 'tango-app-api-middleware';
2
- import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
1
+ import { logger } from 'tango-app-api-middleware';
3
2
 
4
3
  export async function roleValidation( req, res, next ) {
5
4
  try {
@@ -40,118 +39,3 @@ export async function isSuperAdmin( req, res, next ) {
40
39
  }
41
40
  }
42
41
 
43
- export async function sendAlert( req, res, next ) {
44
- try {
45
- const inputData = req.body;
46
- const openSearch = JSON.parse( process.env.OPENSEARCH );
47
- if ( inputData.auditStatus == 'ReAudited' && inputData.type == 'physical' && inputData?.isReSend == undefined ) {
48
- const getOne = await getOpenSearchById( openSearch.EyeTestInput, inputData.id );
49
- const id = `${inputData.id}_${getOne?.body?._source?.optumId}_${inputData.fileId}`;
50
- const getId = await getOpenSearchById( openSearch.eyeTestEmailAlert, id );
51
- const inputUpdatedData = getId?.body;
52
- if ( inputUpdatedData ) {
53
- return res.sendError( 'Do you want resend mail?', 202 );
54
- } else {
55
- return next();
56
- }
57
- } else {
58
- return next();
59
- }
60
- } catch ( error ) {
61
- const err = error.message;
62
- return res.sendError( err, 500 );
63
- }
64
- }
65
-
66
- /**
67
- * Send HTML Email using AWS SES
68
- * @param {Object} params
69
- * @param {string} params.toEmail - Recipient email address
70
- * @param {string} params.userName - Recipient name
71
- * @param {number} params.compliancePercentage - Compliance score
72
- */
73
- export async function sendComplianceEmail( {
74
- toEmail,
75
- fromEmail, // sender email added here
76
- userName,
77
- compliancePercentage,
78
- } ) {
79
- // Initialize AWS SES client
80
- const sesClient = new SESClient( {
81
- region: 'ap-south-1', // Change to your AWS region
82
- credentials: {
83
- accessKeyId: process.env.AWS_ACCESS_KEY_ID,
84
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
85
- },
86
- } );
87
- const htmlBody = `
88
- <!DOCTYPE html>
89
- <html>
90
- <head>
91
- <meta charset="UTF-8" />
92
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
93
- <title>Non Compliance Report</title>
94
- <style>
95
- body { font-family: 'Inter', sans-serif; margin: 0; padding: 24px; background: #f9fafb; color: #121a26; }
96
- .container { max-width: 700px; background: #fff; padding: 24px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
97
- .title { font-size: 24px; font-weight: 700; color: #121a26; }
98
- .subtitle { font-size: 16px; color: #384860; line-height: 1.5; margin-top: 8px; }
99
- .table { width: 100%; border-collapse: collapse; margin-top: 16px; }
100
- .table th, .table td { text-align: left; padding: 12px 16px; border-bottom: 1px solid #eaeef0; color: #667085; }
101
- .footer { margin-top: 32px; font-size: 14px; color: #384860; }
102
- .compliance { font-size: 18px; font-weight: 700; color: #f04438; margin-top: 16px; }
103
- </style>
104
- </head>
105
- <body>
106
- <div class="container">
107
- <p class="title">Non Compliance on Eye Test Procedures</p>
108
- <p class="subtitle">
109
- Dear ${userName},<br><br>
110
- Please ensure that all conducted eye tests meet the required compliance standards.<br>
111
- Your prompt attention to this matter will help us maintain the highest standards and avoid any discrepancies.<br>
112
- Please take a look at the below findings.
113
- </p>
114
-
115
- <table class="table">
116
- <thead>
117
- <tr>
118
- <th>RM Name</th>
119
- <th>Comments</th>
120
- </tr>
121
- </thead>
122
- <tbody>
123
- <tr><td>JCC (Jackson Cross Cylinder)</td><td>Lorem ipsum dolor sit amet consectetur.</td></tr>
124
- <tr><td>DuoChrome Test</td><td>Lorem ipsum dolor sit amet consectetur.</td></tr>
125
- <tr><td>Prescription Verification</td><td>Lorem ipsum dolor sit amet consectetur.</td></tr>
126
- <tr><td>Distance-VA-Check</td><td>Lorem ipsum dolor sit amet consectetur.</td></tr>
127
- </tbody>
128
- </table>
129
-
130
- <p class="compliance">Compliance Percentage: ${compliancePercentage}%</p>
131
- <p class="footer">Regards,<br>Team Tango</p>
132
- </div>
133
- </body>
134
- </html>`;
135
-
136
- const params = {
137
- Source: fromEmail, // sender email (must be verified in SES)
138
- Destination: {
139
- ToAddresses: [ toEmail ],
140
- },
141
- Message: {
142
- Subject: { Data: 'Non Compliance on Eye Test Procedures' },
143
- Body: { Html: { Data: htmlBody } },
144
- },
145
- };
146
-
147
- try {
148
- const response = await sesClient.send( new SendEmailCommand( params ) );
149
- // console.log( 'Email sent successfully:', response.MessageId );
150
- return response;
151
- } catch ( error ) {
152
- // console.error( 'Error sending email:', error );
153
- throw error;
154
- }
155
- }
156
-
157
-