tango-app-api-store-zone 3.3.1-beta.19 → 3.3.1-beta.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.
@@ -13,6 +13,34 @@ export const validateAddTagParams = {
13
13
  body: addTagSchema,
14
14
  };
15
15
 
16
+ // zone tagging
17
+ export const zoneAddTagSchema = joi.object( {
18
+ clientId: joi.string().required(),
19
+ tagName: joi.string().required(),
20
+ productName: joi.string().required(),
21
+ rgbColor: joi.string().required(),
22
+ rgbBorderColor: joi.string().required(),
23
+ groupName: joi.string().allow( '', null ).optional(),
24
+ isExistingGroup: joi.boolean().optional(),
25
+ } );
26
+
27
+ export const validateZoneAddTagParams = {
28
+ body: zoneAddTagSchema,
29
+ };
30
+
31
+ // zone grouping
32
+ export const zoneGroupAddTagSchema = joi.object( {
33
+ clientId: joi.string().required(),
34
+ groupName: joi.string().required(),
35
+ productName: joi.string().required(),
36
+ tagName: joi.string().optional(),
37
+ zonesTagged: joi.array().items( joi.string() ).optional(),
38
+ } );
39
+
40
+ export const validateZoneGroupAddTagParams = {
41
+ body: zoneGroupAddTagSchema,
42
+ };
43
+
16
44
  export const tagSchema = joi.object( {
17
45
  clientId: joi.string().required(),
18
46
  storeId: joi.string().required(),
@@ -34,6 +62,20 @@ export const validateUpdateTagParams = {
34
62
  body: validateUpdateTagSchema,
35
63
  };
36
64
 
65
+ export const validateZoneUpdateTagSchema = joi.object( {
66
+ clientId: joi.string().required(),
67
+ tagName: joi.string().required(),
68
+ productName: joi.string().required(),
69
+ _id: joi.string().optional(),
70
+ groupName: joi.string().allow( '', null ).optional(),
71
+ isExistingGroup: joi.boolean().optional(),
72
+ oldTag: joi.string().optional(),
73
+ } );
74
+
75
+ export const validateZoneUpdateTagParams = {
76
+ body: validateZoneUpdateTagSchema,
77
+ };
78
+
37
79
 
38
80
  export const validateDeleteTagSchema = joi.object( {
39
81
  tagName: joi.string().required(),
@@ -45,6 +87,25 @@ export const validateDeleteTagParams = {
45
87
  body: validateDeleteTagSchema,
46
88
  };
47
89
 
90
+ export const validateZoneDeleteTagSchema = joi.object( {
91
+ tagName: joi.string().required(),
92
+ clientId: joi.string().required(),
93
+ } );
94
+
95
+ export const validateZoneDeleteTagParams = {
96
+ body: validateZoneDeleteTagSchema,
97
+ };
98
+
99
+ export const validateZoneGroupDeleteTagSchema = joi.object( {
100
+ groupName: joi.string().required(),
101
+ clientId: joi.string().required(),
102
+ _id: joi.string().required(),
103
+ } );
104
+
105
+ export const validateZoneGroupDeleteTagParams = {
106
+ body: validateZoneGroupDeleteTagSchema,
107
+ };
108
+
48
109
  export const validateTaggingSchema = joi.object( {
49
110
  clientId: joi.string().required(),
50
111
  storeId: joi.string().required(),
@@ -111,3 +172,73 @@ export const getStreamSchema= joi.object( {
111
172
  export const getStreamParams = {
112
173
  body: getStreamSchema,
113
174
  };
175
+
176
+ export const validateZoneConfigTaggingSchema = joi.object( {
177
+ clientId: joi.string().required(),
178
+ limit: joi.number().integer().min( 1 ).optional(),
179
+ offset: joi.number().integer().min( 0 ).optional(),
180
+ searchValue: joi.string().allow( '' ).optional(),
181
+ export: joi.boolean().optional(),
182
+ sortBy: joi.number().optional(),
183
+ sortColumName: joi.string().allow( '' ).optional(),
184
+ } );
185
+
186
+ export const validateZoneConfigTaggingParams = {
187
+ body: validateZoneConfigTaggingSchema,
188
+ };
189
+
190
+ export const validateZoneGroupSchema = joi.object( {
191
+ clientId: joi.string().required(),
192
+ limit: joi.number().integer().min( 1 ).optional(),
193
+ offset: joi.number().integer().min( 0 ).optional(),
194
+ searchValue: joi.string().allow( '' ).optional(),
195
+ export: joi.boolean().optional(),
196
+ sortBy: joi.number().optional(),
197
+ sortColumName: joi.string().allow( '' ).optional(),
198
+ } );
199
+
200
+ export const validateZoneGroupingParams = {
201
+ body: validateZoneGroupSchema,
202
+ };
203
+
204
+ // bulk zone tagging - array of zones (request body is array directly)
205
+ export const bulkZoneAddTagSchema = joi.array().items(
206
+ joi.object( {
207
+ clientId: joi.string().required(),
208
+ tagName: joi.string().required(),
209
+ productName: joi.string().required(),
210
+ rgbColor: joi.string().required(),
211
+ rgbBorderColor: joi.string().required(),
212
+ groupName: joi.string().allow( '', null ).optional(),
213
+ } ),
214
+ ).min( 1 ).required();
215
+
216
+ export const validateBulkZoneAddTagParams = {
217
+ body: bulkZoneAddTagSchema,
218
+ };
219
+
220
+ // bulk zone-group (request body)
221
+ export const bulkZoneGroupAddTagSchema = joi.array().items(
222
+ joi.object( {
223
+ clientId: joi.string().required(),
224
+ groupName: joi.string().required(),
225
+ productName: joi.string().required(),
226
+ } ),
227
+ ).min( 1 ).required();
228
+
229
+ export const validateBulkZoneGroupAddTagParams = {
230
+ body: bulkZoneGroupAddTagSchema,
231
+ };
232
+
233
+ export const validateZoneGroupUpdateSchema = joi.object( {
234
+ _id: joi.string().optional(),
235
+ clientId: joi.string().required(),
236
+ groupName: joi.string().required(),
237
+ oldGroupName: joi.string().optional(),
238
+ productName: joi.string().required(),
239
+ zonesTagged: joi.array().items( joi.string() ).optional(),
240
+ } );
241
+
242
+ export const validateZoneGroupUpdateParams = {
243
+ body: validateZoneGroupUpdateSchema,
244
+ };
@@ -4,12 +4,14 @@ import express from 'express';
4
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
+ import { bulkZoneExists, bulkZoneGroupExists } from '../validations/zone.validations.js';
7
8
 
8
9
  export const zoneTaggingRouter = express.Router();
9
10
 
10
11
  zoneTaggingRouter.post( '/addCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateAddTagParams ), tagController.addCustomTag );
11
12
  zoneTaggingRouter.get( '/customTagList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.customTagList );
12
13
  zoneTaggingRouter.get( '/customTagListv2', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), tagController.customTagListv2 );
14
+ zoneTaggingRouter.get( '/customTagListv3', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), tagController.customTagListv3 );
13
15
  zoneTaggingRouter.post( '/tagging', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateTaggingParams ), tagController.tagging );
14
16
  zoneTaggingRouter.get( '/cameraList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.getCameraList );
15
17
  zoneTaggingRouter.post( '/cameraListv2', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateTagParams ), tagController.getCameraListv2 );
@@ -24,4 +26,17 @@ zoneTaggingRouter.post( '/updateCamera', isAllowedSessionHandler, accessVerifica
24
26
 
25
27
  zoneTaggingRouter.get( '/updateOldZone', tagController.updateOldData );
26
28
 
29
+ // settings config - zone routes
30
+ zoneTaggingRouter.post( '/getZoneTaggingDetails', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateZoneConfigTaggingParams ), tagController.getZoneTaggingDetails );
31
+ zoneTaggingRouter.post( '/addZoneCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateZoneAddTagParams ), tagController.addZoneCustomTag );
32
+ // bulk zone upload
33
+ zoneTaggingRouter.post( '/bulkZoneUpload', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateBulkZoneAddTagParams ), bulkZoneExists, tagController.uploadBulkZoneTag );
34
+ zoneTaggingRouter.post( '/updateZoneCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateZoneUpdateTagParams ), tagController.updateZoneCustomTag );
35
+ zoneTaggingRouter.post( '/deleteZoneCustomTag', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateZoneDeleteTagSchema ), tagController.deleteZoneCustomTag );
27
36
 
37
+ // settings config - zoneGrouping routes
38
+ zoneTaggingRouter.post( '/getZoneGroupDetails', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ ] } ] } ), validate( validation.validateZoneGroupingParams ), tagController.getZoneGroupDetails );
39
+ zoneTaggingRouter.post( '/addZoneGroup', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateZoneGroupAddTagParams ), tagController.addZoneGroup );
40
+ zoneTaggingRouter.post( '/bulkZoneGroupUpload', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isAdd' ] } ] } ), validate( validation.validateBulkZoneGroupAddTagParams ), bulkZoneGroupExists, tagController.uploadBulkZoneGroup );
41
+ zoneTaggingRouter.post( '/updateZoneGroup', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateZoneGroupUpdateParams ), tagController.updateZoneGroup );
42
+ zoneTaggingRouter.post( '/deleteZoneGroup', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoEye', name: 'ZoneTag', permissions: [ 'isEdit' ] } ] } ), validate( validation.validateZoneGroupDeleteTagParams ), tagController.deleteZoneGroup );
@@ -0,0 +1,55 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const findOne = async ( query ={}, record = {} ) => {
4
+ return await model.zonegroupsModel.findOne( query, record );
5
+ };
6
+
7
+ export const find = async ( query = {}, record = {}, options = {} ) => {
8
+ let queryBuilder = model.zonegroupsModel.find( query, record );
9
+
10
+ // Apply pagination if provided
11
+ if ( options.skip !== undefined ) {
12
+ queryBuilder = queryBuilder.skip( options.skip );
13
+ }
14
+ if ( options.limit !== undefined ) {
15
+ queryBuilder = queryBuilder.limit( options.limit );
16
+ }
17
+ if ( options.sort !== undefined ) {
18
+ queryBuilder = queryBuilder.sort( options.sort );
19
+ }
20
+
21
+ return await queryBuilder;
22
+ };
23
+
24
+ export const aggregate = async ( query ={} ) => {
25
+ return await model.zonegroupsModel.aggregate( query );
26
+ };
27
+
28
+ // export const deleteMany = async ( query = {} ) => {
29
+ // return await model.zonegroupsModel.deleteMany( query );
30
+ // };
31
+
32
+ export const deleteOne = async ( query = {} ) => {
33
+ return await model.zonegroupsModel.deleteOne( query );
34
+ };
35
+
36
+ // export const insertMany = async ( data = [] ) => {
37
+ // return await model.zonegroupsModel.insertMany( data );
38
+ // };
39
+
40
+ // export const updateMany = async ( query = {}, record ={} ) => {
41
+ // return await model.zonegroupsModel.updateMany( query, record );
42
+ // };
43
+
44
+ export const updateOne = async ( query = {}, record ={} ) => {
45
+ return await model.zonegroupsModel.updateOne( query, record );
46
+ };
47
+
48
+ export const create = async ( data = [] ) => {
49
+ return await model.zonegroupsModel.create( data );
50
+ };
51
+
52
+ export const count = async ( query = {} ) => {
53
+ return await model.zonegroupsModel.countDocuments( query );
54
+ };
55
+
@@ -0,0 +1,56 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export const findOne = async ( query ={}, record = {} ) => {
4
+ console.log( 'customZoneTagService findOne query :', query );
5
+ return await model.customZonetagsModel.findOne( query, record );
6
+ };
7
+
8
+ export const find = async ( query = {}, record = {}, options = {} ) => {
9
+ let queryBuilder = model.customZonetagsModel.find( query, record );
10
+
11
+ // Apply pagination if provided
12
+ if ( options.skip !== undefined ) {
13
+ queryBuilder = queryBuilder.skip( options.skip );
14
+ }
15
+ if ( options.limit !== undefined ) {
16
+ queryBuilder = queryBuilder.limit( options.limit );
17
+ }
18
+ if ( options.sort !== undefined ) {
19
+ queryBuilder = queryBuilder.sort( options.sort );
20
+ }
21
+
22
+ return await queryBuilder;
23
+ };
24
+
25
+ export const aggregate = async ( query ={}, record = {} ) => {
26
+ return await model.customZonetagsModel.aggregate( query );
27
+ };
28
+
29
+ // export const deleteMany = async ( query = {} ) => {
30
+ // return await model.customZonetagsModel.deleteMany( query );
31
+ // };
32
+
33
+ export const deleteOne = async ( query = {} ) => {
34
+ return await model.customZonetagsModel.deleteOne( query );
35
+ };
36
+
37
+ // export const insertMany = async ( data = [] ) => {
38
+ // return await model.customZonetagsModel.insertMany( data );
39
+ // };
40
+
41
+ export const updateMany = async ( query = {}, record ={} ) => {
42
+ return await model.customZonetagsModel.updateMany( query, record );
43
+ };
44
+
45
+ export const updateOne = async ( query = {}, record ={} ) => {
46
+ return await model.customZonetagsModel.updateOne( query, record );
47
+ };
48
+
49
+ export const create = async ( data = [] ) => {
50
+ return await model.customZonetagsModel.create( data );
51
+ };
52
+
53
+ export const count = async ( query = {} ) => {
54
+ return await model.customZonetagsModel.countDocuments( query );
55
+ };
56
+
@@ -36,3 +36,6 @@ export const create = async ( data = [] ) => {
36
36
  return await model.taggingModel.create( data );
37
37
  };
38
38
 
39
+ export const getDistinct = async ( fieldName, filter = {} ) => {
40
+ return await model.taggingModel.distinct( fieldName, filter );
41
+ };
@@ -0,0 +1,127 @@
1
+ import { logger } from 'tango-app-api-middleware';
2
+ import * as customZoneTagService from '../services/customzonetag.service.js';
3
+ import * as customzonegrouping from '../services/customzonegrouping.service.js';
4
+
5
+
6
+ export async function bulkZoneExists( req, res, next ) {
7
+ try {
8
+ const zonesArray = req.body;
9
+
10
+ // Validate zones array exists and is not empty
11
+ if ( !zonesArray || !Array.isArray( zonesArray ) || zonesArray.length === 0 ) {
12
+ return res.sendError( 'zone file should not be empty', 400 );
13
+ }
14
+
15
+ // Validate all zones have the same clientId
16
+ const clientIds = zonesArray.map( ( zone ) => zone.clientId );
17
+ const uniqueClientIds = [ ...new Set( clientIds ) ];
18
+ if ( uniqueClientIds.length > 1 ) {
19
+ return res.sendError( 'All zones must have the same clientId', 400 );
20
+ }
21
+ console.log( 'uniqueClientIds :', uniqueClientIds );
22
+ if ( !uniqueClientIds[0] ) {
23
+ return res.sendError( 'clientId is required for all zones', 400 );
24
+ }
25
+ const clientId = uniqueClientIds[0];
26
+
27
+ // Check for duplicate tagNames within the request
28
+ const tagNameList = zonesArray.map( ( zone ) => zone.tagName );
29
+ const uniqueTagNames = [ ...new Set( tagNameList ) ];
30
+ if ( uniqueTagNames.length !== tagNameList.length ) {
31
+ // const duplicates = tagNameList.filter( ( tagName, index ) => tagNameList.indexOf( tagName ) !== index );
32
+ return res.sendError( `Duplicate zone name found in request.`, 400 );
33
+ }
34
+
35
+ // Check if any tagNames already exist in the database for this client
36
+ const existingZones = await customZoneTagService.find( {
37
+ clientId: clientId,
38
+ tagName: { $in: tagNameList },
39
+ } );
40
+
41
+ if ( existingZones && existingZones.length > 0 ) {
42
+ // const existingTagNames = existingZones.map( ( zone ) => zone.tagName );
43
+ return res.sendError( `Zone names already exist for this client.`, 409 );
44
+ }
45
+
46
+ // Check for duplicate groupNames within the request (if provided)
47
+ const groupNameList = zonesArray
48
+ .filter( ( zone ) => zone.groupName && zone.groupName !== '' && zone.groupName !== null )
49
+ .map( ( zone ) => zone.groupName );
50
+
51
+ if ( groupNameList.length > 0 ) {
52
+ const uniqueGroupNames = [ ...new Set( groupNameList ) ];
53
+ if ( uniqueGroupNames.length !== groupNameList.length ) {
54
+ // const duplicateGroups = groupNameList.filter( ( groupName, index ) => groupNameList.indexOf( groupName ) !== index );
55
+ return res.sendError( `Duplicate group names found in request.`, 400 );
56
+ }
57
+
58
+ // Check if any groupNames already exist in the database for this client
59
+ const existingGroups = await customzonegrouping.find( {
60
+ clientId: clientId,
61
+ groupName: { $in: uniqueGroupNames },
62
+ } );
63
+
64
+ if ( existingGroups && existingGroups.length > 0 ) {
65
+ // const existingGroupNames = existingGroups.map( ( group ) => group.groupName );
66
+ return res.sendError( `Group names already exist for this client.`, 409 );
67
+ }
68
+ }
69
+
70
+ // Attach clientId to req for use in controller
71
+ req.bulkZoneClientId = clientId;
72
+ next();
73
+ } catch ( error ) {
74
+ const err = error.message || 'Internal Server Error';
75
+ logger.error( { error: error, message: req.body, function: 'bulkZoneExists' } );
76
+ return res.sendError( err, 500 );
77
+ }
78
+ }
79
+
80
+
81
+ export async function bulkZoneGroupExists( req, res, next ) {
82
+ try {
83
+ const groupsArray = req.body;
84
+
85
+ // Validate groups array exists and is not empty
86
+ if ( !groupsArray || !Array.isArray( groupsArray ) || groupsArray.length === 0 ) {
87
+ return res.sendError( 'group file should not be empty', 400 );
88
+ }
89
+
90
+ // Validate all groups have the same clientId
91
+ const clientIds = groupsArray.map( ( group ) => group.clientId );
92
+ const uniqueClientIds = [ ...new Set( clientIds ) ];
93
+ if ( uniqueClientIds.length > 1 ) {
94
+ return res.sendError( 'All groups must have the same clientId', 400 );
95
+ }
96
+ console.log( 'uniqueClientIds :', uniqueClientIds );
97
+ if ( !uniqueClientIds[0] ) {
98
+ return res.sendError( 'clientId is required for all groups', 400 );
99
+ }
100
+ const clientId = uniqueClientIds[0];
101
+
102
+ // Check for duplicate groupNames within the request
103
+ const groupNameList = groupsArray.map( ( group ) => group.groupName );
104
+ const uniqueGroupNames = [ ...new Set( groupNameList ) ];
105
+ if ( uniqueGroupNames.length !== groupNameList.length ) {
106
+ return res.sendError( `Duplicate group names found in request.`, 400 );
107
+ }
108
+
109
+ // Check if any groupNames already exist in the database for this client
110
+ const existingGroups = await customzonegrouping.find( {
111
+ clientId: clientId,
112
+ groupName: { $in: uniqueGroupNames },
113
+ } );
114
+
115
+ if ( existingGroups && existingGroups.length > 0 ) {
116
+ return res.sendError( `Group names already exist for this client.`, 409 );
117
+ }
118
+
119
+ // Attach clientId to req for use in controller
120
+ req.bulkZoneClientId = clientId;
121
+ next();
122
+ } catch ( error ) {
123
+ const err = error.message || 'Internal Server Error';
124
+ logger.error( { error: error, message: req.body, function: 'bulkZoneGroupExists' } );
125
+ return res.sendError( err, 500 );
126
+ }
127
+ }