tango-app-api-trax 1.0.0-task.120 → 1.0.0-task.121

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.
@@ -0,0 +1,14 @@
1
+
2
+ {
3
+ "type": "service_account",
4
+ "project_id": "tango-trax",
5
+ "private_key_id": "2bf70eb4a3b9f4e74138bce76063c78c75e166d7",
6
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXwmrIk6t5vfdE\niIskCwdg9Q1EyugQQeA5ve8z6hKrXng/goz+gpkonPI5pHHNELgIoOaC6+3QvxRA\nKB30ETqMKkZJQORy0zUaDQq+qyqNTj5AgNizAtnxMOAf46PIe5gWvDaXkyiHN/cE\ngfFdRyW7ctm4EDub7Ii69fr96X9mmbhOtuP/4tG+MhGIe5JmHnVvM75kC1aWb+ob\n8EaQfLeWpxYqXtsEZoCHbVTm+pDUWMGqiMko7C84BcxKOT4RFk4MeV99T0UaZtab\ncgQlWFmbcvev4KeNkkkmbVCSbBawAe1EsY8QMSj1telikh0NExNodeatIbuYBtc1\nnFqaxv7zAgMBAAECggEAHBtr/54qAjBG3bCUZKaORUzdmkIiXPB2gPtGlEzkDE1A\n5DJfvruddkIrMrXcRei0zRRP3SupLiJVs9Q6R/vw5gjmX6bfKM0pZpvHw6ycAvPc\n38F9YRpEF0HAIOfea8FIV92gFs6wkOqym2kdtPL6cA9Dd625/JUAdfAc/m4CpJPG\n4mjPoNEwMi2a66RW1CghmkQ8VgnxGk05UawZ4f6r+ABko5Q/hX/B+crApbriGPo6\nMBVtqxKGcrAmdTXWF8Bpua3I8hwGRqenLc6CY1kPHCb3XleOj+BkGGxzUGRKkJcU\nwkIiLub//XlTnM8V4R72VqKOP0Zo9SUrqPtPEg8FcQKBgQDI8SWGg5NMAsGhmopl\naUtkAKrZEK/waNBVxeFfKmXhq+hZYZ0Fj4ewI/jvKRPF0zPNWuwQuYSb3LxqmaFc\ng0iQT/crlF1skU7a0vZm7wumSxuMJq+qVcEmG8e8tD9hUGAZDImWeLqZ5UfSNbcb\nF82IeFoB5LWBAq8W2ecST4QA1wKBgQDBV2puSB1jqa9ZVgUIiEGsWzgQLSJ43AmM\nLRy058kuGr11XxLXZvc0v3rB8MhMoaNurFXcUjX67dAV3F8ejqL65dCQHwBDiS32\nsMiMmHfCGBHUn/MsjsZ3LTljLC08ltAoeEuluaW9v8sT93BbrIhpdEmD+tDegqdU\nv/QMKAnDRQKBgQClTgyK3k8cpt/YLCRSTQ7iU9I5BAtZAUDybvl6qoxp3Fwmu7DL\nVEpR0yYEyYwkoBzrgTLWh2faOPsfzwb57l6RqdcymLlKiTePuSFPiLPSt9MPtvuo\nayecTBpC2R2S1uZXdQLzMJqB5CbzfZEGzswcyrVw/U97tFOJvvTjEVsMvQKBgHdj\nWHhzFZrWTE45HPCQ2yToSy1KAbBqB4dE0CYxvvw2TOmuZL8YeOxclRwvaDBR287a\nokZjiavCsCzfoOkIoUGXKfvk+M+7ZOOhdKXE/KahIFmQz6OjIpCzH23K+MAiTLXA\n2s2iXuNWDLvunrYtSyr7QO47skDEozllMvlSu/yVAoGAWKjKVyJZeX1yh6ndzfRh\nszTRQ31W77guZm3j0CJtA7SO8eRWLdeg4BwlMT1YFer/Z65QvhJUgAdnh0Iu4Yv/\niFJ6ZwkNWnWg0239WhSroeVwIobafB/0maILkax5NcBcBvIZxBbvS4Y7bR3HqA7r\nxKbTG5i67w5TetuhLWQjt10=\n-----END PRIVATE KEY-----\n",
7
+ "client_email": "firebase-adminsdk-k7lom@tango-trax.iam.gserviceaccount.com",
8
+ "client_id": "112026772051782321525",
9
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
10
+ "token_uri": "https://oauth2.googleapis.com/token",
11
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
12
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-k7lom%40tango-trax.iam.gserviceaccount.com",
13
+ "universe_domain": "googleapis.com"
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-trax",
3
- "version": "1.0.0-task.120",
3
+ "version": "1.0.0-task.121",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -26,7 +26,11 @@
26
26
  "tango-api-schema": "^2.1.87",
27
27
  "tango-app-api-middleware": "^3.1.43-alpha.10",
28
28
  "winston": "^3.13.1",
29
- "winston-daily-rotate-file": "^5.0.0"
29
+ "winston-daily-rotate-file": "^5.0.0",
30
+ "url": "^0.11.4",
31
+ "path": "^0.12.7",
32
+ "firebase-admin": "^13.0.0",
33
+ "fs": "^0.0.1-security"
30
34
  },
31
35
  "devDependencies": {
32
36
  "eslint": "^8.57.0",
@@ -6,12 +6,23 @@ import * as CLassign from '../services/checklistAssign.service.js';
6
6
  import * as checklistLogs from '../services/checklistlog.service.js';
7
7
  import * as lenskartEmployeeMapping from '../services/lenskartEmployeeMapping.service.js';
8
8
  import * as storeService from '../services/store.service.js';
9
+ import * as userService from '../services/user.service.js';
9
10
  import dayjs from 'dayjs';
10
11
  import customParseFormat from 'dayjs/plugin/customParseFormat.js';
11
12
  import timeZone from 'dayjs/plugin/timezone.js';
12
13
  import utc from 'dayjs/plugin/utc.js';
13
14
  import { logger } from 'tango-app-api-middleware';
14
15
  import mongoose from 'mongoose';
16
+ import admin from 'firebase-admin';
17
+ import path from 'path';
18
+ import { fileURLToPath } from 'url';
19
+ const __filename = fileURLToPath( import.meta.url ); // Get the current file path
20
+ const __dirname = path.dirname( __filename );
21
+ const serviceAccountPath = path.join( __dirname, '..', '..', 'fir-51e77-firebase-adminsdk-x3sdp-fd902b74ae.json' );
22
+ admin.initializeApp( {
23
+ credential: admin.credential.cert( serviceAccountPath ),
24
+ } );
25
+
15
26
  const ObjectId = mongoose.Types.ObjectId;
16
27
  dayjs.extend( customParseFormat );
17
28
  dayjs.extend( utc );
@@ -407,6 +418,8 @@ async function insertData( requestData ) {
407
418
  element4.publishDate = getCLconfig.publishDate;
408
419
  element4.locationCount = getCLconfig.locationCount;
409
420
  element4.scheduleRepeatedType = getCLconfig.scheduleRepeatedType;
421
+ element4.approvalEnable = getCLconfig.approver.length ? true : false;
422
+ element4.remainder = getCLconfig?.remainder || [];
410
423
  }
411
424
  if ( userIdList.length ) {
412
425
  allQuestion = allQuestion.filter( ( item ) => typeof item._id == 'undefined' );
@@ -867,3 +880,106 @@ export async function getUserStoreList( req, res ) {
867
880
  return res.sendError( error, 500 );
868
881
  }
869
882
  };
883
+
884
+ export async function pushNotification( req, res ) {
885
+ try {
886
+ let query = [ {
887
+ $match: {
888
+ date_iso: new Date( req.body.date ),
889
+ $expr: { $gt: [ { $size: '$remainder' }, 0 ] },
890
+ checklistStatus: { $ne: 'submit' },
891
+ checkListType: { $in: [ 'custom' ] },
892
+ timeFlag: 0,
893
+ },
894
+ } ];
895
+
896
+ if ( req.body.client_id && req.body.client_id.length ) {
897
+ query.push( {
898
+ $match: {
899
+ client_id: { $in: req.body.client_id },
900
+ },
901
+ } );
902
+ }
903
+
904
+ query.push( {
905
+ $project: {
906
+ scheduleEndTime_iso: 1,
907
+ store_id: 1,
908
+ storeName: 1,
909
+ checkListId: 1,
910
+ checkListName: 1,
911
+ client_id: 1,
912
+ date_iso: 1,
913
+ userId: 1,
914
+ scheduleEndTime: 1,
915
+ remainder: 1,
916
+ },
917
+ } );
918
+
919
+
920
+ let checkList = await processedchecklist.aggregate( query );
921
+
922
+ if ( !checkList.length ) {
923
+ return res.sendError( 'no data', 204 );
924
+ }
925
+
926
+ let checklistDetails = [];
927
+
928
+ let promises = checkList.map( async ( item ) => {
929
+ await checkTimeZone( [ item ] );
930
+ } );
931
+
932
+ await Promise.all( promises );
933
+
934
+ async function checkTimeZone( ele ) {
935
+ return Promise.all(
936
+ ele.map( async ( data ) => {
937
+ let getStoreZone = await storeService.findOne(
938
+ { storeId: data.store_id, clientId: data.client_id },
939
+ { storeProfile: 1 },
940
+ );
941
+ if ( getStoreZone ) {
942
+ let checklistDate = dayjs( dayjs( data.scheduleEndTime, 'hh:mm A' ) ).tz( getStoreZone.storeProfile.timeZone, true );
943
+ let date = dayjs().tz( getStoreZone.storeProfile.timeZone );
944
+ if ( data?.remainder?.length && data.remainder.includes( checklistDate.diff( date, 'minute' ) ) ) {
945
+ let getToken = await userService.findOne( { _id: data.userId }, { fcmToken: 1 } );
946
+ if ( getToken?.fcmToken ) {
947
+ let existCheck = checklistDetails.findIndex( ( item ) => item.checklistName == data.checkListName );
948
+ if ( existCheck ) {
949
+ checklistDetails[existCheck].token.push( getToken.fcmToken );
950
+ } else {
951
+ checklistDetails.push( { checklistName: data.checkListName, token: [ getToken.fcmToken ] } );
952
+ }
953
+ }
954
+ }
955
+ }
956
+ } ),
957
+ );
958
+ }
959
+
960
+ if ( !checklistDetails.length ) {
961
+ return res.sendError( 'no data found', 204 );
962
+ }
963
+
964
+ checklistDetails.forEach( async ( item ) => {
965
+ const message = {
966
+ tokens: item.token,
967
+ notification: {
968
+ title: 'Remainder to Fil checklist',
969
+ body: `${item.checklistName} checklist is going to breach within few minutes`,
970
+ },
971
+ data: {
972
+ customKey: 'customValue',
973
+ },
974
+ };
975
+ const response = await admin.messaging().sendEachForMulticast( message );
976
+ if ( response.successCount ) {
977
+ return res.sendSuccess( 'Push notification send successfully' );
978
+ }
979
+ return res.sendError( 'Push notification send Failed', 500 );
980
+ } );
981
+ } catch ( e ) {
982
+ logger.error( { function: 'pushNotification', error: e } );
983
+ return res.sendError( e, 500 );
984
+ }
985
+ }
@@ -29,7 +29,7 @@ export async function storeList( req, res ) {
29
29
  if ( !req.query?.date ) {
30
30
  return res.sendError( 'date is required', 400 );
31
31
  }
32
- let userChecklist = await processedchecklist.find( { userId: req.user._id, userEmail: req.user.email, date_string: dayjs( req.query.date ).format( 'YYYY-MM-DD' ) }, { store_id: 1, storeName: 1 } );
32
+ let userChecklist = await processedchecklist.find( { userId: req.user._id, userEmail: req.user.email, client_id: req.user.clientId, date_string: dayjs( req.query.date ).format( 'YYYY-MM-DD' ) }, { store_id: 1, storeName: 1 } );
33
33
  if ( !userChecklist.length ) {
34
34
  return res.sendSuccess( [] );
35
35
  }
@@ -39,7 +39,7 @@ export async function storeList( req, res ) {
39
39
  );
40
40
 
41
41
  let storeIdList = userChecklist.map( ( item ) => item.store_id );
42
- let storeStatus = await storeService.find( { storeId: { $in: storeIdList }, status: 'active' }, { storeId: 1, storeName: 1 } );
42
+ let storeStatus = await storeService.find( { storeId: { $in: storeIdList }, status: 'active', clientId: req.user.clientId }, { storeId: 1, storeName: 1 } );
43
43
  if ( storeStatus.length ) {
44
44
  storeStatus = storeStatus.map( ( item ) => {
45
45
  return { store_id: item.storeId, storeName: item.storeName };
@@ -1271,7 +1271,7 @@ export async function submitTask( req, res ) {
1271
1271
  };
1272
1272
  await checklistLogs.create( logInsertData );
1273
1273
 
1274
- updateOpenSearch( user, requestData );
1274
+ updateOpenSearchTask( user, requestData );
1275
1275
 
1276
1276
  return res.sendSuccess( 'Task Updated Successfully' );
1277
1277
  } else {
@@ -1329,6 +1329,51 @@ async function updateOpenSearch( user, data ) {
1329
1329
  }
1330
1330
  }
1331
1331
 
1332
+ async function updateOpenSearchTask( user, data ) {
1333
+ let findQuery = [ {
1334
+ $match: {
1335
+ $and: [
1336
+ { _id: new ObjectId( data.processedcheckListId ) },
1337
+ { userId: user._id },
1338
+ { date_string: data.date },
1339
+ ],
1340
+ },
1341
+ } ];
1342
+
1343
+ let getchecklist = await processedTask.aggregate( findQuery );
1344
+ if ( getchecklist.length ) {
1345
+ let logInsertData = {
1346
+ store_id: getchecklist[0].store_id,
1347
+ storeName: getchecklist[0].storeName,
1348
+ action: 'OpenSearch insert Triggered',
1349
+ checklistId: getchecklist[0].checkListId,
1350
+ checkListName: getchecklist[0].checkListName,
1351
+ client_id: user.clientId,
1352
+ };
1353
+ await checklistLogs.create( logInsertData );
1354
+ const requestOptions = {
1355
+ method: 'POST',
1356
+ headers: {
1357
+ 'Content-Type': 'application/json',
1358
+ },
1359
+ body: JSON.stringify( { doc: { ...getchecklist[0] } } ),
1360
+ };
1361
+ let url = JSON.parse( process.env.LAMBDAURL );
1362
+ let searchResponse = await fetch( url.submitTask, requestOptions );
1363
+ if ( searchResponse.ok ) {
1364
+ let logInsertData = {
1365
+ store_id: getchecklist[0].store_id,
1366
+ storeName: getchecklist[0].storeName,
1367
+ action: 'OpenSearch inserted Successfully',
1368
+ checklistId: getchecklist[0].checkListId,
1369
+ checkListName: getchecklist[0].checkListName,
1370
+ client_id: user.clientId,
1371
+ };
1372
+ await checklistLogs.create( logInsertData );
1373
+ }
1374
+ }
1375
+ }
1376
+
1332
1377
  export async function dashboard( req, res ) {
1333
1378
  try {
1334
1379
  let requestData = req.query;
@@ -1930,7 +1975,7 @@ export async function taskQuestionList( req, res ) {
1930
1975
  }
1931
1976
  }
1932
1977
 
1933
- return res.sendSuccess( checklist );
1978
+ return res.sendSuccess( [ checklist ] );
1934
1979
  } catch ( error ) {
1935
1980
  logger.error( { function: 'taskQuestionList', error } );
1936
1981
  return res.sendError( error.message || 'Internal Server Error', 500 );
@@ -1955,10 +2000,17 @@ export async function uploadAnswerImage( req, res ) {
1955
2000
  }
1956
2001
 
1957
2002
  let date = dayjs().format( 'YYYY-MM-DD' );
2003
+ let folder;
2004
+
2005
+ if ( input.type == 'custom' ) {
2006
+ folder = 'checklist-answers';
2007
+ } else {
2008
+ folder = 'task-answers';
2009
+ }
1958
2010
 
1959
2011
  if ( req.files && req.files.answerImage ) {
1960
2012
  let imageUrl;
1961
- let filePath = `checklist-answers/${req.user.clientId}/${date}/${input.checklistId}/${input.sectionName.replace( ' ', '' )}/${input.questionNo}/`;
2013
+ let filePath = `${folder}/${req.user.clientId}/${date}/${input.checklistId}/${input.sectionName.replace( ' ', '' )}/${input.questionNo}/`;
1962
2014
  let params = {
1963
2015
  fileName: `${Date.now()}-${Math.floor( 1000 + Math.random() * 9000 )}.${req.files.answerImage.name.split( '.' )[1]}`,
1964
2016
  Key: filePath,
@@ -2095,8 +2147,15 @@ export async function login( req, res ) {
2095
2147
  refreshToken: token?.refreshToken,
2096
2148
  type: 'retail',
2097
2149
  };
2150
+
2151
+ let userDetails = await userService.findOne( { fcmToken: inputData.fcmToken } );
2152
+
2153
+ if ( userDetails ) {
2154
+ await userService.updateOne( { _id: userDetails?._id }, { fcmToken: '' } );
2155
+ }
2156
+
2098
2157
  const auth = await create( record );
2099
- await userService.updateOne( { _id: result?._id }, { refreshToken: token?.refreshToken } );
2158
+ await userService.updateOne( { _id: result?._id }, { refreshToken: token?.refreshToken, fcmToken: inputData.fcmToken } );
2100
2159
 
2101
2160
  if ( auth ) {
2102
2161
  return res.sendSuccess( { result: token } );
@@ -2201,7 +2260,7 @@ export async function getStoreLocation( req, res, next ) {
2201
2260
  return res.sendError( 'No store/Checklist assigned to the user!', 400 );
2202
2261
  }
2203
2262
  } catch ( error ) {
2204
- console.log( 'SOP Mobile store check middleware error=>', error );
2263
+ logger.error( { function: 'SOP Mobile store check middleware error', error: error } );
2205
2264
  let msg = error.error ? error.error : error;
2206
2265
  return res.sendError( msg, 500 );
2207
2266
  }
@@ -3,7 +3,6 @@ import { aggregate } from '../services/processedchecklist.services.js';
3
3
  import dayjs from 'dayjs';
4
4
  import * as processedchecklistService from '../services/processedchecklist.services.js';
5
5
  import * as processedchecklistconfigService from '../services/processedchecklistconfig.services.js';
6
- import * as checklistconfigService from '../services/checklist.service.js';
7
6
 
8
7
 
9
8
  import utc from 'dayjs/plugin/utc.js';
@@ -783,7 +782,9 @@ export const flagTablesV1 = async ( req, res ) => {
783
782
  { date_iso: { $lte: toDate } },
784
783
  );
785
784
 
786
- if ( requestData?.filter === 'question' ) {
785
+ if ( requestData?.filter === 'all' ) {
786
+ findAndQuery.push( { $or: [ { questionFlag: { $gte: 1 } }, { timeFlag: { $gte: 1 } }, { checkListType: { $ne: 'custom' } } ] } );
787
+ } else if ( requestData?.filter === 'question' ) {
787
788
  findAndQuery.push( { checkListType: 'custom' } );
788
789
  findAndQuery.push( { questionFlag: { $gte: 1 } } );
789
790
  } else if ( requestData?.filter === 'time' ) {
@@ -2585,34 +2586,105 @@ export const checklistDropdownSourceChecklist = async ( req, res ) => {
2585
2586
  export const checklistDropdownV1 = async ( req, res ) => {
2586
2587
  try {
2587
2588
  let requestData = req.body;
2589
+ let fromDate = new Date( requestData.fromDate );
2590
+ let toDate = new Date( requestData.toDate );
2591
+ let userTimezoneOffset = toDate.getTimezoneOffset() * 60000;
2592
+ toDate = new Date( toDate.getTime() - userTimezoneOffset );
2593
+ toDate.setUTCHours( 23, 59, 59, 59 );
2588
2594
  let result = {};
2589
- let findQuery = [];
2590
- let findAndQuery = [];
2591
- findAndQuery.push(
2595
+
2596
+ let findQuery = [
2597
+ { $match: { $and: [
2592
2598
  { client_id: requestData.clientId },
2593
- { isdeleted: false },
2594
- );
2595
- findQuery.push( { $match: { $and: findAndQuery } } );
2596
- findQuery.push( {
2597
- $project: {
2598
- sourceCheckList_id: '$_id',
2599
- checkListName: 1,
2600
- checkListNameLowercase: { $toLower: '$checkListName' },
2601
- checkListType: 1,
2602
- createdByName: 1,
2603
- storeCount: 1,
2604
- scheduleRepeatedType: 1,
2605
- scheduleStartTime: 1,
2606
- scheduleEndTime: 1,
2607
- publish: 1,
2599
+ {
2600
+ $or: [
2601
+ { store_id: { $in: requestData.storeId } },
2602
+ { aiStoreList: { $in: requestData.storeId } },
2603
+ ],
2604
+ },
2605
+ { date_iso: { $gte: fromDate } },
2606
+ { date_iso: { $lte: toDate } },
2607
+ {
2608
+ $or: [
2609
+ { questionFlag: { $gte: 1 } },
2610
+ { timeFlag: { $gte: 1 } },
2611
+ { checkListType: { $ne: 'custom' } },
2612
+ ],
2613
+ },
2614
+ ] } },
2615
+ {
2616
+ $project: {
2617
+ sourceCheckList_id: 1,
2618
+ checkListName: 1,
2619
+ },
2608
2620
  },
2609
- } );
2610
- if ( requestData.sortColumnName && requestData.sortColumnName != '' && requestData.sortBy && requestData.sortBy !='' ) {
2611
- findQuery.push( { $sort: { [requestData.sortColumnName]: requestData.sortBy } } );
2612
- } else {
2613
- findQuery.push( { $sort: { ['checkListNameLowercase']: 1 } } );
2614
- }
2615
- let getChecklistData = await checklistconfigService.aggregate( findQuery );
2621
+ {
2622
+ $group: {
2623
+ _id: '$sourceCheckList_id',
2624
+ checkListName: { $last: '$checkListName' },
2625
+ },
2626
+ },
2627
+ {
2628
+ $project: {
2629
+ _id: 0,
2630
+ sourceCheckList_id: '$_id',
2631
+ checkListName: 1,
2632
+ },
2633
+ },
2634
+ {
2635
+ $lookup: {
2636
+ from: 'checklistconfigs',
2637
+ let: { sourceId: '$sourceCheckList_id' },
2638
+ pipeline: [
2639
+ {
2640
+ $match: {
2641
+ $expr: {
2642
+ $and: [
2643
+ { $eq: [ '$_id', '$$sourceId' ] },
2644
+ ],
2645
+ },
2646
+ },
2647
+ },
2648
+ {
2649
+ $project: {
2650
+ _id: 1,
2651
+ checkListName: 1,
2652
+ checkListNameLowercase: { $toLower: '$checkListName' },
2653
+ checkListType: 1,
2654
+ createdByName: 1,
2655
+ publish: 1,
2656
+ scheduleEndTime: 1,
2657
+ scheduleRepeatedType: 1,
2658
+ scheduleStartTime: 1,
2659
+ sourceCheckList_id: '$_id',
2660
+ storeCount: 1,
2661
+ },
2662
+ },
2663
+ ], as: 'checklistData',
2664
+ },
2665
+ },
2666
+ { $unwind: { path: '$checklistData', preserveNullAndEmptyArrays: true } },
2667
+ {
2668
+ $project: {
2669
+ _id: '$checklistData._id',
2670
+ checkListName: '$checklistData.checkListName',
2671
+ checkListNameLowercase: { $toLower: '$checkListName' },
2672
+ checkListType: '$checklistData.checkListType',
2673
+ createdByName: '$checklistData.createdByName',
2674
+ publish: '$checklistData.publish',
2675
+ scheduleEndTime: '$checklistData.scheduleEndTime',
2676
+ scheduleRepeatedType: '$checklistData.scheduleRepeatedType',
2677
+ scheduleStartTime: '$checklistData.scheduleStartTime',
2678
+ sourceCheckList_id: '$checklistData._id',
2679
+ storeCount: '$checklistData.storeCount',
2680
+ },
2681
+ },
2682
+ ];
2683
+
2684
+ findQuery.push( { $sort: { checkListName: 1 } } );
2685
+
2686
+ let getChecklistData = await processedchecklistService.aggregate( findQuery );
2687
+
2616
2688
  if ( !getChecklistData.length ) {
2617
2689
  return res.sendError( { error: 'No Data Found' }, 204 );
2618
2690
  }
@@ -5,7 +5,7 @@ import * as assignedService from '../services/checklistAssign.service.js';
5
5
  import * as clientService from '../services/clients.services.js';
6
6
  import * as reisedTicketService from '../services/ticket.service.js';
7
7
  import * as userService from '../services/user.service.js';
8
- import * as domainService from '../services/domain.service.js';
8
+ // import * as domainService from '../services/domain.service.js';
9
9
  import * as storeService from '../services/store.service.js';
10
10
  import mongoose from 'mongoose';
11
11
  import * as processedchecklistConfig from '../services/processedchecklistconfig.services.js';
@@ -13,6 +13,7 @@ import * as processedchecklist from '../services/processedchecklist.services.js'
13
13
  import * as checklistLogs from '../services/checklistlog.service.js';
14
14
  import * as tagService from '../services/tagging.service.js';
15
15
  import * as alertsServices from '../services/clientRequest.service.js';
16
+ import * as traxApprover from '../services/approver.service.js';
16
17
  const ObjectId = mongoose.Types.ObjectId;
17
18
  import dayjs from 'dayjs';
18
19
  import customParseFormat from 'dayjs/plugin/customParseFormat.js';
@@ -779,18 +780,25 @@ export const assignedUserDetails = async ( req, res ) => {
779
780
  }
780
781
  }
781
782
 
782
- let checklistCount = await assignedService.aggregate( query );
783
-
784
- query.push( { $skip: skip }, { $limit: limit } );
783
+ query.push( {
784
+ $facet: {
785
+ data: [
786
+ { $skip: skip }, { $limit: limit },
787
+ ],
788
+ count: [
789
+ { $count: 'total' },
790
+ ],
791
+ },
792
+ } );
785
793
 
786
794
  let checklistDetails = await assignedService.aggregate( query );
787
795
 
788
- if ( !checklistDetails.length ) {
796
+ if ( !checklistDetails[0].data.length ) {
789
797
  return res.sendError( 'no data found', 204 );
790
798
  }
791
799
 
792
800
  let userDetails = [];
793
- checklistDetails.forEach( ( item ) => {
801
+ checklistDetails[0].data.forEach( ( item ) => {
794
802
  userDetails.push( {
795
803
  id: item._id,
796
804
  userName: item.userName,
@@ -802,7 +810,7 @@ export const assignedUserDetails = async ( req, res ) => {
802
810
  checkFlag: item.checkFlag,
803
811
  } );
804
812
  } );
805
- return res.sendSuccess( { users: userDetails, count: checklistCount.length } );
813
+ return res.sendSuccess( { users: userDetails, count: checklistDetails[0].count[0].total } );
806
814
  } catch ( e ) {
807
815
  logger.error( 'assignedUserDetails =>', e );
808
816
  return res.sendError( e, 500 );
@@ -892,7 +900,7 @@ export const updateConfigure =async ( req, res ) => {
892
900
  let logInsertData = {
893
901
  action: inputBody.submitType == 'publish' ? 'checklistPublishUsingConfigPage' : 'checklistConfigDraft',
894
902
  checklistId: inputBody.checkListDetails._id,
895
- checkListName: inputBody?.checkListDetails.checklistName,
903
+ checkListName: inputBody?.checkListDetails.checkListName,
896
904
  createdBy: req.user._id,
897
905
  createdByName: req.user.userName,
898
906
  client_id: req.body.clientId,
@@ -939,8 +947,32 @@ export const updateConfigure =async ( req, res ) => {
939
947
  configEndDate: inputBody?.checkListDetails?.configEndDate || '',
940
948
  specificDate: inputBody?.checkListDetails?.specificDate || [],
941
949
  allowOnce: inputBody?.checkListDetails?.allowOnce || false,
950
+ approver: inputBody?.checkListDetails?.approver || [],
951
+ remainder: inputBody?.checkListDetails?.remainder || [],
942
952
  };
943
953
 
954
+ if ( inputBody?.checkListDetails?.approver.length ) {
955
+ let data = [];
956
+ let existEmail = await traxApprover.find( { checkListId: inputBody.checkListDetails._id, isDeleted: false } );
957
+ let mailList = existEmail.map( ( item ) => item.userEmail );
958
+ existEmail = inputBody?.checkListDetails?.approver.filter( ( item ) => mailList.includes( item.value ) ).map( ( item ) => item.value );
959
+ let userMailList = inputBody?.checkListDetails?.approver.map( ( ele ) => ele.value );
960
+ inputBody?.checkListDetails?.approver.forEach( ( ele ) => {
961
+ if ( !existEmail.includes( ele.value ) ) {
962
+ data.push( {
963
+ userEmail: ele.value,
964
+ checkListId: inputBody.checkListDetails._id,
965
+ type: 'checklist',
966
+ } );
967
+ }
968
+ } );
969
+
970
+ await traxApprover.updateMany( { checkListId: inputBody.checkListDetails._id, userEmail: { $nin: userMailList } }, { isDeleted: true } );
971
+ if ( data.length ) {
972
+ await traxApprover.insertMany( data );
973
+ }
974
+ }
975
+
944
976
 
945
977
  if ( checklistDetails.checkListType != 'custom' && !checklistDetails.client_id ) {
946
978
  let getchecklistNumber = await checklistService.findOne( { client_id: req.body.clientId, type: 'checklist' }, { checkListNumber: 1 } );
@@ -1282,7 +1314,7 @@ export const validateUser = async ( req, res ) => {
1282
1314
 
1283
1315
  if ( !req.body?.addUser ) {
1284
1316
  if ( req.body.hasOwnProperty( 'delete' ) ) {
1285
- let checkExists = await assignedService.findOne( { userEmail: req.body.assignedUsers[0].userEmail, storeName: req.body.assignedUsers[0].storeName } );
1317
+ let checkExists = await assignedService.findOne( { userEmail: req.body.assignedUsers[0].userEmail, storeName: req.body.assignedUsers[0].storeName, checkListId: req.body.id } );
1286
1318
  if ( checkExists ) {
1287
1319
  return res.sendError( 'User already Exists', 400 );
1288
1320
  }
@@ -1349,11 +1381,11 @@ export const validateUser = async ( req, res ) => {
1349
1381
  ];
1350
1382
  let userDetails = await userService.aggregate( query );
1351
1383
  if ( !userDetails.length ) {
1352
- let checkDomain = item.userEmail.split( '@' )[1].toLowerCase();
1353
- let brandDomainExists = await domainService.find( { domain: { $regex: checkDomain } } );
1354
- if ( !brandDomainExists ) {
1355
- domainExists.push( { message: 'Domain is not exists', email: item.userEmail } );
1356
- }
1384
+ // let checkDomain = item.userEmail.split( '@' )[1].toLowerCase();
1385
+ // let brandDomainExists = await domainService.findOne( { domain: { $regex: checkDomain } } );
1386
+ // if ( !brandDomainExists ) {
1387
+ // domainExists.push( { message: 'Domain is not exists', email: item.userEmail } );
1388
+ // }
1357
1389
  let filteredEmail = userEmail.find( ( ele ) => ele.userEmail.toLowerCase() == item.userEmail.toLowerCase() );
1358
1390
  if ( !filteredEmail ) {
1359
1391
  userEmail.push( { userName: item.userName, userEmail: item.userEmail } );
@@ -1390,7 +1422,7 @@ export const validateUser = async ( req, res ) => {
1390
1422
  }
1391
1423
  } else {
1392
1424
  if ( req.body.hasOwnProperty( 'delete' ) ) {
1393
- let checkExists = await assignedService.findOne( { userEmail: req.body.assignedUsers[0].userEmail, storeName: req.body.assignedUsers[0].storeName } );
1425
+ let checkExists = await assignedService.findOne( { userEmail: req.body.assignedUsers[0].userEmail, storeName: req.body.assignedUsers[0].storeName, checkListId: req.body.id } );
1394
1426
  if ( checkExists ) {
1395
1427
  return res.sendError( 'User already Exists', 400 );
1396
1428
  }
@@ -1956,6 +1988,8 @@ async function insertPCBulkV3( getCLconfig, checklistId, currentdate, updatedche
1956
1988
  element4.publishDate = getCLconfig.publishDate;
1957
1989
  element4.locationCount = getCLconfig.locationCount;
1958
1990
  element4.scheduleRepeatedType = getCLconfig.scheduleRepeatedType;
1991
+ element4.approvalEnable = getCLconfig.approver.length ? true : false;
1992
+ element4.remainder = getCLconfig?.remainder || [];
1959
1993
  }
1960
1994
  if ( userIdList.length ) {
1961
1995
  allQuestion = allQuestion.filter( ( item ) => typeof item._id == 'undefined' );
@@ -2011,7 +2045,7 @@ export const aiChecklist = async ( req, res ) => {
2011
2045
 
2012
2046
  export const preDefinedChecklist = async ( req, res ) => {
2013
2047
  try {
2014
- let data = [ 'opertaionchecklist', 'storehygiene', 'dailystorechecklist', 'lossprevention' ];
2048
+ let data = [ 'opertaionchecklist', 'storehygiene', 'dailystorechecklist', 'lossprevention', 'Infrastructure', 'dailystoreweekday' ];
2015
2049
  let details = [];
2016
2050
  let predefinedWithoutClient = [];
2017
2051
  let predefinedDetails = [];