tango-app-api-store-builder 1.0.1-alpha

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 ADDED
@@ -0,0 +1,41 @@
1
+
2
+
3
+ module.exports = {
4
+ 'env': {
5
+ 'es2021': true,
6
+ 'node': true,
7
+ },
8
+ 'extends': 'google',
9
+ 'overrides': [
10
+ {
11
+ 'env': {
12
+ 'node': true,
13
+ },
14
+ 'files': [
15
+ '.eslintrc.{js,cjs}',
16
+ ],
17
+ 'parserOptions': {
18
+ 'sourceType': 'script',
19
+ },
20
+ },
21
+ ],
22
+ 'parserOptions': {
23
+ 'ecmaVersion': 'latest',
24
+ 'sourceType': 'module',
25
+ },
26
+ 'rules': {
27
+ 'linebreak-style': [ 'error', 'windows' ],
28
+ 'require-jsdoc': 'off',
29
+ 'arrow-spacing': 'error',
30
+ 'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
31
+ 'object-curly-spacing': [ 'error', 'always' ],
32
+ 'space-in-parens': [ 'error', 'always' ],
33
+ 'keyword-spacing': 'error',
34
+ 'array-bracket-spacing': [ 'error', 'always' ],
35
+ 'spaced-comment': [ 'error', 'always' ],
36
+ 'max-len': [ 'error', { 'code': 700 } ],
37
+ 'no-unused-vars': 'error',
38
+ 'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
39
+ 'prefer-const': 'off',
40
+ },
41
+ };
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # README #
2
+
3
+ This README would normally document whatever steps are necessary to get your application up and running.
4
+
5
+ ### What is this repository for? ###
6
+
7
+ * Quick summary
8
+ * Version
9
+ * [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
10
+
11
+ ### How do I get set up? ###
12
+
13
+ * Summary of set up
14
+ * Configuration
15
+ * Dependencies
16
+ * Database configuration
17
+ * How to run tests
18
+ * Deployment instructions
19
+
20
+ ### Contribution guidelines ###
21
+
22
+ * Writing tests
23
+ * Code review
24
+ * Other guidelines
25
+
26
+ ### Who do I talk to? ###
27
+
28
+ * Repo owner or admin
29
+ * Other community or team contact
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { storeBuilderRouter } from './src/routes/storeBuilder.routes.js';
2
+
3
+ export { storeBuilderRouter };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "tango-app-api-store-builder",
3
+ "version": "1.0.1-alpha",
4
+ "description": "storeBuilder",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "start": "nodemon --exec \"eslint --fix . && node index.js\""
9
+ },
10
+ "engines": {
11
+ "node": ">=18.10.0"
12
+ },
13
+ "author": "praveenraj",
14
+ "license": "ISC",
15
+ "dependencies": {
16
+ "aws-sdk": "^2.1692.0",
17
+ "cors": "^2.8.5",
18
+ "dayjs": "^1.11.13",
19
+ "dotenv": "^16.4.7",
20
+ "express": "^4.21.2",
21
+ "express-fileupload": "^1.5.1",
22
+ "handlebars": "^4.7.8",
23
+ "joi": "^17.13.3",
24
+ "mongodb": "^6.12.0",
25
+ "nodemon": "^3.1.9",
26
+ "tango-api-schema": "^2.2.23",
27
+ "tango-app-api-middleware": "^3.1.48",
28
+ "winston": "^3.17.0",
29
+ "winston-daily-rotate-file": "^5.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "eslint": "^8.57.1",
33
+ "eslint-config-google": "^0.14.0",
34
+ "eslint-config-semistandard": "^17.0.0",
35
+ "eslint-config-standard": "^17.1.0",
36
+ "eslint-plugin-import": "^2.31.0",
37
+ "eslint-plugin-promise": "^6.6.0"
38
+ }
39
+ }
@@ -0,0 +1,485 @@
1
+ import * as storeBuilderService from '../service/storeBuilder.service.js';
2
+ import * as storeService from '../service/store.service.js';
3
+ import * as planoService from '../service/planogram.service.js';
4
+ import { logger, fileUpload, signedUrl } from 'tango-app-api-middleware';
5
+ import dayjs from 'dayjs';
6
+ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
7
+ import utc from 'dayjs/plugin/utc.js';
8
+ import mongoose from 'mongoose';
9
+ dayjs.extend( utc );
10
+ dayjs.extend( customParseFormat );
11
+
12
+ export async function createStoreBuilder( req, res ) {
13
+ try {
14
+ let data = [];
15
+ let checkStoreLayoutExists = await planoService.findOne( { storeId: req.body.storeId, clientId: req.body.clientId } );
16
+ if ( checkStoreLayoutExists ) {
17
+ return res.sendError( 'Store already exists', 400 );
18
+ }
19
+ let insertData = {
20
+ storeName: req.body.storeName,
21
+ storeId: req.body.storeId,
22
+ layoutName: `${req.body.storeName} - Layout`,
23
+ clientId: req.body.clientId,
24
+ createdBy: req.user._id,
25
+ createdByName: req.user.userName,
26
+ createdByEmail: req.user.email,
27
+ floorNumber: req.body.floorNumber,
28
+ };
29
+ let planoId = await planoService.create( insertData );
30
+ let params = {
31
+ storeName: req.body.storeName,
32
+ storeId: req.body.storeId,
33
+ layoutName: `${req.body.storeName} - Layout`,
34
+ clientId: req.body.clientId,
35
+ createdBy: req.user._id,
36
+ createdByName: req.user.userName,
37
+ createdByEmail: req.user.email,
38
+ planoId: planoId._id,
39
+ };
40
+ for ( let i=1; i<=req.body.floorNumber; i++ ) {
41
+ data.push( { ...params, floorNumber: i, floorName: `floor ${i}` } );
42
+ }
43
+ await storeBuilderService.insertMany( data );
44
+ return res.sendSuccess( { message: 'Store Layout Created Successfully', id: planoId._id } );
45
+ } catch ( e ) {
46
+ logger.error( { functionName: 'createStoreBuilder', error: e } );
47
+ return res.sendError( e, 500 );
48
+ }
49
+ }
50
+
51
+ export async function updateStoreLayout( req, res ) {
52
+ try {
53
+ let getLayoutDetails = await storeBuilderService.findOne( { _id: req.body.id } );
54
+ if ( !getLayoutDetails ) {
55
+ return res.sendError( 'no data found', 204 );
56
+ }
57
+ getLayoutDetails.status = req.body.status;
58
+ getLayoutDetails.layoutPolygon = req.body.layoutPolygon;
59
+ getLayoutDetails.save().then( () => {
60
+ return res.sendSuccess( 'Store Layout Updated Successfully' );
61
+ } ).catch( ( e ) => {
62
+ return res.sendError( e, 500 );
63
+ } );
64
+ } catch ( e ) {
65
+ logger.error( { functionName: 'updateStoreLayout', error: e } );
66
+ return res.sendError( e, 500 );
67
+ }
68
+ }
69
+
70
+ export async function updateFloor( req, res ) {
71
+ try {
72
+ let getLayoutDetails = await planoService.findOne( { _id: req.body.id } );
73
+ if ( !getLayoutDetails ) {
74
+ return res.sendError( 'no data found', 204 );
75
+ }
76
+ let params = {
77
+ storeName: getLayoutDetails.storeName,
78
+ storeId: getLayoutDetails.storeId,
79
+ layoutName: `${getLayoutDetails.storeName} - Layout`,
80
+ clientId: getLayoutDetails.clientId,
81
+ createdBy: req.user._id,
82
+ createdByName: req.user.userName,
83
+ createdByEmail: req.user.email,
84
+ planoId: req.body.id,
85
+ };
86
+ let data = [];
87
+ let num = getLayoutDetails.floorNumber + req.body.floorNumber;
88
+ for ( let i=getLayoutDetails.floorNumber + 1; i <= num; i++ ) {
89
+ data.push( { ...params, floorNumber: i, floorName: `floor ${i}` } );
90
+ }
91
+ getLayoutDetails.floorNumber = num;
92
+ getLayoutDetails.save();
93
+ await storeBuilderService.insertMany( data );
94
+ return res.sendSuccess( 'Floor added successfully' );
95
+ } catch ( e ) {
96
+ logger.error( { functionName: 'updateFloor', error: e } );
97
+ return res.sendError( e, 500 );
98
+ }
99
+ }
100
+
101
+ export async function getLayoutList( req, res ) {
102
+ try {
103
+ let limit = req.body?.limit || 10;
104
+ let page = req.body?.offset || 0;
105
+ let skip = limit * page;
106
+ let query = [
107
+ {
108
+ $match: {
109
+ clientId: req.body.clientId,
110
+ },
111
+ },
112
+ ];
113
+ if ( req.body?.sortColumnName == '' && req.body.sortBy == '' ) {
114
+ query.push( { $sort: { createdAt: -1 } } );
115
+ }
116
+ if ( req.body?.filter.length ) {
117
+ query.push( {
118
+ $match: {
119
+ status: { $in: req.body.filter },
120
+ },
121
+ } );
122
+ }
123
+ if ( req.body.searchValue.length ) {
124
+ let storeList = req.body.searchValue.split( ',' );
125
+ if ( storeList.length > 1 ) {
126
+ req.body.searchValue = storeList.map( ( ele ) => ele.toLowerCase() );
127
+ query.push(
128
+ {
129
+ $addFields: {
130
+ store: { $toLower: '$storeName' },
131
+ },
132
+ }, {
133
+ $match: {
134
+ store: { $in: req.body.searchValue },
135
+ },
136
+ },
137
+ );
138
+ } else {
139
+ query.push(
140
+ {
141
+ $match: {
142
+ storeName: { $regex: req.body.searchValue, $options: 'i' },
143
+ },
144
+ },
145
+ );
146
+ }
147
+ }
148
+ if ( req.body?.sortColumnName != '' && req.body.sortBy != '' ) {
149
+ query.push( {
150
+ $sort: { [req.body.sortColumnName]: req.body.sortBy },
151
+ } );
152
+ }
153
+ query.push( {
154
+ $facet: {
155
+ data: [
156
+ { $limit: limit }, { $skip: skip },
157
+ ],
158
+ count: [
159
+ { $count: 'total' },
160
+ ],
161
+ },
162
+ } );
163
+ let storeLayoutList = await planoService.aggregate( query );
164
+ if ( !storeLayoutList[0].data.length ) {
165
+ return res.sendError( 'No data found', 204 );
166
+ }
167
+
168
+ storeLayoutList[0].data.forEach( ( ele ) => {
169
+ ele.createdAt = dayjs.utc( ele.createdAt ).format( 'DD MMM, YYYY' );
170
+ } );
171
+
172
+ return res.sendSuccess( { data: storeLayoutList[0].data, count: storeLayoutList[0].count?.[0]?.total || 0 } );
173
+ } catch ( e ) {
174
+ logger.error( { functionName: 'getLayoutList', error: e } );
175
+ return res.sendError( e, 500 );
176
+ }
177
+ }
178
+
179
+ export async function uploadBulkStore( req, res ) {
180
+ try {
181
+ let data = [];
182
+ let planoData = [];
183
+ let error = [];
184
+ let storeList = req.body.data.map( ( ele ) => ele['storeName'].toLowerCase() );
185
+ let query = [
186
+ {
187
+ $addFields: {
188
+ store: { $toLower: '$storeName' },
189
+ },
190
+ },
191
+ {
192
+ $match: {
193
+ store: { $in: storeList },
194
+ clientId: req.body.clientId,
195
+ },
196
+ },
197
+ {
198
+ $project: {
199
+ storeName: 1,
200
+ storeId: 1,
201
+ },
202
+ },
203
+ ];
204
+ let getStoreDetails = await storeService.aggregate( query );
205
+ if ( !getStoreDetails.length ) {
206
+ let invalidStoreList = [ ...new Set( req.body.data.map( ( ele ) => ele.storeName ) ) ];
207
+ return res.sendError( [ { message: 'Invalid Stores', value: invalidStoreList } ], 400 );
208
+ }
209
+ let existStore = getStoreDetails.map( ( element ) => element.storeName.toLowerCase() );
210
+ let invalidStoreList = req.body.data.filter( ( ele ) => !existStore.includes( ele.storeName.toLowerCase() ) );
211
+ if ( invalidStoreList.length ) {
212
+ invalidStoreList = [ ...new Set( invalidStoreList.map( ( ele ) => ele.storeName ) ) ];
213
+ error.push( { message: 'Invalid Stores', value: invalidStoreList } );
214
+ }
215
+ storeList = [ ...new Set( getStoreDetails.map( ( item ) => item.storeId ) ) ];
216
+
217
+ let duplicateStoreList = await planoService.find( { storeId: storeList } );
218
+ if ( duplicateStoreList.length ) {
219
+ let existStore = [];
220
+ let planoIdList = duplicateStoreList.map( ( item ) => item._id );
221
+ let getStorePlanoDetails = await storeBuilderService.find( { planoId: { $in: planoIdList } }, { floorNumber: 1, storeName: 1 } );
222
+ if ( getStorePlanoDetails ) {
223
+ getStorePlanoDetails.forEach( ( item ) => {
224
+ let existsData = req.body.data.find( ( ele ) => ele.storeName.toLowerCase() == item.storeName.toLowerCase() && ele.floorNumber == item.floorNumber );
225
+ if ( existsData ) {
226
+ existStore.push( item.storeName );
227
+ }
228
+ } );
229
+ }
230
+ if ( existStore.length ) {
231
+ error.push( { message: 'Duplicate Store Name', value: existStore } );
232
+ }
233
+ }
234
+
235
+ if ( error.length ) {
236
+ return res.sendError( error, 400 );
237
+ }
238
+
239
+ for ( let ele of getStoreDetails ) {
240
+ let getNumber = req.body.data.filter( ( store ) => store.storeName == ele.storeName ).sort( ( a, b ) => b.floorNumber - a.floorNumber );
241
+ let insertData = {
242
+ storeName: ele.storeName,
243
+ storeId: ele.storeId,
244
+ layoutName: `${ele.storeName} - Layout`,
245
+ clientId: req.body.clientId,
246
+ createdBy: req.user._id,
247
+ createdByName: req.user.userName,
248
+ createdByEmail: req.user.email,
249
+ floorNumber: getNumber?.[0]?.floorNumber,
250
+ };
251
+ let planoRes = await planoService.create( insertData );
252
+ planoData.push( { id: planoRes._id, storeName: planoRes.storeName } );
253
+ }
254
+
255
+ req.body.data.forEach( ( item ) => {
256
+ let findStore = data.find( ( ele ) => ele.storeName.toLowerCase() == item.storeName.toLowerCase() && ele.floorNumber == item.floorNumber );
257
+ if ( !findStore ) {
258
+ let getStoreData = req.body.data.filter( ( ele ) => ele.storeName.toLowerCase() == item.storeName.toLowerCase() && ele.floorNumber == item.floorNumber );
259
+ getStoreData = getStoreData.sort( ( a, b ) => a.step - b.step );
260
+ let layoutPolygon = [];
261
+ getStoreData.forEach( ( ele ) => {
262
+ let findEle = layoutPolygon.filter( ( element ) => element.elementType == ele.elements );
263
+ layoutPolygon.push( {
264
+ elementType: ele.elements,
265
+ distance: ele.distance,
266
+ unit: 'ft',
267
+ direction: ele.direction,
268
+ angle: ele.degree,
269
+ elementNumber: findEle.length ? `${findEle.length + 1}` : `1`,
270
+ } );
271
+ } );
272
+
273
+ let getStoreId = getStoreDetails.find( ( ele ) => ele.storeName == item.storeName );
274
+ if ( getStoreId ) {
275
+ let getPlanoId = planoData.find( ( ele ) => ele.storeName == item.storeName );
276
+ data.push( {
277
+ storeName: getStoreId.storeName,
278
+ storeId: getStoreId.storeId,
279
+ layoutName: `${item.storeName} - Layout`,
280
+ clientId: req.body.clientId,
281
+ createdBy: req.user._id,
282
+ createdByName: req.user.userName,
283
+ createdByEmail: req.user.email,
284
+ layoutPolygon: layoutPolygon,
285
+ floorNumber: item.floorNumber,
286
+ floorName: `floor ${item.floorNumber}`,
287
+ planoId: getPlanoId?.id,
288
+ } );
289
+ }
290
+ }
291
+ } );
292
+ await storeBuilderService.insertMany( data );
293
+ let planoIdList = planoData.map( ( ele ) => ele.id );
294
+ return res.sendSuccess( { message: 'Bulk Stored upload successfully', id: planoIdList.toString() } );
295
+ } catch ( e ) {
296
+ logger.error( { functionName: 'uploadBulkStore', error: e, message: req.body } );
297
+ return res.sendError( e, 500 );
298
+ }
299
+ }
300
+
301
+ export async function uploadFile( req, res ) {
302
+ try {
303
+ let getPlanoDetails = await planoService.findOne( { _id: req.body.id } );
304
+ if ( !getPlanoDetails ) {
305
+ return res.sendError( 'No data found' );
306
+ }
307
+ if ( req.files.file ) {
308
+ let bucket = JSON.parse( process.env.Bucket );
309
+ let params ={
310
+ Bucket: bucket.storeBuilder,
311
+ Key: `${getPlanoDetails.clientId}/${getPlanoDetails.storeName}/attachments/`,
312
+ fileName: req.files.file.name,
313
+ ContentType: req.files.file.mimetype,
314
+ body: req.files.file.data,
315
+ };
316
+ let fileuploadRes = await fileUpload( params );
317
+ if ( getPlanoDetails ) {
318
+ let updateRes = await planoService.updateOne( { _id: getPlanoDetails. _id }, { $push: { attachments: fileuploadRes.Key } } );
319
+ if ( updateRes.modifiedCount ) {
320
+ let params = {
321
+ Bucket: bucket.storeBuilder,
322
+ file_path: fileuploadRes.Key,
323
+ };
324
+ let getSignedUrl = await signedUrl( params );
325
+ return res.sendSuccess( { url: getSignedUrl, name: fileuploadRes.Key.split( '/' ).pop() } );
326
+ }
327
+ } else {
328
+ return res.sendError( 'Something went wrong', 500 );
329
+ }
330
+ }
331
+ } catch ( e ) {
332
+ logger.error( { functionName: 'uploadFile', error: e, message: req.body } );
333
+ return res.sendError( e, 500 );
334
+ }
335
+ }
336
+
337
+ export async function getStoreDetails( req, res ) {
338
+ try {
339
+ let getStoreDetails = await storeService.findOne( { storeId: req.body.storeId, clientId: req.body.clientId } );
340
+ if ( !getStoreDetails ) {
341
+ return res.sendError( 'No data found', 204 );
342
+ }
343
+ getStoreDetails = { ...getStoreDetails._doc, cameraBaseImage: '', attachments: [] };
344
+ const camera = await storeService.findCamera( { storeId: req.body.storeId, isUp: true, isActivated: true }, { thumbnailImage: 1 } );
345
+ if ( camera.thumbnailImage ) {
346
+ const bucket= JSON.parse( process.env.BUCKET );
347
+ const params = {
348
+ file_path: camera.thumbnailImage,
349
+ Bucket: bucket.baseImage,
350
+ };
351
+ const cameraBaseImage = await signedUrl( params );
352
+ getStoreDetails.cameraBaseImage = cameraBaseImage;
353
+ }
354
+
355
+ let getAttachments = await planoService.findOne( { storeId: req.body.storeId, clientId: req.body.clientId }, { attachments: 1 } );
356
+ let bucket = JSON.parse( process.env.BUCKET );
357
+ for ( let attach of getAttachments?.attachments ) {
358
+ let params = {
359
+ Bucket: bucket.storeBuilder,
360
+ file_path: attach,
361
+ };
362
+ let getSignedUrl = await signedUrl( params );
363
+ getStoreDetails.attachments .push( { url: getSignedUrl, name: attach.split( '/' ).pop() } );
364
+ }
365
+ return res.sendSuccess( getStoreDetails );
366
+ } catch ( e ) {
367
+ logger.error( { functionName: 'getStoreDetails', error: e, message: req.body } );
368
+ return res.sendError( e, 500 );
369
+ }
370
+ }
371
+
372
+ export async function storeList( req, res ) {
373
+ try {
374
+ let idList = req.body.id.map( ( item ) => new mongoose.Types.ObjectId );
375
+ let query = { _id: { $in: req.body.id } };
376
+ let getStoreList = await planoService.find( query );
377
+ if ( !getStoreList ) {
378
+ return res.sendError( 'No data found', 204 );
379
+ }
380
+ idList = getStoreList.map( ( item ) => new mongoose.Types.ObjectId( item._id ) );
381
+ query = [
382
+ {
383
+ $match: {
384
+ planoId: { $in: idList },
385
+ },
386
+ },
387
+ {
388
+ $group: {
389
+ _id: '$storeName',
390
+ storeId: { $first: '$storeId' },
391
+ floor: { $push: { floorName: '$floorName', id: '$_id', layoutPolygon: '$layoutPolygon' } },
392
+ planoId: { $first: '$planoId' },
393
+ },
394
+ },
395
+ {
396
+ $project: {
397
+ _id: 0,
398
+ storeName: '$_id',
399
+ storeId: 1,
400
+ floor: 1,
401
+ planoId: 1,
402
+ },
403
+ },
404
+ { $sort: { createdAt: -1 } },
405
+ ];
406
+ getStoreList = await storeBuilderService.aggregate( query );
407
+ if ( !getStoreList.length ) {
408
+ return res.sendError( 'No data found', 204 );
409
+ }
410
+ return res.sendSuccess( getStoreList );
411
+ } catch ( e ) {
412
+ logger.error( { functionName: 'storeList', error: e, message: req.body } );
413
+ return res.sendError( e, 500 );
414
+ }
415
+ }
416
+
417
+ export async function deleteStoreLayout( req, res ) {
418
+ try {
419
+ let getDetails = await planoService.findOne( { _id: req.body.id } );
420
+ if ( !getDetails ) {
421
+ return res.sendError( 'No data found', 204 );
422
+ }
423
+
424
+ await storeBuilderService.deleteMany( { planoId: req.body.id } );
425
+ await planoService.deleteOne( { _id: req.body.id } );
426
+ return res.sendSuccess( 'Store layout successfully' );
427
+ } catch ( e ) {
428
+ logger.error( { functionName: 'deleteStoreLayout', error: e, message: req.body } );
429
+ return res.sendError( e, 500 );
430
+ }
431
+ }
432
+
433
+ export async function deleteFile( req, res ) {
434
+ try {
435
+ let getPlanoDetails = await planoService.findOne( { _id: req.body.id } );
436
+ if ( !getPlanoDetails ) {
437
+ return res.sendError( 'No data found', 204 );
438
+ }
439
+
440
+ let updateFileRes = await planoService.updateOne( { _id: req.body.id }, { $unset: { 'attachments.0': req.body.fileIndex } } );
441
+ updateFileRes = await planoService.updateOne( { _id: req.body.id }, { $pull: { 'attachments': null } } );
442
+ if ( updateFileRes.matchedCount ) {
443
+ return res.sendSuccess( 'File removed successfully' );
444
+ }
445
+ } catch ( e ) {
446
+ logger.error( { functionName: 'deleteFile', error: e, message: req.body } );
447
+ return res.sendError( e, 500 );
448
+ }
449
+ }
450
+
451
+ export async function deleteFloor( req, res ) {
452
+ try {
453
+ let getBuilderDetails = await storeBuilderService.findOne( { _id: req.body.id } );
454
+ if ( !getBuilderDetails ) {
455
+ return res.sendError( 'No data found', 204 );
456
+ }
457
+
458
+ await storeBuilderService.deleteOne( { _id: req.body.id } );
459
+ return res.sendSuccess( 'Floor Deleted successfully' );
460
+ } catch ( e ) {
461
+ logger.error( { functionName: 'deleteFloor', error: e, message: req.body } );
462
+ return res.sendError( e, 500 );
463
+ }
464
+ }
465
+
466
+ export async function updateStatus( req, res ) {
467
+ try {
468
+ let getBuilderDetails = await planoService.find( { storeId: { $in: req.body.storeId } } );
469
+ if ( !getBuilderDetails.length ) {
470
+ return res.sendError( 'No data found', 204 );
471
+ }
472
+
473
+ getBuilderDetails.status = req.body.status;
474
+ await planoService.updateMany( { storeId: { $in: req.body.storeId } }, { status: req.body.status } );
475
+ let planoId = getBuilderDetails.map( ( item ) => item._id );
476
+ await storeBuilderService.updateMany( { planoId: { $in: planoId } }, { status: req.body.status } );
477
+
478
+ return res.sendSuccess( 'Statu updated successfully' );
479
+ } catch ( e ) {
480
+ logger.error( { functionName: 'updateStatus', error: e, message: req.body } );
481
+ return res.sendError( e, 500 );
482
+ }
483
+ }
484
+
485
+
@@ -0,0 +1,82 @@
1
+ import joi from 'joi';
2
+
3
+ export const createBuilderSchema = joi.object( {
4
+ storeName: joi.string().required(),
5
+ storeId: joi.string().required(),
6
+ clientId: joi.string().required(),
7
+ floorNumber: joi.number().required(),
8
+ } );
9
+
10
+ export const createBuilder = {
11
+ body: createBuilderSchema,
12
+ };
13
+
14
+ export const updateStoreLayoutSchema = joi.object( {
15
+ id: joi.string().required(),
16
+ layoutPolygon: joi.array().required(),
17
+ status: joi.string().required(),
18
+ } );
19
+
20
+ export const updateStoreLayout = {
21
+ body: updateStoreLayoutSchema,
22
+ };
23
+
24
+ export const storeLayoutListSchema = joi.object( {
25
+ limit: joi.number().required(),
26
+ offset: joi.number().required(),
27
+ filter: joi.array().items( joi.any() ).min( 0 ),
28
+ searchValue: joi.string().required().allow( '' ),
29
+ sortColumnName: joi.string().required().allow( '' ),
30
+ sortBy: joi.number().required().allow( '' ),
31
+ clientId: joi.string().required(),
32
+ } );
33
+
34
+ export const storeLayoutList ={
35
+ body: storeLayoutListSchema,
36
+ };
37
+
38
+ export const updateFloorSchema = joi.object( {
39
+ id: joi.string().required(),
40
+ floorNumber: joi.number().required(),
41
+ } );
42
+
43
+ export const updateFloor = {
44
+ body: updateFloorSchema,
45
+ };
46
+
47
+ export const storeListSchema = joi.object( {
48
+ id: joi.array().items( joi.any() ).min( 1 ).required(),
49
+ } );
50
+
51
+ export const storeList = {
52
+ body: storeListSchema,
53
+ };
54
+
55
+ export const storeDetailSchema = joi.object( {
56
+ storeId: joi.string().required(),
57
+ clientId: joi.string().required(),
58
+ } );
59
+
60
+ export const storeDetails = {
61
+ body: storeDetailSchema,
62
+ };
63
+
64
+ export const deleteStoreLayoutSchema = joi.object( {
65
+ id: joi.string().required(),
66
+ } );
67
+
68
+
69
+ export const deleteStoreLayout = {
70
+ params: deleteStoreLayoutSchema,
71
+ };
72
+
73
+ export const updateStatusSchema = joi.object( {
74
+ storeId: joi.array().required(),
75
+ status: joi.string().required(),
76
+ } );
77
+
78
+ export const updateStatus = {
79
+ body: updateStatusSchema,
80
+ };
81
+
82
+
@@ -0,0 +1,22 @@
1
+ import express from 'express';
2
+ import { isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
3
+ import * as storeBuilderController from '../controllers/storeBuilder.controller.js';
4
+ import * as validateDtos from '../dtos/validation.dtos.js';
5
+
6
+ export const storeBuilderRouter = express.Router();
7
+
8
+ storeBuilderRouter
9
+ .post( '/createStoreLayout', isAllowedSessionHandler, validate( validateDtos.createBuilder ), storeBuilderController.createStoreBuilder )
10
+ .post( '/updateStoreLayout', isAllowedSessionHandler, validate( validateDtos.updateStoreLayout ), storeBuilderController.updateStoreLayout )
11
+ .post( '/storeLayoutList', isAllowedSessionHandler, validate( validateDtos.storeLayoutList ), storeBuilderController.getLayoutList )
12
+ .post( '/updateFloor', isAllowedSessionHandler, validate( validateDtos.updateFloor ), storeBuilderController.updateFloor )
13
+ .post( '/uploadBulkStore', isAllowedSessionHandler, storeBuilderController.uploadBulkStore )
14
+ .post( '/uploadFile', isAllowedSessionHandler, storeBuilderController.uploadFile )
15
+ .post( '/storeList', isAllowedSessionHandler, validate( validateDtos.storeList ), storeBuilderController.storeList )
16
+ .post( '/storeDetails', isAllowedSessionHandler, validate( validateDtos.storeDetails ), storeBuilderController.getStoreDetails )
17
+ .delete( '/deleteStoreLayout:/id', isAllowedSessionHandler, validate( validateDtos.deleteStoreLayout ), storeBuilderController.deleteStoreLayout )
18
+ .post( '/removeFile', isAllowedSessionHandler, storeBuilderController.deleteFile )
19
+ .post( '/deleteFloor', isAllowedSessionHandler, storeBuilderController.deleteFloor )
20
+ .post( '/updateStatus', isAllowedSessionHandler, validate( validateDtos.updateStatus ), storeBuilderController.updateStatus );
21
+
22
+
@@ -0,0 +1,33 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export async function find( query={}, field={} ) {
4
+ return model.planogramModel.find( query, field );
5
+ }
6
+
7
+ export async function findOne( query={}, field={} ) {
8
+ return model.planogramModel.findOne( query, field );
9
+ }
10
+
11
+ export async function insertMany( data ) {
12
+ return model.planogramModel.insertMany( data );
13
+ }
14
+
15
+ export async function aggregate( query ) {
16
+ return model.planogramModel.aggregate( query );
17
+ }
18
+
19
+ export async function updateOne( query, record ) {
20
+ return model.planogramModel.updateOne( query, record );
21
+ }
22
+
23
+ export async function updateMany( query, record ) {
24
+ return model.planogramModel.updateMany( query, { $set: record } );
25
+ }
26
+
27
+ export async function deleteOne( query ) {
28
+ return model.planogramModel.deleteOne( query );
29
+ }
30
+
31
+ export async function create( data ) {
32
+ return model.planogramModel.create( data );
33
+ }
@@ -0,0 +1,25 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export async function find( query={}, field={} ) {
4
+ return model.storeModel.find( query, field );
5
+ }
6
+
7
+ export async function findOne( query={}, field={} ) {
8
+ return model.storeModel.findOne( query, field );
9
+ }
10
+
11
+ export async function insertMany( data ) {
12
+ return model.storeModel.insertMany( data );
13
+ }
14
+
15
+ export async function aggregate( query ) {
16
+ return model.storeModel.aggregate( query );
17
+ }
18
+
19
+ export async function updateOne( query, record ) {
20
+ return model.storeModel.updateOne( query, { $set: record } );
21
+ }
22
+
23
+ export async function findCamera( query, field ) {
24
+ return model.cameraModel.findOne( query.field );
25
+ }
@@ -0,0 +1,33 @@
1
+ import model from 'tango-api-schema';
2
+
3
+ export async function find( query={}, field={} ) {
4
+ return model.storeLayoutModel.find( query, field );
5
+ }
6
+
7
+ export async function findOne( query={}, field={} ) {
8
+ return model.storeLayoutModel.findOne( query, field ).sort( { floorNumber: -1 } );
9
+ }
10
+
11
+ export async function insertMany( data ) {
12
+ return model.storeLayoutModel.insertMany( data );
13
+ }
14
+
15
+ export async function deleteMany( data ) {
16
+ return model.storeLayoutModel.deleteMany( data );
17
+ }
18
+
19
+ export async function deleteOne( data ) {
20
+ return model.storeLayoutModel.deleteOne( data );
21
+ }
22
+
23
+ export async function aggregate( query ) {
24
+ return model.storeLayoutModel.aggregate( query, { collation: { locale: 'en_US', numericOrdering: true } } );
25
+ }
26
+
27
+ export async function updateOne( query, record ) {
28
+ return model.storeLayoutModel.updateOne( query, { $set: record } );
29
+ }
30
+
31
+ export async function updateMany( query, record ) {
32
+ return model.storeLayoutModel.updateMany( query, { $set: record } );
33
+ }