tango-app-api-trax 3.4.1-alpha-20 → 3.4.1-approvecheck-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { fileUpload, chunkArray, logger, sendPushNotification } from 'tango-app-api-middleware';
1
+ import { signedUrl, fileUpload, chunkArray, logger, sendPushNotification, sendTeamsNotification, insertOpenSearchData } from 'tango-app-api-middleware';
2
2
  import * as checklistService from '../services/checklist.service.js';
3
3
  import * as questionService from '../services/checklistQuestion.service.js';
4
4
  import * as assignedService from '../services/checklistAssign.service.js';
@@ -247,15 +247,14 @@ export const create = async ( req, res ) => {
247
247
  section.questions[qIdx].answers[index].nestedQuestion = [];
248
248
  }
249
249
  if ( answer.showLinked ) {
250
- // section.questions[qIdx].answers[nestedIndex].nestedQuestion.push( answer.linkedQuestion );
251
250
  if ( nestedIndex != -1 ) {
252
- // if ( !section.questions[qIdx].answers[nestedIndex].nestedQuestion.includes( answer.linkedQuestion ) ) {
253
- section.questions[qIdx].answers[nestedIndex].nestedQuestion.push( answer.linkedQuestion );
254
- // }
251
+ if ( !section.questions[qIdx].answers[nestedIndex].nestedQuestion.includes( answer.linkedQuestion ) ) {
252
+ section.questions[qIdx].answers[nestedIndex].nestedQuestion.push( answer.linkedQuestion );
253
+ }
255
254
  } else {
256
- // if ( !section.questions[qIdx].answers[index].nestedQuestion.includes( answer.linkedQuestion ) ) {
257
- section.questions[qIdx].answers[index].nestedQuestion.push( answer.linkedQuestion );
258
- // }
255
+ if ( !section.questions[qIdx].answers[index].nestedQuestion.includes( answer.linkedQuestion ) ) {
256
+ section.questions[qIdx].answers[index].nestedQuestion.push( answer.linkedQuestion );
257
+ }
259
258
  }
260
259
  let nestedLinkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
261
260
  if ( nestedLinkedQuestion ) {
@@ -272,18 +271,6 @@ export const create = async ( req, res ) => {
272
271
  }
273
272
  }
274
273
  }
275
- let checkNestedLevel = false;
276
- section.questions.forEach( ( qns ) => {
277
- qns.answers.forEach( ( answ ) => {
278
- if ( answ.nestedQuestion.length > 20 ) {
279
- checkNestedLevel = true;
280
- }
281
- } );
282
- } );
283
-
284
- if ( checkNestedLevel ) {
285
- return res.sendError( { message: 'Unable to create more than 20 linked questions.' }, 400 );
286
- }
287
274
 
288
275
  let sectionList = {
289
276
  section: section.name,
@@ -296,10 +283,54 @@ export const create = async ( req, res ) => {
296
283
  };
297
284
  await questionService.create( sectionList ).then( async ( data ) => {
298
285
  if ( i == inputBody.sections.length - 1 ) {
286
+ let actionType = 'created';
287
+ let teamsMsg;
288
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
289
+ actionType = 'Create';
290
+ teamsMsg = 'ClientId: '+ req.body.clientId + ', Action: '+ actionType + ', ChecklistId: '+ checkListId + ', Checklist Name: '+ inputBody.checklistName + ', UpDatedBy: '+ req.user.email;
291
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
292
+
293
+ let logObj = {
294
+ client_id: inputBody.clientId,
295
+ createAt: new Date(),
296
+ sourceCheckList_id: checkListId,
297
+ checkListName: inputBody.checklistName,
298
+ fromCheckListName: '',
299
+ type: 'checklist',
300
+ action: 'created',
301
+ storeName: '',
302
+ store_id: '',
303
+ createdByEmail: req.user.email,
304
+ createdBy: req.user.userName,
305
+ coverage: 'store',
306
+ logDetails: {},
307
+ userType: req.user.userType,
308
+ };
309
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
310
+ if ( inputBody.submitType == 'save' ) {
311
+ let logObj = {
312
+ client_id: inputBody.clientId,
313
+ createAt: new Date(),
314
+ sourceCheckList_id: checkListId,
315
+ checkListName: inputBody.checklistName,
316
+ fromCheckListName: '',
317
+ type: 'checklist',
318
+ action: 'draft',
319
+ storeName: '',
320
+ store_id: '',
321
+ createdByEmail: req.user.email,
322
+ createdBy: req.user.userName,
323
+ coverage: 'store',
324
+ logDetails: {},
325
+ userType: req.user.userType,
326
+ };
327
+
328
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
329
+ }
330
+
299
331
  return res.sendSuccess( { checklistId: checkListId, msg: 'CheckList Created Successfully' } );
300
332
  }
301
333
  } ).catch( ( e ) => {
302
- console.log( e );
303
334
  return res.sendError( e, 500 );
304
335
  } );
305
336
  }
@@ -309,11 +340,11 @@ export const create = async ( req, res ) => {
309
340
  }
310
341
  }
311
342
  } ).catch( async ( e ) => {
312
- console.log( e );
313
343
  await checklistService.deleteOne( { _id: checkListId } );
314
344
  return res.sendError( e, 500 );
315
345
  } );
316
346
  } catch ( e ) {
347
+ // console.log( 'e', e );
317
348
  logger.error( 'create =>', e );
318
349
  return res.sendError( e, 500 );
319
350
  }
@@ -373,23 +404,23 @@ export const getConfigDetails = async ( req, res ) => {
373
404
  let questionDetails = await questionService.find( query );
374
405
  if ( questionDetails.length ) {
375
406
  let sections = [];
376
- // let bucket = JSON.parse( process.env.BUCKET );
407
+ let bucket = JSON.parse( process.env.BUCKET );
377
408
  questionDetails.forEach( ( item ) => {
378
409
  item.question.forEach( async ( question ) => {
379
410
  if ( question.questionReferenceImage && question.questionReferenceImage !='' ) {
380
- // let inputData = {
381
- // Bucket: bucket.sop,
382
- // file_path: decodeURIComponent( question.questionReferenceImage ),
383
- // };
384
- question.questionReferenceImage = JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+question.questionReferenceImage;
411
+ let inputData = {
412
+ Bucket: bucket.sop,
413
+ file_path: decodeURIComponent( question.questionReferenceImage ),
414
+ };
415
+ question.questionReferenceImage = await signedUrl( inputData );
385
416
  }
386
417
  question.answers.forEach( async ( answer ) => {
387
418
  if ( answer.referenceImage != '' ) {
388
- // let inputData = {
389
- // Bucket: bucket.sop,
390
- // file_path: decodeURIComponent( answer.referenceImage ),
391
- // };
392
- answer.referenceImage = JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+answer.referenceImage;
419
+ let inputData = {
420
+ Bucket: bucket.sop,
421
+ file_path: decodeURIComponent( answer.referenceImage ),
422
+ };
423
+ answer.referenceImage = await signedUrl( inputData );
393
424
  }
394
425
  } );
395
426
  } );
@@ -621,6 +652,30 @@ export const deleteChecklist = async ( req, res ) => {
621
652
  await processedchecklist.deleteMany( { date_string: { $ne: date }, date_iso: { $gt: date }, sourceCheckList_id: req.params.checklistId, checklistStatus: { $ne: 'submit' } } );
622
653
  logger.info( { function: 'deleteChecklist', query: { date_string: { $ne: date }, date_iso: { $gt: date }, sourceCheckList_id: req.params.checklistId, checklistStatus: { $ne: 'submit' } } } );
623
654
  checklistDetails.save().then( () => {
655
+ let actionType = 'Deleted';
656
+ let teamsMsg;
657
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
658
+ teamsMsg = 'ClientId: '+ checklistDetails.client_id + ', Action: '+ actionType + ', ChecklistId: '+ req.params.checklistId + ', Checklist Name: '+ checklistDetails.checkListName + ', UpDatedBy: '+ req.user.email;
659
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
660
+
661
+ let logObj = {
662
+ client_id: checklistDetails.client_id,
663
+ createAt: new Date(),
664
+ sourceCheckList_id: checklistDetails._id,
665
+ checkListName: checklistDetails.checkListName,
666
+ fromCheckListName: '',
667
+ type: 'checklist',
668
+ action: 'deleted',
669
+ storeName: '',
670
+ store_id: '',
671
+ createdByEmail: req.user.email,
672
+ createdBy: req.user.userName,
673
+ coverage: checklistDetails.coverage,
674
+ logDetails: {},
675
+ userType: req.user.userType,
676
+ };
677
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
678
+
624
679
  return res.sendSuccess( { message: 'Checklist Deleted Successfully' } );
625
680
  } ).catch( ( e ) => {
626
681
  return res.sendError( e, 500 );
@@ -694,6 +749,29 @@ export const duplicateChecklist = async ( req, res ) => {
694
749
  sections.push( sectionDetails );
695
750
  }
696
751
  await questionService.insertMany( sections );
752
+ let actionType = 'Duplicated';
753
+ let teamsMsg;
754
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
755
+ teamsMsg = 'ClientId: '+ checkDetails.client_id + ', Action: '+ actionType + ', ChecklistId: '+ data._id + ', Checklist Name: '+ checkDetails.checkListName + ', UpDatedBy: '+ req.user.email;
756
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
757
+
758
+ let logObj = {
759
+ client_id: checkDetails.client_id,
760
+ createAt: new Date(),
761
+ sourceCheckList_id: checkDetails._id,
762
+ checkListName: checkDetails.checkListName,
763
+ fromCheckListName: '',
764
+ type: 'checklist',
765
+ action: 'duplicated',
766
+ storeName: '',
767
+ store_id: '',
768
+ createdByEmail: req.user.email,
769
+ createdBy: req.user.userName,
770
+ coverage: checkDetails.coverage,
771
+ logDetails: {},
772
+ userType: req.user.userType,
773
+ };
774
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
697
775
  return res.sendSuccess( { message: 'CheckList Duplicated Successfully' } );
698
776
  } else {
699
777
  return res.sendSuccess( { message: 'duplicated Successfully' } );
@@ -730,6 +808,8 @@ export const update = async ( req, res ) => {
730
808
  return res.sendError( 'no data found', 204 );
731
809
  }
732
810
 
811
+ let getExistQuestions = await questionService.find( { checkListId: req.params.checklistId, client_id: req.body.clientId } );
812
+
733
813
  inputBody.sections.forEach( async ( element ) => {
734
814
  if ( !element.questions.length && inputBody.submitType == 'configure' ) {
735
815
  return res.sendError( { message: 'Question is Required' }, 400 );
@@ -740,128 +820,235 @@ export const update = async ( req, res ) => {
740
820
  }
741
821
  } );
742
822
 
743
- checkListDetails.checkListName = inputBody.checklistName;
744
- checkListDetails.checkListDescription = inputBody.checklistDescription;
745
- checkListDetails.questionCount = questionCount;
746
823
 
747
- checkListDetails.save().then( async () => {
748
- let checkListId = req.params.checklistId;
749
- let logInsertData = {
750
- action: 'checklistUpdate',
751
- checklistId: checkListId,
752
- checkListName: inputBody.checklistName,
753
- createdBy: req.user._id,
754
- createdByName: req.user.userName,
755
- client_id: req.body.clientId,
756
- sections: inputBody?.sections,
757
- createdByEmail: req.user.email,
758
- };
759
- await checklistLogs.create( logInsertData );
760
- if ( inputBody.sections.length ) {
761
- let sectionId =[];
762
- for ( let i = 0; i < inputBody?.sections?.length; i++ ) {
763
- let section = inputBody.sections[i];
764
- section.questions.forEach( ( section ) => {
765
- if ( section.questionReferenceImage && section.questionReferenceImage !='' ) {
766
- let imgUrl = section.questionReferenceImage.split( '?' )[0];
824
+ let params = {
825
+ checkListName: inputBody.checklistName,
826
+ checkListDescription: inputBody.checklistDescription,
827
+ questionCount: questionCount,
828
+ };
829
+
830
+ await checklistService.updateOne( { _id: req.params.checklistId }, params );
831
+ let checkListId = req.params.checklistId;
832
+ let logInsertData = {
833
+ action: 'checklistUpdate',
834
+ checklistId: checkListId,
835
+ checkListName: inputBody.checklistName,
836
+ createdBy: req.user._id,
837
+ createdByName: req.user.userName,
838
+ client_id: req.body.clientId,
839
+ sections: inputBody?.sections,
840
+ createdByEmail: req.user.email,
841
+ };
842
+ await checklistLogs.create( logInsertData );
843
+ let sectionList =[];
844
+ if ( inputBody.sections.length ) {
845
+ for ( let i = 0; i < inputBody?.sections?.length; i++ ) {
846
+ let section = inputBody.sections[i];
847
+ section.questions.forEach( ( section ) => {
848
+ if ( section.questionReferenceImage && section.questionReferenceImage !='' ) {
849
+ let imgUrl = section.questionReferenceImage.split( '?' )[0];
850
+ let url = imgUrl.split( '/' );
851
+ url.splice( 0, 3 );
852
+ section.questionReferenceImage = url.join( '/' );
853
+ }
854
+ section.answers.forEach( ( answer ) => {
855
+ if ( answer.referenceImage != '' ) {
856
+ let imgUrl = answer.referenceImage.split( '?' )[0];
767
857
  let url = imgUrl.split( '/' );
768
858
  url.splice( 0, 3 );
769
- section.questionReferenceImage = url.join( '/' );
859
+ answer.referenceImage = url.join( '/' );
770
860
  }
771
- // if (['image', 'descriptiveImage'].includes(section.answerType)) {
772
- section.answers.forEach( ( answer ) => {
773
- if ( answer.referenceImage != '' ) {
774
- let imgUrl = answer.referenceImage.split( '?' )[0];
775
- let url = imgUrl.split( '/' );
776
- url.splice( 0, 3 );
777
- answer.referenceImage = url.join( '/' );
778
- }
779
- } );
780
- // }
781
861
  } );
862
+ } );
782
863
 
783
- for ( let [ index, question ] of section.questions.entries() ) {
784
- await processNested( index, question );
785
- }
864
+ for ( let [ index, question ] of section.questions.entries() ) {
865
+ await processNested( index, question );
866
+ }
786
867
 
787
- async function processNested( qIdx, question, nestedIndex=-1 ) {
788
- if ( question?.answers?.length ) {
789
- for ( let [ index, answer ] of question?.answers?.entries() ) {
790
- if ( !section.questions[qIdx].answers[index]?.nestedQuestion && nestedIndex == -1 ) {
791
- section.questions[qIdx].answers[index].nestedQuestion = [];
792
- }
793
- if ( answer.showLinked ) {
794
- if ( nestedIndex != -1 ) {
795
- // if ( !section.questions[qIdx].answers[nestedIndex].nestedQuestion.includes( answer.linkedQuestion ) ) {
868
+ async function processNested( qIdx, question, nestedIndex=-1 ) {
869
+ if ( question?.answers?.length ) {
870
+ for ( let [ index, answer ] of question?.answers?.entries() ) {
871
+ if ( !section.questions[qIdx].answers[index]?.nestedQuestion && nestedIndex == -1 ) {
872
+ section.questions[qIdx].answers[index].nestedQuestion = [];
873
+ }
874
+ if ( answer.showLinked ) {
875
+ if ( nestedIndex != -1 ) {
876
+ if ( !section.questions[qIdx].answers[nestedIndex].nestedQuestion.includes( answer.linkedQuestion ) ) {
796
877
  section.questions[qIdx].answers[nestedIndex].nestedQuestion.push( answer.linkedQuestion );
797
- // }
798
- } else {
799
- // if ( !section.questions[qIdx].answers[index].nestedQuestion.includes( answer.linkedQuestion ) ) {
878
+ }
879
+ } else {
880
+ if ( !section.questions[qIdx].answers[index].nestedQuestion.includes( answer.linkedQuestion ) ) {
800
881
  section.questions[qIdx].answers[index].nestedQuestion.push( answer.linkedQuestion );
801
- // }
802
882
  }
803
- let nestedLinkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
804
- if ( nestedLinkedQuestion ) {
805
- let findNestedAnswers = nestedLinkedQuestion.answers.find( ( item ) => item.showLinked );
806
- if ( findNestedAnswers ) {
807
- if ( nestedIndex != -1 ) {
808
- await processNested( qIdx, nestedLinkedQuestion, nestedIndex );
809
- } else {
810
- await processNested( qIdx, nestedLinkedQuestion, index );
811
- }
883
+ }
884
+ let nestedLinkedQuestion = section.questions.find( ( item ) => item.qno == answer.linkedQuestion );
885
+ if ( nestedLinkedQuestion ) {
886
+ let findNestedAnswers = nestedLinkedQuestion.answers.find( ( item ) => item.showLinked );
887
+ if ( findNestedAnswers ) {
888
+ if ( nestedIndex != -1 ) {
889
+ await processNested( qIdx, nestedLinkedQuestion, nestedIndex );
890
+ } else {
891
+ await processNested( qIdx, nestedLinkedQuestion, index );
812
892
  }
813
893
  }
814
894
  }
815
895
  }
816
896
  }
817
897
  }
898
+ }
818
899
 
819
- let checkNestedLevel = false;
820
- section.questions.forEach( ( qns ) => {
821
- qns.answers.forEach( ( answ ) => {
822
- if ( answ.nestedQuestion.length > 20 ) {
823
- checkNestedLevel = true;
824
- }
825
- } );
826
- } );
900
+ sectionList.push( {
901
+ section: section.name,
902
+ sectionOldName: section.oldName,
903
+ createdBy: req.user._id,
904
+ createdByName: req.user.userName,
905
+ client_id: req.body.clientId,
906
+ checkListId: checkListId,
907
+ question: section.questions,
908
+ checkList: inputBody.checklistName,
909
+ } );
910
+ }
911
+ }
912
+ await questionService.deleteMany( { checkListId: checkListId, client_id: req.body.clientId } );
913
+ if ( sectionList.length ) {
914
+ await questionService.insertMany( sectionList );
915
+ }
827
916
 
828
- console.log( checkNestedLevel, 'lebej' );
917
+ let questionList = {
918
+ questionAdd: [],
919
+ questionEdit: [],
920
+ questionDelete: [],
921
+ };
922
+ let updateSection = [];
829
923
 
830
- if ( checkNestedLevel ) {
831
- return res.sendError( { message: 'Unable to create more than 20 linked questions' }, 400 );
832
- }
924
+ function findDifferences( obj1, obj2 ) {
925
+ return Object.keys( obj1 ).reduce( ( diff, key ) => {
926
+ if ( !isEqual( obj1[key], obj2[key] ) ) {
927
+ diff[key] = { previous: obj1[key], new: obj2[key] };
928
+ }
929
+ return diff;
930
+ }, {} );
931
+ }
833
932
 
834
- let sectionList = {
835
- section: section.name,
836
- sectionOldName: section.oldName,
837
- createdBy: req.user._id,
838
- createdByName: req.user.userName,
839
- client_id: req.body.clientId,
840
- checkListId: checkListId,
841
- question: section.questions,
842
- checkList: inputBody.checklistName,
843
- };
844
- await questionService.create( sectionList ).then( async ( data ) => {
845
- sectionId.push( data._id );
846
- if ( i == inputBody.sections.length - 1 ) {
847
- await questionService.deleteMany( { checkListId: checkListId, client_id: req.body.clientId, _id: { $nin: sectionId } } );
848
- await assignedService.updateMany( { checkListId: checkListId }, { checkListName: inputBody.checklistName } );
849
- return res.sendSuccess( { checklistId: checkListId, msg: 'CheckList Created Successfully' } );
850
- }
851
- } ).catch( ( e ) => {
852
- return res.sendError( e, 500 );
933
+ getExistQuestions.forEach( ( ele ) => {
934
+ let sectionDetails = inputBody.sections.find( ( sec ) => sec.oldName === ele.section );
935
+
936
+ if ( !sectionDetails ) {
937
+ questionList.questionDelete.push( { sectionName: ele.section, questions: ele.question } );
938
+ return;
939
+ }
940
+
941
+ if ( ele.section !== sectionDetails.name ) {
942
+ updateSection.push( { previous: ele.section, new: sectionDetails.name } );
943
+ }
944
+
945
+ ele.question.forEach( ( qn ) => {
946
+ let question = sectionDetails.questions.find( ( qns ) => qns.oldQname === qn.qname );
947
+
948
+ if ( question ) {
949
+ qn.answers.forEach( ( ans ) => {
950
+ delete ans.answeroptionNumber;
853
951
  } );
952
+ question.answers.forEach( ( ans ) => {
953
+ delete ans.answeroptionNumber;
954
+ } );
955
+ let compare = findDifferences( qn, question );
956
+ if ( Object.keys( compare ).length ) {
957
+ questionList.questionEdit.push( { sectionName: ele.section, questions: [ { previous: qn, new: question } ] } );
958
+ }
959
+ } else {
960
+ let sectionIndex = questionList.questionDelete.findIndex( ( sec ) => sec.sectionName === ele.section );
961
+
962
+ if ( sectionIndex !== -1 ) {
963
+ questionList.questionDelete[sectionIndex].questions.push( qn );
964
+ } else {
965
+ questionList.questionDelete.push( { sectionName: ele.section, questions: [ qn ] } );
966
+ }
854
967
  }
855
- } else {
856
- if ( inputBody.submitType == 'save' ) {
857
- await questionService.deleteMany( { checkListId: checkListId, client_id: req.body.clientId } );
858
- return res.sendSuccess( { message: 'CheckList Updated Successfully' } );
859
- }
968
+ } );
969
+ } );
970
+
971
+ inputBody.sections.forEach( ( ele ) => {
972
+ let sectionDetails = getExistQuestions.find( ( sec ) => sec.section === ele.oldName );
973
+
974
+ if ( !sectionDetails ) {
975
+ questionList.questionAdd.push( { sectionName: ele.name, questions: ele.questions } );
976
+ return;
860
977
  }
861
- } ).catch( ( e ) => {
862
- logger.error( 'update =>', e );
863
- return res.sendError( e, 500 );
978
+
979
+ ele.questions.forEach( ( qn ) => {
980
+ let question = sectionDetails.question.find( ( qns ) => qns.qname === qn.oldQname );
981
+
982
+ if ( !question ) {
983
+ let sectionIndex = questionList.questionAdd.findIndex( ( sec ) => sec.sectionName === ele.name );
984
+
985
+ if ( sectionIndex !== -1 ) {
986
+ questionList.questionAdd[sectionIndex].questions.push( qn );
987
+ } else {
988
+ questionList.questionAdd.push( { sectionName: ele.name, questions: [ qn ] } );
989
+ }
990
+ }
991
+ } );
864
992
  } );
993
+
994
+ if ( updateSection.length || questionList.questionAdd.length || questionList.questionEdit.length || questionList.questionDelete.length || inputBody.checklistName.toLowerCase() != checkListDetails.checkListName.toLowerCase() || inputBody.checklistDescription.toLowerCase() != checkListDetails.checkListDescription.toLowerCase() ) {
995
+ let insertLogData = {
996
+ client_id: req.body.clientId,
997
+ createAt: new Date(),
998
+ sourceCheckList_id: req.params.checklistId,
999
+ checkListName: inputBody.checklistName,
1000
+ fromCheckListName: '',
1001
+ type: 'checklist',
1002
+ action: 'edited',
1003
+ storeName: '',
1004
+ store_id: '',
1005
+ createdByEmail: req.user.email,
1006
+ createdBy: req.user.userName,
1007
+ coverage: checkListDetails.coverage,
1008
+ logDetails: {
1009
+ ...( inputBody.checklistName.toLowerCase() == checkListDetails.checkListName.toLowerCase() ) ? { updatedChecklistName: {} } :{ updatedChecklistName: {
1010
+ previous: checkListDetails.checkListName,
1011
+ new: inputBody.checklistName,
1012
+ } },
1013
+ ...( inputBody.checklistDescription.toLowerCase() == checkListDetails.checkListDescription.toLowerCase() ) ? { updatedChecklistDescription: {} } :{ updatedChecklistDescription: {
1014
+ previous: checkListDetails.checkListDescription,
1015
+ new: inputBody.checklistDescription,
1016
+ } },
1017
+ updatedSectionName: updateSection,
1018
+ questionAdd: questionList.questionAdd,
1019
+ questionEdit: questionList.questionEdit,
1020
+ questionDelete: questionList.questionDelete,
1021
+ },
1022
+ userType: req.user.userType,
1023
+ };
1024
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, insertLogData );
1025
+ }
1026
+
1027
+ if ( inputBody.submitType == 'save' ) {
1028
+ let logObj = {
1029
+ client_id: inputBody.clientId,
1030
+ createAt: new Date(),
1031
+ sourceCheckList_id: req.params.checklistId,
1032
+ checkListName: inputBody.checklistName,
1033
+ fromCheckListName: '',
1034
+ type: 'checklist',
1035
+ action: 'draft',
1036
+ storeName: '',
1037
+ store_id: '',
1038
+ createdByEmail: req.user.email,
1039
+ createdBy: req.user.userName,
1040
+ coverage: 'store',
1041
+ logDetails: {},
1042
+ userType: req.user.userType,
1043
+ };
1044
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
1045
+ }
1046
+ let actionType = 'Checklist Updated';
1047
+ let teamsMsg;
1048
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
1049
+ teamsMsg = 'ClientId: '+ req.body.clientId + ', Action: '+ actionType + ', ChecklistId: '+ checkListId + ', Checklist Name: '+ inputBody.checklistName + ', UpDatedBy: '+ req.user.email;
1050
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
1051
+ return res.sendSuccess( { message: 'CheckList Updated Successfully', checklistId: req.params.checklistId } );
865
1052
  } catch ( e ) {
866
1053
  logger.error( 'update =>', e );
867
1054
  return res.sendError( e, 500 );
@@ -889,11 +1076,11 @@ export const uploadImage = async ( req, res ) => {
889
1076
  };
890
1077
  imgUrl = await fileUpload( params );
891
1078
 
892
- // let inputData = {
893
- // Bucket: bucket.sop,
894
- // file_path: imgUrl.Key,
895
- // };
896
- imgUrl = JSON.parse( process.env.CDNURL )?.TraxAnswerCDN+imgUrl.Key;
1079
+ let inputData = {
1080
+ Bucket: bucket.sop,
1081
+ file_path: imgUrl.Key,
1082
+ };
1083
+ imgUrl = await signedUrl( inputData );
897
1084
  if ( !imgUrl ) {
898
1085
  return res.sendError( { message: 'Something went Wrong' }, 500 );
899
1086
  }
@@ -1487,6 +1674,7 @@ export const updateConfigurev1 =async ( req, res ) => {
1487
1674
  await checklistLogs.create( logInsertData );
1488
1675
 
1489
1676
  checklistDetails = await checklistService.findOne( { _id: inputBody.checkListDetails._id, type: 'checklist', isdeleted: false } );
1677
+ let oldPublish = checklistDetails.publish;
1490
1678
 
1491
1679
  if ( [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection' ].includes( inputBody.checkListDetails.checkListType ) && inputBody.uploadUser ) {
1492
1680
  checklistDetails = await checklistService.findOne( { _id: inputBody.checkListDetails._id, type: 'checklist' } );
@@ -1499,8 +1687,9 @@ export const updateConfigurev1 =async ( req, res ) => {
1499
1687
  if ( inputBody.timeZone ) {
1500
1688
  currentDate = dayjs().tz( inputBody.timeZone ).format();
1501
1689
  } else {
1502
- currentDate = dayjs().format();
1690
+ currentDate = dayjs().format( 'HH:mm:ss' );
1503
1691
  }
1692
+ currentDate = dayjs.utc( currentDate, 'HH:mm:ss' ).format();
1504
1693
  let updatedscheduleEndTimeISO = dayjs.utc( inputBody?.checkListDetails?.scheduleEndTime, 'hh:mm A' ).format( 'HH:mm:ss' );
1505
1694
  let newUpdatedDate = dayjs.utc( updatedscheduleEndTimeISO, 'HH:mm:ss' ).format();
1506
1695
 
@@ -1643,6 +1832,124 @@ export const updateConfigurev1 =async ( req, res ) => {
1643
1832
  futureDaysDataRemove( currentDate, req.params.checklistId, checklistDetails.checkListName, '333' );
1644
1833
  }
1645
1834
  }
1835
+ checklistDetails = checklistDetails.toObject();
1836
+ checklistDetails.configStartDate = checklistDetails.configStartDate ? dayjs.utc( checklistDetails?.configStartDate ).format( 'YYYY-MM-DD' ) : '';
1837
+ checklistDetails.configEndDate = checklistDetails.configEndDate ? dayjs.utc( checklistDetails?.configEndDate ).format( 'YYYY-MM-DD' ) : '';
1838
+ checklistDetails.scheduleDate = checklistDetails.scheduleDate ? dayjs.utc( checklistDetails?.scheduleDate ).format( 'YYYY-MM-DD' ) : '';
1839
+ checklistDetails.scheduleRepeatedDay = Array.isArray( checklistDetails.scheduleRepeatedDay ) ? checklistDetails.scheduleRepeatedDay[0] : checklistDetails.scheduleRepeatedDay;
1840
+ configDetails.scheduleRepeatedDay = Array.isArray( configDetails.scheduleRepeatedDay ) ? configDetails?.scheduleRepeatedDay?.[0] || '' : configDetails?.scheduleRepeatedDay;
1841
+ configDetails.scheduleDate = configDetails.scheduleDate ? dayjs( configDetails?.scheduleDate ).format( 'YYYY-MM-DD' ) : '';
1842
+ let removedKeys = [ 'publish', 'publishDate', 'storeCount', 'sections', 'createdAt', 'updatedAt', 'scheduleStartTimeISO', 'scheduleEndTimeISO', 'aiConfig' ];
1843
+ removedKeys.forEach( ( item ) => {
1844
+ delete configDetails?.[item];
1845
+ delete checklistDetails?.[item];
1846
+ } );
1847
+ let differences = findObjectDifference( checklistDetails, configDetails );
1848
+ if ( Object.keys( differences ).length || req.body.added.length || req.body.removed?.user?.length || req.body.removed?.store?.length ) {
1849
+ let showSchedule = false;
1850
+ let scheduleKeys = [ 'scheduleDate', 'schedule', 'scheduleEndTime', 'scheduleStartTime', 'scheduleRepeatedDay', 'scheduleRepeatedType', 'configStartDate', 'configEndDate', 'scheduleWeekDays', 'scheduleRepeatedMonthWeek', 'specificDate' ];
1851
+
1852
+ if ( scheduleKeys.some( ( key ) => differences?.[key] ) ) {
1853
+ showSchedule = true;
1854
+ }
1855
+ let insertData = {
1856
+ client_id: req.body.clientId,
1857
+ createAt: new Date(),
1858
+ sourceCheckList_id: configDetails._id,
1859
+ checkListName: configDetails.checkListName,
1860
+ fromCheckListName: '',
1861
+ type: 'checklist',
1862
+ action: inputBody.checkListDetails.publish ? 'updated' : 'draft',
1863
+ storeName: '',
1864
+ store_id: '',
1865
+ createdByEmail: req.user.email,
1866
+ createdBy: req.user.userName,
1867
+ coverage: configDetails.coverage,
1868
+ logDetails: {
1869
+ schedule: {
1870
+ previous: {
1871
+ ...( showSchedule && checklistDetails.schedule == 'onetime' ) ? { scheduleDateString: dayjs( checklistDetails?.scheduleDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1872
+ schedule: showSchedule ? checklistDetails.schedule : '',
1873
+ time: ( ( showSchedule ) && ( checklistDetails.scheduleStartTime != '' || checklistDetails.scheduleEndTime != '' ) ) ? checklistDetails.scheduleStartTime + ' to ' + checklistDetails.scheduleEndTime : '',
1874
+ scheduleRepeatedDay: showSchedule ? checklistDetails?.scheduleRepeatedDay : '',
1875
+ scheduleRepeatedType: showSchedule ? checklistDetails?.scheduleRepeatedType : '',
1876
+ ...( showSchedule && checklistDetails?.configStartDate ) ? { configStartDate: dayjs( checklistDetails?.configStartDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1877
+ ...( showSchedule && checklistDetails?.configEndDate ) ? { configEndDate: dayjs( checklistDetails?.configEndDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1878
+ scheduleWeekDays: showSchedule ? checklistDetails?.scheduleWeekDays : [],
1879
+ scheduleRepeatedMonthWeek: showSchedule ? checklistDetails?.scheduleRepeatedMonthWeek : '',
1880
+ specificDate: showSchedule ? checklistDetails?.specificDate : [],
1881
+
1882
+ },
1883
+ new: {
1884
+ ...( showSchedule && configDetails.schedule == 'onetime' ) ? { scheduleDateString: dayjs( configDetails?.scheduleDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1885
+ schedule: showSchedule ? configDetails.schedule : '',
1886
+ time: ( ( showSchedule ) && ( configDetails.scheduleStartTime != '' || configDetails.scheduleEndTime != '' ) ) ? configDetails.scheduleStartTime + ' to ' + configDetails.scheduleEndTime : '',
1887
+ scheduleRepeatedDay: showSchedule ? configDetails?.scheduleRepeatedDay : '',
1888
+ scheduleRepeatedType: showSchedule ? configDetails?.scheduleRepeatedType : '',
1889
+ ...( showSchedule && configDetails?.configStartDate ) ? { configStartDate: dayjs( configDetails?.configStartDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1890
+ ...( showSchedule && configDetails?.configEndDate ) ? { configEndDate: dayjs( configDetails?.configEndDate, 'YYYY-MM-DD' ).format( 'DD MMM, YYYY' ) } :{},
1891
+ scheduleWeekDays: showSchedule ? configDetails?.scheduleWeekDays : [],
1892
+ scheduleRepeatedMonthWeek: showSchedule ? configDetails?.scheduleRepeatedMonthWeek : '',
1893
+ specificDate: showSchedule ? configDetails?.specificDate : [],
1894
+ },
1895
+ },
1896
+ response: {
1897
+ previous: [
1898
+ ...( differences?.allowedStoreLocation && checklistDetails.allowedStoreLocation ? [ 'Geo fencing' ] : [] ),
1899
+ ...( differences?.allowedMultiSubmit && checklistDetails.allowedMultiSubmit? [ 'Allow multiple responses' ] : [] ),
1900
+ ...( differences?.allowedOverTime && checklistDetails.allowedOverTime ? [ 'Fill response after configure time.' ] : [] ),
1901
+ ...( differences?.allowOnce && checklistDetails.allowOnce ? [ 'Only one time' ] : [] ),
1902
+ ],
1903
+ new: [
1904
+ ...( differences?.allowedStoreLocation && configDetails.allowedStoreLocation ? [ 'Geo fencing' ] : [] ),
1905
+ ...( differences?.allowedMultiSubmit && configDetails.allowedMultiSubmit? [ 'Allow multiple responses' ] : [] ),
1906
+ ...( differences?.allowedOverTime && configDetails.allowedOverTime ? [ 'Fill response after configure time' ] : [] ),
1907
+ ...( differences?.allowOnce && configDetails.allowOnce ? [ 'Only one time' ] : [] ),
1908
+ ],
1909
+ },
1910
+ ...( differences?.approver ) ? { approver:
1911
+ { previous: checklistDetails?.approver.map( ( item ) => item.name ).toString(),
1912
+ new: configDetails?.approver.map( ( item ) => item.name ).toString() },
1913
+ } : { approver: {} },
1914
+ ...( differences?.owner ) ? { owner:
1915
+ { previous: checklistDetails?.owner.map( ( item ) => item.name ).toString(),
1916
+ new: configDetails?.owner.map( ( item ) => item.name ).toString() },
1917
+ } : { owner: {} },
1918
+ ...( req.body.checkListDetails.coverage == 'store' ) ? { storeAdded: req.body.added } :{ storeAdded: [] },
1919
+ ...( req.body.removed.store.length ) ? { storeRemoved: req.body.removed.store } :{ storeRemoved: [] },
1920
+ ...( req.body.checkListDetails.coverage == 'user' ) ? { userAdded: req.body.added } :{ userAdded: [] },
1921
+ ...( req.body.removed.user.length ) ? { userRemoved: req.body.removed.user } :{ userRemoved: [] },
1922
+ },
1923
+ userType: req.user.userType,
1924
+ };
1925
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, insertData );
1926
+ }
1927
+
1928
+ if ( inputBody.checkListDetails.publish != oldPublish ) {
1929
+ let logObj = {
1930
+ client_id: inputBody.checkListDetails.client_id,
1931
+ createAt: new Date(),
1932
+ sourceCheckList_id: inputBody.checkListDetails._id,
1933
+ checkListName: inputBody.checkListDetails.checkListName,
1934
+ fromCheckListName: '',
1935
+ type: 'checklist',
1936
+ action: inputBody.checkListDetails.publish ? 'published' : 'unpublished',
1937
+ storeName: '',
1938
+ store_id: '',
1939
+ createdByEmail: req.user.email,
1940
+ createdBy: req.user.userName,
1941
+ coverage: inputBody.checkListDetails.coverage,
1942
+ logDetails: {},
1943
+ userType: req.user.userType,
1944
+ };
1945
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
1946
+ }
1947
+ let actionType;
1948
+ let teamsMsg;
1949
+ actionType = inputBody.checkListDetails.publish ? 'configPublish' : 'configDraft';
1950
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
1951
+ teamsMsg = 'ClientId: '+ checklistDetails.client_id + ', Action: '+ actionType + ', ChecklistId: '+ checklistDetails._id + ', Checklist Name: '+ checklistDetails.checkListName + ', UpDatedBy: '+ req.user.email;
1952
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
1646
1953
  if ( response?.modifiedCount || response?.matchedCount || response?.upsertedCount ) {
1647
1954
  return res.sendSuccess( { id, message: 'Configured Updated Successfully' } );
1648
1955
  }
@@ -1654,6 +1961,31 @@ export const updateConfigurev1 =async ( req, res ) => {
1654
1961
  return res.sendError( e, 500 );
1655
1962
  }
1656
1963
  };
1964
+ function findObjectDifference( oldObj, newObj ) {
1965
+ const isEqual = ( a, b ) => JSON.stringify( a ) === JSON.stringify( b );
1966
+
1967
+ const getArrayDiff = ( oldArr, newArr ) => {
1968
+ const removed = oldArr.filter( ( item ) => !newArr.some( ( newItem ) => isEqual( newItem, item ) ) );
1969
+ const added = newArr.filter( ( item ) => !oldArr.some( ( oldItem ) => isEqual( oldItem, item ) ) );
1970
+ if ( removed.length || added.length ) {
1971
+ return { previous: oldArr, new: newArr };
1972
+ }
1973
+ return [];
1974
+ };
1975
+ const difference = Object.keys( oldObj ).reduce( ( diff, key ) => {
1976
+ oldObj[key] = oldObj[key] == null ? '' : oldObj[key];
1977
+ if ( !isEqual( oldObj[key], newObj[key] ) ) {
1978
+ if ( !Array.isArray( newObj[key] ) ) {
1979
+ diff[key] = { previous: oldObj[key], new: newObj[key] };
1980
+ } else {
1981
+ diff[key] = getArrayDiff( oldObj[key] || [], newObj[key] || [] );
1982
+ }
1983
+ }
1984
+ return diff;
1985
+ }, {} );
1986
+
1987
+ return difference;
1988
+ }
1657
1989
 
1658
1990
  export const updatePublish = async ( req, res ) => {
1659
1991
  try {
@@ -1729,11 +2061,29 @@ export const updatePublish = async ( req, res ) => {
1729
2061
 
1730
2062
 
1731
2063
  await checklistService.updateOne( query, getCheckDetails );
2064
+ let logObj = {
2065
+ client_id: req.body.clientId,
2066
+ createAt: new Date(),
2067
+ sourceCheckList_id: req.body.checklistId,
2068
+ checkListName: getCheckDetails.checkListName,
2069
+ fromCheckListName: '',
2070
+ type: 'checklist',
2071
+ action: req.body.publish ? 'published' : 'unpublished',
2072
+ storeName: '',
2073
+ store_id: '',
2074
+ createdByEmail: req.user.email,
2075
+ createdBy: req.user.userName,
2076
+ coverage: getCheckDetails.coverage,
2077
+ logDetails: {},
2078
+ userType: req.user.userType,
2079
+ };
2080
+ insertOpenSearchData( JSON.parse( process.env.OPENSEARCH ).traxActivityLog, logObj );
1732
2081
  if ( getCheckDetails.checkListType == 'custom' ) {
1733
2082
  let currentDate = dayjs.utc().format();
1734
2083
  let updatedscheduleEndTimeISO = dayjs.utc( getCheckDetails.scheduleEndTimeISO ).format( 'HH:mm:ss' );
1735
2084
  let newUpdatedDate = dayjs.utc( updatedscheduleEndTimeISO, 'HH:mm:ss' ).format();
1736
2085
 
2086
+
1737
2087
  if ( req.body.publish && req.body.publish == true ) {
1738
2088
  if ( newUpdatedDate > currentDate ) {
1739
2089
  let deleteQuery = {
@@ -1799,6 +2149,12 @@ export const updatePublish = async ( req, res ) => {
1799
2149
  createdByEmail: req.user.email,
1800
2150
  };
1801
2151
  await checklistLogs.create( logInsertData );
2152
+ let actionType;
2153
+ let teamsMsg;
2154
+ actionType = req.body.publish ? 'publish' : 'unpublish';
2155
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
2156
+ teamsMsg = 'ClientId: '+ getCheckDetails.client_id + ', Action: '+ actionType + ', ChecklistId: '+ getCheckDetails._id + ', Checklist Name: '+ getCheckDetails.checkListName + ', UpDatedBy: '+ req.user.email;
2157
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
1802
2158
  return res.sendSuccess( { checklistName: getCheckDetails.checkListName, message: 'Updated Successfully' } );
1803
2159
  } catch ( e ) {
1804
2160
  logger.error( 'updatePublish erroe =>', e );
@@ -2031,7 +2387,7 @@ export const validateUserv1 = async ( req, res ) => {
2031
2387
  }, {} );
2032
2388
 
2033
2389
  const duplicateUsers = Object.keys( duplicateUser ).filter( ( storeName ) => duplicateUser[storeName].count > 1 );
2034
- console.log( duplicateUsers, 'user' );
2390
+ // console.log( duplicateUsers, 'user' );
2035
2391
  if ( duplicateUsers.length ) {
2036
2392
  return res.sendError( { validate: false, duplicates: duplicateUsers, message: 'Email is Duplicated' }, 400 );
2037
2393
  }
@@ -2070,7 +2426,7 @@ export const validateUserv1 = async ( req, res ) => {
2070
2426
  {
2071
2427
  $project: {
2072
2428
  newEmail: { $toLower: '$email' },
2073
- isActive: 1,
2429
+ // isActive: 1,
2074
2430
  clientId: 1,
2075
2431
  email: 1,
2076
2432
  },
@@ -2078,7 +2434,7 @@ export const validateUserv1 = async ( req, res ) => {
2078
2434
  {
2079
2435
  $match: {
2080
2436
  newEmail: { $in: userEmailList },
2081
- isActive: true,
2437
+ // isActive: true,
2082
2438
  clientId: { $ne: req.body.clientId },
2083
2439
  },
2084
2440
  },
@@ -2120,7 +2476,7 @@ export const validateUserv1 = async ( req, res ) => {
2120
2476
  let newStoreList = storeList.filter( ( ele ) => ele != null && !existsStore.includes( ele.toLowerCase() ) );
2121
2477
  if ( req.body.coverage == 'store' ) {
2122
2478
  assignDetails.forEach( ( item ) => {
2123
- let getStoreDetails = storeDetails.find( ( store ) => store.storeName.toLowerCase() == item.storeName.toLowerCase() );
2479
+ let getStoreDetails = storeDetails.find( ( store ) => store.storeName.trim().toLowerCase() == item.storeName.trim().toLowerCase() );
2124
2480
  if ( getStoreDetails ) {
2125
2481
  let storeUserDetails = userDetails.find( ( ele ) => ele.newEmail.toLowerCase() == item.userEmail.toLowerCase() );
2126
2482
  item._id = getStoreDetails._id;
@@ -2141,6 +2497,10 @@ export const validateUserv1 = async ( req, res ) => {
2141
2497
  } );
2142
2498
  }
2143
2499
 
2500
+ newStoreList = [ ...new Set( newStoreList.map( ( item ) => item ) ) ];
2501
+ newUserList = [ ...new Set( newUserList.map( ( item ) => item ) ) ];
2502
+ existEmail = [ ...new Set( existEmail.map( ( item ) => item ) ) ];
2503
+ inActiveStores = [ ...new Set( inActiveStores.map( ( item ) => item ) ) ];
2144
2504
  if ( ( newUserList.length || newStoreList.length || existEmail.length || inActiveStores.length ) && !req.body?.addUser ) {
2145
2505
  return res.sendError( { validate: false, user: newUserList, store: newStoreList, existEmail, inActiveStores, data: assignDetails }, 400 );
2146
2506
  }
@@ -2586,6 +2946,7 @@ export async function insertSingleProcessData( checklistId, processId = 0, oldDa
2586
2946
  insertdata.restrictAttendance = getCLconfig?.restrictAttendance;
2587
2947
  insertdata.coverage = getCLconfig?.coverage;
2588
2948
  insertdata.rawImageUpload = getCLconfig?.rawImageUpload || false;
2949
+ insertdata.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
2589
2950
 
2590
2951
  let collectSections = [];
2591
2952
  let sectionQuery = [];
@@ -2991,7 +3352,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
2991
3352
  if ( getCLconfig.coverage == 'store' ) {
2992
3353
  let clusterList = allQuestion.filter( ( ele ) => ele?.clusterName ).map( ( item ) => item.assignId );
2993
3354
  if ( clusterList.length ) {
2994
- let clusterDetails = await clusterServices.findcluster( { _id: { $in: clusterList } } );
3355
+ let clusterDetails = await clusterServices.findcluster( { _id: { $in: clusterList }, clientId: getCLconfig.client_id } );
2995
3356
  if ( clusterDetails.length ) {
2996
3357
  let idList = clusterDetails.flatMap( ( item ) => item.stores.map( ( ele ) => ele.store ) );
2997
3358
  let getStoreDetails = await storeService.find( { _id: { $in: idList }, status: 'active' } );
@@ -3058,7 +3419,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3058
3419
  if ( getCLconfig.coverage == 'user' ) {
3059
3420
  let teamsList = allQuestion.filter( ( ele ) => ele?.teamName ).map( ( item ) => item.assignId );
3060
3421
  if ( teamsList.length ) {
3061
- let teamDetails = await teamsServices.findteams( { _id: { $in: teamsList } } );
3422
+ let teamDetails = await teamsServices.findteams( { _id: { $in: teamsList }, clientId: getCLconfig.client_id } );
3062
3423
  if ( teamDetails.length ) {
3063
3424
  let idList = [ ...teamDetails.flatMap( ( item ) => item.users.map( ( ele ) => ele.userId ) ), ...teamDetails.flatMap( ( item ) => item.Teamlead.map( ( ele ) => ele.userId ) ) ];
3064
3425
  let userIdList = allQuestion.filter( ( qn ) => !qn?.teamName ).map( ( qn ) => qn.assignId.toString() );
@@ -3175,6 +3536,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3175
3536
  }
3176
3537
  if ( getsubmitDetails ) {
3177
3538
  getsubmitDetails = [ getsubmitDetails ];
3539
+ // console.log( submittedDetails, getsubmitDetails );
3178
3540
  }
3179
3541
  function findDifferences( obj1, obj2 ) {
3180
3542
  return Object.keys( obj1 ).reduce( ( diff, key ) => {
@@ -3210,7 +3572,6 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3210
3572
  delete data.parentanswer;
3211
3573
  delete data.remarks;
3212
3574
  delete data.linkquestionenabled;
3213
- delete data.uniqueNo;
3214
3575
  if ( data.descriptivetype == null ) {
3215
3576
  delete data.descriptivetype;
3216
3577
  }
@@ -3222,101 +3583,29 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3222
3583
  delete ans.index;
3223
3584
  delete ans.validationAnswer;
3224
3585
  delete ans.answeroptionNumber;
3225
- ans.nestedQuestion = ans?.oldNestedQuestion ? ans.oldNestedQuestion : ans.nestedQuestion;
3226
- ans.linkedQuestion = ans?.oldLinkedQuestion ? ans.oldLinkedQuestion : ans.linkedQuestion;
3227
- delete ans.oldNestedQuestion;
3228
- delete ans.oldLinkedQuestion;
3229
3586
  } );
3230
3587
  const compare = findDifferences( data, qns );
3231
3588
  if ( compare?.answerType || compare?.answers || compare?.linkType ) {
3232
3589
  logger.info( 'compare =>', compare );
3233
- logger.info( 'compareSection =>', { section: section.sectionName } );
3234
- logger.info( 'qno =>', { qno: data.qno } );
3235
3590
  modifiedCount++;
3236
- question.push( { question: qns, type: 'qnEdit' } );
3591
+ question.push( qns );
3237
3592
  } else {
3238
- if ( getsubmitDetails[0].questionAnswers[index].questions[findQuestion].qname != qns.qname ) {
3239
- question.push( { type: 'nameChange', question: qns } );
3240
- }
3241
- // getsubmitDetails[0].questionAnswers[index].questions[findQuestion].qname = qns.qname;
3593
+ getsubmitDetails[0].questionAnswers[index].questions[findQuestion].qname = qns.qname;
3594
+ question.push( getsubmitDetails[0].questionAnswers[index].questions[findQuestion] );
3242
3595
  }
3243
3596
  } else {
3244
3597
  modifiedCount++;
3245
- question.push( { question: qns, type: 'add' } );
3598
+ question.push( qns );
3246
3599
  }
3247
3600
  } );
3248
- // getsubmitDetails[0].questionAnswers[index].questions = question;
3249
- sectionList.push( { sectionName: section.sectionName, oldName: section.sectionOldName, question: question, type: 'edit' } );
3601
+ getsubmitDetails[0].questionAnswers[index].questions = question;
3602
+ sectionList.push( getsubmitDetails[0].questionAnswers[index] );
3250
3603
  } else {
3251
3604
  modifiedCount++;
3252
- sectionList.push( { section: section, type: 'add' } );
3605
+ sectionList.push( section );
3253
3606
  }
3254
3607
  }
3255
- // getsubmitDetails[0].questionAnswers = sectionList;
3256
- sectionList.forEach( ( sec ) => {
3257
- if ( sec.type == 'add' ) {
3258
- getsubmitDetails[0].questionAnswers.push( sec.section );
3259
- } else {
3260
- sec.question.forEach( ( qn ) => {
3261
- let sectionDetails = getsubmitDetails[0].questionAnswers.findIndex( ( section ) => section.sectionName == sec?.oldName || section.sectionName == sec.sectionName );
3262
- if ( qn.type == 'add' ) {
3263
- getsubmitDetails[0].questionAnswers[sectionDetails].questions.push( qn.question );
3264
- } else {
3265
- let questions = getsubmitDetails[0].questionAnswers[sectionDetails].questions.reduce( ( acc, ele, idx ) => {
3266
- if ( ele.qname.trim() == qn?.question?.oldQname?.trim() || ele.qname.trim() == qn.question.qname.trim() ) {
3267
- acc.push( idx );
3268
- }
3269
- return acc;
3270
- }, [] );
3271
- if ( questions.length && [ 'qnEdit', 'nameChange' ].includes( qn.type ) ) {
3272
- if ( qn.type == 'qnEdit' ) {
3273
- let checkLinkType = getsubmitDetails[0].questionAnswers[sectionDetails].questions[questions[0]].linkType;
3274
- if ( checkLinkType && !qn.question.linkType ) {
3275
- questions.forEach( ( qnIdx, index ) => {
3276
- if ( index != 0 ) {
3277
- getsubmitDetails[0].questionAnswers[sectionDetails].questions.splice( qnIdx, 1 );
3278
- }
3279
- } );
3280
- questions = [ questions[0] ];
3281
- }
3282
- }
3283
- questions.forEach( ( qnIdx ) => {
3284
- if ( qn.type == 'qnEdit' ) {
3285
- getsubmitDetails[0].questionAnswers[sectionDetails].questions[qnIdx].answers.forEach( ( ele ) => {
3286
- console.log( ele?.nestedQuestion );
3287
- if ( ele?.nestedQuestion.length ) {
3288
- ele?.nestedQuestion.forEach( ( nested ) => {
3289
- let findIndex = getsubmitDetails[0].questionAnswers[sectionDetails].questions.findIndex( ( qn ) => qn.uniqueNo == nested );
3290
- if ( findIndex != -1 ) {
3291
- delete getsubmitDetails[0].questionAnswers[sectionDetails].questions[findIndex].userAnswer;
3292
- let questionDetails = getsubmitDetails[0].questionAnswers[sectionDetails].questions[findIndex];
3293
- let checkQuestionExists = getsubmitDetails[0].questionAnswers[sectionDetails].questions.filter( ( qnDetails ) => qnDetails.qname == questionDetails.qname );
3294
- if ( checkQuestionExists.length > 1 ) {
3295
- getsubmitDetails[0].questionAnswers[sectionDetails].questions.splice( findIndex, 1 );
3296
- } else {
3297
- delete getsubmitDetails[0].questionAnswers[sectionDetails].questions[findIndex].uniqueNo;
3298
- getsubmitDetails[0].questionAnswers[sectionDetails].questions[findIndex].linkquestionenabled = false;
3299
- getsubmitDetails[0].questionAnswers[sectionDetails].questions[findIndex].answers.forEach( ( ele ) => {
3300
- if ( ele?.oldNestedQuestion?.length ) {
3301
- ele.nestedQuestion = ele.oldNestedQuestion;
3302
- ele.linkedQuestion = ele.oldLinkedQuestion;
3303
- }
3304
- } );
3305
- }
3306
- }
3307
- } );
3308
- }
3309
- } );
3310
- getsubmitDetails[0].questionAnswers[sectionDetails].questions[qnIdx] = qn.question;
3311
- } else {
3312
- getsubmitDetails[0].questionAnswers[sectionDetails].questions[qnIdx].qname = qn.question.qname;
3313
- }
3314
- } );
3315
- }
3316
- }
3317
- } );
3318
- }
3319
- } );
3608
+ getsubmitDetails[0].questionAnswers = sectionList;
3320
3609
  if ( modifiedCount ) {
3321
3610
  getsubmitDetails[0].checklistStatus = 'inprogress';
3322
3611
  getsubmitDetails[0].date_string = dayjs( currentdate ).format( 'YYYY-MM-DD' );
@@ -3370,6 +3659,7 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3370
3659
  element4.restrictAttendance = getCLconfig?.restrictAttendance;
3371
3660
  element4.coverage = getCLconfig?.coverage;
3372
3661
  element4.rawImageUpload = getCLconfig?.rawImageUpload || false;
3662
+ element4.rawVideoUpload = getCLconfig?.rawVideoUpload || false;
3373
3663
  assignUserList.push( { ...element4 } );
3374
3664
  }
3375
3665
  } ) );
@@ -3411,25 +3701,19 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3411
3701
  }
3412
3702
  }
3413
3703
  } else {
3414
- let unAssignedList = assignUserList.reduce( ( acc, item ) => {
3415
- if ( !acc[item.userEmail] ) {
3416
- acc[item.userEmail]=[ item.store_id ];
3417
- } else {
3418
- acc[item.userEmail].push( item.store_id );
3419
- }
3420
- return acc;
3421
- }, {} );
3704
+ let deletedList = [];
3422
3705
 
3423
- let userList = Object.keys( unAssignedList );
3706
+ await processedchecklist.deleteMany( { date_string: insertdata.date_string,
3707
+ date_iso: insertdata.date_iso,
3708
+ client_id: insertdata.client_id,
3709
+ checkListId: updatedchecklist._id, checklistStatus: 'open' } );
3424
3710
 
3425
- await processedchecklist.deleteMany( { userEmail: { $nin: userList }, date_string: insertdata.date_string, date_iso: insertdata.date_iso, client_id: insertdata.client_id, checkListId: updatedchecklist._id, checklistStatus: { $nin: [ 'submit' ] } } );
3426
- if ( getCLconfig.coverage == 'store' ) {
3427
- for ( let key in unAssignedList ) {
3428
- if ( unAssignedList.hasOwnProperty( key ) ) {
3429
- await processedchecklist.deleteMany( { date_string: insertdata.date_string, date_iso: insertdata.date_iso, client_id: insertdata.client_id, checkListId: updatedchecklist._id, $and: [ { userEmail: key }, { store_id: { $nin: unAssignedList[key] } } ], checklistStatus: { $nin: [ 'submit' ] } } );
3430
- }
3431
- }
3432
- }
3711
+
3712
+ let actionType = 'deleteOpenUsers';
3713
+ let teamsMsg;
3714
+ let teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
3715
+ teamsMsg = 'ClientId: '+ insertdata.client_id + ', Action: '+ actionType + ', ChecklistId: '+ getCLconfig._id + ', Checklist Name: '+ getCLconfig.checkListName;
3716
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
3433
3717
 
3434
3718
  let inprogressData = await processedchecklist.find( {
3435
3719
  date_string: insertdata.date_string,
@@ -3440,6 +3724,12 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3440
3724
  }, { userId: 1, store_id: 1 } );
3441
3725
 
3442
3726
  if ( inprogressData.length ) {
3727
+ inprogressData.forEach( ( item ) => {
3728
+ let checkData = assignUserList.find( ( ele ) => ele.userId.toString() == item.userId.toString() && ele.store_id == item.store_id );
3729
+ if ( !checkData ) {
3730
+ deletedList.push( item._id );
3731
+ }
3732
+ } );
3443
3733
  assignUserList = assignUserList.filter( ( item ) => {
3444
3734
  let findData = inprogressData.find( ( ele ) => ele.userId.toString() == item.userId.toString() && ele.store_id == item.store_id );
3445
3735
  if ( !findData ) {
@@ -3448,11 +3738,15 @@ async function insertPCBulkV4( getCLconfig, checklistId, currentdate, updatedche
3448
3738
  } );
3449
3739
  }
3450
3740
 
3451
- await processedchecklist.deleteMany( { date_string: insertdata.date_string,
3452
- date_iso: insertdata.date_iso,
3453
- client_id: insertdata.client_id,
3454
- checkListId: updatedchecklist._id, checklistStatus: 'open' } );
3741
+ if ( deletedList.length ) {
3742
+ await processedchecklist.deleteMany( { date_string: insertdata.date_string, date_iso: insertdata.date_iso, client_id: insertdata.client_id, checkListId: updatedchecklist._id, _id: { $in: deletedList } } );
3743
+ }
3455
3744
  await processedchecklist.insertMany( assignUserList );
3745
+ actionType = 'insertAssignUsers';
3746
+ teamsMsg;
3747
+ teamsAlertUrls = process.env.teamsAlertURL ? JSON.parse( process.env.teamsAlertURL ) : '';
3748
+ teamsMsg = 'ClientId: '+ insertdata.client_id + ', Action: '+ actionType + ', ChecklistId: '+ getCLconfig._id + ', Checklist Name: '+ getCLconfig.checkListName + ', assignedUserCount:'+ assignUserList.length+', inprogressSubmitCount:' + submittedDetails?.length;
3749
+ sendTeamsNotification( teamsAlertUrls.checklist, teamsMsg );
3456
3750
  }
3457
3751
 
3458
3752
  tokenList.forEach( ( item ) => {
@@ -3527,11 +3821,11 @@ async function updateOpenSearch( user, data ) {
3527
3821
  export const aiChecklist = async ( req, res ) => {
3528
3822
  try {
3529
3823
  let storeDetails = await storeService.count( { clientId: req.query.clientId, status: 'active' } );
3530
- let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'queuealert', 'cleaning', 'scrum' ];
3824
+ let aiList = [ 'mobileusagedetection', 'storeopenandclose', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended', 'eyetest', 'remoteoptometrist', 'storehygienemonitoring', 'queuealert', 'cleaning', 'scrum', 'suspiciousactivity', 'boxalert', 'suspiciousfootfall', 'drinking', 'bagdetection' ];
3531
3825
  let checklistDetails = [];
3532
3826
  let publishList = [];
3533
3827
  let unpublishList = [];
3534
- publishList = await checklistService.find( { client_id: req.query.clientId, checkListType: { $in: aiList } }, { publish: 1, checkListName: 1, checkListType: 1, client_id: 1, checkListDescription: 1 } );
3828
+ publishList = await checklistService.find( { client_id: req.query.clientId, checkListType: { $in: aiList } }, { publish: 1, checkListName: 1, checkListType: 1, client_id: 1, checkListDescription: 1, storeCount: 1 } );
3535
3829
  if ( publishList.length ) {
3536
3830
  let existList = publishList.map( ( item ) => item.checkListType );
3537
3831
  aiList = aiList.filter( ( item ) => !existList.includes( item ) );
@@ -3540,9 +3834,13 @@ export const aiChecklist = async ( req, res ) => {
3540
3834
  checklistDetails = [ ...publishList, ...unpublishList ];
3541
3835
 
3542
3836
  checklistDetails.forEach( ( item ) => {
3543
- item.storeCount = storeDetails;
3837
+ if ( ![ 'mobileusagedetection', 'storeopenandclose', 'cleaning', 'scrum', 'uniformdetection', 'staffleftinthemiddle', 'customerunattended' ].includes( item.checkListType ) ) {
3838
+ item.storeCount = storeDetails;
3839
+ }
3544
3840
  } );
3545
3841
 
3842
+ checklistDetails.sort( ( a, b ) => a.checkListName.localeCompare( b.checkListName ) );
3843
+
3546
3844
  return res.sendSuccess( checklistDetails );
3547
3845
  } catch ( e ) {
3548
3846
  logger.error( 'aiChecklist =>', e );
@@ -3724,12 +4022,7 @@ export const selectAssign = async ( req, res ) => {
3724
4022
  // //Select Store and cluster
3725
4023
  if ( requestData.assignType == 'store' ) {
3726
4024
  let storeQuery = [
3727
- {
3728
- $match: {
3729
- ...( req.user.userType==='client'&&req.user.role!='superadmin' ) ? { storeId: { $in: requestData?.assignedStores } } :{ clientId: requestData.clientId },
3730
- status: 'active',
3731
- },
3732
- },
4025
+ { $match: { clientId: requestData.clientId, status: 'active' } },
3733
4026
  {
3734
4027
  $project: {
3735
4028
  storeName: 1,
@@ -3739,6 +4032,8 @@ export const selectAssign = async ( req, res ) => {
3739
4032
  userEmail: { $arrayElemAt: [ '$spocDetails.email', 0 ] },
3740
4033
  contact: { $arrayElemAt: [ '$spocDetails.contact', 0 ] },
3741
4034
  city: '$storeProfile.city',
4035
+ openTime: '$storeProfile.open',
4036
+ closeTime: '$storeProfile.close',
3742
4037
  },
3743
4038
  },
3744
4039
 
@@ -3776,7 +4071,7 @@ export const selectAssign = async ( req, res ) => {
3776
4071
  }
3777
4072
  return res.sendSuccess( { 'totalCount': resuldData.length, 'data': resuldData } );
3778
4073
  } catch ( e ) {
3779
- console.log( 'e =>', e );
4074
+ // console.log( 'e =>', e );
3780
4075
  logger.error( 'selectAssign =>', e );
3781
4076
  return res.sendError( e, 500 );
3782
4077
  }
@@ -3788,7 +4083,9 @@ async function assignUsers( data ) {
3788
4083
  let clusterDetails = await clusterServices.findcluster( { clientId: data.clientId, _id: new mongoose.Types.ObjectId( data.id ) } );
3789
4084
  if ( clusterDetails.length ) {
3790
4085
  let clusterList = clusterDetails[0].stores.map( ( ele ) => ele.store );
4086
+ // console.log( clusterList );
3791
4087
  let storeDetails = await storeService.find( { _id: { $in: clusterList }, status: 'active' } );
4088
+ // console.log( storeDetails.length );
3792
4089
  assignedData = await Promise.all( storeDetails.map( async ( store ) => {
3793
4090
  let userData = {
3794
4091
  storeId: store.storeId,
@@ -3796,7 +4093,7 @@ async function assignUsers( data ) {
3796
4093
  userName: store.spocDetails?.[0]?.name,
3797
4094
  userEmail: store.spocDetails?.[0]?.email,
3798
4095
  clusterName: clusterDetails?.[0]?.clusterName,
3799
- id: clusterDetails?.[0]?._id,
4096
+ id: [ clusterDetails?.[0]?._id ],
3800
4097
  };
3801
4098
  return userData;
3802
4099
  } ) );
@@ -3811,7 +4108,7 @@ async function assignUsers( data ) {
3811
4108
  userName: user.userName,
3812
4109
  userEmail: user.email,
3813
4110
  teamName: teamDetails?.[0]?.teamName,
3814
- id: teamDetails?.[0]?._id,
4111
+ id: [ teamDetails?.[0]?._id ],
3815
4112
  };
3816
4113
  return userData;
3817
4114
  } );
@@ -3849,12 +4146,12 @@ export async function checklistAssign( req, res ) {
3849
4146
  uniqueArr.push( ...uploadData );
3850
4147
  }
3851
4148
  } ) );
3852
-
3853
4149
  if ( uniqueArr.length ) {
3854
4150
  if ( req.body.coverage == 'store' ) {
3855
4151
  uniqueArr = uniqueArr.reduce( ( acc, obj ) => {
3856
4152
  if ( acc[obj.storeName] ) {
3857
4153
  acc[obj.storeName].clusterName += ',' + obj.clusterName;
4154
+ acc[obj.storeName].id.push( ...obj.id );
3858
4155
  } else {
3859
4156
  acc[obj.storeName] = { ...obj };
3860
4157
  }
@@ -3866,6 +4163,7 @@ export async function checklistAssign( req, res ) {
3866
4163
  uniqueArr = uniqueArr.reduce( ( acc, obj ) => {
3867
4164
  if ( acc[obj.userEmail] ) {
3868
4165
  acc[obj.userEmail].teamName += ','+ obj.teamName;
4166
+ acc[obj.userEmail].id.push( ...obj.id );
3869
4167
  } else {
3870
4168
  acc[obj.userEmail] = { ...obj };
3871
4169
  }
@@ -3891,10 +4189,83 @@ export async function updateAssign( req, res ) {
3891
4189
  if ( !checklistDetails ) {
3892
4190
  return res.sendError( 'No data found', 204 );
3893
4191
  }
3894
- req.body.assignedGroup = [ ...new Set( req.body.assignedGroup.map( ( item ) => item.id ) ) ];
3895
- // req.body.assignedGroup = req.body.assignedGroup.map( ( ele ) => {
3896
- // return { id: ele };
3897
- // } );
4192
+ let groupList = [];
4193
+ let groupAssignList = req.body.assignedGroup;
4194
+ req.body.assignedGroup = [ ...new Set( req.body.assignedGroup.flatMap( ( item ) => item.id ) ) ];
4195
+
4196
+ groupAssignList.forEach( ( ele ) => {
4197
+ let gName;
4198
+ if ( ele?.clusterName ) {
4199
+ gName = ele.clusterName.split( ',' );
4200
+ }
4201
+ if ( ele?.teamName ) {
4202
+ gName = ele.teamName.split( ',' );
4203
+ }
4204
+ gName.forEach( ( name ) => {
4205
+ if ( !groupList.includes( name ) ) {
4206
+ groupList.push( name );
4207
+ }
4208
+ } );
4209
+ } );
4210
+
4211
+ let getAssignedDetails = await assignedService.find( { checkListId: req.body.checkListId } );
4212
+ let oldCoverage;
4213
+ if ( getAssignedDetails.length ) {
4214
+ oldCoverage = getAssignedDetails?.[0]?.coverage;
4215
+ let storeClusterDetails = getAssignedDetails.filter( ( ele ) => ele?.storeName || ele?.clusterName );
4216
+ let userTeamDetails = getAssignedDetails.filter( ( ele ) => !ele?.storeName && ( ele?.userName || ele?.teamName ) );
4217
+ storeClusterDetails = [ ...new Set( storeClusterDetails.map( ( ele ) => ele?.storeName || ele?.clusterName ) ) ];
4218
+ userTeamDetails= [ ...new Set( userTeamDetails.map( ( ele ) => ele?.userName || ele?.teamName ) ) ];
4219
+ getAssignedDetails = [ ...storeClusterDetails, ...userTeamDetails ];
4220
+ }
4221
+ let assignedAllList = [ ...req.body.assignedList, ...groupList ];
4222
+ let added = assignedAllList.filter( ( item ) => {
4223
+ let storeUsername;
4224
+ let clusterTeamName;
4225
+ if ( req.body.coverage == 'store' ) {
4226
+ if ( item?.storeName ) {
4227
+ storeUsername = item?.storeName;
4228
+ } else {
4229
+ clusterTeamName = item;
4230
+ }
4231
+ } else {
4232
+ if ( item?.userName ) {
4233
+ storeUsername = item?.userName;
4234
+ } else {
4235
+ clusterTeamName = item;
4236
+ }
4237
+ }
4238
+ if ( !getAssignedDetails.includes( storeUsername ) && !getAssignedDetails.includes( clusterTeamName ) ) {
4239
+ return item;
4240
+ }
4241
+ } ).map( ( ele ) => {
4242
+ if ( req.body.coverage == 'store' ) {
4243
+ return ele?.storeName || ele;
4244
+ } else {
4245
+ return ele?.userName || ele;
4246
+ }
4247
+ } );
4248
+ let removed = getAssignedDetails.filter( ( item ) => {
4249
+ let list;
4250
+ if ( req.body.coverage == 'store' ) {
4251
+ list = assignedAllList.map( ( item ) => item?.storeName );
4252
+ let clusterList = assignedAllList.filter( ( item ) => !item?.storeName );
4253
+ list = [ ...list, ...clusterList ];
4254
+ } else {
4255
+ list = assignedAllList.map( ( item ) => item.userName );
4256
+ let teamList = assignedAllList.filter( ( item ) => !item?.userName );
4257
+ list = [ ...list, ...teamList ];
4258
+ }
4259
+ if ( !list.includes( item ) ) {
4260
+ return item;
4261
+ }
4262
+ } );
4263
+ if ( getAssignedDetails.length ) {
4264
+ removed = { user: oldCoverage == 'user' ? removed : [], store: oldCoverage == 'store' ? removed : [] };
4265
+ } else {
4266
+ removed = { user: [], store: [] };
4267
+ }
4268
+
3898
4269
  await assignedService.deleteMany( { checkListId: req.body.checkListId } );
3899
4270
  let assignedUserList = [];
3900
4271
  let userEmailList = req.body.assignedList.map( ( ele ) => ele.userEmail.toLowerCase() );
@@ -3912,7 +4283,7 @@ export async function updateAssign( req, res ) {
3912
4283
  },
3913
4284
  ];
3914
4285
  let assignUserDetails = await userService.aggregate( query );
3915
- await Promise.all( req.body.assignedList.map( async ( assign ) => {
4286
+ for ( let assign of req.body.assignedList ) {
3916
4287
  let userDetails = assignUserDetails.find( ( ele ) => ele.email.toLowerCase() == assign.userEmail.toLowerCase() );
3917
4288
  if ( !userDetails ) {
3918
4289
  let userData = {
@@ -3922,7 +4293,7 @@ export async function updateAssign( req, res ) {
3922
4293
  clientId: req.body.clientId,
3923
4294
  };
3924
4295
  userDetails = await createUser( userData );
3925
- userDetails = userDetails;
4296
+ assignUserDetails.push( userDetails );
3926
4297
  }
3927
4298
  let data = {
3928
4299
  ...assign,
@@ -3936,7 +4307,7 @@ export async function updateAssign( req, res ) {
3936
4307
  };
3937
4308
  delete data._id;
3938
4309
  assignedUserList.push( data );
3939
- } ) );
4310
+ }
3940
4311
  let assignGroupDetails = [];
3941
4312
  if ( req.body.coverage == 'store' ) {
3942
4313
  assignGroupDetails = await clusterServices.findcluster( { _id: { $in: req.body.assignedGroup } } );
@@ -3958,9 +4329,231 @@ export async function updateAssign( req, res ) {
3958
4329
  }
3959
4330
  } ) );
3960
4331
  await assignedService.insertMany( assignedUserList );
3961
- return res.sendSuccess( 'Assign details updated successfully' );
4332
+ return res.sendSuccess( { messgage: 'Assign details updated successfully', added, removed } );
3962
4333
  } catch ( e ) {
3963
4334
  logger.error( { functionName: 'updateAssign', error: e } );
3964
4335
  return res.sendError( e, 500 );
3965
4336
  }
3966
4337
  }
4338
+
4339
+ export async function updateAiConfigure( req, res ) {
4340
+ try {
4341
+ if ( !req.body.storeList.length && req.body.publish ) {
4342
+ return res.sendError( 'Please assign a store', 400 );
4343
+ }
4344
+ if ( !req.body.id && !req.body.type ) {
4345
+ return res.sendError( 'Type/Id is required', 400 );
4346
+ }
4347
+ if ( req.body.aiConfig?.assignConfig && req.body.aiConfig?.assignConfig == 'global' && !req.body?.aiConfig?.events?.length ) {
4348
+ return res.sendError( 'Event is required', 400 );
4349
+ }
4350
+ let query;
4351
+ query = req.body.type ? { checkListType: req.body.type, client_id: { $exists: false } } : { _id: req.body.id, client_id: req.body.clientId };
4352
+ let aiChecklistDetails = await checklistService.findOne( query );
4353
+ if ( !aiChecklistDetails ) {
4354
+ return res.sendError( 'No data found', 204 );
4355
+ }
4356
+ let details = {
4357
+ checkListName: aiChecklistDetails.checkListName,
4358
+ checkListDescription: aiChecklistDetails.checkListDescription,
4359
+ client_id: req.body.clientId,
4360
+ publish: req.body.publish,
4361
+ aiConfig: req.body.aiConfig,
4362
+ ...( !req.body?.id ) ? { createdBy: req.user._id, createdByName: req.user.userName } : {},
4363
+ questionCount: 0,
4364
+ storeCount: req.body.storeList.length,
4365
+ type: 'checklist',
4366
+ checkListType: aiChecklistDetails.checkListType,
4367
+ schedule: 'daily',
4368
+ ...( req.body.publish ) ? { publishDate: new Date() } :{},
4369
+ approver: req.body?.approver || [],
4370
+ scheduleRepeatedDay: [ '01' ],
4371
+ scheduleStartTime: '06:00 AM',
4372
+ scheduleEndTime: '11:59 PM',
4373
+ enableNewDeployedStore: req.body.enableNewDeployedStore,
4374
+ checkListNumber: aiChecklistDetails?.checkListNumber || 1,
4375
+ };
4376
+ let aiResponse = await checklistService.updateOne( { checkListType: aiChecklistDetails.checkListType, client_id: req.body.clientId }, details );
4377
+ let checklistId = req.body?.id || aiResponse?.upsertedId;
4378
+ if ( req.body?.approver ) {
4379
+ let data = [];
4380
+ let existEmail = await traxApprover.find( { checkListId: checklistId, isDeleted: false } );
4381
+ let mailList = existEmail.map( ( item ) => item.userEmail );
4382
+ existEmail = req.body?.approver.filter( ( item ) => mailList.includes( item.value ) ).map( ( item ) => item.value );
4383
+ let userMailList = req.body?.approver.map( ( ele ) => ele.value );
4384
+ req.body?.approver.forEach( ( ele ) => {
4385
+ if ( !existEmail.includes( ele.value ) ) {
4386
+ data.push( {
4387
+ userEmail: ele.value,
4388
+ checkListId: checklistId,
4389
+ type: 'checklist',
4390
+ checkListName: aiChecklistDetails.checkListName,
4391
+ client_id: req.body.clientId,
4392
+ } );
4393
+ }
4394
+ } );
4395
+
4396
+ await traxApprover.updateMany( { checkListId: checklistId, userEmail: { $nin: userMailList } }, { isDeleted: true } );
4397
+ if ( data.length ) {
4398
+ await traxApprover.insertMany( data );
4399
+ }
4400
+ }
4401
+ if ( req.body.storeList ) {
4402
+ let storeData = [];
4403
+ req.body.storeList.forEach( ( ele ) => {
4404
+ let eventTime = [];
4405
+ Object.keys( ele ).forEach( ( key ) => {
4406
+ let keyValue ={};
4407
+ if ( req.body.aiConfig?.assignConfig && req.body.aiConfig?.assignConfig == 'store' && key.includes( 'startTime' ) ) {
4408
+ let num = key.slice( -1 );
4409
+ if ( ele[key] && ele[`configTime${num}`] ) {
4410
+ keyValue['time'] = ele[key];
4411
+ keyValue['duration'] = ele[`configTime${num}`];
4412
+ eventTime.push( keyValue );
4413
+ }
4414
+ }
4415
+ } );
4416
+ if ( req.body.aiConfig?.assignConfig && req.body.aiConfig?.assignConfig == 'global' ) {
4417
+ req.body.aiConfig.events.forEach( ( event ) => {
4418
+ if ( event.time.split( ':' ).length <= 2 ) {
4419
+ event.time = event.time + ':00';
4420
+ }
4421
+ } );
4422
+ eventTime = req.body.aiConfig.events;
4423
+ }
4424
+ storeData.push( {
4425
+ storeName: ele.storeName,
4426
+ ...( req.body.aiConfig?.assignConfig ) ? { events: eventTime } : { events: [] },
4427
+ checkListId: checklistId,
4428
+ client_id: req.body.clientId,
4429
+ checkListName: aiChecklistDetails.checkListName,
4430
+ store_id: ele.storeId,
4431
+ assignId: ele._id,
4432
+ } );
4433
+ } );
4434
+ await assignedService.deleteMany( { checkListId: checklistId } );
4435
+ await assignedService.insertMany( storeData );
4436
+ if ( req.body.publish ) {
4437
+ let processedData = {
4438
+ client_id: req.body.clientId,
4439
+ date_iso: new Date( dayjs().format( 'YYYY-MM-DD' ) ),
4440
+ date_string: dayjs().format( 'YYYY-MM-DD' ),
4441
+ sourceCheckList_id: checklistId,
4442
+ checkListName: aiChecklistDetails.checkListName,
4443
+ checkListDescription: aiChecklistDetails.checkListDescription,
4444
+ scheduleStartTime: '06:00 AM',
4445
+ scheduleEndTime: '11:59 PM',
4446
+ scheduleStartTime_iso: dayjs.utc( '06:00 AM', 'hh:mm A' ).format(),
4447
+ scheduleEndTime_iso: dayjs.utc( '11:59 PM', 'hh:mm A' ).format(),
4448
+ allowedOverTime: false,
4449
+ allowedStoreLocation: false,
4450
+ createdBy: req.user._id,
4451
+ createdByName: req.user.userName,
4452
+ questionAnswers: [],
4453
+ isdeleted: false,
4454
+ questionCount: 0,
4455
+ storeCount: req.body.storeList.length,
4456
+ publishDate: details?.publishDate,
4457
+ locationCount: 1,
4458
+ checkListType: aiChecklistDetails.checkListType,
4459
+ scheduleRepeatedType: 'daily',
4460
+ aiStoreList: storeData.length? storeData.map( ( store ) => {
4461
+ return { storeName: store.storeName, events: store.events, storeId: store.store_id };
4462
+ } ) : [],
4463
+ aiConfig: req.body.aiConfig,
4464
+ approver: req.body?.approver || [],
4465
+ };
4466
+ let configResponse = await processedchecklistConfig.updateOne( { date_string: dayjs().format( 'YYYY-MM-DD' ), sourceCheckList_id: checklistId, checkListType: aiChecklistDetails.checkListType }, processedData );
4467
+ let data = {
4468
+ ...( configResponse?.upsertedId ) ? { checkListId: configResponse?.upsertedId } : {},
4469
+ checkListName: aiChecklistDetails.checkListName,
4470
+ checkListDescription: aiChecklistDetails.checkListDescription,
4471
+ date_iso: new Date( dayjs().format( 'YYYY-MM-DD' ) ),
4472
+ date_string: dayjs().format( 'YYYY-MM-DD' ),
4473
+ allowedOverTime: false,
4474
+ allowedStoreLocation: false,
4475
+ scheduleStartTime: '06:00 AM',
4476
+ scheduleStartTime_iso: dayjs.utc( '06:00 AM', 'hh:mm A' ).format(),
4477
+ scheduleEndTime: '11:59 PM',
4478
+ scheduleEndTime_iso: dayjs.utc( '11:59 PM', 'hh:mm A' ).format(),
4479
+ createdBy: req.user._id,
4480
+ createdByName: req.user.userName,
4481
+ sourceCheckList_id: checklistId,
4482
+ checkListType: aiChecklistDetails.checkListType,
4483
+ storeCount: storeData.length,
4484
+ questionCount: 0,
4485
+ publishDate: new Date(),
4486
+ locationCount: 0,
4487
+ scheduleRepeatedType: 'daily',
4488
+ client_id: req.body.clientId,
4489
+ aiStoreList: storeData?.length ? storeData.map( ( store ) => store.store_id ) : [],
4490
+ approvalEnable: req.body?.approver.length ? true : false,
4491
+ };
4492
+ await processedchecklist.updateOne( { date_string: dayjs().format( 'YYYY-MM-DD' ), sourceCheckList_id: checklistId, checkListType: aiChecklistDetails.checkListType }, data );
4493
+ }
4494
+ }
4495
+ return res.sendSuccess( 'Checklist updated successfully' );
4496
+ } catch ( e ) {
4497
+ logger.error( { functionName: 'updateAiConfigure', error: e } );
4498
+ return res.sendError( e, 500 );
4499
+ }
4500
+ }
4501
+
4502
+
4503
+ export async function getAiDetails( req, res ) {
4504
+ try {
4505
+ let storeList = [];
4506
+ if ( !req.query.id && !req.query.type ) {
4507
+ return res.sendError( 'Type/Id is required', 400 );
4508
+ }
4509
+ let query = req.query.type ? { checkListType: req.query.type, client_id: { $exists: false } } : { _id: req.query.id, client_id: req.query.clientId };
4510
+ let checklistDetails = await checklistService.findOne( query );
4511
+ if ( !checklistDetails ) {
4512
+ return res.sendError( 'No data found', 204 );
4513
+ }
4514
+ let clientDetails = await clientService.findOne( { clientId: req.query.clientId }, { 'planDetails.product': 1 } );
4515
+ if ( !clientDetails ) {
4516
+ return res.sendError( 'No data found', 204 );
4517
+ }
4518
+ if ( req.query?.id ) {
4519
+ storeList = await assignedService.find( { checkListId: req.query?.id } );
4520
+ let data = [];
4521
+ await Promise.all( ( storeList.map( async ( ele ) => {
4522
+ let element = {};
4523
+ element['storeName'] = ele.storeName,
4524
+ element['storeId'] = ele.store_id;
4525
+ element['_id'] = ele.assignId;
4526
+ let getStoreDetails = await storeService.findOne( { storeId: ele.store_id, status: 'active', clientId: req.query.clientId } );
4527
+ if ( getStoreDetails ) {
4528
+ element['openTime'] = getStoreDetails?.storeProfile?.open;
4529
+ element['closeTime'] = getStoreDetails?.storeProfile?.close;
4530
+ }
4531
+ if ( [ 'cleaning', 'scrum' ].includes( checklistDetails.checkListType ) && checklistDetails?.aiConfig?.assignConfig == 'store' ) {
4532
+ ele.events.forEach( ( event, index ) => {
4533
+ element[`startTime${index+1}`] = event.time;
4534
+ element[`configTime${index+1}`] = event.duration;
4535
+ } );
4536
+ }
4537
+ data.push( element );
4538
+ } ) ) );
4539
+ storeList = data;
4540
+ }
4541
+
4542
+ let response = {
4543
+ checkListName: checklistDetails?.checkListName,
4544
+ checkListDescription: checklistDetails?.checkListDescription,
4545
+ publish: checklistDetails?.publish,
4546
+ aiConfig: checklistDetails?.aiConfig,
4547
+ storeList: storeList,
4548
+ approver: checklistDetails?.approver,
4549
+ storeCount: checklistDetails?.storeCount,
4550
+ ...( checklistDetails?.client_id ) ? { clientId: checklistDetails?.client_id } :{},
4551
+ enableNewDeployedStore: checklistDetails?.enableNewDeployedStore,
4552
+ product: clientDetails?.planDetails?.product.map( ( product ) => product.productName ),
4553
+ };
4554
+ return res.sendSuccess( response );
4555
+ } catch ( e ) {
4556
+ logger.error( { functionName: getAiDetails, error: e } );
4557
+ return res.sendError( e, 500 );
4558
+ }
4559
+ }