tango-app-api-trax 1.0.0-beta-task.19 → 1.0.0-beta-task.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-trax",
3
- "version": "1.0.0-beta-task.19",
3
+ "version": "1.0.0-beta-task.20",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -45,7 +45,7 @@ export const downloadInsert = async ( req, res ) => {
45
45
 
46
46
  if ( requestData.sourceCheckList_id && requestData.sourceCheckList_id != '' ) {
47
47
  let getChecklistQuery = [];
48
- getChecklistQuery.push( { $project: { sourceCheckList_id: 1, date_iso: 1, store_id: 1, checklistStatus: 1 } } );
48
+ getChecklistQuery.push( { $project: { sourceCheckList_id: 1, date_iso: 1, store_id: 1, checklistStatus: 1, redoStatus: 1 } } );
49
49
  getChecklistQuery.push( {
50
50
  $match: {
51
51
  $and: [
@@ -3,6 +3,7 @@
3
3
  import { logger } from 'tango-app-api-middleware';
4
4
  import * as storeService from '../services/store.service.js';
5
5
  import * as groupService from '../services/group.service.js';
6
+ import * as clusterService from '../services/cluster.service.js';
6
7
  import * as processedchecklistconfigService from '../services/processedchecklistconfig.services.js';
7
8
  import * as processedChecklist from '../services/processedchecklist.services.js';
8
9
  import * as checklistLogs from '../services/checklistlog.service.js';
@@ -35,7 +36,11 @@ async function LamdaServiceCall( url, data ) {
35
36
  export async function getchecklist( req, res ) {
36
37
  try {
37
38
  let url = JSON.parse( process.env.LAMBDAURL );
39
+ console.log( url.checklistQuestion );
40
+
38
41
  let resultData = await LamdaServiceCall( url.checklistQuestion, req.body );
42
+ console.log( resultData );
43
+
39
44
  if ( resultData ) {
40
45
  if ( resultData.status_code == '200' ) {
41
46
  return res.sendSuccess( resultData );
@@ -302,14 +307,14 @@ export async function approveChecklist( req, res ) {
302
307
 
303
308
 
304
309
  if ( searchResponse.ok ) {
305
- return res.sendSuccess( 'Checklist Approved successfully' );
310
+ return res.sendSuccess( 'Checklist has been approved the submitted stores' );
306
311
  } else {
307
312
  return res.sendError( 'Something went wrong', 500 );
308
313
  }
309
314
  }
310
315
  } else {
311
- let redoList = checklistDetails.filter( ( ele ) => ele.checklistStatus == 'open' ).map( ( item ) => item.storeName );
312
- return res.sendError( `redo stores ${redoList.toString()}`, 400 );
316
+ let redoList = taskDetails.filter( ( ele ) => ele.checklistStatus == 'open' );
317
+ return res.sendError( `${redoList.length} stores has not been approved since those stores are not submitted`, 400 );
313
318
  }
314
319
  } catch ( e ) {
315
320
  logger.error( { function: 'approveChecklist', error: e } );
@@ -488,3 +493,274 @@ export async function approvalstatus( req, res ) {
488
493
  return res.sendError( error, 500 );
489
494
  }
490
495
  }
496
+
497
+ export const headerStoresV2 = async ( req, res ) => {
498
+ try {
499
+ let reqestData = req.body;
500
+ let getUserEmail = req.user.email;
501
+ let getUserType = req.user.userType;
502
+ let getRole = req.user.role;
503
+ let getClientId = reqestData.clientId;
504
+ let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
505
+ console.log( totalStores.length );
506
+
507
+ if ( totalStores && totalStores.length>0 ) {
508
+ let storeQuery = [];
509
+ if ( reqestData.city.length>0 && reqestData.clusters.length>0 ) {
510
+ let unqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
511
+ let unqueGroupStores = await getClusterStores( getClientId, reqestData.clusters );
512
+ storeQuery = [
513
+ {
514
+ $match: {
515
+ $and: [
516
+ { storeId: { $in: totalStores } },
517
+ { storeId: { $in: unqueCityStores } },
518
+ { storeId: { $in: unqueGroupStores } },
519
+ ],
520
+ },
521
+ },
522
+ {
523
+ $project: {
524
+ _id: 0,
525
+ storeId: '$storeId',
526
+ storeName: '$storeName',
527
+ },
528
+ },
529
+ ];
530
+ } else if ( reqestData.city.length>0 ) {
531
+ let uniqueCityStores = await getLocationStores( getClientId, reqestData.city, req );
532
+ storeQuery = [
533
+ {
534
+ $match: {
535
+ $and: [
536
+ { storeId: { $in: totalStores } },
537
+ { storeId: { $in: uniqueCityStores } },
538
+ ],
539
+ },
540
+ },
541
+ {
542
+ $project: {
543
+ _id: 0,
544
+ storeId: '$storeId',
545
+ storeName: '$storeName',
546
+ },
547
+ },
548
+ ];
549
+ } else if ( reqestData.clusters.length>0 ) {
550
+ let uniqueclusterStores = await getClusterStores( getClientId, reqestData.clusters );
551
+ storeQuery = [
552
+ {
553
+ $match: {
554
+ $and: [
555
+ { storeId: { $in: totalStores } },
556
+ { storeId: { $in: uniqueclusterStores } },
557
+ ],
558
+ },
559
+ },
560
+ {
561
+ $project: {
562
+ _id: 0,
563
+ storeId: '$storeId',
564
+ storeName: '$storeName',
565
+ },
566
+ },
567
+ ];
568
+ } else {
569
+ let totalStores = await getStoresList( getUserEmail, getClientId, getUserType, getRole, req );
570
+ storeQuery = [
571
+ {
572
+ $match: {
573
+ $and: [
574
+ { storeId: { $in: totalStores } },
575
+ ],
576
+ },
577
+ },
578
+ {
579
+ $project: {
580
+ _id: 0,
581
+ storeId: '$storeId',
582
+ storeName: '$storeName',
583
+ },
584
+ },
585
+ ];
586
+ }
587
+
588
+ const storeList = await storeService.aggregate( storeQuery );
589
+ if ( storeList && storeList.length > 0 ) {
590
+ return res.sendSuccess( { storesData: storeList } );
591
+ } else {
592
+ return res.sendError( 'No Stores', 400 );
593
+ }
594
+ } else {
595
+ return res.sendError( 'No Stores', 400 );
596
+ }
597
+ } catch ( error ) {
598
+ logger.error( { error: error, message: req.query, function: 'headerStoresV2' } );
599
+ return res.sendError( { error: error }, 500 );
600
+ }
601
+ };
602
+
603
+
604
+ async function getStoresList( getUserEmail, getClientId, getUserType, getRole, req ) {
605
+ try {
606
+ if ( getUserEmail && getUserEmail !='' && getClientId && getClientId !='' && getUserType && getUserType !='' && getRole && getRole!='' ) {
607
+ let overAllStores = [];
608
+ if ( getUserType == 'tango' ) {
609
+ let getAllS = await getAssignedAllStores( getClientId );
610
+ if ( getAllS && getAllS.length >0 ) {
611
+ overAllStores = getAllS;
612
+ }
613
+ return overAllStores;
614
+ } else if ( getUserType == 'client' ) {
615
+ if ( getRole == 'superadmin' ) {
616
+ let getAllS = await getAssignedAllStores( getClientId );
617
+ if ( getAllS && getAllS.length >0 ) {
618
+ overAllStores = getAllS;
619
+ }
620
+ return overAllStores;
621
+ } else {
622
+ return req.body.assignedStores;
623
+ }
624
+ }
625
+ } else {
626
+ return false;
627
+ }
628
+ } catch ( error ) {
629
+ logger.error( { error: error, message: req.query, function: 'getAllStores' } );
630
+ }
631
+ };
632
+
633
+
634
+ async function getAssignedAllStores( userClientId ) {
635
+ try {
636
+ if ( userClientId && userClientId !='' ) {
637
+ let storeQuery = [
638
+ {
639
+ $match: {
640
+ $and: [
641
+ { clientId: { $eq: userClientId } },
642
+ ],
643
+ },
644
+ },
645
+ {
646
+ $group: {
647
+ _id: null,
648
+ stores: { $push: '$storeId' },
649
+ },
650
+ },
651
+ ];
652
+ const storeList = await storeService.aggregate( storeQuery );
653
+ if ( storeList && storeList.length>0 && storeList[0]?.stores.length > 0 ) {
654
+ let uniqueStores = [ ...new Set( storeList[0].stores ) ];
655
+ return uniqueStores;
656
+ } else {
657
+ return false;
658
+ }
659
+ } else {
660
+ return false;
661
+ }
662
+ } catch ( error ) {
663
+ logger.error( { error: error, message: data, function: 'getAssignedAllStores' } );
664
+ return false;
665
+ }
666
+ }
667
+
668
+
669
+ async function getClusterStores( userClientId, ClusterList ) {
670
+ try {
671
+ if ( userClientId && userClientId !='' && ClusterList && ClusterList.length >0 ) {
672
+ let ClusterQuery = [
673
+ {
674
+ $match: {
675
+ $and: [
676
+ { clientId: { $eq: userClientId } },
677
+ { clusterName: { $in: ClusterList } },
678
+ ],
679
+ },
680
+ },
681
+ {
682
+ $unwind: {
683
+ path: '$storeList', preserveNullAndEmptyArrays: true,
684
+ },
685
+ },
686
+ {
687
+ $group: {
688
+ _id: null,
689
+ storesList: { $push: '$stores' },
690
+ },
691
+ },
692
+ {
693
+ $project: {
694
+ storesList: {
695
+ $reduce: {
696
+ input: '$storesList', // Merge arrays using $reduce
697
+ initialValue: [],
698
+ in: { $concatArrays: [ '$$value', '$$this' ] },
699
+ },
700
+ },
701
+ },
702
+ },
703
+ ];
704
+ const clusterStoreList = await clusterService.aggregateCluster( ClusterQuery );
705
+ if ( clusterStoreList && clusterStoreList.length>0 && clusterStoreList[0]?.storesList.length > 0 ) {
706
+ let storeIds = clusterStoreList[0].storesList.map( ( data ) => data.storeId );
707
+ let uniqueStores = [ ...new Set( storeIds ) ];
708
+ return uniqueStores;
709
+ } else {
710
+ return false;
711
+ }
712
+ } else {
713
+ return false;
714
+ }
715
+ } catch ( error ) {
716
+ logger.error( { error: error, message: data, function: 'getClusterStores' } );
717
+ return false;
718
+ }
719
+ }
720
+
721
+
722
+ async function getLocationStores( userClientId, cityList, req ) {
723
+ try {
724
+ if ( userClientId && userClientId !='' && cityList && cityList.length >0 ) {
725
+ let filter = [
726
+ { clientId: { $eq: userClientId } },
727
+ { 'storeProfile.city': { $in: cityList } },
728
+ ];
729
+ if ( req.body.assignedStores&&req.body.assignedStores.length>0 ) {
730
+ filter.push( { storeId: { $in: req.body.assignedStores } } );
731
+ }
732
+
733
+ let storeQuery = [
734
+ {
735
+ $match: {
736
+ $and: filter,
737
+ },
738
+ },
739
+ {
740
+ $project: {
741
+ _id: 0,
742
+ storeId: '$storeId',
743
+ },
744
+ },
745
+ {
746
+ $group: {
747
+ _id: null,
748
+ stores: { $push: '$storeId' },
749
+ },
750
+ },
751
+ ];
752
+ const cityStoreList = await storeService.aggregate( storeQuery );
753
+ if ( cityStoreList && cityStoreList.length>0 && cityStoreList[0]?.stores.length > 0 ) {
754
+ let uniqueStores = [ ...new Set( cityStoreList[0].stores ) ];
755
+ return uniqueStores;
756
+ } else {
757
+ return [];
758
+ }
759
+ } else {
760
+ return [];
761
+ }
762
+ } catch ( error ) {
763
+ logger.error( { error: error, function: 'getLocationStores' } );
764
+ return false;
765
+ }
766
+ }
@@ -5,6 +5,7 @@ import * as PCLconfig from '../services/processedchecklistconfig.services.js';
5
5
  import * as processedTaskConfigService from '../services/processedTaskConfig.service.js';
6
6
  import * as storeService from '../services/store.service.js';
7
7
  import * as checklistService from '../services/checklist.service.js';
8
+ import * as taskConfigService from '../services/taskConfig.service.js';
8
9
  import * as processedTask from '../services/processedTaskList.service.js';
9
10
  import * as checklistLogs from '../services/checklistlog.service.js';
10
11
  import { insertSingleProcessData } from './trax.controller.js';
@@ -23,6 +24,8 @@ import { join } from 'path';
23
24
  import handlebars from 'handlebars';
24
25
  dayjs.extend( customParseFormat );
25
26
  dayjs.extend( timeZone );
27
+ import isSameOrBefore from 'dayjs/plugin/isSameOrBefore.js';
28
+ dayjs.extend( isSameOrBefore );
26
29
 
27
30
  export async function storeList( req, res ) {
28
31
  try {
@@ -441,11 +444,19 @@ export async function sopMobilechecklistValidater( req, res, next ) {
441
444
  export async function sopMobilechecklistQuestionValidator( req, res, next ) {
442
445
  try {
443
446
  let requestData = req.body;
447
+
448
+ logger.error( { function: 'CheckEmptyQA', error: requestData } );
449
+
444
450
  requestData.questionAnswers = typeof requestData.questionAnswers == 'string' ? JSON.parse( requestData.questionAnswers ) : requestData.questionAnswers;
445
451
  let getChecklistQA = await processedchecklist.findOne( { _id: new ObjectId( requestData.processedcheckListId ) }, { questionAnswers: 1 } );
446
452
  if ( !getChecklistQA ) {
447
453
  return res.sendError( 'Check List Got Edited Please Fill Again', 422 );
448
454
  }
455
+
456
+ if ( !requestData.questionAnswers.length ) {
457
+ return res.sendError( 'Please Fill all Required Fields', 400 );
458
+ }
459
+
449
460
  if ( requestData.submittype == 'submit' ) {
450
461
  let reqAnswers = requestData.questionAnswers;
451
462
  let CLQAnswers = getChecklistQA.questionAnswers;
@@ -1343,7 +1354,7 @@ export async function submitTask( req, res ) {
1343
1354
  `v5 => Checklist Save => store Name: ${storeName}, User Email: ${userEmail}, Checklist Name: ${checkListName}`,
1344
1355
  );
1345
1356
  updateData.submitTime_string = currentDateTime.format( 'hh:mm A, DD MMM YYYY' );
1346
- } else {
1357
+ } else if ( submittype === 'submit' ) {
1347
1358
  logger.info(
1348
1359
  `v5 => Checklist Submit => store Name: ${storeName}, User Email: ${userEmail}, Checklist Name: ${checkListName}`,
1349
1360
  );
@@ -1385,6 +1396,38 @@ export async function submitTask( req, res ) {
1385
1396
  await processedTask.deleteMany( { _id: { $in: deleteIds } } );
1386
1397
  }
1387
1398
  }
1399
+ } else if ( submittype === 'draft' ) {
1400
+ const query2 = [
1401
+ {
1402
+ $match: {
1403
+ _id: checklist.sourceCheckList_id,
1404
+ },
1405
+ },
1406
+ ];
1407
+ const [ taskConfig ] = await taskConfigService.aggregate( query2 );
1408
+
1409
+ if ( taskConfig.scheduleEndTimeISO ) {
1410
+ const endDate = dayjs( taskConfig.scheduleEndTimeISO ).utc();
1411
+ const startDate = dayjs().add( 1, 'day' );
1412
+
1413
+ let currentDate = startDate;
1414
+
1415
+ while ( currentDate.isSameOrBefore( endDate ) ) {
1416
+ const updateDate = currentDate.format( 'YYYY-MM-DD' );
1417
+
1418
+ const updateQuery = {
1419
+ sourceCheckList_id: taskConfig._id,
1420
+ date_string: updateDate,
1421
+ userId: user._id,
1422
+ };
1423
+
1424
+ if ( Object.values( updateQuery ).length === 3 ) {
1425
+ await processedTask.updateOne( updateQuery, { questionAnswers, checklistStatus: 'inprogress' } );
1426
+ }
1427
+
1428
+ currentDate = currentDate.add( 1, 'day' );
1429
+ }
1430
+ }
1388
1431
  }
1389
1432
  const logInsertData = {
1390
1433
  // eslint-disable-next-line camelcase
@@ -332,6 +332,38 @@ export const checklistPerformance = async ( req, res ) => {
332
332
  timeFlag: { $sum: '$timeFlag' },
333
333
  questionFlagCount: { $sum: '$questionFlag' },
334
334
  checkListType: { $last: '$checkListType' },
335
+ redo: { $sum: { $cond: [ { $eq: [ '$redoStatus', true ] }, 1, 0 ] } },
336
+ task: {
337
+ $sum: {
338
+ $reduce: {
339
+ input: '$questionAnswers',
340
+ initialValue: 0,
341
+ in: {
342
+ $add: [
343
+ '$$value',
344
+ {
345
+ $reduce: {
346
+ input: { $ifNull: [ '$$this.questions', [] ] },
347
+ initialValue: 0,
348
+ in: {
349
+ $add: [
350
+ '$$value',
351
+ {
352
+ $cond: [
353
+ { $ifNull: [ '$$this.taskId', false ] },
354
+ 1,
355
+ 0,
356
+ ],
357
+ },
358
+ ],
359
+ },
360
+ },
361
+ },
362
+ ],
363
+ },
364
+ },
365
+ },
366
+ },
335
367
  },
336
368
  } );
337
369
  findQuery.push( {
@@ -350,6 +382,8 @@ export const checklistPerformance = async ( req, res ) => {
350
382
  submittedChecklist: 1,
351
383
  flaggedChecklist: { $add: [ '$timeFlag', '$questionFlagCount' ] },
352
384
  checkListType: 1,
385
+ redo: 1,
386
+ task: 1,
353
387
  },
354
388
  } );
355
389
 
@@ -381,11 +415,13 @@ export const checklistPerformance = async ( req, res ) => {
381
415
  const exportdata = [];
382
416
  getChecklistPerformanceData[0].data.forEach( ( element ) => {
383
417
  exportdata.push( {
384
- 'Checklist Name': element.checkListName,
385
- 'Scheduled': element.scheduleRepeatedType,
386
- 'Assigned To': element.storeCount,
387
- 'Submitted': element.submittedChecklist,
388
- 'Flags': element.flaggedChecklist,
418
+ 'Checklist Name': element.checkListName || '--',
419
+ 'Scheduled': element.scheduleRepeatedType || '--',
420
+ 'Assigned To': element.storeCount || '--',
421
+ 'Submitted': element.submittedChecklist || '--',
422
+ 'Flags': element.flaggedChecklist || '--',
423
+ 'Tasks': element.task || '--',
424
+ 'ReDo': element.redo || '--',
389
425
  } );
390
426
  } );
391
427
  return await download( exportdata, res );
@@ -1138,7 +1174,11 @@ export const checklistInfo = async ( req, res ) => {
1138
1174
  );
1139
1175
 
1140
1176
  if ( requestData.checklistStatus && requestData.checklistStatus != 'All' ) {
1141
- findAndQuery.push( { checklistStatus: requestData.checklistStatus } );
1177
+ if ( requestData.checklistStatus == 'redo' ) {
1178
+ findAndQuery.push( { redoStatus: true } );
1179
+ } else {
1180
+ findAndQuery.push( { checklistStatus: requestData.checklistStatus } );
1181
+ }
1142
1182
  }
1143
1183
 
1144
1184
  if ( requestData.groupByType == 'Checklist' ) {
@@ -11,6 +11,15 @@ export const checklistSchema = joi.object( {
11
11
  export const checklistValidation = {
12
12
  body: checklistSchema,
13
13
  };
14
+ export const validateHeaderSchemav2 = joi.object( {
15
+ clientId: joi.string().required(),
16
+ city: joi.array().required(),
17
+ clusters: joi.array().required(),
18
+ } );
19
+ export const validateHeaderParamsv2 = {
20
+ body: validateHeaderSchemav2,
21
+ };
22
+
14
23
 
15
24
  export const checklistDetailsSchema = joi.object( {
16
25
  checkListId: joi.string().optional(),
@@ -1,10 +1,10 @@
1
1
 
2
2
 
3
- import { getchecklist, viewchecklist, getMobileUseagelist, storeOpencloselist, getcustomerunattendedlist, storesList, checklistDropdown, redoChecklist, approveChecklist, approvalstatus, getLogs } from '../controllers/gallery.controller.js';
3
+ import { getchecklist, viewchecklist, getMobileUseagelist, storeOpencloselist, getcustomerunattendedlist, storesList, checklistDropdown, redoChecklist, approveChecklist, approvalstatus, getLogs, headerStoresV2 } from '../controllers/gallery.controller.js';
4
4
  import express from 'express';
5
5
  export const galleryRouter = express.Router();
6
- import { isAllowedSessionHandler } from 'tango-app-api-middleware';
7
-
6
+ import { validate, isAllowedSessionHandler, isAllowedClient, getAssinedStore } from 'tango-app-api-middleware';
7
+ import * as validationDtos from '../dtos/validation.dtos.js';
8
8
  galleryRouter
9
9
  .post( '/getchecklist', isAllowedSessionHandler, getchecklist );
10
10
  galleryRouter
@@ -26,3 +26,5 @@ galleryRouter
26
26
  .post( '/redo', isAllowedSessionHandler, redoChecklist )
27
27
  .post( '/approvalstatus', isAllowedSessionHandler, approvalstatus )
28
28
  .post( '/getLogs', isAllowedSessionHandler, getLogs );
29
+ galleryRouter
30
+ .post( '/headerStores_v2', isAllowedSessionHandler, isAllowedClient, validate( validationDtos.validateHeaderParamsv2 ), getAssinedStore, headerStoresV2 );
@@ -0,0 +1,28 @@
1
+ import clusterModel from 'tango-api-schema/schema/cluster.model.js';
2
+
3
+ export async function updateOneCluster( query, record ) {
4
+ return await clusterModel.updateOne( query, { $set: record } );
5
+ };
6
+
7
+ export async function updateCluster( query, record ) {
8
+ return await clusterModel.updateMany( query, record );
9
+ };
10
+
11
+ export async function aggregateCluster( query ) {
12
+ return await clusterModel.aggregate( query );
13
+ };
14
+
15
+ export async function findOneCluster( query ={}, field={} ) {
16
+ return await clusterModel.findOne( query, field );
17
+ };
18
+ export async function deleteCluster( query ={} ) {
19
+ return await clusterModel.deleteOne( query );
20
+ };
21
+
22
+ export async function createclusterModel( data ) {
23
+ return await clusterModel.create( data );
24
+ };
25
+
26
+ export async function findcluster( query, project ) {
27
+ return await clusterModel.find( query, project );
28
+ };