tango-app-api-store-builder 1.0.0-beta-86 → 1.0.0-beta-87

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.
@@ -9,6 +9,7 @@ import * as fixtureShelfService from '../service/fixtureShelf.service.js';
9
9
  import * as planoProductService from '../service/planoProduct.service.js';
10
10
  import * as planoMappingService from '../service/planoMapping.service.js';
11
11
  import * as planoTaskService from '../service/planoTask.service.js';
12
+ import * as processedTaskService from '../service/processedTaskservice.js';
12
13
  // import * as planoComplianceService from '../service/planoCompliance.service.js';
13
14
  // import * as planoTaskComplianceService from '../service/planoTask.service.js';
14
15
  // import * as planoQrConversionRequestService from '../service/planoQrConversionRequest.service.js';
@@ -18,7 +19,6 @@ import JSZip from 'jszip';
18
19
  import { signedUrl } from 'tango-app-api-middleware';
19
20
  import fs from 'fs';
20
21
  import https from 'https';
21
- import dayjs from 'dayjs';
22
22
  import os from 'os';
23
23
  import { fileURLToPath } from 'url';
24
24
  import path from 'path';
@@ -4216,35 +4216,36 @@ export async function downloadPlanoImage( req, res ) {
4216
4216
  const targetPath = path.join( targetFolder, file );
4217
4217
  if ( storeList.includes( fileName ) ) {
4218
4218
  if ( fs.existsSync( sourcePath ) ) {
4219
- let chckFixtureCount = await storeFixtureService.findAndSort( { storeName: fileName }, { associatedElementFixtureNumber: 1 }, { associatedElementFixtureNumber: -1 } );
4220
- console.log( chckFixtureCount[0].associatedElementFixtureNumber );
4221
- if ( chckFixtureCount[0].associatedElementFixtureNumber < 10 ) {
4222
- sharp( sourcePath )
4223
- .extract( { left: 1200, top: 30, width: 3800, height: 3200 } )
4224
- .toFile( targetPath )
4225
- .then( () => {
4226
- fs.unlinkSync( sourcePath );
4227
- console.log( 'Image cropped successfully!' );
4228
- } )
4229
- .catch( ( err ) => {
4230
- console.error( 'Error cropping image:', err );
4231
- } );
4232
- } else {
4233
- fs.copyFile( sourcePath, targetPath, ( err ) => {
4234
- if ( err ) {
4235
- fs.unlinkSync( sourcePath );
4236
- console.error( 'Error copying file:', err );
4237
- } else {
4238
- console.log( `File moved from Downloads to ${targetFolder}` );
4239
- }
4240
- } );
4241
- }
4219
+ // let chckFixtureCount = await storeFixtureService.findAndSort( { storeName: fileName }, { associatedElementFixtureNumber: 1 }, { associatedElementFixtureNumber: -1 } );
4220
+ // console.log( chckFixtureCount[0].associatedElementFixtureNumber );
4221
+ // if ( chckFixtureCount[0].associatedElementFixtureNumber < 10 ) {
4222
+ // sharp( sourcePath )
4223
+ // .extract( { left: 1200, top: 30, width: 3800, height: 3200 } )
4224
+ // .toFile( targetPath )
4225
+ // .then( () => {
4226
+ // fs.unlinkSync( sourcePath );
4227
+ // console.log( 'Image cropped successfully!' );
4228
+ // } )
4229
+ // .catch( ( err ) => {
4230
+ // console.error( 'Error cropping image:', err );
4231
+ // } );
4232
+ // } else {
4233
+ fs.copyFile( sourcePath, targetPath, ( err ) => {
4234
+ if ( err ) {
4235
+ console.error( 'Error copying file:', err );
4236
+ } else {
4237
+ fs.unlinkSync( sourcePath );
4238
+ console.log( `File moved from Downloads to ${targetFolder}` );
4239
+ }
4240
+ } );
4241
+ // }
4242
4242
  } else {
4243
4243
  console.warn( 'File not found in Downloads:', fileName );
4244
4244
  }
4245
4245
  }
4246
4246
  }
4247
4247
  } );
4248
+ return res.sendSuccess( 'Image Generated SuccessFully' );
4248
4249
  }
4249
4250
 
4250
4251
  if ( req.body?.merge ) {
@@ -4253,12 +4254,13 @@ export async function downloadPlanoImage( req, res ) {
4253
4254
  fs.mkdirSync( targetFolder, { recursive: true } );
4254
4255
  console.log( 'Created folder:', targetFolder );
4255
4256
  }
4257
+ let spacing = 500;
4256
4258
  for ( let store of storeList ) {
4257
4259
  if ( store != undefined ) {
4258
4260
  const image1 = path.join( __dirname, '..', '..', `oldImages/${store}.png` );
4259
4261
  const image2 = path.join( __dirname, '..', '..', `newImages/${store}.png` );
4260
4262
 
4261
- const output = path.join( __dirname, '..', '..', `mergedImages/${store}merged.png` );
4263
+ const output = path.join( targetFolder, `/${store}.png` );
4262
4264
 
4263
4265
 
4264
4266
  const [ img1, img2 ] = await Promise.all( [
@@ -4268,7 +4270,7 @@ export async function downloadPlanoImage( req, res ) {
4268
4270
 
4269
4271
  const [ meta1, meta2 ] = await Promise.all( [ img1.metadata(), img2.metadata() ] );
4270
4272
 
4271
- const canvasWidth = meta1.width + meta2.width;
4273
+ const canvasWidth = meta1.width + meta2.width + spacing;
4272
4274
  const canvasHeight = Math.max( meta1.height, meta2.height );
4273
4275
 
4274
4276
  const [ img1Buffer, img2Buffer ] = await Promise.all( [
@@ -4280,23 +4282,2447 @@ export async function downloadPlanoImage( req, res ) {
4280
4282
  create: {
4281
4283
  width: canvasWidth,
4282
4284
  height: canvasHeight,
4283
- channels: 3,
4285
+ channels: 4,
4284
4286
  background: { r: 255, g: 255, b: 255 },
4285
4287
  },
4286
4288
  } )
4287
4289
  .composite( [
4288
4290
  { input: img1Buffer, top: 0, left: 0 },
4289
- { input: img2Buffer, top: 0, left: meta1.width },
4291
+ { input: img2Buffer, top: 0, left: meta1.width + spacing },
4290
4292
  ] )
4291
4293
  .toFile( output );
4292
4294
 
4293
4295
  console.log( 'Images merged successfully!' );
4294
4296
  }
4295
4297
  }
4298
+ let zip = new JSZip;
4299
+ const promises = storeList.map( async ( store ) => {
4300
+ try {
4301
+ const file = fs.readFileSync( `${targetFolder}/${store}.png` );
4302
+ zip.file( `${store}.png`, file );
4303
+ } catch ( err ) {
4304
+ console.error( `Error reading ${store}.png:`, err );
4305
+ }
4306
+ } );
4307
+
4308
+ await Promise.all( promises );
4309
+
4310
+ const zipBuffer = await zip.generateAsync( { type: 'nodebuffer' } );
4311
+
4312
+ res.set( {
4313
+ 'Content-Type': 'application/zip',
4314
+ 'Content-Disposition': 'attachment; filename=download.zip',
4315
+ } );
4316
+
4317
+ let rmFolderList = [ 'oldImages', 'newImages', 'mergedImages' ];
4318
+ for ( let folder of rmFolderList ) {
4319
+ const filePath = path.join( __dirname, '..', '..', folder );
4320
+ fs.rm( filePath, { recursive: true, force: true } );
4321
+ }
4322
+
4323
+ return res.send( zipBuffer );
4296
4324
  }
4297
- return res.sendSuccess( 'Image Generated SuccessFully' );
4298
4325
  } catch ( e ) {
4299
4326
  console.log( e );
4300
4327
  return res.sendError( e, 500 );
4301
4328
  }
4302
4329
  }
4330
+
4331
+
4332
+ export async function updateCrestPlanogram( req, res ) {
4333
+ try {
4334
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
4335
+ return res.sendError( 'Unauthorized', 401 );
4336
+ }
4337
+
4338
+ const startTime = Date.now();
4339
+
4340
+ const layoutApiUrl = 'https://api.getcrest.ai/api/ms_shelfsensei/layout/';
4341
+ let staticToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ1NTE3MjQxLCJpYXQiOjE3NDU1MTM2NDEsImp0aSI6Ijg3MWVlNTA3ODY2OTQ5OTVhMTQ0YTk4NzQyNzY0MzEzIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.eGzTMGwwstr13M0Hu1Ls5-gkE_oSPMJJBL2wgygT6Ac';
4342
+
4343
+ async function fetchStoreData( store, bearerToken, res ) {
4344
+ const payload = JSON.stringify( { store_id: store.toObject().storeName } );
4345
+
4346
+ try {
4347
+ const response = await fetch( layoutApiUrl, {
4348
+ method: 'POST',
4349
+ headers: {
4350
+ 'Authorization': `Bearer ${bearerToken}`,
4351
+ 'Content-Type': 'application/json',
4352
+ 'Content-Length': Buffer.byteLength( payload ),
4353
+ },
4354
+ body: payload,
4355
+ } );
4356
+
4357
+ const data = await response.text();
4358
+ let jsonData = null;
4359
+
4360
+ try {
4361
+ jsonData = JSON.parse( data );
4362
+ } catch ( parseError ) {
4363
+ logger.error( { functionName: `Warning: Received invalid JSON for store ${store.toObject().storeName}`, error: parseError } );
4364
+ console.warn( `Warning: Received invalid JSON for store ${store.toObject().storeName}` );
4365
+ return { storeName: store.toObject().storeName, data: null };
4366
+ }
4367
+
4368
+ if ( jsonData.result === 'Token is invalid or expired' ) {
4369
+ console.log( 'Token expired, retrying...' );
4370
+ try {
4371
+ const newToken = await fetchNewToken();
4372
+ staticToken = newToken;
4373
+ return await fetchStoreData( store, newToken, res );
4374
+ } catch ( retryError ) {
4375
+ logger.error( { functionName: 'Failed to refresh token', error: retryError } );
4376
+ console.log( retryError );
4377
+ return res.sendError( 'Failed to refresh token', 401 );
4378
+ }
4379
+ }
4380
+
4381
+ return { storeName: store.toObject().storeName, data: jsonData };
4382
+ } catch ( error ) {
4383
+ logger.error( { functionName: `Error fetching data for ${store.toObject().storeName}:`, error } );
4384
+ console.error( `Error fetching data for ${store.toObject().storeName}:`, error.message );
4385
+ return { storeName: store.toObject().storeName, data: null };
4386
+ }
4387
+ }
4388
+
4389
+
4390
+ const fetchNewToken = async () => {
4391
+ const fetchWithCookies = fetchCookie( fetch );
4392
+
4393
+ const email = 'tango.lenskart@getcrest.ai';
4394
+ const password = 'Tangolenskart@123';
4395
+
4396
+ const credentials = JSON.stringify( { email, password } );
4397
+
4398
+ const invalidateUrl = 'https://app.getcrest.ai/api/ms_iam/user/session/override/';
4399
+ const tokenUrl = 'https://app.getcrest.ai/api/ms_iam/token/';
4400
+
4401
+ try {
4402
+ const invalidateRes = await fetchWithCookies( invalidateUrl, {
4403
+ method: 'POST',
4404
+ headers: {
4405
+ 'Content-Type': 'application/json',
4406
+ },
4407
+ body: credentials,
4408
+ } );
4409
+
4410
+ const invalidateData = await invalidateRes.json();
4411
+ console.log( 'Invalidate response:', invalidateData );
4412
+
4413
+ console.log( 'Fetching new token...' );
4414
+ const tokenRes = await fetchWithCookies( tokenUrl, {
4415
+ method: 'POST',
4416
+ headers: {
4417
+ 'Content-Type': 'application/json',
4418
+ 'Accept': 'application/json, text/javascript, */*; q=0.01',
4419
+ },
4420
+ body: credentials,
4421
+ } );
4422
+
4423
+ const tokenData = await tokenRes.json();
4424
+ console.log( 'Token response:', tokenData );
4425
+
4426
+ return tokenData.access;
4427
+ } catch ( error ) {
4428
+ console.error( 'Error fetching new token:', error );
4429
+ throw error;
4430
+ }
4431
+ };
4432
+
4433
+ let storeList = await storeService.find( { ...( req?.body?.storeName ) ? { storeName: req?.body?.storeName } : {}, clientId: '11' } );
4434
+
4435
+ const constantFixtureLength = 1220;
4436
+ const constantDetailedFixtureLength = 1220;
4437
+
4438
+ const constantFixtureWidth = 610;
4439
+ const constantDetailedFixtureWidth = 1524;
4440
+
4441
+ const mmToFeet = 305;
4442
+
4443
+ function roundToTwo( num ) {
4444
+ return Math.round( num * 100 ) / 100;
4445
+ }
4446
+
4447
+ for ( let i = 0; i < storeList.length; i++ ) {
4448
+ const storeData = await fetchStoreData( storeList[i], staticToken, res );
4449
+
4450
+ if ( storeData?.data?.message !== 'SUCCESS' ) continue;
4451
+
4452
+ const storeDetails = storeList[i];
4453
+
4454
+ const existingPlanogram = await planoService.findOne( { storeName: storeData.storeName } );
4455
+
4456
+ if ( existingPlanogram ) {
4457
+ const checkTaskSubmitted = await planoTaskService.findOne( { planoId: existingPlanogram.toObject()._id } );
4458
+
4459
+ const checkTaskCreated = await processedTaskService.findOne( { storeName: storeData.storeName, date_iso: { $gte: new Date( ), $lte: new Date( ) }, isPlano: true } );
4460
+
4461
+ if ( checkTaskSubmitted || checkTaskCreated ) {
4462
+ continue;
4463
+ }
4464
+ }
4465
+
4466
+
4467
+ if ( existingPlanogram?.toObject()?._id && mongoose.Types.ObjectId.isValid( existingPlanogram?.toObject()?._id ) ) {
4468
+ await Promise.all( [ planoService.deleteOne( { _id: existingPlanogram?.toObject()?._id } ), storeBuilderService.deleteOne( { planoId: existingPlanogram?.toObject()?._id } ),
4469
+ storeFixtureService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ), fixtureShelfService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
4470
+ planoMappingService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
4471
+ ] );
4472
+ }
4473
+
4474
+
4475
+ const planoInsertData = {
4476
+ storeName: storeData.storeName,
4477
+ storeId: storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
4478
+ layoutName: `${storeData.storeName} - Layout`,
4479
+ clientId: '11',
4480
+ attachments: [],
4481
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
4482
+ createdByName: 'Bejan',
4483
+ createdByEmail: 'bejan@tangotech.co.in',
4484
+ status: 'completed',
4485
+ floorNumber: 1,
4486
+ productResolutionLevel: 'L2',
4487
+ scanType: 'qr',
4488
+ };
4489
+
4490
+ const insertedPlano = await planoService.upsertOne( { storeName: storeData.storeName }, planoInsertData );
4491
+ const planoDoc = insertedPlano.toObject();
4492
+
4493
+ const leftWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'LEFT WALL' );
4494
+ const leftFixtures = leftWall.flatMap( ( wall ) => wall.fixtures );
4495
+ const rightWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT WALL' );
4496
+ const rightFixtures = rightWall.flatMap( ( wall ) => wall.fixtures );
4497
+ const backWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT VERTICAL WALL' );
4498
+ const backFixtures = backWall.flatMap( ( wall ) => wall.fixtures );
4499
+ const floorFixtures = storeData.data.result.filter(
4500
+ ( entry ) => entry['main'] === 'Euro Center' || entry['main'] === 'Euro Center Dr',
4501
+ );
4502
+
4503
+ const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
4504
+ const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
4505
+
4506
+ const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
4507
+ const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
4508
+
4509
+ const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
4510
+ const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
4511
+
4512
+ const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
4513
+ const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
4514
+
4515
+ const maxFixturesPerRow = floorFixtures.length/2;
4516
+ const totalRows = 2;
4517
+
4518
+ const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
4519
+ const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
4520
+
4521
+ const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
4522
+ const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
4523
+
4524
+ const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
4525
+ const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
4526
+
4527
+ const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
4528
+ const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
4529
+
4530
+ const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
4531
+ const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
4532
+
4533
+ const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet );
4534
+ const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet );
4535
+
4536
+ const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
4537
+ const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
4538
+
4539
+ const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
4540
+ const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
4541
+
4542
+
4543
+ const floorInsertData = {
4544
+ storeName: planoDoc.storeName,
4545
+ storeId: planoDoc.storeId,
4546
+ layoutName: `${planoDoc.storeName} - Layout`,
4547
+ clientId: '11',
4548
+ floorNumber: 1,
4549
+ floorName: 'floor 1',
4550
+ layoutPolygon: [
4551
+ {
4552
+ elementType: 'wall',
4553
+ distance: finalXDistance,
4554
+ unit: 'ft',
4555
+ direction: 'right',
4556
+ angle: 90,
4557
+ elementNumber: 1,
4558
+ detailedDistance: finalXDetailedDistance,
4559
+ },
4560
+ {
4561
+ elementType: 'wall',
4562
+ distance: finalYDistance,
4563
+ unit: 'ft',
4564
+ direction: 'down',
4565
+ angle: 90,
4566
+ elementNumber: 2,
4567
+ detailedDistance: finalYDetailedDistance,
4568
+ },
4569
+ {
4570
+ elementType: 'wall',
4571
+ distance: finalXDistance,
4572
+ unit: 'ft',
4573
+ direction: 'left',
4574
+ angle: 90,
4575
+ elementNumber: 3,
4576
+ detailedDistance: finalXDetailedDistance,
4577
+ },
4578
+ {
4579
+ elementType: 'wall',
4580
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
4581
+ unit: 'ft',
4582
+ direction: 'up',
4583
+ angle: 90,
4584
+ elementNumber: 4,
4585
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
4586
+ },
4587
+ {
4588
+ elementType: 'entrance',
4589
+ distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
4590
+ unit: 'ft',
4591
+ direction: 'up',
4592
+ angle: 90,
4593
+ elementNumber: 1,
4594
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
4595
+ },
4596
+ {
4597
+ elementType: 'wall',
4598
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
4599
+ unit: 'ft',
4600
+ direction: 'up',
4601
+ angle: 90,
4602
+ elementNumber: 5,
4603
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
4604
+ },
4605
+ ],
4606
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
4607
+ createdByName: 'Bejan',
4608
+ createdByEmail: 'bejan@tangotech.co.in',
4609
+ status: 'completed',
4610
+ planoId: planoDoc._id,
4611
+ };
4612
+
4613
+ const layoutDoc = await storeBuilderService.upsertOne( { planoId: planoDoc._id }, floorInsertData );
4614
+
4615
+ let fixtureCounter = 1;
4616
+
4617
+ const leftFixturePromises = leftFixtures.map( async ( fixture, index ) => {
4618
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
4619
+ if ( !fixtureConfig ) return;
4620
+ const fixtureConfigDoc = fixtureConfig.toObject();
4621
+
4622
+ const fixtureData = {
4623
+ 'clientId': layoutDoc.clientId,
4624
+ 'storeName': layoutDoc.storeName,
4625
+ 'storeId': layoutDoc.storeId,
4626
+ 'planoId': layoutDoc.planoId,
4627
+ 'floorId': layoutDoc._id,
4628
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
4629
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
4630
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4631
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4632
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
4633
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
4634
+ 'fixtureType': 'wall',
4635
+ 'fixtureHeight': {
4636
+ 'value': 0,
4637
+ 'unit': 'mm',
4638
+ },
4639
+ 'fixtureLength': {
4640
+ 'value': constantFixtureLength,
4641
+ 'unit': 'mm',
4642
+ },
4643
+ 'fixtureWidth': {
4644
+ 'value': constantFixtureWidth,
4645
+ 'unit': 'mm',
4646
+ },
4647
+ 'associatedElementType': 'wall',
4648
+ 'associatedElementNumber': 1,
4649
+ 'relativePosition': {
4650
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
4651
+ 'y': 0,
4652
+ 'unit': 'ft',
4653
+ },
4654
+ 'fixtureNumber': fixtureCounter,
4655
+ 'detailedFixtureLength': {
4656
+ 'value': constantDetailedFixtureLength,
4657
+ 'unit': 'mm',
4658
+ },
4659
+ 'detailedFixtureWidth': {
4660
+ 'value': constantDetailedFixtureWidth,
4661
+ 'unit': 'mm',
4662
+ },
4663
+ 'relativeDetailedPosition': {
4664
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
4665
+ 'y': 0,
4666
+ 'unit': 'ft',
4667
+ },
4668
+ 'productResolutionLevel': 'L2',
4669
+ 'associatedElementFixtureNumber': index+1,
4670
+ 'header': fixture.header,
4671
+ 'footer': fixture.footer,
4672
+ 'fixtureConfigId': fixtureConfigDoc._id,
4673
+ };
4674
+
4675
+ const createdFixture = await storeFixtureService.upsertOne(
4676
+ {
4677
+ floorId: layoutDoc._id,
4678
+ fixtureNumber: fixtureCounter++,
4679
+ },
4680
+ fixtureData,
4681
+ );
4682
+
4683
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
4684
+
4685
+ await Promise.all(
4686
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
4687
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
4688
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
4689
+
4690
+ const shelfData = {
4691
+ 'clientId': '11',
4692
+ 'storeName': layoutDoc.storeName,
4693
+ 'storeId': layoutDoc.storeId,
4694
+ 'planoId': layoutDoc.planoId,
4695
+ 'floorId': layoutDoc._id,
4696
+ 'fixtureId': createdFixture._id,
4697
+ 'shelfNumber': j + 1,
4698
+ 'shelfOrder': 'LTR',
4699
+ 'shelfCapacity': configShelf.shelfCapacity,
4700
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
4701
+ 'sectionZone': configShelf.shelfZone,
4702
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
4703
+ };
4704
+
4705
+ await fixtureShelfService.upsertOne(
4706
+ {
4707
+ fixtureId: createdFixture._id,
4708
+ shelfNumber: j + 1,
4709
+ },
4710
+ shelfData,
4711
+ );
4712
+ } ),
4713
+ );
4714
+
4715
+ await Promise.all(
4716
+ fixture.productZones?.map( async ( zone ) => {
4717
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
4718
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
4719
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
4720
+
4721
+ await Promise.all(
4722
+ vms.map( async ( vm ) => {
4723
+ let configData = vmConfig[0];
4724
+
4725
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
4726
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
4727
+ }
4728
+
4729
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
4730
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
4731
+ }
4732
+
4733
+ if ( !configData ) return;
4734
+
4735
+ const insertData = {
4736
+ 'clientId': '11',
4737
+ 'productId': 'VMCR',
4738
+ 'type': 'vm',
4739
+ 'productName': vm.productName,
4740
+ 'productHeight': {
4741
+ 'value': configData.vmHeightmm,
4742
+ 'unit': 'mm',
4743
+ },
4744
+ 'productWidth': {
4745
+ 'value': configData.vmWidthmm,
4746
+ 'unit': 'mm',
4747
+ },
4748
+ 'startYPosition': configData.startShelf,
4749
+ 'endYPosition': configData.endShelf,
4750
+ 'xZone': configData.zone,
4751
+ 'fixtureConfigId': fixtureConfig._id,
4752
+ };
4753
+
4754
+ const vmTemplate = await planoProductService.upsertOne(
4755
+ {
4756
+ 'productName': vm.productName,
4757
+ 'fixtureConfigId': fixtureConfig._id,
4758
+ 'productHeight.value': configData.vmHeightmm,
4759
+ 'productWidth.value': configData.vmWidthmm,
4760
+ 'startYPosition': configData.startShelf,
4761
+ 'endYPosition': configData.endShelf,
4762
+ 'xZone': configData.zone,
4763
+ },
4764
+ insertData,
4765
+ );
4766
+
4767
+ const vmData = {
4768
+ 'clientId': layoutDoc.clientId,
4769
+ 'storeName': layoutDoc.storeName,
4770
+ 'storeId': layoutDoc.storeId,
4771
+ 'planoId': layoutDoc.planoId,
4772
+ 'floorId': layoutDoc._id,
4773
+ 'type': 'vm',
4774
+ 'fixtureId': createdFixture._id,
4775
+ 'productId': vmTemplate._id,
4776
+ };
4777
+
4778
+ await planoMappingService.upsertOne(
4779
+ {
4780
+ fixtureId: createdFixture._id,
4781
+ productId: vmTemplate._id,
4782
+ },
4783
+ vmData,
4784
+ );
4785
+ } ),
4786
+ );
4787
+ } ) || [],
4788
+ );
4789
+ } );
4790
+
4791
+ const backFixturePromises = backFixtures.map( async ( fixture, index ) => {
4792
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
4793
+ if ( !fixtureConfig ) return;
4794
+ const fixtureConfigDoc = fixtureConfig.toObject();
4795
+
4796
+ const fixtureData = {
4797
+ 'clientId': layoutDoc.clientId,
4798
+ 'storeName': layoutDoc.storeName,
4799
+ 'storeId': layoutDoc.storeId,
4800
+ 'planoId': layoutDoc.planoId,
4801
+ 'floorId': layoutDoc._id,
4802
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
4803
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
4804
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4805
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4806
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
4807
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
4808
+ 'fixtureType': 'wall',
4809
+ 'fixtureHeight': {
4810
+ 'value': 0,
4811
+ 'unit': 'mm',
4812
+ },
4813
+ 'fixtureLength': {
4814
+ 'value': constantFixtureWidth,
4815
+ 'unit': 'mm',
4816
+ },
4817
+ 'fixtureWidth': {
4818
+ 'value': constantFixtureLength,
4819
+ 'unit': 'mm',
4820
+ },
4821
+ 'associatedElementType': 'wall',
4822
+ 'associatedElementNumber': 2,
4823
+ 'relativePosition': {
4824
+ 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
4825
+ 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
4826
+ 'unit': 'ft',
4827
+ },
4828
+ 'fixtureNumber': fixtureCounter,
4829
+ 'detailedFixtureLength': {
4830
+ 'value': constantDetailedFixtureLength,
4831
+ 'unit': 'mm',
4832
+ },
4833
+ 'detailedFixtureWidth': {
4834
+ 'value': constantDetailedFixtureWidth,
4835
+ 'unit': 'mm',
4836
+ },
4837
+ 'relativeDetailedPosition': {
4838
+ 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
4839
+ 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
4840
+ 'unit': 'ft',
4841
+ },
4842
+ 'productResolutionLevel': 'L2',
4843
+ 'associatedElementFixtureNumber': index+1,
4844
+ 'header': fixture.header,
4845
+ 'footer': fixture.footer,
4846
+ 'fixtureConfigId': fixtureConfigDoc._id,
4847
+ };
4848
+
4849
+ const createdFixture = await storeFixtureService.upsertOne(
4850
+ {
4851
+ floorId: layoutDoc._id,
4852
+ fixtureNumber: fixtureCounter++,
4853
+ },
4854
+ fixtureData,
4855
+ );
4856
+
4857
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
4858
+
4859
+ await Promise.all(
4860
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
4861
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
4862
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
4863
+
4864
+ const shelfData = {
4865
+ 'clientId': '11',
4866
+ 'storeName': layoutDoc.storeName,
4867
+ 'storeId': layoutDoc.storeId,
4868
+ 'planoId': layoutDoc.planoId,
4869
+ 'floorId': layoutDoc._id,
4870
+ 'fixtureId': createdFixture._id,
4871
+ 'shelfNumber': j + 1,
4872
+ 'shelfOrder': 'LTR',
4873
+ 'shelfCapacity': configShelf.shelfCapacity,
4874
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
4875
+ 'sectionZone': configShelf.shelfZone,
4876
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
4877
+ }; ;
4878
+
4879
+ await fixtureShelfService.upsertOne(
4880
+ {
4881
+ fixtureId: createdFixture._id,
4882
+ shelfNumber: j + 1,
4883
+ },
4884
+ shelfData,
4885
+ );
4886
+ } ),
4887
+ );
4888
+
4889
+ await Promise.all(
4890
+ fixture.productZones?.map( async ( zone ) => {
4891
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
4892
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
4893
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
4894
+
4895
+ await Promise.all(
4896
+ vms.map( async ( vm ) => {
4897
+ let configData = vmConfig[0];
4898
+
4899
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
4900
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
4901
+ }
4902
+
4903
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
4904
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
4905
+ }
4906
+
4907
+ if ( !configData ) return;
4908
+
4909
+ const insertData = {
4910
+ 'clientId': '11',
4911
+ 'productId': 'VMCR',
4912
+ 'type': 'vm',
4913
+ 'productName': vm.productName,
4914
+ 'productHeight': {
4915
+ 'value': configData.vmHeightmm,
4916
+ 'unit': 'mm',
4917
+ },
4918
+ 'productWidth': {
4919
+ 'value': configData.vmWidthmm,
4920
+ 'unit': 'mm',
4921
+ },
4922
+ 'startYPosition': configData.startShelf,
4923
+ 'endYPosition': configData.endShelf,
4924
+ 'xZone': configData.zone,
4925
+ 'fixtureConfigId': fixtureConfig._id,
4926
+ };
4927
+
4928
+ const vmTemplate = await planoProductService.upsertOne(
4929
+ {
4930
+ 'productName': vm.productName,
4931
+ 'fixtureConfigId': fixtureConfig._id,
4932
+ 'productHeight.value': configData.vmHeightmm,
4933
+ 'productWidth.value': configData.vmWidthmm,
4934
+ 'startYPosition': configData.startShelf,
4935
+ 'endYPosition': configData.endShelf,
4936
+ 'xZone': configData.zone,
4937
+ },
4938
+ insertData,
4939
+ );
4940
+
4941
+ const vmData = {
4942
+ 'clientId': layoutDoc.clientId,
4943
+ 'storeName': layoutDoc.storeName,
4944
+ 'storeId': layoutDoc.storeId,
4945
+ 'planoId': layoutDoc.planoId,
4946
+ 'floorId': layoutDoc._id,
4947
+ 'type': 'vm',
4948
+ 'fixtureId': createdFixture._id,
4949
+ 'productId': vmTemplate._id,
4950
+ };
4951
+
4952
+ await planoMappingService.upsertOne(
4953
+ {
4954
+ fixtureId: createdFixture._id,
4955
+ productId: vmTemplate._id,
4956
+ },
4957
+ vmData,
4958
+ );
4959
+ } ),
4960
+ );
4961
+ } ) || [],
4962
+ );
4963
+ } );
4964
+
4965
+ const rightFixturePromises = rightFixtures.map( async ( fixture, index ) => {
4966
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
4967
+ if ( !fixtureConfig ) return;
4968
+ const fixtureConfigDoc = fixtureConfig.toObject();
4969
+
4970
+ const fixtureData = {
4971
+ 'clientId': layoutDoc.clientId,
4972
+ 'storeName': layoutDoc.storeName,
4973
+ 'storeId': layoutDoc.storeId,
4974
+ 'planoId': layoutDoc.planoId,
4975
+ 'floorId': layoutDoc._id,
4976
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
4977
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
4978
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4979
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
4980
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
4981
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
4982
+ 'fixtureType': 'wall',
4983
+ 'fixtureHeight': {
4984
+ 'value': 0,
4985
+ 'unit': 'mm',
4986
+ },
4987
+ 'fixtureLength': {
4988
+ 'value': constantFixtureLength,
4989
+ 'unit': 'mm',
4990
+ },
4991
+ 'fixtureWidth': {
4992
+ 'value': constantFixtureWidth,
4993
+ 'unit': 'mm',
4994
+ },
4995
+ 'associatedElementType': 'wall',
4996
+ 'associatedElementNumber': 3,
4997
+ 'relativePosition': {
4998
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
4999
+ 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
5000
+ 'unit': 'ft',
5001
+ },
5002
+ 'fixtureNumber': fixtureCounter,
5003
+ 'detailedFixtureLength': {
5004
+ 'value': constantDetailedFixtureLength,
5005
+ 'unit': 'mm',
5006
+ },
5007
+ 'detailedFixtureWidth': {
5008
+ 'value': constantDetailedFixtureWidth,
5009
+ 'unit': 'mm',
5010
+ },
5011
+ 'relativeDetailedPosition': {
5012
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
5013
+ 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
5014
+ 'unit': 'ft',
5015
+ },
5016
+ 'productResolutionLevel': 'L2',
5017
+ 'associatedElementFixtureNumber': index+1,
5018
+ 'header': fixture.header,
5019
+ 'footer': fixture.footer,
5020
+ 'fixtureConfigId': fixtureConfigDoc._id,
5021
+ };
5022
+
5023
+ const createdFixture = await storeFixtureService.upsertOne(
5024
+ {
5025
+ floorId: layoutDoc._id,
5026
+ fixtureNumber: fixtureCounter++,
5027
+ },
5028
+ fixtureData,
5029
+ );
5030
+
5031
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
5032
+
5033
+ await Promise.all(
5034
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
5035
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
5036
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
5037
+
5038
+ const shelfData = {
5039
+ 'clientId': '11',
5040
+ 'storeName': layoutDoc.storeName,
5041
+ 'storeId': layoutDoc.storeId,
5042
+ 'planoId': layoutDoc.planoId,
5043
+ 'floorId': layoutDoc._id,
5044
+ 'fixtureId': createdFixture._id,
5045
+ 'shelfNumber': j + 1,
5046
+ 'shelfOrder': 'LTR',
5047
+ 'shelfCapacity': configShelf.shelfCapacity,
5048
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
5049
+ 'sectionZone': configShelf.shelfZone,
5050
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
5051
+ };
5052
+
5053
+ await fixtureShelfService.upsertOne(
5054
+ {
5055
+ fixtureId: createdFixture._id,
5056
+ shelfNumber: j + 1,
5057
+ },
5058
+ shelfData,
5059
+ );
5060
+ } ),
5061
+ );
5062
+
5063
+ await Promise.all(
5064
+ fixture.productZones?.map( async ( zone ) => {
5065
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
5066
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
5067
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
5068
+
5069
+ await Promise.all(
5070
+ vms.map( async ( vm ) => {
5071
+ let configData = vmConfig[0];
5072
+
5073
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
5074
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
5075
+ }
5076
+
5077
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
5078
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
5079
+ }
5080
+
5081
+ if ( !configData ) return;
5082
+
5083
+ const insertData = {
5084
+ 'clientId': '11',
5085
+ 'productId': 'VMCR',
5086
+ 'type': 'vm',
5087
+ 'productName': vm.productName,
5088
+ 'productHeight': {
5089
+ 'value': configData.vmHeightmm,
5090
+ 'unit': 'mm',
5091
+ },
5092
+ 'productWidth': {
5093
+ 'value': configData.vmWidthmm,
5094
+ 'unit': 'mm',
5095
+ },
5096
+ 'startYPosition': configData.startShelf,
5097
+ 'endYPosition': configData.endShelf,
5098
+ 'xZone': configData.zone,
5099
+ 'fixtureConfigId': fixtureConfig._id,
5100
+ };
5101
+
5102
+ const vmTemplate = await planoProductService.upsertOne(
5103
+ {
5104
+ 'productName': vm.productName,
5105
+ 'fixtureConfigId': fixtureConfig._id,
5106
+ 'productHeight.value': configData.vmHeightmm,
5107
+ 'productWidth.value': configData.vmWidthmm,
5108
+ 'startYPosition': configData.startShelf,
5109
+ 'endYPosition': configData.endShelf,
5110
+ 'xZone': configData.zone,
5111
+ },
5112
+ insertData,
5113
+ );
5114
+
5115
+ const vmData = {
5116
+ 'clientId': layoutDoc.clientId,
5117
+ 'storeName': layoutDoc.storeName,
5118
+ 'storeId': layoutDoc.storeId,
5119
+ 'planoId': layoutDoc.planoId,
5120
+ 'floorId': layoutDoc._id,
5121
+ 'type': 'vm',
5122
+ 'fixtureId': createdFixture._id,
5123
+ 'productId': vmTemplate._id,
5124
+ };
5125
+
5126
+ await planoMappingService.upsertOne(
5127
+ {
5128
+ fixtureId: createdFixture._id,
5129
+ productId: vmTemplate._id,
5130
+ },
5131
+ vmData,
5132
+ );
5133
+ } ),
5134
+ );
5135
+ } ) || [],
5136
+ );
5137
+ } );
5138
+
5139
+ const floorFixturePromises = floorFixtures.map( async ( fixture, index ) => {
5140
+ const centerRow = Math.floor( totalRows / 2 );
5141
+
5142
+ const startingX = roundToTwo( ( finalXDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) );
5143
+ const detailedStartingX = roundToTwo( ( finalXDetailedDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) );
5144
+
5145
+ const startingY = finalYDistance / 2 - centerRow * ( constantFixtureWidth / mmToFeet );
5146
+ const detailedStartingY = finalYDetailedDistance / 2 - centerRow * ( constantDetailedFixtureWidth / mmToFeet );
5147
+
5148
+ const colIndex = Math.floor( index / 2 );
5149
+ const rowIndex = index % 2 === 0 ? 1 : 0;
5150
+
5151
+ const xPos = roundToTwo( startingX + colIndex * ( constantFixtureLength / mmToFeet ) );
5152
+ const yPos = roundToTwo( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) );
5153
+
5154
+ const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
5155
+ const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
5156
+
5157
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.main } );
5158
+ if ( !fixtureConfig ) return;
5159
+
5160
+ const fixtureConfigDoc = fixtureConfig.toObject();
5161
+
5162
+ const fixtureData = {
5163
+ 'clientId': layoutDoc.clientId,
5164
+ 'storeName': layoutDoc.storeName,
5165
+ 'storeId': layoutDoc.storeId,
5166
+ 'planoId': layoutDoc.planoId,
5167
+ 'floorId': layoutDoc._id,
5168
+ 'fixtureName': `Fixture ${index+1} - ${fixture.main}`,
5169
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
5170
+ 'fixtureBrandCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
5171
+ 'fixtureBrandSubCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
5172
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
5173
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
5174
+ 'fixtureType': 'floor',
5175
+ 'fixtureHeight': {
5176
+ 'value': 0,
5177
+ 'unit': 'mm',
5178
+ },
5179
+ 'fixtureLength': {
5180
+ 'value': constantFixtureLength,
5181
+ 'unit': 'mm',
5182
+ },
5183
+ 'fixtureWidth': {
5184
+ 'value': constantFixtureWidth,
5185
+ 'unit': 'mm',
5186
+ },
5187
+ 'relativePosition': {
5188
+ 'x': xPos,
5189
+ 'y': yPos,
5190
+ 'unit': 'ft',
5191
+ },
5192
+ 'fixtureNumber': fixtureCounter,
5193
+ 'detailedFixtureLength': {
5194
+ 'value': constantDetailedFixtureLength,
5195
+ 'unit': 'mm',
5196
+ },
5197
+ 'detailedFixtureWidth': {
5198
+ 'value': constantDetailedFixtureWidth,
5199
+ 'unit': 'mm',
5200
+ },
5201
+ 'relativeDetailedPosition': {
5202
+ 'x': detailedXPos,
5203
+ 'y': detailedYPos,
5204
+ 'unit': 'ft',
5205
+ },
5206
+ 'productResolutionLevel': 'L2',
5207
+ 'associatedElementFixtureNumber': index+1,
5208
+ 'fixtureConfigId': fixtureConfigDoc._id,
5209
+ };
5210
+
5211
+
5212
+ const createdFixture = await storeFixtureService.upsertOne(
5213
+ {
5214
+ floorId: layoutDoc._id,
5215
+ fixtureNumber: fixtureCounter++,
5216
+ },
5217
+ fixtureData,
5218
+ );
5219
+
5220
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
5221
+
5222
+ await Promise.all(
5223
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
5224
+ const shelfSection = fixture.centerSuperSubMain.find(
5225
+ ( product ) => product.isVisualMerchandiser === false || product.isVisualMerchandiser === true,
5226
+ );
5227
+
5228
+ const shelfData = {
5229
+ 'clientId': '11',
5230
+ 'storeName': layoutDoc.storeName,
5231
+ 'storeId': layoutDoc.storeId,
5232
+ 'planoId': layoutDoc.planoId,
5233
+ 'floorId': layoutDoc._id,
5234
+ 'fixtureId': createdFixture._id,
5235
+ 'shelfNumber': j + 1,
5236
+ 'shelfOrder': 'LTR',
5237
+ 'shelfCapacity': configShelf.shelfCapacity,
5238
+ 'sectionName': fixture.centerSuperSubMain.find( ( product ) => product.isVisualMerchandiser === true ) ? shelfSection?.name + ' PIDs' : shelfSection?.name,
5239
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
5240
+ };
5241
+
5242
+ await fixtureShelfService.upsertOne(
5243
+ {
5244
+ fixtureId: createdFixture._id,
5245
+ shelfNumber: j + 1,
5246
+ },
5247
+ shelfData,
5248
+ );
5249
+ } ),
5250
+ );
5251
+
5252
+ const vm = fixture.centerSuperSubMain.find( ( vm ) => vm.isVisualMerchandiser );
5253
+ const vmConfig = fixtureConfigDoc.vmConfig;
5254
+
5255
+ if ( vm ) {
5256
+ const [ configData1, configData2 ] = [ vmConfig[0], vmConfig[1] ];
5257
+
5258
+ const insertData1 = {
5259
+ 'clientId': '11',
5260
+ 'productId': 'VMCR',
5261
+ 'type': 'vm',
5262
+ 'productName': vm.name,
5263
+ 'productHeight': {
5264
+ 'value': configData1.vmHeightmm,
5265
+ 'unit': 'mm',
5266
+ },
5267
+ 'productWidth': {
5268
+ 'value': configData1.vmWidthmm,
5269
+ 'unit': 'mm',
5270
+ },
5271
+ 'startYPosition': configData1.startShelf,
5272
+ 'endYPosition': configData1.endShelf,
5273
+ 'xZone': configData1.zone,
5274
+ 'fixtureConfigId': fixtureConfig._id,
5275
+ };
5276
+ const insertData2 = {
5277
+ 'clientId': '11',
5278
+ 'productId': 'VMCR',
5279
+ 'type': 'vm',
5280
+ 'productName': ' ',
5281
+ 'productHeight': {
5282
+ 'value': configData2.vmHeightmm,
5283
+ 'unit': 'mm',
5284
+ },
5285
+ 'productWidth': {
5286
+ 'value': configData2.vmWidthmm,
5287
+ 'unit': 'mm',
5288
+ },
5289
+ 'startYPosition': configData2.startShelf,
5290
+ 'endYPosition': configData2.endShelf,
5291
+ 'xZone': configData2.zone,
5292
+ 'fixtureConfigId': fixtureConfig._id,
5293
+ };
5294
+
5295
+ const [ vmTemplate1, vmTemplate2 ] = await Promise.all( [
5296
+ planoProductService.upsertOne(
5297
+ {
5298
+ 'productName': vm.name,
5299
+ 'fixtureConfigId': fixtureConfig._id,
5300
+ 'productHeight.value': configData1.vmHeightmm,
5301
+ 'productWidth.value': configData1.vmWidthmm,
5302
+ 'startYPosition': configData1.startShelf,
5303
+ 'endYPosition': configData1.endShelf,
5304
+ 'xZone': configData1.zone,
5305
+ },
5306
+ insertData1,
5307
+ ),
5308
+ planoProductService.upsertOne(
5309
+ {
5310
+ 'productName': ' ',
5311
+ 'fixtureConfigId': fixtureConfig._id,
5312
+ 'productHeight.value': configData2.vmHeightmm,
5313
+ 'productWidth.value': configData2.vmWidthmm,
5314
+ 'startYPosition': configData2.startShelf,
5315
+ 'endYPosition': configData2.endShelf,
5316
+ 'xZone': configData2.zone,
5317
+ },
5318
+ insertData2,
5319
+ ),
5320
+ ] );
5321
+
5322
+ const vmData1 = {
5323
+ 'clientId': layoutDoc.clientId,
5324
+ 'storeName': layoutDoc.storeName,
5325
+ 'storeId': layoutDoc.storeId,
5326
+ 'planoId': layoutDoc.planoId,
5327
+ 'floorId': layoutDoc._id,
5328
+ 'type': 'vm',
5329
+ 'fixtureId': createdFixture._id,
5330
+ 'productId': vmTemplate1._id,
5331
+ };
5332
+ const vmData2 = {
5333
+ 'clientId': layoutDoc.clientId,
5334
+ 'storeName': layoutDoc.storeName,
5335
+ 'storeId': layoutDoc.storeId,
5336
+ 'planoId': layoutDoc.planoId,
5337
+ 'floorId': layoutDoc._id,
5338
+ 'type': 'vm',
5339
+ 'fixtureId': createdFixture._id,
5340
+ 'productId': vmTemplate2._id,
5341
+ };
5342
+
5343
+ await Promise.all( [
5344
+ planoMappingService.upsertOne(
5345
+ {
5346
+ fixtureId: createdFixture._id,
5347
+ productId: vmTemplate1._id,
5348
+ },
5349
+ vmData1,
5350
+ ),
5351
+ planoMappingService.upsertOne(
5352
+ {
5353
+ fixtureId: createdFixture._id,
5354
+ productId: vmTemplate2._id,
5355
+ },
5356
+ vmData2,
5357
+ ),
5358
+ ] );
5359
+ }
5360
+ } );
5361
+
5362
+ await Promise.all( [ ...leftFixturePromises, ...backFixturePromises, ...rightFixturePromises, ...floorFixturePromises ] );
5363
+
5364
+ const now = Date.now();
5365
+ const elapsedMinutes = ( now - startTime ) / 1000 / 60;
5366
+ console.log( `Store name: ${storeData.storeName}, Iteration ${i + 1}: total elapsed time = ${elapsedMinutes.toFixed( 2 )} minutes` );
5367
+ }
5368
+
5369
+ res.sendSuccess( 'Updated Successfully' );
5370
+ } catch ( e ) {
5371
+ logger.error( { functionName: 'updateCrestPlanogram', error: e } );
5372
+ return res.sendError( e.message || 'Internal Server Error', 500 );
5373
+ }
5374
+ }
5375
+
5376
+ export async function getVideoLinks( req, res ) {
5377
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
5378
+ return res.sendError( 'Unauthorized', 401 );
5379
+ }
5380
+ try {
5381
+ const query = [
5382
+ {
5383
+ $match: {
5384
+ date_string: { $gte: req.body.fromDate, $lte: req.body.toDate },
5385
+ type: 'layout',
5386
+ status: req.body.status,
5387
+ },
5388
+ },
5389
+ {
5390
+ $lookup: {
5391
+ from: 'planograms',
5392
+ let: { plano_id: '$planoId' },
5393
+ pipeline: [
5394
+ {
5395
+ $match: {
5396
+ $expr: {
5397
+ $and: [
5398
+ { $eq: [ '$_id', '$$plano_id' ] },
5399
+ ],
5400
+ },
5401
+ },
5402
+ },
5403
+ {
5404
+ $project: {
5405
+ storeName: 1,
5406
+ _id: 0,
5407
+ },
5408
+ },
5409
+ ],
5410
+ as: 'planogram',
5411
+ },
5412
+ },
5413
+ { $unwind: { path: '$planogram', preserveNullAndEmptyArrays: true } },
5414
+ {
5415
+ $project: {
5416
+ storeName: '$planogram.storeName',
5417
+ answers: 1,
5418
+ type: 1,
5419
+ status: 1,
5420
+ planoId: 1,
5421
+ floorId: 1,
5422
+ },
5423
+ },
5424
+ ];
5425
+ const responseData = await planoTaskService.aggregate( query );
5426
+
5427
+ const videoData = [];
5428
+
5429
+ const seenStores = new Set();
5430
+
5431
+ for ( const data of responseData ) {
5432
+ const store = await planoService.findOne( { _id: data.planoId } );
5433
+ if ( seenStores.has( store?.toObject()?.storeName ) ) {
5434
+ continue;
5435
+ }
5436
+ const [ q1, q2, q3 ] = data.answers;
5437
+
5438
+ const params = {
5439
+ Bucket: 'tango-planogram',
5440
+ file_path: q3?.video || null,
5441
+ };
5442
+
5443
+ const videoUrl = await signedUrl( params );
5444
+
5445
+ videoData.push( {
5446
+ date: data.date_string,
5447
+ store: store?.toObject()?.storeName,
5448
+ videoUrl,
5449
+ } );
5450
+
5451
+ seenStores.add( store?.toObject()?.storeName );
5452
+ }
5453
+
5454
+ const resData = {
5455
+ count: videoData.length,
5456
+ data: videoData,
5457
+ };
5458
+
5459
+ res.sendSuccess( resData );
5460
+ } catch ( e ) {
5461
+ console.log( e );
5462
+ return res.sendError( e, 500 );
5463
+ }
5464
+ }
5465
+
5466
+ export async function updateExcelPlanogram( req, res ) {
5467
+ try {
5468
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
5469
+ return res.sendError( 'Unauthorized', 401 );
5470
+ }
5471
+
5472
+ const startTime = Date.now();
5473
+
5474
+ const workbook = xlsx.read( req.files.file.data, { type: 'buffer' } );
5475
+ const sheetName = 'Sheet1';
5476
+ const raw = xlsx.utils.sheet_to_json( workbook.Sheets[sheetName] );
5477
+
5478
+ const storeNames = new Set();
5479
+
5480
+ raw.forEach( ( entry ) => storeNames.add( entry?.['Store ID'] ) );
5481
+
5482
+ const storeNameArr = Array.from( storeNames );
5483
+
5484
+ const storeList = await storeService.find( { clientId: '11', storeName: { $in: storeNameArr } }, { storeName: 1, storeId: 1 } );
5485
+
5486
+ function transformFixtureData( inputData ) {
5487
+ const storeMap = new Map();
5488
+
5489
+ inputData.forEach( ( item ) => {
5490
+ const storeName = item['Store ID'];
5491
+ if ( !storeMap.has( storeName ) ) {
5492
+ storeMap.set( storeName, [] );
5493
+ }
5494
+ storeMap.get( storeName ).push( item );
5495
+ } );
5496
+
5497
+ const result = [];
5498
+
5499
+ for ( const [ storeName, storeItems ] of storeMap.entries() ) {
5500
+ const wallGroups = new Map();
5501
+ const fixtureGroupMap = new Map();
5502
+
5503
+ function addZoneProduct( fixture, zoneName, productName, isVM ) {
5504
+ let zone = fixture.productZones.find( ( z ) => z.zoneName === zoneName );
5505
+ if ( !zone ) {
5506
+ zone = { zoneName, products: [] };
5507
+ fixture.productZones.push( zone );
5508
+ }
5509
+
5510
+ if ( !zone.products.some( ( p ) => p.productName === productName && p.isMerchandisingElement === isVM ) ) {
5511
+ zone.products.push( {
5512
+ productName,
5513
+ isMerchandisingElement: isVM,
5514
+ } );
5515
+ }
5516
+ }
5517
+
5518
+ storeItems.forEach( ( item ) => {
5519
+ const wall = item.Wall || 'Unknown';
5520
+ const locator = item['Store Fixture Locator'];
5521
+ const wallUpper = wall.toUpperCase();
5522
+ const isCenterWall = wallUpper.includes( 'CENTRE' );
5523
+ const fixtureKey = wall + '::' + locator;
5524
+
5525
+ if ( !fixtureGroupMap.has( fixtureKey ) ) {
5526
+ if ( isCenterWall ) {
5527
+ console.log();
5528
+ fixtureGroupMap.set( fixtureKey, {
5529
+ type: 'center',
5530
+ id: item['Store Fixture ID'],
5531
+ main: item['Fixture Type'],
5532
+ centerSubMain: item['Brand-Category'],
5533
+ fixtureLocator: locator,
5534
+ centerSuperSubMain: [
5535
+ {
5536
+ name: item['Brand-Category'],
5537
+ isVisualMerchandiser: false,
5538
+ },
5539
+ ],
5540
+ } );
5541
+ } else {
5542
+ fixtureGroupMap.set( fixtureKey, {
5543
+ type: 'wall',
5544
+ id: item['Store Fixture ID'],
5545
+ footer: 'Storage Box',
5546
+ header: item['Brand-Category'],
5547
+ fixtureName: `${locator} - ${item['Fixture Type']}`,
5548
+ fixtureType: item['Fixture Type'],
5549
+ productZones: [],
5550
+ fixtureSpacing: 0,
5551
+ fixtureSubname: [ item['Brand - Sub Category'] ],
5552
+ wall: wallUpper + ' WALL',
5553
+ } );
5554
+ }
5555
+ }
5556
+
5557
+ const fixture = fixtureGroupMap.get( fixtureKey );
5558
+
5559
+ if ( fixture.type === 'wall' ) {
5560
+ if ( item.VM ) addZoneProduct( fixture, item.Zone, item.VM, true );
5561
+ if ( item.Allocation ) addZoneProduct( fixture, item.Zone, item.Allocation, false );
5562
+ }
5563
+ } );
5564
+
5565
+ const structuredData = [];
5566
+
5567
+ for ( const fixture of fixtureGroupMap.values() ) {
5568
+ if ( fixture.type === 'center' ) {
5569
+ structuredData.push( {
5570
+ id: fixture.id,
5571
+ main: fixture.main,
5572
+ centerSubMain: fixture.centerSubMain,
5573
+ fixtureLocator: fixture.fixtureLocator,
5574
+ centerSuperSubMain: fixture.centerSuperSubMain,
5575
+ } );
5576
+ } else {
5577
+ const wallName = fixture.wall;
5578
+ if ( !wallGroups.has( wallName ) ) {
5579
+ wallGroups.set( wallName, {
5580
+ main: wallName,
5581
+ fixtures: [],
5582
+ } );
5583
+ }
5584
+ wallGroups.get( wallName ).fixtures.push( fixture );
5585
+ }
5586
+ }
5587
+
5588
+ result.push( {
5589
+ storeName,
5590
+ data: [
5591
+ ...Array.from( wallGroups.values() ),
5592
+ ...structuredData,
5593
+ ],
5594
+ } );
5595
+ }
5596
+
5597
+ return result;
5598
+ }
5599
+
5600
+
5601
+ const finalData = transformFixtureData( raw );
5602
+
5603
+
5604
+ const constantFixtureLength = 1220;
5605
+ const constantDetailedFixtureLength = 1220;
5606
+
5607
+ const constantFixtureWidth = 610;
5608
+ const constantDetailedFixtureWidth = 1524;
5609
+
5610
+ const mmToFeet = 305;
5611
+
5612
+ function roundToTwo( num ) {
5613
+ return Math.round( num * 100 ) / 100;
5614
+ }
5615
+
5616
+ for ( let i = 0; i < storeList.length; i++ ) {
5617
+ const storeData = finalData.find( ( store ) => store.storeName === storeList[i].toObject().storeName );
5618
+
5619
+ const storeDetails = storeList[i];
5620
+
5621
+ const existingPlanogram = await planoService.findOne( { storeName: storeData.storeName } );
5622
+
5623
+ if ( existingPlanogram ) {
5624
+ const checkTaskSubmitted = await planoTaskService.findOne( { planoId: existingPlanogram.toObject()._id } );
5625
+
5626
+ const checkTaskCreated = await processedTaskService.findOne( { storeName: storeData.storeName, date_iso: { $gte: new Date( ), $lte: new Date( ) }, isPlano: true } );
5627
+
5628
+ if ( checkTaskSubmitted || checkTaskCreated ) {
5629
+ continue;
5630
+ }
5631
+ }
5632
+
5633
+
5634
+ if ( existingPlanogram?.toObject()?._id && mongoose.Types.ObjectId.isValid( existingPlanogram?.toObject()?._id ) ) {
5635
+ await Promise.all( [ planoService.deleteOne( { _id: existingPlanogram?.toObject()?._id } ), storeBuilderService.deleteOne( { planoId: existingPlanogram?.toObject()?._id } ),
5636
+ storeFixtureService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ), fixtureShelfService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
5637
+ planoMappingService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
5638
+ ] );
5639
+ }
5640
+
5641
+
5642
+ const planoInsertData = {
5643
+ storeName: storeData.storeName,
5644
+ storeId: storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
5645
+ layoutName: `${storeData.storeName} - Layout`,
5646
+ clientId: '11',
5647
+ attachments: [],
5648
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
5649
+ createdByName: 'Bejan',
5650
+ createdByEmail: 'bejan@tangotech.co.in',
5651
+ status: 'completed',
5652
+ floorNumber: 1,
5653
+ productResolutionLevel: 'L2',
5654
+ scanType: 'qr',
5655
+ };
5656
+
5657
+ const insertedPlano = await planoService.upsertOne( { storeName: storeData.storeName }, planoInsertData );
5658
+ const planoDoc = insertedPlano.toObject();
5659
+
5660
+ const leftWall = storeData.data.filter( ( entry ) => entry['main'] === 'LEFT WALL' );
5661
+ const leftFixtures = leftWall.flatMap( ( wall ) => wall.fixtures );
5662
+ const rightWall = storeData.data.filter( ( entry ) => entry['main'] === 'RIGHT WALL' );
5663
+ const rightFixtures = rightWall.flatMap( ( wall ) => wall.fixtures );
5664
+ const backWall = storeData.data.filter( ( entry ) => entry['main'] === 'BACK WALL' );
5665
+ const backFixtures = backWall.flatMap( ( wall ) => wall.fixtures );
5666
+ const frontWall = storeData.data.filter( ( entry ) => entry['main'] === 'FRONT WALL' );
5667
+ const frontFixtures = frontWall.flatMap( ( wall ) => wall.fixtures );
5668
+ const floorFixtures = storeData.data.filter( ( entry ) => entry['main'] === 'Euro Center' );
5669
+
5670
+
5671
+ const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
5672
+ const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
5673
+
5674
+ const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
5675
+ const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
5676
+
5677
+ const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
5678
+ const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
5679
+
5680
+ const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
5681
+ const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
5682
+
5683
+ const maxFixturesPerRow = floorFixtures.length/2;
5684
+ const totalRows = 2;
5685
+
5686
+ const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
5687
+ const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
5688
+
5689
+ const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
5690
+ const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
5691
+
5692
+ const frontXDistanceFeet = frontFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
5693
+ const frontXDetailedDistanceFeet = frontFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
5694
+
5695
+ const frontYDistanceFeet = frontFixtures.length ? roundToTwo( ( ( frontFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
5696
+ const frontYDetailedDistanceFeet = frontFixtures.length ? roundToTwo( ( ( frontFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
5697
+
5698
+ const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
5699
+ const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
5700
+
5701
+ const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
5702
+ const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
5703
+
5704
+ const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
5705
+ const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
5706
+
5707
+ const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet, frontYDistanceFeet );
5708
+ const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet, frontYDetailedDistanceFeet );
5709
+
5710
+ const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet + frontXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet + frontXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
5711
+ const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet + frontXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet + frontXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
5712
+
5713
+ const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
5714
+ const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
5715
+
5716
+
5717
+ const floorInsertData = {
5718
+ storeName: planoDoc.storeName,
5719
+ storeId: planoDoc.storeId,
5720
+ layoutName: `${planoDoc.storeName} - Layout`,
5721
+ clientId: '11',
5722
+ floorNumber: 1,
5723
+ floorName: 'floor 1',
5724
+ layoutPolygon: [
5725
+ {
5726
+ elementType: 'wall',
5727
+ distance: finalXDistance,
5728
+ unit: 'ft',
5729
+ direction: 'right',
5730
+ angle: 90,
5731
+ elementNumber: 1,
5732
+ detailedDistance: finalXDetailedDistance,
5733
+ },
5734
+ {
5735
+ elementType: 'wall',
5736
+ distance: finalYDistance,
5737
+ unit: 'ft',
5738
+ direction: 'down',
5739
+ angle: 90,
5740
+ elementNumber: 2,
5741
+ detailedDistance: finalYDetailedDistance,
5742
+ },
5743
+ {
5744
+ elementType: 'wall',
5745
+ distance: finalXDistance,
5746
+ unit: 'ft',
5747
+ direction: 'left',
5748
+ angle: 90,
5749
+ elementNumber: 3,
5750
+ detailedDistance: finalXDetailedDistance,
5751
+ },
5752
+ {
5753
+ elementType: 'wall',
5754
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
5755
+ unit: 'ft',
5756
+ direction: 'up',
5757
+ angle: 90,
5758
+ elementNumber: 4,
5759
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
5760
+ },
5761
+ {
5762
+ elementType: 'entrance',
5763
+ distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
5764
+ unit: 'ft',
5765
+ direction: 'up',
5766
+ angle: 90,
5767
+ elementNumber: 1,
5768
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
5769
+ },
5770
+ {
5771
+ elementType: 'wall',
5772
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
5773
+ unit: 'ft',
5774
+ direction: 'up',
5775
+ angle: 90,
5776
+ elementNumber: 5,
5777
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
5778
+ },
5779
+ ],
5780
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
5781
+ createdByName: 'Bejan',
5782
+ createdByEmail: 'bejan@tangotech.co.in',
5783
+ status: 'completed',
5784
+ planoId: planoDoc._id,
5785
+ };
5786
+
5787
+ const layoutDoc = await storeBuilderService.upsertOne( { planoId: planoDoc._id }, floorInsertData );
5788
+
5789
+ let fixtureCounter = 1;
5790
+ const frontFixturePromises = frontFixtures.map( async ( fixture, index ) => {
5791
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
5792
+ if ( !fixtureConfig ) return;
5793
+ const fixtureConfigDoc = fixtureConfig.toObject();
5794
+
5795
+ const fixtureData = {
5796
+ 'clientId': layoutDoc.clientId,
5797
+ 'storeName': layoutDoc.storeName,
5798
+ 'storeId': layoutDoc.storeId,
5799
+ 'planoId': layoutDoc.planoId,
5800
+ 'floorId': layoutDoc._id,
5801
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
5802
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
5803
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
5804
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
5805
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
5806
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
5807
+ 'fixtureType': 'wall',
5808
+ 'fixtureHeight': {
5809
+ 'value': 0,
5810
+ 'unit': 'mm',
5811
+ },
5812
+ 'fixtureLength': {
5813
+ 'value': constantFixtureWidth,
5814
+ 'unit': 'mm',
5815
+ },
5816
+ 'fixtureWidth': {
5817
+ 'value': constantFixtureLength,
5818
+ 'unit': 'mm',
5819
+ },
5820
+ 'associatedElementType': 'wall',
5821
+ 'associatedElementNumber': 2,
5822
+ 'relativePosition': {
5823
+ 'x': 0,
5824
+ 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( frontFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
5825
+ 'unit': 'ft',
5826
+ },
5827
+ 'fixtureNumber': fixtureCounter,
5828
+ 'detailedFixtureLength': {
5829
+ 'value': constantDetailedFixtureLength,
5830
+ 'unit': 'mm',
5831
+ },
5832
+ 'detailedFixtureWidth': {
5833
+ 'value': constantDetailedFixtureWidth,
5834
+ 'unit': 'mm',
5835
+ },
5836
+ 'relativeDetailedPosition': {
5837
+ 'x': 0,
5838
+ 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( frontFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
5839
+ 'unit': 'ft',
5840
+ },
5841
+ 'productResolutionLevel': 'L2',
5842
+ 'associatedElementFixtureNumber': index+1,
5843
+ 'header': fixture.header,
5844
+ 'footer': fixture.footer,
5845
+ 'fixtureConfigId': fixtureConfigDoc._id,
5846
+ };
5847
+
5848
+ const createdFixture = await storeFixtureService.upsertOne(
5849
+ {
5850
+ floorId: layoutDoc._id,
5851
+ fixtureNumber: fixtureCounter++,
5852
+ },
5853
+ fixtureData,
5854
+ );
5855
+
5856
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
5857
+
5858
+ await Promise.all(
5859
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
5860
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
5861
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
5862
+
5863
+ const shelfData = {
5864
+ 'clientId': '11',
5865
+ 'storeName': layoutDoc.storeName,
5866
+ 'storeId': layoutDoc.storeId,
5867
+ 'planoId': layoutDoc.planoId,
5868
+ 'floorId': layoutDoc._id,
5869
+ 'fixtureId': createdFixture._id,
5870
+ 'shelfNumber': j + 1,
5871
+ 'shelfOrder': 'LTR',
5872
+ 'shelfCapacity': configShelf.shelfCapacity,
5873
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
5874
+ 'sectionZone': configShelf.shelfZone,
5875
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
5876
+ }; ;
5877
+
5878
+ await fixtureShelfService.upsertOne(
5879
+ {
5880
+ fixtureId: createdFixture._id,
5881
+ shelfNumber: j + 1,
5882
+ },
5883
+ shelfData,
5884
+ );
5885
+ } ),
5886
+ );
5887
+
5888
+ await Promise.all(
5889
+ fixture.productZones?.map( async ( zone ) => {
5890
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
5891
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
5892
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
5893
+
5894
+ await Promise.all(
5895
+ vms.map( async ( vm ) => {
5896
+ let configData = vmConfig[0];
5897
+
5898
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
5899
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
5900
+ }
5901
+
5902
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
5903
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
5904
+ }
5905
+
5906
+ if ( !configData ) return;
5907
+
5908
+ const insertData = {
5909
+ 'clientId': '11',
5910
+ 'productId': 'VMCR',
5911
+ 'type': 'vm',
5912
+ 'productName': vm.productName,
5913
+ 'productHeight': {
5914
+ 'value': configData.vmHeightmm,
5915
+ 'unit': 'mm',
5916
+ },
5917
+ 'productWidth': {
5918
+ 'value': configData.vmWidthmm,
5919
+ 'unit': 'mm',
5920
+ },
5921
+ 'startYPosition': configData.startShelf,
5922
+ 'endYPosition': configData.endShelf,
5923
+ 'xZone': configData.zone,
5924
+ 'fixtureConfigId': fixtureConfig._id,
5925
+ };
5926
+
5927
+ const vmTemplate = await planoProductService.upsertOne(
5928
+ {
5929
+ 'productName': vm.productName,
5930
+ 'fixtureConfigId': fixtureConfig._id,
5931
+ 'productHeight.value': configData.vmHeightmm,
5932
+ 'productWidth.value': configData.vmWidthmm,
5933
+ 'startYPosition': configData.startShelf,
5934
+ 'endYPosition': configData.endShelf,
5935
+ 'xZone': configData.zone,
5936
+ },
5937
+ insertData,
5938
+ );
5939
+
5940
+ const vmData = {
5941
+ 'clientId': layoutDoc.clientId,
5942
+ 'storeName': layoutDoc.storeName,
5943
+ 'storeId': layoutDoc.storeId,
5944
+ 'planoId': layoutDoc.planoId,
5945
+ 'floorId': layoutDoc._id,
5946
+ 'type': 'vm',
5947
+ 'fixtureId': createdFixture._id,
5948
+ 'productId': vmTemplate._id,
5949
+ };
5950
+
5951
+ await planoMappingService.upsertOne(
5952
+ {
5953
+ fixtureId: createdFixture._id,
5954
+ productId: vmTemplate._id,
5955
+ },
5956
+ vmData,
5957
+ );
5958
+ } ),
5959
+ );
5960
+ } ) || [],
5961
+ );
5962
+ } );
5963
+
5964
+ const leftFixturePromises = leftFixtures.map( async ( fixture, index ) => {
5965
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
5966
+ if ( !fixtureConfig ) return;
5967
+ const fixtureConfigDoc = fixtureConfig.toObject();
5968
+
5969
+ const fixtureData = {
5970
+ 'clientId': layoutDoc.clientId,
5971
+ 'storeName': layoutDoc.storeName,
5972
+ 'storeId': layoutDoc.storeId,
5973
+ 'planoId': layoutDoc.planoId,
5974
+ 'floorId': layoutDoc._id,
5975
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
5976
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
5977
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
5978
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
5979
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
5980
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
5981
+ 'fixtureType': 'wall',
5982
+ 'fixtureHeight': {
5983
+ 'value': 0,
5984
+ 'unit': 'mm',
5985
+ },
5986
+ 'fixtureLength': {
5987
+ 'value': constantFixtureLength,
5988
+ 'unit': 'mm',
5989
+ },
5990
+ 'fixtureWidth': {
5991
+ 'value': constantFixtureWidth,
5992
+ 'unit': 'mm',
5993
+ },
5994
+ 'associatedElementType': 'wall',
5995
+ 'associatedElementNumber': 1,
5996
+ 'relativePosition': {
5997
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
5998
+ 'y': 0,
5999
+ 'unit': 'ft',
6000
+ },
6001
+ 'fixtureNumber': fixtureCounter,
6002
+ 'detailedFixtureLength': {
6003
+ 'value': constantDetailedFixtureLength,
6004
+ 'unit': 'mm',
6005
+ },
6006
+ 'detailedFixtureWidth': {
6007
+ 'value': constantDetailedFixtureWidth,
6008
+ 'unit': 'mm',
6009
+ },
6010
+ 'relativeDetailedPosition': {
6011
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
6012
+ 'y': 0,
6013
+ 'unit': 'ft',
6014
+ },
6015
+ 'productResolutionLevel': 'L2',
6016
+ 'associatedElementFixtureNumber': index+1,
6017
+ 'header': fixture.header,
6018
+ 'footer': fixture.footer,
6019
+ 'fixtureConfigId': fixtureConfigDoc._id,
6020
+ };
6021
+
6022
+ const createdFixture = await storeFixtureService.upsertOne(
6023
+ {
6024
+ floorId: layoutDoc._id,
6025
+ fixtureNumber: fixtureCounter++,
6026
+ },
6027
+ fixtureData,
6028
+ );
6029
+
6030
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
6031
+
6032
+ await Promise.all(
6033
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
6034
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
6035
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
6036
+
6037
+ const shelfData = {
6038
+ 'clientId': '11',
6039
+ 'storeName': layoutDoc.storeName,
6040
+ 'storeId': layoutDoc.storeId,
6041
+ 'planoId': layoutDoc.planoId,
6042
+ 'floorId': layoutDoc._id,
6043
+ 'fixtureId': createdFixture._id,
6044
+ 'shelfNumber': j + 1,
6045
+ 'shelfOrder': 'LTR',
6046
+ 'shelfCapacity': configShelf.shelfCapacity,
6047
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
6048
+ 'sectionZone': configShelf.shelfZone,
6049
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
6050
+ };
6051
+
6052
+ await fixtureShelfService.upsertOne(
6053
+ {
6054
+ fixtureId: createdFixture._id,
6055
+ shelfNumber: j + 1,
6056
+ },
6057
+ shelfData,
6058
+ );
6059
+ } ),
6060
+ );
6061
+
6062
+ await Promise.all(
6063
+ fixture.productZones?.map( async ( zone ) => {
6064
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
6065
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
6066
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
6067
+
6068
+ await Promise.all(
6069
+ vms.map( async ( vm ) => {
6070
+ let configData = vmConfig[0];
6071
+
6072
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
6073
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
6074
+ }
6075
+
6076
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
6077
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
6078
+ }
6079
+
6080
+ if ( !configData ) return;
6081
+
6082
+ const insertData = {
6083
+ 'clientId': '11',
6084
+ 'productId': 'VMCR',
6085
+ 'type': 'vm',
6086
+ 'productName': vm.productName,
6087
+ 'productHeight': {
6088
+ 'value': configData.vmHeightmm,
6089
+ 'unit': 'mm',
6090
+ },
6091
+ 'productWidth': {
6092
+ 'value': configData.vmWidthmm,
6093
+ 'unit': 'mm',
6094
+ },
6095
+ 'startYPosition': configData.startShelf,
6096
+ 'endYPosition': configData.endShelf,
6097
+ 'xZone': configData.zone,
6098
+ 'fixtureConfigId': fixtureConfig._id,
6099
+ };
6100
+
6101
+ const vmTemplate = await planoProductService.upsertOne(
6102
+ {
6103
+ 'productName': vm.productName,
6104
+ 'fixtureConfigId': fixtureConfig._id,
6105
+ 'productHeight.value': configData.vmHeightmm,
6106
+ 'productWidth.value': configData.vmWidthmm,
6107
+ 'startYPosition': configData.startShelf,
6108
+ 'endYPosition': configData.endShelf,
6109
+ 'xZone': configData.zone,
6110
+ },
6111
+ insertData,
6112
+ );
6113
+
6114
+ const vmData = {
6115
+ 'clientId': layoutDoc.clientId,
6116
+ 'storeName': layoutDoc.storeName,
6117
+ 'storeId': layoutDoc.storeId,
6118
+ 'planoId': layoutDoc.planoId,
6119
+ 'floorId': layoutDoc._id,
6120
+ 'type': 'vm',
6121
+ 'fixtureId': createdFixture._id,
6122
+ 'productId': vmTemplate._id,
6123
+ };
6124
+
6125
+ await planoMappingService.upsertOne(
6126
+ {
6127
+ fixtureId: createdFixture._id,
6128
+ productId: vmTemplate._id,
6129
+ },
6130
+ vmData,
6131
+ );
6132
+ } ),
6133
+ );
6134
+ } ) || [],
6135
+ );
6136
+ } );
6137
+
6138
+ const backFixturePromises = backFixtures.map( async ( fixture, index ) => {
6139
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
6140
+ if ( !fixtureConfig ) return;
6141
+ const fixtureConfigDoc = fixtureConfig.toObject();
6142
+
6143
+ const fixtureData = {
6144
+ 'clientId': layoutDoc.clientId,
6145
+ 'storeName': layoutDoc.storeName,
6146
+ 'storeId': layoutDoc.storeId,
6147
+ 'planoId': layoutDoc.planoId,
6148
+ 'floorId': layoutDoc._id,
6149
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
6150
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
6151
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
6152
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
6153
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
6154
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
6155
+ 'fixtureType': 'wall',
6156
+ 'fixtureHeight': {
6157
+ 'value': 0,
6158
+ 'unit': 'mm',
6159
+ },
6160
+ 'fixtureLength': {
6161
+ 'value': constantFixtureWidth,
6162
+ 'unit': 'mm',
6163
+ },
6164
+ 'fixtureWidth': {
6165
+ 'value': constantFixtureLength,
6166
+ 'unit': 'mm',
6167
+ },
6168
+ 'associatedElementType': 'wall',
6169
+ 'associatedElementNumber': 2,
6170
+ 'relativePosition': {
6171
+ 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
6172
+ 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
6173
+ 'unit': 'ft',
6174
+ },
6175
+ 'fixtureNumber': fixtureCounter,
6176
+ 'detailedFixtureLength': {
6177
+ 'value': constantDetailedFixtureLength,
6178
+ 'unit': 'mm',
6179
+ },
6180
+ 'detailedFixtureWidth': {
6181
+ 'value': constantDetailedFixtureWidth,
6182
+ 'unit': 'mm',
6183
+ },
6184
+ 'relativeDetailedPosition': {
6185
+ 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
6186
+ 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
6187
+ 'unit': 'ft',
6188
+ },
6189
+ 'productResolutionLevel': 'L2',
6190
+ 'associatedElementFixtureNumber': index+1,
6191
+ 'header': fixture.header,
6192
+ 'footer': fixture.footer,
6193
+ 'fixtureConfigId': fixtureConfigDoc._id,
6194
+ };
6195
+
6196
+ const createdFixture = await storeFixtureService.upsertOne(
6197
+ {
6198
+ floorId: layoutDoc._id,
6199
+ fixtureNumber: fixtureCounter++,
6200
+ },
6201
+ fixtureData,
6202
+ );
6203
+
6204
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
6205
+
6206
+ await Promise.all(
6207
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
6208
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
6209
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
6210
+
6211
+ const shelfData = {
6212
+ 'clientId': '11',
6213
+ 'storeName': layoutDoc.storeName,
6214
+ 'storeId': layoutDoc.storeId,
6215
+ 'planoId': layoutDoc.planoId,
6216
+ 'floorId': layoutDoc._id,
6217
+ 'fixtureId': createdFixture._id,
6218
+ 'shelfNumber': j + 1,
6219
+ 'shelfOrder': 'LTR',
6220
+ 'shelfCapacity': configShelf.shelfCapacity,
6221
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
6222
+ 'sectionZone': configShelf.shelfZone,
6223
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
6224
+ }; ;
6225
+
6226
+ await fixtureShelfService.upsertOne(
6227
+ {
6228
+ fixtureId: createdFixture._id,
6229
+ shelfNumber: j + 1,
6230
+ },
6231
+ shelfData,
6232
+ );
6233
+ } ),
6234
+ );
6235
+
6236
+ await Promise.all(
6237
+ fixture.productZones?.map( async ( zone ) => {
6238
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
6239
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
6240
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
6241
+
6242
+ await Promise.all(
6243
+ vms.map( async ( vm ) => {
6244
+ let configData = vmConfig[0];
6245
+
6246
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
6247
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
6248
+ }
6249
+
6250
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
6251
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
6252
+ }
6253
+
6254
+ if ( !configData ) return;
6255
+
6256
+ const insertData = {
6257
+ 'clientId': '11',
6258
+ 'productId': 'VMCR',
6259
+ 'type': 'vm',
6260
+ 'productName': vm.productName,
6261
+ 'productHeight': {
6262
+ 'value': configData.vmHeightmm,
6263
+ 'unit': 'mm',
6264
+ },
6265
+ 'productWidth': {
6266
+ 'value': configData.vmWidthmm,
6267
+ 'unit': 'mm',
6268
+ },
6269
+ 'startYPosition': configData.startShelf,
6270
+ 'endYPosition': configData.endShelf,
6271
+ 'xZone': configData.zone,
6272
+ 'fixtureConfigId': fixtureConfig._id,
6273
+ };
6274
+
6275
+ const vmTemplate = await planoProductService.upsertOne(
6276
+ {
6277
+ 'productName': vm.productName,
6278
+ 'fixtureConfigId': fixtureConfig._id,
6279
+ 'productHeight.value': configData.vmHeightmm,
6280
+ 'productWidth.value': configData.vmWidthmm,
6281
+ 'startYPosition': configData.startShelf,
6282
+ 'endYPosition': configData.endShelf,
6283
+ 'xZone': configData.zone,
6284
+ },
6285
+ insertData,
6286
+ );
6287
+
6288
+ const vmData = {
6289
+ 'clientId': layoutDoc.clientId,
6290
+ 'storeName': layoutDoc.storeName,
6291
+ 'storeId': layoutDoc.storeId,
6292
+ 'planoId': layoutDoc.planoId,
6293
+ 'floorId': layoutDoc._id,
6294
+ 'type': 'vm',
6295
+ 'fixtureId': createdFixture._id,
6296
+ 'productId': vmTemplate._id,
6297
+ };
6298
+
6299
+ await planoMappingService.upsertOne(
6300
+ {
6301
+ fixtureId: createdFixture._id,
6302
+ productId: vmTemplate._id,
6303
+ },
6304
+ vmData,
6305
+ );
6306
+ } ),
6307
+ );
6308
+ } ) || [],
6309
+ );
6310
+ } );
6311
+
6312
+ const rightFixturePromises = rightFixtures.map( async ( fixture, index ) => {
6313
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
6314
+ if ( !fixtureConfig ) return;
6315
+ const fixtureConfigDoc = fixtureConfig.toObject();
6316
+
6317
+ const fixtureData = {
6318
+ 'clientId': layoutDoc.clientId,
6319
+ 'storeName': layoutDoc.storeName,
6320
+ 'storeId': layoutDoc.storeId,
6321
+ 'planoId': layoutDoc.planoId,
6322
+ 'floorId': layoutDoc._id,
6323
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
6324
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
6325
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
6326
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
6327
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
6328
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
6329
+ 'fixtureType': 'wall',
6330
+ 'fixtureHeight': {
6331
+ 'value': 0,
6332
+ 'unit': 'mm',
6333
+ },
6334
+ 'fixtureLength': {
6335
+ 'value': constantFixtureLength,
6336
+ 'unit': 'mm',
6337
+ },
6338
+ 'fixtureWidth': {
6339
+ 'value': constantFixtureWidth,
6340
+ 'unit': 'mm',
6341
+ },
6342
+ 'associatedElementType': 'wall',
6343
+ 'associatedElementNumber': 3,
6344
+ 'relativePosition': {
6345
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
6346
+ 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
6347
+ 'unit': 'ft',
6348
+ },
6349
+ 'fixtureNumber': fixtureCounter,
6350
+ 'detailedFixtureLength': {
6351
+ 'value': constantDetailedFixtureLength,
6352
+ 'unit': 'mm',
6353
+ },
6354
+ 'detailedFixtureWidth': {
6355
+ 'value': constantDetailedFixtureWidth,
6356
+ 'unit': 'mm',
6357
+ },
6358
+ 'relativeDetailedPosition': {
6359
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
6360
+ 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
6361
+ 'unit': 'ft',
6362
+ },
6363
+ 'productResolutionLevel': 'L2',
6364
+ 'associatedElementFixtureNumber': index+1,
6365
+ 'header': fixture.header,
6366
+ 'footer': fixture.footer,
6367
+ 'fixtureConfigId': fixtureConfigDoc._id,
6368
+ };
6369
+
6370
+ const createdFixture = await storeFixtureService.upsertOne(
6371
+ {
6372
+ floorId: layoutDoc._id,
6373
+ fixtureNumber: fixtureCounter++,
6374
+ },
6375
+ fixtureData,
6376
+ );
6377
+
6378
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
6379
+
6380
+ await Promise.all(
6381
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
6382
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
6383
+ const shelfSection = shelfZone.products.find( ( product ) => !product.isMerchandisingElement );
6384
+
6385
+ const shelfData = {
6386
+ 'clientId': '11',
6387
+ 'storeName': layoutDoc.storeName,
6388
+ 'storeId': layoutDoc.storeId,
6389
+ 'planoId': layoutDoc.planoId,
6390
+ 'floorId': layoutDoc._id,
6391
+ 'fixtureId': createdFixture._id,
6392
+ 'shelfNumber': j + 1,
6393
+ 'shelfOrder': 'LTR',
6394
+ 'shelfCapacity': configShelf.shelfCapacity,
6395
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
6396
+ 'sectionZone': configShelf.shelfZone,
6397
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
6398
+ };
6399
+
6400
+ await fixtureShelfService.upsertOne(
6401
+ {
6402
+ fixtureId: createdFixture._id,
6403
+ shelfNumber: j + 1,
6404
+ },
6405
+ shelfData,
6406
+ );
6407
+ } ),
6408
+ );
6409
+
6410
+ await Promise.all(
6411
+ fixture.productZones?.map( async ( zone ) => {
6412
+ const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
6413
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
6414
+ const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
6415
+
6416
+ await Promise.all(
6417
+ vms.map( async ( vm ) => {
6418
+ let configData = vmConfig[0];
6419
+
6420
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
6421
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
6422
+ }
6423
+
6424
+ if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
6425
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
6426
+ }
6427
+
6428
+ if ( !configData ) return;
6429
+
6430
+ const insertData = {
6431
+ 'clientId': '11',
6432
+ 'productId': 'VMCR',
6433
+ 'type': 'vm',
6434
+ 'productName': vm.productName,
6435
+ 'productHeight': {
6436
+ 'value': configData.vmHeightmm,
6437
+ 'unit': 'mm',
6438
+ },
6439
+ 'productWidth': {
6440
+ 'value': configData.vmWidthmm,
6441
+ 'unit': 'mm',
6442
+ },
6443
+ 'startYPosition': configData.startShelf,
6444
+ 'endYPosition': configData.endShelf,
6445
+ 'xZone': configData.zone,
6446
+ 'fixtureConfigId': fixtureConfig._id,
6447
+ };
6448
+
6449
+ const vmTemplate = await planoProductService.upsertOne(
6450
+ {
6451
+ 'productName': vm.productName,
6452
+ 'fixtureConfigId': fixtureConfig._id,
6453
+ 'productHeight.value': configData.vmHeightmm,
6454
+ 'productWidth.value': configData.vmWidthmm,
6455
+ 'startYPosition': configData.startShelf,
6456
+ 'endYPosition': configData.endShelf,
6457
+ 'xZone': configData.zone,
6458
+ },
6459
+ insertData,
6460
+ );
6461
+
6462
+ const vmData = {
6463
+ 'clientId': layoutDoc.clientId,
6464
+ 'storeName': layoutDoc.storeName,
6465
+ 'storeId': layoutDoc.storeId,
6466
+ 'planoId': layoutDoc.planoId,
6467
+ 'floorId': layoutDoc._id,
6468
+ 'type': 'vm',
6469
+ 'fixtureId': createdFixture._id,
6470
+ 'productId': vmTemplate._id,
6471
+ };
6472
+
6473
+ await planoMappingService.upsertOne(
6474
+ {
6475
+ fixtureId: createdFixture._id,
6476
+ productId: vmTemplate._id,
6477
+ },
6478
+ vmData,
6479
+ );
6480
+ } ),
6481
+ );
6482
+ } ) || [],
6483
+ );
6484
+ } );
6485
+
6486
+ const floorFixturePromises = floorFixtures.map( async ( fixture, index ) => {
6487
+ const centerRow = Math.floor( totalRows / 2 );
6488
+
6489
+ const startingX = roundToTwo( ( finalXDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) );
6490
+ const detailedStartingX = roundToTwo( ( finalXDetailedDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) );
6491
+
6492
+ const startingY = finalYDistance / 2 - centerRow * ( constantFixtureWidth / mmToFeet );
6493
+ const detailedStartingY = finalYDetailedDistance / 2 - centerRow * ( constantDetailedFixtureWidth / mmToFeet );
6494
+
6495
+ const colIndex = Math.floor( index / 2 );
6496
+ const rowIndex = index % 2 === 0 ? 1 : 0;
6497
+
6498
+ const xPos = roundToTwo( startingX + colIndex * ( constantFixtureLength / mmToFeet ) );
6499
+ const yPos = roundToTwo( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) );
6500
+
6501
+ const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
6502
+ const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
6503
+
6504
+ console.log( fixture );
6505
+
6506
+ console.log( fixture.main );
6507
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.main } );
6508
+ if ( !fixtureConfig ) return;
6509
+
6510
+ const fixtureConfigDoc = fixtureConfig.toObject();
6511
+
6512
+ console.log( fixtureConfigDoc );
6513
+
6514
+ const fixtureData = {
6515
+ 'clientId': layoutDoc.clientId,
6516
+ 'storeName': layoutDoc.storeName,
6517
+ 'storeId': layoutDoc.storeId,
6518
+ 'planoId': layoutDoc.planoId,
6519
+ 'floorId': layoutDoc._id,
6520
+ 'fixtureName': `Fixture ${index+1} - ${fixture.main}`,
6521
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
6522
+ 'fixtureBrandCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
6523
+ 'fixtureBrandSubCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
6524
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
6525
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
6526
+ 'fixtureType': 'floor',
6527
+ 'fixtureHeight': {
6528
+ 'value': 0,
6529
+ 'unit': 'mm',
6530
+ },
6531
+ 'fixtureLength': {
6532
+ 'value': constantFixtureLength,
6533
+ 'unit': 'mm',
6534
+ },
6535
+ 'fixtureWidth': {
6536
+ 'value': constantFixtureWidth,
6537
+ 'unit': 'mm',
6538
+ },
6539
+ 'relativePosition': {
6540
+ 'x': xPos,
6541
+ 'y': yPos,
6542
+ 'unit': 'ft',
6543
+ },
6544
+ 'fixtureNumber': fixtureCounter,
6545
+ 'detailedFixtureLength': {
6546
+ 'value': constantDetailedFixtureLength,
6547
+ 'unit': 'mm',
6548
+ },
6549
+ 'detailedFixtureWidth': {
6550
+ 'value': constantDetailedFixtureWidth,
6551
+ 'unit': 'mm',
6552
+ },
6553
+ 'relativeDetailedPosition': {
6554
+ 'x': detailedXPos,
6555
+ 'y': detailedYPos,
6556
+ 'unit': 'ft',
6557
+ },
6558
+ 'productResolutionLevel': 'L2',
6559
+ 'associatedElementFixtureNumber': index+1,
6560
+ 'fixtureConfigId': fixtureConfigDoc._id,
6561
+ };
6562
+
6563
+ console.log( fixtureData );
6564
+
6565
+
6566
+ const createdFixture = await storeFixtureService.upsertOne(
6567
+ {
6568
+ floorId: layoutDoc._id,
6569
+ fixtureNumber: fixtureCounter++,
6570
+ },
6571
+ fixtureData,
6572
+ );
6573
+
6574
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) return;
6575
+
6576
+ await Promise.all(
6577
+ fixtureConfigDoc.shelfConfig.map( async ( configShelf, j ) => {
6578
+ const shelfSection = fixture.centerSuperSubMain.find(
6579
+ ( product ) => product.isVisualMerchandiser === false || product.isVisualMerchandiser === true,
6580
+ );
6581
+
6582
+ const shelfData = {
6583
+ 'clientId': '11',
6584
+ 'storeName': layoutDoc.storeName,
6585
+ 'storeId': layoutDoc.storeId,
6586
+ 'planoId': layoutDoc.planoId,
6587
+ 'floorId': layoutDoc._id,
6588
+ 'fixtureId': createdFixture._id,
6589
+ 'shelfNumber': j + 1,
6590
+ 'shelfOrder': 'LTR',
6591
+ 'shelfCapacity': configShelf.shelfCapacity,
6592
+ 'sectionName': fixture.centerSuperSubMain.find( ( product ) => product.isVisualMerchandiser === true ) ? shelfSection?.name + ' PIDs' : shelfSection?.name,
6593
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
6594
+ };
6595
+
6596
+ await fixtureShelfService.upsertOne(
6597
+ {
6598
+ fixtureId: createdFixture._id,
6599
+ shelfNumber: j + 1,
6600
+ },
6601
+ shelfData,
6602
+ );
6603
+ } ),
6604
+ );
6605
+
6606
+ const vm = fixture.centerSuperSubMain.find( ( vm ) => vm.isVisualMerchandiser );
6607
+ const vmConfig = fixtureConfigDoc.vmConfig;
6608
+
6609
+ if ( vm ) {
6610
+ const [ configData1, configData2 ] = [ vmConfig[0], vmConfig[1] ];
6611
+
6612
+ const insertData1 = {
6613
+ 'clientId': '11',
6614
+ 'productId': 'VMCR',
6615
+ 'type': 'vm',
6616
+ 'productName': vm.name,
6617
+ 'productHeight': {
6618
+ 'value': configData1.vmHeightmm,
6619
+ 'unit': 'mm',
6620
+ },
6621
+ 'productWidth': {
6622
+ 'value': configData1.vmWidthmm,
6623
+ 'unit': 'mm',
6624
+ },
6625
+ 'startYPosition': configData1.startShelf,
6626
+ 'endYPosition': configData1.endShelf,
6627
+ 'xZone': configData1.zone,
6628
+ 'fixtureConfigId': fixtureConfig._id,
6629
+ };
6630
+ const insertData2 = {
6631
+ 'clientId': '11',
6632
+ 'productId': 'VMCR',
6633
+ 'type': 'vm',
6634
+ 'productName': ' ',
6635
+ 'productHeight': {
6636
+ 'value': configData2.vmHeightmm,
6637
+ 'unit': 'mm',
6638
+ },
6639
+ 'productWidth': {
6640
+ 'value': configData2.vmWidthmm,
6641
+ 'unit': 'mm',
6642
+ },
6643
+ 'startYPosition': configData2.startShelf,
6644
+ 'endYPosition': configData2.endShelf,
6645
+ 'xZone': configData2.zone,
6646
+ 'fixtureConfigId': fixtureConfig._id,
6647
+ };
6648
+
6649
+ const [ vmTemplate1, vmTemplate2 ] = await Promise.all( [
6650
+ planoProductService.upsertOne(
6651
+ {
6652
+ 'productName': vm.name,
6653
+ 'fixtureConfigId': fixtureConfig._id,
6654
+ 'productHeight.value': configData1.vmHeightmm,
6655
+ 'productWidth.value': configData1.vmWidthmm,
6656
+ 'startYPosition': configData1.startShelf,
6657
+ 'endYPosition': configData1.endShelf,
6658
+ 'xZone': configData1.zone,
6659
+ },
6660
+ insertData1,
6661
+ ),
6662
+ planoProductService.upsertOne(
6663
+ {
6664
+ 'productName': ' ',
6665
+ 'fixtureConfigId': fixtureConfig._id,
6666
+ 'productHeight.value': configData2.vmHeightmm,
6667
+ 'productWidth.value': configData2.vmWidthmm,
6668
+ 'startYPosition': configData2.startShelf,
6669
+ 'endYPosition': configData2.endShelf,
6670
+ 'xZone': configData2.zone,
6671
+ },
6672
+ insertData2,
6673
+ ),
6674
+ ] );
6675
+
6676
+ const vmData1 = {
6677
+ 'clientId': layoutDoc.clientId,
6678
+ 'storeName': layoutDoc.storeName,
6679
+ 'storeId': layoutDoc.storeId,
6680
+ 'planoId': layoutDoc.planoId,
6681
+ 'floorId': layoutDoc._id,
6682
+ 'type': 'vm',
6683
+ 'fixtureId': createdFixture._id,
6684
+ 'productId': vmTemplate1._id,
6685
+ };
6686
+ const vmData2 = {
6687
+ 'clientId': layoutDoc.clientId,
6688
+ 'storeName': layoutDoc.storeName,
6689
+ 'storeId': layoutDoc.storeId,
6690
+ 'planoId': layoutDoc.planoId,
6691
+ 'floorId': layoutDoc._id,
6692
+ 'type': 'vm',
6693
+ 'fixtureId': createdFixture._id,
6694
+ 'productId': vmTemplate2._id,
6695
+ };
6696
+
6697
+ await Promise.all( [
6698
+ planoMappingService.upsertOne(
6699
+ {
6700
+ fixtureId: createdFixture._id,
6701
+ productId: vmTemplate1._id,
6702
+ },
6703
+ vmData1,
6704
+ ),
6705
+ planoMappingService.upsertOne(
6706
+ {
6707
+ fixtureId: createdFixture._id,
6708
+ productId: vmTemplate2._id,
6709
+ },
6710
+ vmData2,
6711
+ ),
6712
+ ] );
6713
+ }
6714
+ } );
6715
+
6716
+ await Promise.all( [ ...frontFixturePromises, ...leftFixturePromises, ...backFixturePromises, ...rightFixturePromises, ...floorFixturePromises ] );
6717
+
6718
+ const now = Date.now();
6719
+ const elapsedMinutes = ( now - startTime ) / 1000 / 60;
6720
+ console.log( `Store name: ${storeData.storeName}, Iteration ${i + 1}: total elapsed time = ${elapsedMinutes.toFixed( 2 )} minutes` );
6721
+ }
6722
+
6723
+ res.sendSuccess( finalData );
6724
+ } catch ( e ) {
6725
+ logger.error( { functionName: 'updateCrestPlanogram', error: e } );
6726
+ return res.sendError( e.message || 'Internal Server Error', 500 );
6727
+ }
6728
+ }