tango-app-api-store-zone 3.3.1-beta.1 → 3.3.1-beta.10

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/.eslintrc.cjs CHANGED
@@ -36,7 +36,7 @@ module.exports = {
36
36
  'no-unused-vars': 'error',
37
37
  'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
38
38
  'prefer-const': 'off',
39
- 'no-console': 'error',
39
+ // 'no-console': 'error',
40
40
  },
41
41
  };
42
42
 
package/app.js ADDED
@@ -0,0 +1,43 @@
1
+
2
+ import express from 'express';
3
+ import { zoneTaggingRouter } from './index.js';
4
+
5
+ import dotenv from 'dotenv';
6
+ import { logger } from 'tango-app-api-middleware';
7
+ import { connectdb } from './config/database/database.js';
8
+ import responseMiddleware from './config/response/response.js';
9
+ import errorMiddleware from './config/response/error.js';
10
+ import pkg from 'body-parser';
11
+ import cors from 'cors';
12
+ // import swagger from 'swagger-ui-express';
13
+ // import { swaggerConfig } from './config/swagger/swagger.js';
14
+
15
+ const { json, urlencoded } = pkg;
16
+
17
+ const env=dotenv.config();
18
+
19
+ const app = express();
20
+ const PORT = process.env.PORT || 3000;
21
+
22
+
23
+ if ( env.error ) {
24
+ logger.error( '.env not found' );
25
+ process.exit( 1 );
26
+ }
27
+ app.use( cors() );
28
+ app.use( responseMiddleware );
29
+ app.use( errorMiddleware );
30
+ app.use( json( { limit: '500mb' } ) );
31
+ app.use(
32
+ urlencoded( {
33
+ extended: true,
34
+ } ),
35
+ );
36
+ app.use( '/zoneTagging', zoneTaggingRouter );
37
+ // app.use( '/api-docs', swagger.serve, swagger.setup( swaggerConfig ) );
38
+
39
+ app.listen( PORT, () => {
40
+ connectdb();
41
+ } );
42
+
43
+
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "tango-app-api-store-zone",
3
- "version": "3.3.1-beta.1",
3
+ "version": "3.3.1-beta.10",
4
4
  "description": "zone",
5
- "main": "index.js",
5
+ "main": "app.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "start": "nodemon --exec \"eslint --fix . && node index.js\""
8
+ "start": "nodemon --exec \"eslint --fix . && node app.js\""
9
9
  },
10
10
  "engines": {
11
11
  "node": ">=18.10.0"
@@ -17,12 +17,12 @@
17
17
  "dotenv": "^16.4.5",
18
18
  "express": "^4.19.2",
19
19
  "handlebars": "^4.7.8",
20
- "joi-to-swagger": "^6.2.0",
20
+ "joi": "^17.12.1",
21
21
  "mongodb": "^6.5.0",
22
22
  "nodemon": "^3.1.0",
23
23
  "swagger-ui-express": "^5.0.0",
24
- "tango-api-schema": "^2.1.1",
25
- "tango-app-api-middleware": "^3.1.19",
24
+ "tango-api-schema": "^2.3.26",
25
+ "tango-app-api-middleware": "^3.1.43-alpha.6",
26
26
  "winston": "^3.13.0",
27
27
  "winston-daily-rotate-file": "^5.0.0"
28
28
  },
@@ -5,6 +5,8 @@ import * as storeService from '../services/store.service.js';
5
5
  import * as clientService from '../services/client.service.js';
6
6
  import * as externalService from '../services/external.service.js';
7
7
  import { signedUrl, listFileByPath, fileUpload, insertOpenSearchData } from 'tango-app-api-middleware';
8
+ import * as processedchecklistconfigService from '../services/processedchecklistconfig.services.js';
9
+
8
10
  import axios from 'axios';
9
11
  export const addCustomTag = async ( req, res ) => {
10
12
  try {
@@ -16,6 +18,7 @@ export const addCustomTag = async ( req, res ) => {
16
18
  storeId: inputData.storeId,
17
19
  tagName: inputData.tagName,
18
20
  rgbColor: inputData.rgbColor,
21
+ productName: inputData.productName,
19
22
  rgbBorderColor: inputData.rgbBorderColor,
20
23
  };
21
24
  await taggingService.deleteMany( { clientId: inputData.clientId, storeId: inputData.storeId, tagName: inputData.tagName, isDeleted: true } );
@@ -30,8 +33,8 @@ export const addCustomTag = async ( req, res ) => {
30
33
  date: new Date(),
31
34
  logType: 'zone',
32
35
  logSubType: 'addCustomTag',
33
- changes: [ `${inputData.tagName} customtag Created.` ],
34
- eventType: '',
36
+ changes: [ `${inputData.tagName} custom tag` ],
37
+ eventType: 'create',
35
38
  showTo: [ 'client', 'tango' ],
36
39
  };
37
40
  insertOpenSearchData( JSON.parse( process.env.OPENSEARCH )?.activityLog, logObj );
@@ -44,7 +47,7 @@ export const addCustomTag = async ( req, res ) => {
44
47
 
45
48
  export const customTagList = async ( req, res ) => {
46
49
  try {
47
- let customTagList = [ 'Front', 'Back' ];
50
+ let customTagList = [ 'Front', 'Back', 'Tracker-in', 'Tracker-out' ];
48
51
  let storeDetails = await storeService.findOne( { storeId: req.query.storeId }, { product: 1 } );
49
52
  let clientDetails = await clientService.findOne( { clientId: req.query.clientId }, { featureConfigs: 1 } );
50
53
  if ( clientDetails && clientDetails?.featureConfigs?.isExcludedArea ) {
@@ -149,6 +152,14 @@ export const customTagList = async ( req, res ) => {
149
152
  i.rgbColor = 'rgba(193, 214, 114, 0.5)';
150
153
  i.rgbBorderColor = 'rgb(203, 224, 124)';
151
154
  }
155
+ if ( i.tagName === 'Tracker-in' ) {
156
+ i.rgbColor = 'rgba(123, 95, 105, 0.5)';
157
+ i.rgbBorderColor = 'rgb(133, 105, 115)';
158
+ }
159
+ if ( i.tagName === 'Tracker-out' ) {
160
+ i.rgbColor = 'rgba(12, 195, 111, 0.5)';
161
+ i.rgbBorderColor = 'rgb(22, 205, 125)';
162
+ }
152
163
  } );
153
164
 
154
165
  return res.sendSuccess( customTagList );
@@ -157,6 +168,181 @@ export const customTagList = async ( req, res ) => {
157
168
  return res.sendError( e, 500 );
158
169
  }
159
170
  };
171
+ export const customTagListv2 = async ( req, res ) => {
172
+ try {
173
+ // Step 1: Base tag list
174
+ let customTagList = [
175
+ { tagName: 'Front', productName: 'tangoTraffic' },
176
+ { tagName: 'Back', productName: 'tangoTraffic' },
177
+ { tagName: 'Tracker-in', productName: 'tangoTracker' },
178
+ { tagName: 'Tracker-out', productName: 'tangoTracker' },
179
+ ];
180
+
181
+ // Step 2: Fetch store & client details in parallel
182
+ const [ storeDetails, clientDetails ] = await Promise.all( [
183
+ storeService.findOne(
184
+ { storeId: req.query.storeId },
185
+ { product: 1 },
186
+ ),
187
+ clientService.findOne(
188
+ { clientId: req.query.clientId },
189
+ { featureConfigs: 1 },
190
+ ),
191
+ ] );
192
+
193
+ // Step 3: Add conditional tags
194
+ if ( clientDetails?.featureConfigs?.isExcludedArea ) {
195
+ customTagList.push( { tagName: 'Excluded Area', productName: 'tangoTraffic' } );
196
+ }
197
+ if ( clientDetails?.featureConfigs?.isPasserByData ) {
198
+ customTagList.push( { tagName: 'Passer By', productName: 'tangoTraffic' } );
199
+ }
200
+ if ( storeDetails?.product?.includes( 'tangoZone' ) ) {
201
+ customTagList.push(
202
+ { tagName: 'Entry/Exit', productName: 'tangoZone' },
203
+ { tagName: 'Billing', productName: 'tangoZone' },
204
+ );
205
+ }
206
+ if ( req.query.selectedProduct && req.query.selectedProduct != '' ) {
207
+ customTagList = customTagList.filter( ( ele ) => ele.productName === req.query.selectedProduct );
208
+ }
209
+ // Step 4: Fetch existing tags
210
+ const tagInfo = await taggingService.find(
211
+ { clientId: req.query.clientId, productName: req.query.selectedProduct },
212
+ { tagName: 1, rgbColor: 1, rgbBorderColor: 1, productName: 1 },
213
+ );
214
+
215
+ // Merge all tags
216
+ const mergedTags = [ ...customTagList, ...tagInfo ];
217
+
218
+ // Step 5: Build unique tag list
219
+ const uniqueTags = [ ...new Map( mergedTags.map( ( tag ) => [ tag.tagName, tag ] ) ).values() ];
220
+
221
+ // Step 6: Query counts per tag
222
+ const tagNames = uniqueTags.map( ( t ) => t.tagName );
223
+
224
+ const taggingDetails = await taggingService.aggregate( [
225
+ {
226
+ $match: {
227
+ productName: req.query.selectedProduct,
228
+ clientId: req.query.clientId,
229
+ storeId: req.query.storeId,
230
+ coordinates: { $exists: true, $ne: [] },
231
+ tagName: { $in: tagNames },
232
+ },
233
+ },
234
+ { $group: { _id: '$tagName', count: { $sum: 1 } } },
235
+ ] );
236
+
237
+ const countMap = new Map( taggingDetails.map( ( t ) => [ t._id, t.count ] ) );
238
+
239
+ // Step 7: Tag colors config (instead of many ifs)
240
+ const tagColors = {
241
+ 'Front': { rgbColor: 'rgba(89, 80, 5, 0.5)', rgbBorderColor: 'rgb(99, 90, 15)' },
242
+ 'Back': { rgbColor: 'rgba(94, 60, 107, 0.5)', rgbBorderColor: 'rgb(104, 70, 117)' },
243
+ 'Excluded Area': { rgbColor: 'rgba(186, 60, 214, 0.5)', rgbBorderColor: 'rgb(196, 70, 224)' },
244
+ 'Passer By': { rgbColor: 'rgba(81, 153, 247, 0.5)', rgbBorderColor: 'rgb(91, 163, 257)' },
245
+ 'Entry/Exit': { rgbColor: 'rgba(224, 43, 170, 0.5)', rgbBorderColor: 'rgb(234, 53, 180)' },
246
+ 'Billing': { rgbColor: 'rgba(193, 214, 114, 0.5)', rgbBorderColor: 'rgb(203, 224, 124)' },
247
+ 'Tracker-in': { rgbColor: 'rgba(123, 95, 105, 0.5)', rgbBorderColor: 'rgb(133, 105, 115)' },
248
+ 'Tracker-out': { rgbColor: 'rgba(12, 195, 111, 0.5)', rgbBorderColor: 'rgb(22, 205, 125)' },
249
+ };
250
+
251
+ // Step 8: Final processing
252
+ const finalTags = uniqueTags.map( ( tag ) => ( {
253
+ tagName: tag.tagName,
254
+ productName: tag.productName,
255
+ count: countMap.get( tag.tagName ) || 0,
256
+ rgbColor: tag.rgbColor || tagColors[tag.tagName]?.rgbColor,
257
+ rgbBorderColor: tag.rgbBorderColor || tagColors[tag.tagName]?.rgbBorderColor,
258
+ } ) );
259
+
260
+
261
+ // Step 9: Sort by count (desc)
262
+ finalTags.sort( ( a, b ) => b.count - a.count );
263
+ if ( req.query.selectedProduct && req.query.selectedProduct === 'tangoTrax' ) {
264
+ let Query = [ {
265
+ $match: {
266
+ client_id: req.query.clientId,
267
+ checkListType: { $ne: 'custom' },
268
+ },
269
+ }, {
270
+ $group: {
271
+ _id: '$sourceCheckList_id',
272
+ sourceCheckList_id: { $last: '$sourceCheckList_id' },
273
+ tagName: { $last: '$checkListName' },
274
+ },
275
+ },
276
+ {
277
+ $lookup: {
278
+ from: 'cameras',
279
+ let: { checkListName: '$tagName' },
280
+ pipeline: [
281
+ {
282
+ $match: {
283
+ $expr: {
284
+ $anyElementTrue: {
285
+ $map: {
286
+ input: { $ifNull: [ '$taggedChecklist', [] ] }, // ✅ default to empty array
287
+ as: 'tc',
288
+ in: { $eq: [ '$$tc.checkListName', '$$checkListName' ] },
289
+ },
290
+ },
291
+ },
292
+ },
293
+ },
294
+ {
295
+ $project: {
296
+ storeId: 1,
297
+ },
298
+ },
299
+ ], as: 'cameraList',
300
+ },
301
+ },
302
+
303
+ {
304
+ $project: {
305
+ tagName: 1,
306
+ type: 'checklist',
307
+ count: { $size: '$cameraList' },
308
+ },
309
+ },
310
+ {
311
+ $sort: {
312
+ count: -1,
313
+ },
314
+ },
315
+
316
+ ];
317
+ let getChecklistData = await processedchecklistconfigService.aggregate( Query );
318
+ if ( finalTags&&finalTags.length>0 ) {
319
+ let merged = getChecklistData.map( ( item ) => {
320
+ let match = finalTags.find( ( a ) => a.tagName === item.tagName );
321
+ if ( match ) {
322
+ return { ...item, ...match, count: item.count + match.count }; // add counts
323
+ }
324
+ return item;
325
+ } );
326
+
327
+ // also include any arr1 items not in arr2
328
+ finalTags.forEach( ( a ) => {
329
+ if ( !merged.find( ( m ) => m.tagName === a.tagName ) ) {
330
+ merged.push( a );
331
+ }
332
+ } );
333
+ merged.sort( ( a, b ) => b.count - a.count );
334
+ return res.sendSuccess( merged );
335
+ } else {
336
+ return res.sendSuccess( getChecklistData );
337
+ }
338
+ } else {
339
+ return res.sendSuccess( finalTags );
340
+ }
341
+ } catch ( e ) {
342
+ logger.error( { error: e, function: 'customTagList' } );
343
+ return res.sendError( e, 500 );
344
+ }
345
+ };
160
346
 
161
347
  export const tagging = async ( req, res ) => {
162
348
  try {
@@ -173,7 +359,6 @@ export const tagging = async ( req, res ) => {
173
359
  } );
174
360
  let taggingDetails = await taggingService.findOne( { clientId: InputData.clientId, storeId: InputData.storeId, cameraId: InputData.cameraId, tagName: InputData.tagName, isDeleted: false } );
175
361
 
176
- const previousTagging = await taggingService.findOne( { clientId: InputData.clientId, storeId: InputData.storeId, tagName: InputData.tagName } );
177
362
  if ( !taggingDetails ) {
178
363
  const logObj = {
179
364
  clientId: InputData.clientId,
@@ -183,17 +368,17 @@ export const tagging = async ( req, res ) => {
183
368
  date: new Date(),
184
369
  logType: 'zone',
185
370
  logSubType: 'addZoneTagging',
186
- changes: [ `${InputData.tagName} zone added tagging` ],
187
- eventType: '',
371
+ changes: [ `${InputData.tagName} zone tagging` ],
372
+ eventType: 'create',
188
373
  showTo: [ 'client', 'tango' ],
189
374
  };
190
375
  insertOpenSearchData( JSON.parse( process.env.OPENSEARCH )?.activityLog, logObj );
191
- if ( previousTagging?.rgbColor ) {
192
- InputData = { ...InputData, rgbColor: previousTagging.rgbColor };
376
+ if ( InputData.coordinates[0].color ) {
377
+ InputData = { ...InputData, rgbColor: InputData.coordinates[0].color };
193
378
  }
194
379
 
195
- if ( previousTagging?.rgbBorderColor ) {
196
- InputData = { ...InputData, rgbBorderColor: previousTagging.rgbBorderColor };
380
+ if ( InputData.coordinates[0].rgbBorderColor ) {
381
+ InputData = { ...InputData, rgbBorderColor: InputData.coordinates[0].rgbBorderColor };
197
382
  }
198
383
  let response = await taggingService.create( InputData );
199
384
  await taggingService.deleteOne( { clientId: InputData.clientId, storeId: InputData.storeId, cameraId: { $exists: false }, tagName: InputData.tagName } );
@@ -207,12 +392,33 @@ export const tagging = async ( req, res ) => {
207
392
  date: new Date(),
208
393
  logType: 'zone',
209
394
  logSubType: 'updateZoneTagging',
210
- changes: [ `${InputData.tagName} zone Updated tagging` ],
211
- eventType: '',
395
+ changes: [ `${InputData.tagName} zone tagging` ],
396
+ eventType: 'update',
397
+ taggingId: taggingDetails._id,
398
+ previous: [
399
+ JSON.parse( JSON.stringify( taggingDetails ) ),
400
+ ],
401
+ current: {
402
+ ...taggingDetails.toObject(),
403
+ },
404
+ oldData: {
405
+ tagName: taggingDetails.tagName,
406
+ streamName: taggingDetails.streamName,
407
+ },
408
+ newData: {
409
+ tagName: taggingDetails.tagName,
410
+ streamName: taggingDetails.streamName,
411
+ },
412
+ showTo: [ 'tango', 'client' ],
212
413
  };
414
+
415
+ delete logObj?.current?.coordinates;
416
+
213
417
  insertOpenSearchData( JSON.parse( process.env.OPENSEARCH )?.activityLog, logObj );
214
418
  taggingDetails.cameraId = InputData.cameraId;
215
419
  taggingDetails.streamName = InputData.streamName;
420
+ taggingDetails.checkListName = InputData.checkListName;
421
+ taggingDetails.productName = InputData.productName;
216
422
  // if ( req.body?.redoPoint ) {
217
423
  // taggingDetails.coordinates = InputData.coordinates[0];
218
424
  // taggingDetails.save();
@@ -245,7 +451,7 @@ export const tagging = async ( req, res ) => {
245
451
  let externalDetails = await externalService.findOne( { storeId: InputData.storeId, zoneName: InputData.tagName, clientId: InputData.clientId } );
246
452
 
247
453
  if ( !externalDetails ) {
248
- let data ={
454
+ let data = {
249
455
  'storeId': InputData.storeId,
250
456
  'clientId': InputData.clientId,
251
457
  'productName': 'tangoZone',
@@ -309,11 +515,13 @@ export const getCameraList = async ( req, res ) => {
309
515
  if ( !cameraDetails.length ) {
310
516
  return res.sendError( 'no data found', 204 );
311
517
  }
312
- const folderPath = { file_path: `${req.query.storeId}/zone_base_images/`,
518
+ const folderPath = {
519
+ file_path: `${req.query.storeId}/zone_base_images/`,
313
520
  Bucket: JSON.parse( process.env.BUCKET ).zoneBaseImage, MaxKeys: 1000,
314
521
  };
315
522
  let fileList = await listFileByPath( folderPath );
316
- const TaggedfolderPath = { file_path: `${req.query.storeId}/zone_tagged_image/`,
523
+ const TaggedfolderPath = {
524
+ file_path: `${req.query.storeId}/zone_tagged_image/`,
317
525
  Bucket: JSON.parse( process.env.BUCKET ).zoneTaggingImage, MaxKeys: 1000,
318
526
  };
319
527
  let tagFileList = await listFileByPath( TaggedfolderPath );
@@ -339,7 +547,7 @@ export const getCameraList = async ( req, res ) => {
339
547
  tagFileList.data.forEach( ( item ) => {
340
548
  if ( item.Key.length > 1 ) {
341
549
  let splitStream = item.Key.split( '/' );
342
- let getStream = splitStream[splitStream.length -1].split( '.' );
550
+ let getStream = splitStream[splitStream.length - 1].split( '.' );
343
551
 
344
552
  if ( getStream && getStream[0] == `${req.query.storeId}_${camera.streamName}` ) {
345
553
  tagPath = item.Key;
@@ -350,21 +558,23 @@ export const getCameraList = async ( req, res ) => {
350
558
  if ( fileList?.data.length ) {
351
559
  fileList.data.forEach( ( ele ) => {
352
560
  let splitStream = ele.Key.split( '/' );
353
- let getStream = splitStream[splitStream.length -1].split( '.' );
561
+ let getStream = splitStream[splitStream.length - 1].split( '.' );
354
562
  if ( getStream && getStream[0] == `${req.query.storeId}_${camera.streamName}` ) {
355
563
  imgPath = ele.Key;
356
564
  }
357
565
  } );
358
566
  }
359
567
  if ( tagPath ) {
360
- const params = { file_path: tagPath,
568
+ const params = {
569
+ file_path: tagPath,
361
570
  Bucket: JSON.parse( process.env.BUCKET ).zoneTaggingImage,
362
571
  };
363
572
  const cameraTagImage = await signedUrl( params );
364
573
  camera.tagImg = cameraTagImage;
365
574
  }
366
575
  if ( imgPath ) {
367
- const baseParams = { file_path: imgPath,
576
+ const baseParams = {
577
+ file_path: imgPath,
368
578
  Bucket: JSON.parse( process.env.BUCKET ).zoneBaseImage,
369
579
  };
370
580
  const cameraBaseImage = await signedUrl( baseParams );
@@ -380,6 +590,87 @@ export const getCameraList = async ( req, res ) => {
380
590
  return res.sendError( e, 500 );
381
591
  }
382
592
  };
593
+ export const getCameraListv2 = async ( req, res ) => {
594
+ try {
595
+ let cameraDetails = await cameraService.find( { clientId: req.query.clientId, storeId: req.query.storeId, isActivated: true, isUp: true }, { cameraNumber: 1, streamName: 1, isActivated: 1, isUp: 1, cameraName: 1, taggedChecklist: 1 } );
596
+ if ( !cameraDetails.length ) {
597
+ return res.sendError( 'no data found', 204 );
598
+ }
599
+ const folderPath = {
600
+ file_path: `${req.query.storeId}/zone_base_images/`,
601
+ Bucket: JSON.parse( process.env.BUCKET ).zoneBaseImage, MaxKeys: 1000,
602
+ };
603
+ let fileList = await listFileByPath( folderPath );
604
+ const TaggedfolderPath = {
605
+ file_path: `${req.query.storeId}/zone_tagged_image/`,
606
+ Bucket: JSON.parse( process.env.BUCKET ).zoneTaggingImage, MaxKeys: 1000,
607
+ };
608
+ let tagFileList = await listFileByPath( TaggedfolderPath );
609
+ for ( let [ index, camera ] of cameraDetails.entries() ) {
610
+ let tagList = [];
611
+ let tagPath;
612
+ let imgPath;
613
+ camera = {
614
+ ...camera._doc,
615
+ baseImg: '',
616
+ tagImg: '',
617
+ };
618
+ let taggingDetails = await taggingService.find( { cameraId: camera._id, streamName: camera.streamName, clientId: req.query.clientId, isDeleted: false }, { tagName: 1, coordinates: 1 } );
619
+ if ( taggingDetails.length ) {
620
+ tagList = taggingDetails.filter( ( item ) => item.coordinates.length ).map( ( item ) => {
621
+ if ( item.coordinates.length ) {
622
+ return { tagName: item.tagName, color: item.coordinates[0].color };
623
+ }
624
+ } );
625
+ }
626
+
627
+ if ( tagFileList.data.length ) {
628
+ tagFileList.data.forEach( ( item ) => {
629
+ if ( item.Key.length > 1 ) {
630
+ let splitStream = item.Key.split( '/' );
631
+ let getStream = splitStream[splitStream.length - 1].split( '.' );
632
+
633
+ if ( getStream && getStream[0] == `${req.query.storeId}_${camera.streamName}` ) {
634
+ tagPath = item.Key;
635
+ }
636
+ }
637
+ } );
638
+ }
639
+ if ( fileList?.data.length ) {
640
+ fileList.data.forEach( ( ele ) => {
641
+ let splitStream = ele.Key.split( '/' );
642
+ let getStream = splitStream[splitStream.length - 1].split( '.' );
643
+ if ( getStream && getStream[0] == `${req.query.storeId}_${camera.streamName}` ) {
644
+ imgPath = ele.Key;
645
+ }
646
+ } );
647
+ }
648
+ if ( tagPath ) {
649
+ const params = {
650
+ file_path: tagPath,
651
+ Bucket: JSON.parse( process.env.BUCKET ).zoneTaggingImage,
652
+ };
653
+ const cameraTagImage = await signedUrl( params );
654
+ camera.tagImg = cameraTagImage;
655
+ }
656
+ if ( imgPath ) {
657
+ const baseParams = {
658
+ file_path: imgPath,
659
+ Bucket: JSON.parse( process.env.BUCKET ).zoneBaseImage,
660
+ };
661
+ const cameraBaseImage = await signedUrl( baseParams );
662
+ camera.baseImg = cameraBaseImage;
663
+ }
664
+ camera.tagging = tagList;
665
+ cameraDetails[index] = camera;
666
+ }
667
+ cameraDetails.sort( ( a, b ) => a.tagging?.length > b.tagging?.length ? -1 : 1 );
668
+ return res.sendSuccess( cameraDetails );
669
+ } catch ( e ) {
670
+ logger.error( { error: e, function: 'getCameraListv2' } );
671
+ return res.sendError( e, 500 );
672
+ }
673
+ };
383
674
 
384
675
  export const updateTag = async ( req, res ) => {
385
676
  try {
@@ -417,9 +708,21 @@ export const updateTag = async ( req, res ) => {
417
708
  date: new Date(),
418
709
  logType: 'zone',
419
710
  logSubType: 'updateCustomTag',
420
- changes: [ `${req.body.tagName} tagName Updated` ],
421
- eventType: '',
422
- showTo: [ 'client', 'tango' ],
711
+ changes: [ `${req.body.tagName} tagName` ],
712
+ eventType: 'update',
713
+ previous: {
714
+ tagName: req.body.existTag,
715
+ },
716
+ current: {
717
+ tagName: req.body.tagName,
718
+ },
719
+ oldData: {
720
+ tagName: req.body.existTag,
721
+ },
722
+ newData: {
723
+ tagName: req.body.tagName,
724
+ },
725
+ showTo: [ 'tango', 'client' ],
423
726
  };
424
727
  insertOpenSearchData( JSON.parse( process.env.OPENSEARCH )?.activityLog, logObj );
425
728
  if ( tagUpdate.modifiedCount || tagUpdate.matchedCount ) {
@@ -485,9 +788,9 @@ export const deleteTag = async ( req, res ) => {
485
788
  email: req.user?.email,
486
789
  date: new Date(),
487
790
  logType: 'zone',
488
- logSubType: 'deleteTag',
489
- changes: [ `${req.body.tagName} tag Deleted` ],
490
- eventType: '',
791
+ logSubType: 'deleteCustomTag',
792
+ changes: [ `${req.body.tagName} tag` ],
793
+ eventType: 'delete',
491
794
  showTo: [ 'client', 'tango' ],
492
795
  };
493
796
  insertOpenSearchData( JSON.parse( process.env.OPENSEARCH )?.activityLog, logObj );
@@ -678,6 +981,28 @@ export const updateOldData = async ( req, res ) => {
678
981
  return res.sendError( e, 500 );
679
982
  }
680
983
  };
984
+ export async function updateCamera( req, res ) {
985
+ try {
986
+ let findoneCheckList = await processedchecklistconfigService.findOne( {
987
+ client_id: req.body.clientId, checkListName: req.body.selectedZone,
988
+ } );
989
+
990
+ let updateData = {
991
+ checkListName: req.body.selectedZone,
992
+ sourceCheckList_id: findoneCheckList?.sourceCheckList_id,
993
+ };
994
+ if ( req.body.type === 'tagCamera' ) {
995
+ await cameraService.updateOne( { _id: req.body._id }, { $push: { taggedChecklist: updateData } } );
996
+ } else {
997
+ await cameraService.updateOne( { _id: req.body._id }, { $pull: { taggedChecklist: updateData } } );
998
+ }
999
+
1000
+ res.sendSuccess( 'updated Sucessfully' );
1001
+ } catch ( e ) {
1002
+ logger.error( { error: e, function: 'updateOldData' } );
1003
+ return res.sendError( e, 500 );
1004
+ }
1005
+ };
681
1006
 
682
1007
  export const deletezoneTagging = async ( req, res ) => {
683
1008
  let data = req.body;
@@ -4,6 +4,7 @@ export const addTagSchema = joi.object( {
4
4
  clientId: joi.string().required(),
5
5
  tagName: joi.string().required(),
6
6
  storeId: joi.string().required(),
7
+ productName: joi.string().required(),
7
8
  rgbColor: joi.string().required(),
8
9
  rgbBorderColor: joi.string().required(),
9
10
  } );
@@ -52,6 +53,8 @@ export const validateTaggingSchema = joi.object( {
52
53
  streamName: joi.string().required(),
53
54
  redoPoint: joi.boolean().optional(),
54
55
  redraw: joi.boolean().optional(),
56
+ productName: joi.string().required(),
57
+ checkListName: joi.string().optional(),
55
58
  } );
56
59
 
57
60
  export const validateTaggingParams = {
@@ -1,22 +1,25 @@
1
1
 
2
2
 
3
3
  import express from 'express';
4
- import { isAllowedSessionHandler, validate, authorize } from 'tango-app-api-middleware';
4
+ import { isAllowedSessionHandler, validate, accessVerification } from 'tango-app-api-middleware';
5
5
  import * as validation from '../dtos/validation.dtos.js';
6
6
  import * as tagController from '../controllers/zoneTagging.controller.js';
7
7
 
8
8
  export const zoneTaggingRouter = express.Router();
9
9
 
10
- zoneTaggingRouter.post( '/addCustomTag', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateAddTagParams ), tagController.addCustomTag );
11
- zoneTaggingRouter.get( '/customTagList', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isView' ] } ] } ), validate( validation.validateTagParams ), tagController.customTagList );
12
- zoneTaggingRouter.post( '/tagging', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateTaggingParams ), tagController.tagging );
13
- zoneTaggingRouter.get( '/cameraList', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isView' ] } ] } ), validate( validation.validateTagParams ), tagController.getCameraList );
14
- zoneTaggingRouter.post( '/updateCustomTag', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateUpdateTagParams ), tagController.updateTag );
15
- zoneTaggingRouter.post( '/deleteCustomTag', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isDelete' ] } ] } ), validate( validation.validateDeleteTagParams ), tagController.deleteTag );
16
- zoneTaggingRouter.get( '/getCameraTagging', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isView' ] } ] } ), validate( validation.validateCameraTagParams ), tagController.getCameraTagging );
17
- zoneTaggingRouter.get( '/getZoneTagging', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isView' ] } ] } ), validate( validation.validateZonetagParams ), tagController.getZoneList );
18
- zoneTaggingRouter.post( '/updatezoneTagging', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateCamZonetagParams ), tagController.updatezoneTagging );
19
- zoneTaggingRouter.post( '/deleteZoneTag', isAllowedSessionHandler, authorize( { userType: [ 'tango', 'client' ], access: [ { featureName: 'analytics', name: 'tangoZone', permissions: [ 'isEdit' ] } ] } ), validate( validation.updateCoordinatesParams ), tagController.deletezoneTagging );
10
+ zoneTaggingRouter.post( '/addCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateAddTagParams ), tagController.addCustomTag );
11
+ zoneTaggingRouter.get( '/customTagList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.customTagList );
12
+ zoneTaggingRouter.get( '/customTagListv2', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), tagController.customTagListv2 );
13
+ zoneTaggingRouter.post( '/tagging', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateTaggingParams ), tagController.tagging );
14
+ zoneTaggingRouter.get( '/cameraList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.getCameraList );
15
+ zoneTaggingRouter.get( '/cameraListv2', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.getCameraListv2 );
16
+ zoneTaggingRouter.post( '/updateCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateUpdateTagParams ), tagController.updateTag );
17
+ zoneTaggingRouter.post( '/deleteCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateDeleteTagParams ), tagController.deleteTag );
18
+ zoneTaggingRouter.get( '/getCameraTagging', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateCameraTagParams ), tagController.getCameraTagging );
19
+ zoneTaggingRouter.get( '/getZoneTagging', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateZonetagParams ), tagController.getZoneList );
20
+ zoneTaggingRouter.post( '/updatezoneTagging', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateCamZonetagParams ), tagController.updatezoneTagging );
21
+ zoneTaggingRouter.post( '/deleteZoneTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.updateCoordinatesParams ), tagController.deletezoneTagging );
22
+ zoneTaggingRouter.post( '/updateCamera', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), tagController.updateCamera );
20
23
 
21
24
  zoneTaggingRouter.get( '/updateOldZone', tagController.updateOldData );
22
25
 
@@ -0,0 +1,35 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const find = ( query = {}, record = {} ) => {
4
+ return model.processedchecklistconfigModel.find( query, record );
5
+ };
6
+
7
+ export const findOne = ( query = {}, record = {} ) => {
8
+ return model.processedchecklistconfigModel.findOne( query, record ).sort( { updatedAt: -1 } );
9
+ };
10
+
11
+ export const updateOne = ( query = {}, record = {} ) => {
12
+ return model.processedchecklistconfigModel.updateOne( query, { $set: record }, { upsert: true } );
13
+ };
14
+
15
+ export const updateMany = ( query = {}, record = {} ) => {
16
+ return model.processedchecklistconfigModel.updateMany( query, { $set: record } );
17
+ };
18
+
19
+ export const deleteMany = ( query = {} ) => {
20
+ return model.processedchecklistconfigModel.deleteMany( query );
21
+ };
22
+
23
+ export const aggregate = ( query = [] ) => {
24
+ return model.processedchecklistconfigModel.aggregate( query );
25
+ };
26
+
27
+ export const getClientCount = ( query = {} ) => {
28
+ return model.processedchecklistconfigModel.count( query );
29
+ };
30
+
31
+ export const insert = ( document={} ) => {
32
+ return model.processedchecklistconfigModel.create( document );
33
+ };
34
+
35
+