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
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.
|
|
3
|
+
"version": "3.3.1-beta.10",
|
|
4
4
|
"description": "zone",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "app.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"start": "nodemon --exec \"eslint --fix . && node
|
|
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
|
|
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.
|
|
25
|
-
"tango-app-api-middleware": "^3.1.
|
|
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}
|
|
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
|
|
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 (
|
|
192
|
-
InputData = { ...InputData, rgbColor:
|
|
376
|
+
if ( InputData.coordinates[0].color ) {
|
|
377
|
+
InputData = { ...InputData, rgbColor: InputData.coordinates[0].color };
|
|
193
378
|
}
|
|
194
379
|
|
|
195
|
-
if (
|
|
196
|
-
InputData = { ...InputData, 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
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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 = {
|
|
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
|
|
421
|
-
eventType: '',
|
|
422
|
-
|
|
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: '
|
|
489
|
-
changes: [ `${req.body.tagName} tag
|
|
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,
|
|
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,
|
|
11
|
-
zoneTaggingRouter.get( '/customTagList', isAllowedSessionHandler,
|
|
12
|
-
zoneTaggingRouter.
|
|
13
|
-
zoneTaggingRouter.
|
|
14
|
-
zoneTaggingRouter.
|
|
15
|
-
zoneTaggingRouter.
|
|
16
|
-
zoneTaggingRouter.
|
|
17
|
-
zoneTaggingRouter.
|
|
18
|
-
zoneTaggingRouter.
|
|
19
|
-
zoneTaggingRouter.
|
|
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
|
+
|