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

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.
@@ -19,6 +19,12 @@ import { signedUrl } from 'tango-app-api-middleware';
19
19
  import fs from 'fs';
20
20
  import https from 'https';
21
21
  import dayjs from 'dayjs';
22
+ import os from 'os';
23
+ import { fileURLToPath } from 'url';
24
+ import path from 'path';
25
+
26
+ const __filename = fileURLToPath( import.meta.url );
27
+ const __dirname = path.dirname( __filename );
22
28
 
23
29
 
24
30
  export async function getStoreNames( req, res ) {
@@ -2650,12 +2656,18 @@ export async function createCrestPlanogram( req, res ) {
2650
2656
  for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2651
2657
  const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2652
2658
  const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2659
+ const pids = fixture.productZones[i].products.filter( ( vm ) => !vm.isMerchandisingElement );
2660
+
2653
2661
 
2654
2662
  for ( const vm of vms ) {
2655
2663
  let configData = vmConfig[0];
2656
2664
 
2657
2665
  if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2658
- configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2666
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
2667
+ }
2668
+
2669
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' && pids.length ) {
2670
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
2659
2671
  }
2660
2672
 
2661
2673
  if ( !configData ) continue;
@@ -2809,12 +2821,17 @@ export async function createCrestPlanogram( req, res ) {
2809
2821
  for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2810
2822
  const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2811
2823
  const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2824
+ const pids = fixture.productZones[i].products.filter( ( vm ) => !vm.isMerchandisingElement );
2812
2825
 
2813
2826
  for ( const vm of vms ) {
2814
2827
  let configData = vmConfig[0];
2815
2828
 
2816
2829
  if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2817
- configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2830
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
2831
+ }
2832
+
2833
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' && pids.length ) {
2834
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
2818
2835
  }
2819
2836
 
2820
2837
 
@@ -2969,13 +2986,19 @@ export async function createCrestPlanogram( req, res ) {
2969
2986
  for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2970
2987
  const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2971
2988
  const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2989
+ const pids = fixture.productZones[i].products.filter( ( vm ) => !vm.isMerchandisingElement );
2990
+
2972
2991
 
2973
2992
  for ( const vm of vms ) {
2974
2993
  let configData = vmConfig[0];
2975
2994
 
2976
2995
 
2977
2996
  if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2978
- configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2997
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
2998
+ }
2999
+
3000
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' && pids.length ) {
3001
+ configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
2979
3002
  }
2980
3003
 
2981
3004
 
@@ -3289,6 +3312,249 @@ export async function updateCrestVms( req, res ) {
3289
3312
  }
3290
3313
  }
3291
3314
 
3315
+
3316
+ async function filterStores() {
3317
+ const stores = [
3318
+ 'ST338', 'LKST1304', 'ST303', 'LKST1228', 'LKST499', 'LKST479', 'ST320',
3319
+ 'LKST515', 'LKST406', 'ST392', 'ST328', 'ST332', 'LKST487', 'ST312',
3320
+ 'LKST615', 'LKST352', 'LKST457', 'LKST439', 'LKST347', 'LKST1084',
3321
+ 'LKST380', 'ST298', 'LKST356', 'LKST223', 'LKST480', 'ST30', 'ST285',
3322
+ 'LKST500', 'LKST466', 'LKST321', 'LKST678', 'LKST383', 'LKST365',
3323
+ 'LKST374', 'ST302', 'LKST420', 'LKST394', 'LKST444', 'LKST314',
3324
+ 'LKST01', 'LKST357', 'LKST465', 'LKST331', 'LKST440', 'LKST345',
3325
+ 'LKST389', 'ST330', 'LKST299', 'ST244', 'LKST294', 'ST314', 'LKST361',
3326
+ 'LKST377', 'LKST390', 'ST335', 'LKST416', 'ST293', 'LKST341', 'LKST501',
3327
+ 'LKST408', 'LKST227', 'LKST353', 'LKST364', 'ST318', 'LKST326',
3328
+ 'LKST344', 'ST321', 'LKST384', 'LKST496', 'LKST427', 'LKST325',
3329
+ 'LKST282', 'ST197', 'LKST388', 'LKST338', 'LKST371', 'ST326', 'LKST428',
3330
+ 'LKST112', 'LKST334', 'ST319', 'LKST464', 'LKST490', 'LKST11',
3331
+ 'LKST502', 'LKST1438',
3332
+ ];
3333
+
3334
+ const rawData = fs.readFileSync( 'crest_scrap_v1.json', 'utf8' );
3335
+ const allStores = JSON.parse( rawData );
3336
+
3337
+ const filteredStores = allStores.filter( ( store ) => stores.includes( store.storeName ) );
3338
+
3339
+ fs.writeFileSync( 'crest_filtered.json', JSON.stringify( filteredStores, null, 2 ) );
3340
+ }
3341
+
3342
+ import fsp from 'fs/promises';
3343
+
3344
+ import sharp from 'sharp';
3345
+
3346
+
3347
+ const stitchImagesFromZips = async () => {
3348
+ const zip1Path = 'crest_plano.zip';
3349
+ const zip2Path = 'tango_plano.zip';
3350
+ const outputDir = 'stitched';
3351
+
3352
+ const loadZip = async ( zipPath ) => {
3353
+ const buffer = await fsp.readFile( zipPath );
3354
+ return await JSZip.loadAsync( buffer );
3355
+ };
3356
+
3357
+ const extractImages = async ( zip ) => {
3358
+ const imageFiles = {};
3359
+ const imageRegex = /\.(png|jpe?g)$/i;
3360
+
3361
+ for ( const [ name, file ] of Object.entries( zip.files ) ) {
3362
+ const base = path.basename( name );
3363
+ if ( !file.dir && imageRegex.test( base ) ) {
3364
+ imageFiles[base] = await file.async( 'nodebuffer' );
3365
+ }
3366
+ }
3367
+
3368
+ return imageFiles;
3369
+ };
3370
+
3371
+ const stitchOrCenter = async ( buffer1, buffer2, outputPath ) => {
3372
+ const totalWidth = 7000;
3373
+ const width1 = Math.round( totalWidth * 0.3 );
3374
+ const width2 = Math.round( totalWidth * 0.7 );
3375
+
3376
+ let img1 = buffer1 ? await sharp( buffer1 ).resize( { width: width1 } ).toBuffer() : null;
3377
+ let img2 = buffer2 ? await sharp( buffer2 ).resize( { width: width2 } ).toBuffer() : null;
3378
+
3379
+ const [ meta1, meta2 ] = await Promise.all( [
3380
+ img1 ? sharp( img1 ).metadata() : Promise.resolve( { height: 0 } ),
3381
+ img2 ? sharp( img2 ).metadata() : Promise.resolve( { height: 0 } ),
3382
+ ] );
3383
+
3384
+ const maxHeight = Math.max( meta1.height, meta2.height );
3385
+
3386
+ const composites = [];
3387
+ if ( img1 ) composites.push( { input: img1, top: 0, left: 0 } );
3388
+ if ( img2 ) composites.push( { input: img2, top: 0, left: width1 } );
3389
+
3390
+ await sharp( {
3391
+ create: {
3392
+ width: totalWidth,
3393
+ height: maxHeight,
3394
+ channels: 4,
3395
+ background: { r: 255, g: 255, b: 255, alpha: 0 },
3396
+ },
3397
+ } )
3398
+ .composite( composites )
3399
+ .png()
3400
+ .toFile( outputPath );
3401
+ };
3402
+
3403
+ try {
3404
+ await fsp.mkdir( outputDir, { recursive: true } );
3405
+
3406
+ const [ zip1, zip2 ] = await Promise.all( [ loadZip( zip1Path ), loadZip( zip2Path ) ] );
3407
+ const [ images1, images2 ] = await Promise.all( [ extractImages( zip1 ), extractImages( zip2 ) ] );
3408
+
3409
+ const allFilenames = new Set( [ ...Object.keys( images1 ), ...Object.keys( images2 ) ] );
3410
+
3411
+ for ( const name of allFilenames ) {
3412
+ const buffer1 = images1[name] || null;
3413
+ const buffer2 = images2[name] || null;
3414
+ const outputPath = path.join( outputDir, `${name.replace( /\.[^/.]+$/, '' )}.png` );
3415
+
3416
+ try {
3417
+ await stitchOrCenter( buffer1, buffer2, outputPath );
3418
+ console.log( ` Processed: ${name}` );
3419
+ } catch ( err ) {
3420
+ console.error( ` Error processing ${name}:`, err.message );
3421
+ }
3422
+ }
3423
+ } catch ( err ) {
3424
+ console.error( ' Unexpected error:', err.message );
3425
+ }
3426
+ };
3427
+
3428
+ // stitchImagesFromZips();
3429
+
3430
+
3431
+ import { Builder, By, until } from 'selenium-webdriver';
3432
+ import chrome from 'selenium-webdriver/chrome.js';
3433
+ import fetch from 'node-fetch';
3434
+
3435
+ import fetchCookie from 'fetch-cookie';
3436
+
3437
+
3438
+ async function downloadCrestImages() {
3439
+ const storeList = await planoService.find( {} );
3440
+ const storeIds = storeList.map( ( store ) => store.toObject().storeName );
3441
+
3442
+ const invalidateUrl = 'https://app.getcrest.ai/api/ms_iam/user/session/override/';
3443
+ const tokenUrl = 'https://app.getcrest.ai/api/ms_iam/token/';
3444
+
3445
+ let authToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ0NzE4MjUzLCJpYXQiOjE3NDQ3MTQ2NTMsImp0aSI6Ijk5ZTAyYjU4ODg2NjQ3MDk4Y2NlY2NmODZlYzYzYTU4IiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.7g1XS48l7mVsOcDXHLC7VFLFyJ-p13e2kkJlb8uFc_g';
3446
+
3447
+ const fetchWithCookies = fetchCookie( fetch );
3448
+
3449
+ async function fetchNewToken() {
3450
+ const invalidate = await fetchWithCookies( invalidateUrl, {
3451
+ 'method': 'POST',
3452
+ 'headers': { 'Content-Type': 'application/json' },
3453
+ 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3454
+ } );
3455
+
3456
+ const invalidateData = await invalidate.json();
3457
+
3458
+ console.log( invalidateData );
3459
+
3460
+ console.log( 'Fetching new token...' );
3461
+ const res = await fetchWithCookies( tokenUrl, {
3462
+ 'method': 'POST',
3463
+ 'Accept': 'application/json, text/javascript, */*; q=0.01',
3464
+ 'headers': { 'Content-Type': 'application/json' },
3465
+ 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3466
+ } );
3467
+
3468
+ if ( !res.ok ) {
3469
+ throw new Error( `Failed to fetch token: ${res.status}` );
3470
+ }
3471
+
3472
+ const data = await res.json();
3473
+ console.log( data );
3474
+ authToken = data.access;
3475
+ return authToken;
3476
+ }
3477
+
3478
+ async function runAutomation( token, storeId, retries = 3 ) {
3479
+ let attempts = 0;
3480
+
3481
+ while ( attempts < retries ) {
3482
+ const options = new chrome.Options();
3483
+ options.addArguments( 'headless' );
3484
+ options.addArguments( 'disable-gpu' );
3485
+
3486
+ const driver = await new Builder()
3487
+ .forBrowser( 'chrome' )
3488
+ .setChromeOptions( options )
3489
+ .build();
3490
+
3491
+ try {
3492
+ const url = `https://app.getcrest.ai/pvt/?auth=${token}&module=planno&store_id=${storeId}`;
3493
+ await driver.get( url );
3494
+ const currentUrl = await driver.getCurrentUrl();
3495
+ if ( currentUrl.includes( '/login' ) ) {
3496
+ console.warn( `Redirected to login for store ${storeId}. Retrying with new token...` );
3497
+ await driver.quit();
3498
+ const newToken = await fetchNewToken();
3499
+ return await runAutomation( newToken, storeId, retries );
3500
+ }
3501
+
3502
+ const button = await driver.wait( until.elementLocated(
3503
+ By.xpath( '//*[contains(@class, "MuiButtonBase-root") and contains(@class, "MuiButton-root") and contains(@class, "MuiButton-text") and contains(@class, "MuiButton-disableElevation") and contains(@class, "jss35") and contains(@class, "jss47") and contains(@class, "jss37") and contains(@class, "jss144")]' ),
3504
+ ), 10000 );
3505
+ await button.click();
3506
+
3507
+ const checkbox = await driver.wait(
3508
+ until.elementLocated(
3509
+ By.xpath( '//*[contains(@class, "MuiCheckbox-root") and contains(@class, "MuiIconButton-root")]//input[@type="checkbox"]' ),
3510
+ ),
3511
+ 10000,
3512
+ );
3513
+ await checkbox.click();
3514
+
3515
+ const downloadIcon = await driver.wait(
3516
+ until.elementLocated(
3517
+ By.xpath( '//button[contains(@class, "cool-tooltip")]' ),
3518
+ ),
3519
+ 10000,
3520
+ );
3521
+ await downloadIcon.click();
3522
+
3523
+
3524
+ console.log( `Download triggered for store: ${storeId}` );
3525
+ await driver.sleep( 5000 );
3526
+ return;
3527
+ } catch ( err ) {
3528
+ attempts++;
3529
+ console.error( `Error for store ${storeId}, attempt ${attempts}: ${err.message}` );
3530
+ if ( attempts >= retries ) {
3531
+ console.error( `Failed for store ${storeId} after ${retries} attempts` );
3532
+ } else {
3533
+ console.log( `Retrying for store ${storeId}, attempt ${attempts + 1}` );
3534
+ }
3535
+ } finally {
3536
+ try {
3537
+ if ( driver && ( await driver.getSession() ) ) {
3538
+ await driver.quit();
3539
+ }
3540
+ } catch ( e ) {
3541
+
3542
+ }
3543
+ }
3544
+ }
3545
+ }
3546
+
3547
+ for ( const storeId of storeIds ) {
3548
+ try {
3549
+ console.log( `Starting automation for store: ${storeId}` );
3550
+ await runAutomation( authToken, storeId );
3551
+ } catch ( error ) {
3552
+ console.error( `Automation failed for store ${storeId}: ${error.message}` );
3553
+ }
3554
+ }
3555
+ }
3556
+
3557
+ // downloadCrestImages();
3292
3558
  export async function updatePlanoFixtureLayout( planoId, floorId ) {
3293
3559
  try {
3294
3560
  console.log( 'dfghj' );
@@ -3305,330 +3571,332 @@ export async function updatePlanoFixtureLayout( planoId, floorId ) {
3305
3571
  }
3306
3572
 
3307
3573
  const insertedPlano = await planoService.findOne( { _id: planoId } );
3574
+ if ( insertedPlano ) {
3575
+ const planoDoc = insertedPlano.toObject();
3308
3576
 
3309
- const planoDoc = insertedPlano.toObject();
3310
-
3311
- const fixtureData = await storeFixtureService.findAndSort( { planoId: planoId, floorId: floorId }, {}, { fixtureNumber: 1 } );
3577
+ const fixtureData = await storeFixtureService.findAndSort( { planoId: planoId, floorId: floorId }, {}, { fixtureNumber: 1 } );
3312
3578
 
3313
- const leftFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 1 );
3314
- const rightFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 3 );
3315
- const backFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 2 );
3316
- const floorFixtures = fixtureData.filter( ( fixture ) => fixture.fixtureType == 'floor' );
3579
+ const leftFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 1 );
3580
+ const rightFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 3 );
3581
+ const backFixtures = fixtureData.filter( ( fixture ) => fixture.associatedElementType == 'wall' && fixture.associatedElementNumber == 2 );
3582
+ const floorFixtures = fixtureData.filter( ( fixture ) => fixture.fixtureType == 'floor' );
3317
3583
 
3318
- // console.log( leftFixtures, 'left' );
3319
- // console.log( rightFixtures, 'rightFixtures' );
3320
- // console.log( backFixtures, 'backFixtures' );
3321
- // console.log( floorFixtures, 'floorFixtures' );
3584
+ // console.log( leftFixtures, 'left' );
3585
+ // console.log( rightFixtures, 'rightFixtures' );
3586
+ // console.log( backFixtures, 'backFixtures' );
3587
+ // console.log( floorFixtures, 'floorFixtures' );
3322
3588
 
3323
- const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3324
- const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
3589
+ const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3590
+ const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
3325
3591
 
3326
- const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
3327
- const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
3592
+ const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
3593
+ const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
3328
3594
 
3329
- const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3330
- const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
3595
+ const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3596
+ const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
3331
3597
 
3332
- const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
3333
- const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
3598
+ const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
3599
+ const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
3334
3600
 
3335
- const maxFixturesPerRow = floorFixtures.length/2;
3336
- const totalRows = 2;
3601
+ const maxFixturesPerRow = floorFixtures.length/2;
3602
+ const totalRows = 2;
3337
3603
 
3338
- const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3339
- const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
3604
+ const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
3605
+ const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
3340
3606
 
3341
- const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
3342
- const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
3607
+ const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
3608
+ const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
3343
3609
 
3344
- const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
3345
- const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
3610
+ const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
3611
+ const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
3346
3612
 
3347
- const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
3348
- const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
3613
+ const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
3614
+ const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
3349
3615
 
3350
- const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
3351
- const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
3616
+ const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
3617
+ const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
3352
3618
 
3353
- const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet );
3354
- const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet );
3619
+ const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet );
3620
+ const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet );
3355
3621
 
3356
- const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
3357
- const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
3622
+ const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
3623
+ const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
3358
3624
 
3359
- const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
3360
- const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
3625
+ const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
3626
+ const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
3361
3627
 
3362
- const floorInsertData = {
3363
- storeName: planoDoc.storeName,
3364
- storeId: planoDoc.storeId,
3365
- layoutName: `${planoDoc.storeName} - Layout`,
3366
- clientId: '11',
3367
- floorNumber: 1,
3368
- floorName: 'floor 1',
3369
- layoutPolygon: [
3370
- {
3371
- elementType: 'wall',
3372
- distance: finalXDistance,
3373
- unit: 'ft',
3374
- direction: 'right',
3375
- angle: 90,
3376
- elementNumber: 1,
3377
- detailedDistance: finalXDetailedDistance,
3378
- },
3379
- {
3380
- elementType: 'wall',
3381
- distance: finalYDistance,
3382
- unit: 'ft',
3383
- direction: 'down',
3384
- angle: 90,
3385
- elementNumber: 2,
3386
- detailedDistance: finalYDetailedDistance,
3387
- },
3388
- {
3389
- elementType: 'wall',
3390
- distance: finalXDistance,
3391
- unit: 'ft',
3392
- direction: 'left',
3393
- angle: 90,
3394
- elementNumber: 3,
3395
- detailedDistance: finalXDetailedDistance,
3396
- },
3397
- {
3398
- elementType: 'wall',
3399
- distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
3400
- unit: 'ft',
3401
- direction: 'up',
3402
- angle: 90,
3403
- elementNumber: 4,
3404
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
3405
- },
3406
- {
3407
- elementType: 'entrance',
3408
- distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
3409
- unit: 'ft',
3410
- direction: 'up',
3411
- angle: 90,
3412
- elementNumber: 1,
3413
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
3414
- },
3415
- {
3416
- elementType: 'wall',
3417
- distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
3418
- unit: 'ft',
3419
- direction: 'up',
3420
- angle: 90,
3421
- elementNumber: 5,
3422
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
3423
- },
3424
- ],
3425
- createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
3426
- createdByName: 'Bejan',
3427
- createdByEmail: 'bejan@tangotech.co.in',
3428
- status: 'completed',
3429
- planoId: planoDoc._id,
3430
- };
3431
-
3432
- await storeBuilderService.upsertOne( { planoId: planoDoc._id }, floorInsertData );
3433
-
3434
- for ( let index = 0; index < leftFixtures.length; index++ ) {
3435
- const fixture = leftFixtures[index];
3436
-
3437
- const fixtureData = {
3438
- 'fixtureHeight': {
3439
- 'value': 0,
3440
- 'unit': 'mm',
3441
- },
3442
- 'fixtureLength': {
3443
- 'value': constantFixtureLength,
3444
- 'unit': 'mm',
3445
- },
3446
- 'fixtureWidth': {
3447
- 'value': constantFixtureWidth,
3448
- 'unit': 'mm',
3449
- },
3450
- 'relativePosition': {
3451
- 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
3452
- 'y': 0,
3453
- 'unit': 'ft',
3454
- },
3455
- 'detailedFixtureLength': {
3456
- 'value': constantDetailedFixtureLength,
3457
- 'unit': 'mm',
3458
- },
3459
- 'detailedFixtureWidth': {
3460
- 'value': constantDetailedFixtureWidth,
3461
- 'unit': 'mm',
3462
- },
3463
- 'relativeDetailedPosition': {
3464
- 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
3465
- 'y': 0,
3466
- 'unit': 'ft',
3467
- },
3628
+ const floorInsertData = {
3629
+ storeName: planoDoc.storeName,
3630
+ storeId: planoDoc.storeId,
3631
+ layoutName: `${planoDoc.storeName} - Layout`,
3632
+ clientId: '11',
3633
+ floorNumber: 1,
3634
+ floorName: 'floor 1',
3635
+ layoutPolygon: [
3636
+ {
3637
+ elementType: 'wall',
3638
+ distance: finalXDistance,
3639
+ unit: 'ft',
3640
+ direction: 'right',
3641
+ angle: 90,
3642
+ elementNumber: 1,
3643
+ detailedDistance: finalXDetailedDistance,
3644
+ },
3645
+ {
3646
+ elementType: 'wall',
3647
+ distance: finalYDistance,
3648
+ unit: 'ft',
3649
+ direction: 'down',
3650
+ angle: 90,
3651
+ elementNumber: 2,
3652
+ detailedDistance: finalYDetailedDistance,
3653
+ },
3654
+ {
3655
+ elementType: 'wall',
3656
+ distance: finalXDistance,
3657
+ unit: 'ft',
3658
+ direction: 'left',
3659
+ angle: 90,
3660
+ elementNumber: 3,
3661
+ detailedDistance: finalXDetailedDistance,
3662
+ },
3663
+ {
3664
+ elementType: 'wall',
3665
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
3666
+ unit: 'ft',
3667
+ direction: 'up',
3668
+ angle: 90,
3669
+ elementNumber: 4,
3670
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
3671
+ },
3672
+ {
3673
+ elementType: 'entrance',
3674
+ distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
3675
+ unit: 'ft',
3676
+ direction: 'up',
3677
+ angle: 90,
3678
+ elementNumber: 1,
3679
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
3680
+ },
3681
+ {
3682
+ elementType: 'wall',
3683
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
3684
+ unit: 'ft',
3685
+ direction: 'up',
3686
+ angle: 90,
3687
+ elementNumber: 5,
3688
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
3689
+ },
3690
+ ],
3691
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
3692
+ createdByName: 'Bejan',
3693
+ createdByEmail: 'bejan@tangotech.co.in',
3694
+ status: 'completed',
3695
+ planoId: planoDoc._id,
3468
3696
  };
3469
3697
 
3470
- await storeFixtureService.updateOne(
3471
- {
3472
- _id: fixture._id,
3698
+ await storeBuilderService.upsertOne( { planoId: planoDoc._id }, floorInsertData );
3699
+
3700
+ for ( let index = 0; index < leftFixtures.length; index++ ) {
3701
+ const fixture = leftFixtures[index];
3702
+
3703
+ const fixtureData = {
3704
+ 'fixtureHeight': {
3705
+ 'value': 0,
3706
+ 'unit': 'mm',
3473
3707
  },
3474
- fixtureData );
3475
- }
3708
+ 'fixtureLength': {
3709
+ 'value': constantFixtureLength,
3710
+ 'unit': 'mm',
3711
+ },
3712
+ 'fixtureWidth': {
3713
+ 'value': constantFixtureWidth,
3714
+ 'unit': 'mm',
3715
+ },
3716
+ 'relativePosition': {
3717
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
3718
+ 'y': 0,
3719
+ 'unit': 'ft',
3720
+ },
3721
+ 'detailedFixtureLength': {
3722
+ 'value': constantDetailedFixtureLength,
3723
+ 'unit': 'mm',
3724
+ },
3725
+ 'detailedFixtureWidth': {
3726
+ 'value': constantDetailedFixtureWidth,
3727
+ 'unit': 'mm',
3728
+ },
3729
+ 'relativeDetailedPosition': {
3730
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
3731
+ 'y': 0,
3732
+ 'unit': 'ft',
3733
+ },
3734
+ };
3476
3735
 
3477
- for ( let index = 0; index < backFixtures.length; index++ ) {
3478
- const fixture = backFixtures[index];
3736
+ await storeFixtureService.updateOne(
3737
+ {
3738
+ _id: fixture._id,
3739
+ },
3740
+ fixtureData );
3741
+ }
3479
3742
 
3480
- const fixtureData = {
3481
- 'fixtureHeight': {
3482
- 'value': 0,
3483
- 'unit': 'mm',
3484
- },
3485
- 'fixtureLength': {
3486
- 'value': constantFixtureWidth,
3487
- 'unit': 'mm',
3488
- },
3489
- 'fixtureWidth': {
3490
- 'value': constantFixtureLength,
3491
- 'unit': 'mm',
3492
- },
3493
- 'relativePosition': {
3494
- 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
3495
- 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
3496
- 'unit': 'ft',
3497
- },
3498
- 'detailedFixtureLength': {
3499
- 'value': constantDetailedFixtureLength,
3500
- 'unit': 'mm',
3501
- },
3502
- 'detailedFixtureWidth': {
3503
- 'value': constantDetailedFixtureWidth,
3504
- 'unit': 'mm',
3505
- },
3506
- 'relativeDetailedPosition': {
3507
- 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
3508
- 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
3509
- 'unit': 'ft',
3510
- },
3511
- };
3743
+ for ( let index = 0; index < backFixtures.length; index++ ) {
3744
+ const fixture = backFixtures[index];
3512
3745
 
3513
- await storeFixtureService.updateOne(
3514
- {
3515
- _id: fixture._id,
3746
+ const fixtureData = {
3747
+ 'fixtureHeight': {
3748
+ 'value': 0,
3749
+ 'unit': 'mm',
3516
3750
  },
3517
- fixtureData );
3518
- }
3751
+ 'fixtureLength': {
3752
+ 'value': constantFixtureWidth,
3753
+ 'unit': 'mm',
3754
+ },
3755
+ 'fixtureWidth': {
3756
+ 'value': constantFixtureLength,
3757
+ 'unit': 'mm',
3758
+ },
3759
+ 'relativePosition': {
3760
+ 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
3761
+ 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
3762
+ 'unit': 'ft',
3763
+ },
3764
+ 'detailedFixtureLength': {
3765
+ 'value': constantDetailedFixtureLength,
3766
+ 'unit': 'mm',
3767
+ },
3768
+ 'detailedFixtureWidth': {
3769
+ 'value': constantDetailedFixtureWidth,
3770
+ 'unit': 'mm',
3771
+ },
3772
+ 'relativeDetailedPosition': {
3773
+ 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
3774
+ 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
3775
+ 'unit': 'ft',
3776
+ },
3777
+ };
3519
3778
 
3520
- for ( let index = 0; index < rightFixtures.length; index++ ) {
3521
- const fixture = rightFixtures[index];
3779
+ await storeFixtureService.updateOne(
3780
+ {
3781
+ _id: fixture._id,
3782
+ },
3783
+ fixtureData );
3784
+ }
3522
3785
 
3523
- const fixtureData = {
3524
- 'fixtureHeight': {
3525
- 'value': 0,
3526
- 'unit': 'mm',
3527
- },
3528
- 'fixtureLength': {
3529
- 'value': constantFixtureLength,
3530
- 'unit': 'mm',
3531
- },
3532
- 'fixtureWidth': {
3533
- 'value': constantFixtureWidth,
3534
- 'unit': 'mm',
3535
- },
3536
- 'relativePosition': {
3537
- 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
3538
- 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
3539
- 'unit': 'ft',
3540
- },
3541
- 'detailedFixtureLength': {
3542
- 'value': constantDetailedFixtureLength,
3543
- 'unit': 'mm',
3544
- },
3545
- 'detailedFixtureWidth': {
3546
- 'value': constantDetailedFixtureWidth,
3547
- 'unit': 'mm',
3548
- },
3549
- 'relativeDetailedPosition': {
3550
- 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
3551
- 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
3552
- 'unit': 'ft',
3553
- },
3554
- };
3786
+ for ( let index = 0; index < rightFixtures.length; index++ ) {
3787
+ const fixture = rightFixtures[index];
3555
3788
 
3556
- await storeFixtureService.updateOne(
3557
- {
3558
- _id: fixture._id,
3789
+ const fixtureData = {
3790
+ 'fixtureHeight': {
3791
+ 'value': 0,
3792
+ 'unit': 'mm',
3559
3793
  },
3560
- fixtureData );
3561
- }
3794
+ 'fixtureLength': {
3795
+ 'value': constantFixtureLength,
3796
+ 'unit': 'mm',
3797
+ },
3798
+ 'fixtureWidth': {
3799
+ 'value': constantFixtureWidth,
3800
+ 'unit': 'mm',
3801
+ },
3802
+ 'relativePosition': {
3803
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
3804
+ 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
3805
+ 'unit': 'ft',
3806
+ },
3807
+ 'detailedFixtureLength': {
3808
+ 'value': constantDetailedFixtureLength,
3809
+ 'unit': 'mm',
3810
+ },
3811
+ 'detailedFixtureWidth': {
3812
+ 'value': constantDetailedFixtureWidth,
3813
+ 'unit': 'mm',
3814
+ },
3815
+ 'relativeDetailedPosition': {
3816
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
3817
+ 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
3818
+ 'unit': 'ft',
3819
+ },
3820
+ };
3562
3821
 
3563
- for ( let index = 0; index < floorFixtures.length; index++ ) {
3564
- const fixture = floorFixtures[index];
3565
- const centerRow = Math.floor( totalRows / 2 );
3822
+ await storeFixtureService.updateOne(
3823
+ {
3824
+ _id: fixture._id,
3825
+ },
3826
+ fixtureData );
3827
+ }
3566
3828
 
3567
- const startingX =roundToTwo( ( ( finalXDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) ) );
3568
- const detailedStartingX = roundToTwo( ( ( finalXDetailedDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ) );
3829
+ for ( let index = 0; index < floorFixtures.length; index++ ) {
3830
+ const fixture = floorFixtures[index];
3831
+ const centerRow = Math.floor( totalRows / 2 );
3569
3832
 
3570
- const startingY = ( finalYDistance / 2 ) - ( centerRow * ( constantFixtureWidth / mmToFeet ) );
3571
- const detailedStartingY = ( finalYDetailedDistance / 2 ) - ( centerRow * ( constantDetailedFixtureWidth / mmToFeet ) );
3833
+ const startingX =roundToTwo( ( ( finalXDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) ) );
3834
+ const detailedStartingX = roundToTwo( ( ( finalXDetailedDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ) );
3572
3835
 
3573
- const colIndex = Math.floor( index / 2 );
3574
- const rowIndex = index % 2 === 0 ? 1 : 0;
3836
+ const startingY = ( finalYDistance / 2 ) - ( centerRow * ( constantFixtureWidth / mmToFeet ) );
3837
+ const detailedStartingY = ( finalYDetailedDistance / 2 ) - ( centerRow * ( constantDetailedFixtureWidth / mmToFeet ) );
3575
3838
 
3839
+ const colIndex = Math.floor( index / 2 );
3840
+ const rowIndex = index % 2 === 0 ? 1 : 0;
3576
3841
 
3577
- const xPos = roundToTwo( ( startingX + colIndex * ( constantFixtureLength / mmToFeet ) ) );
3578
- const yPos = roundToTwo( ( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) ) );
3579
3842
 
3580
- const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
3581
- const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
3843
+ const xPos = roundToTwo( ( startingX + colIndex * ( constantFixtureLength / mmToFeet ) ) );
3844
+ const yPos = roundToTwo( ( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) ) );
3582
3845
 
3846
+ const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
3847
+ const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
3583
3848
 
3584
- const fixtureData = {
3585
- 'fixtureHeight': {
3586
- 'value': 0,
3587
- 'unit': 'mm',
3588
- },
3589
- 'fixtureLength': {
3590
- 'value': constantFixtureLength,
3591
- 'unit': 'mm',
3592
- },
3593
- 'fixtureWidth': {
3594
- 'value': constantFixtureWidth,
3595
- 'unit': 'mm',
3596
- },
3597
- 'relativePosition': {
3598
- 'x': xPos,
3599
- 'y': yPos,
3600
- 'unit': 'ft',
3601
- },
3602
- 'detailedFixtureLength': {
3603
- 'value': constantDetailedFixtureLength,
3604
- 'unit': 'mm',
3605
- },
3606
- 'detailedFixtureWidth': {
3607
- 'value': constantDetailedFixtureWidth,
3608
- 'unit': 'mm',
3609
- },
3610
- 'relativeDetailedPosition': {
3611
- 'x': detailedXPos,
3612
- 'y': detailedYPos,
3613
- 'unit': 'ft',
3614
- },
3615
- };
3616
3849
 
3617
- await storeFixtureService.updateOne(
3618
- {
3619
- _id: fixture._id,
3850
+ const fixtureData = {
3851
+ 'fixtureHeight': {
3852
+ 'value': 0,
3853
+ 'unit': 'mm',
3620
3854
  },
3621
- fixtureData );
3855
+ 'fixtureLength': {
3856
+ 'value': constantFixtureLength,
3857
+ 'unit': 'mm',
3858
+ },
3859
+ 'fixtureWidth': {
3860
+ 'value': constantFixtureWidth,
3861
+ 'unit': 'mm',
3862
+ },
3863
+ 'relativePosition': {
3864
+ 'x': xPos,
3865
+ 'y': yPos,
3866
+ 'unit': 'ft',
3867
+ },
3868
+ 'detailedFixtureLength': {
3869
+ 'value': constantDetailedFixtureLength,
3870
+ 'unit': 'mm',
3871
+ },
3872
+ 'detailedFixtureWidth': {
3873
+ 'value': constantDetailedFixtureWidth,
3874
+ 'unit': 'mm',
3875
+ },
3876
+ 'relativeDetailedPosition': {
3877
+ 'x': detailedXPos,
3878
+ 'y': detailedYPos,
3879
+ 'unit': 'ft',
3880
+ },
3881
+ };
3882
+
3883
+ await storeFixtureService.updateOne(
3884
+ {
3885
+ _id: fixture._id,
3886
+ },
3887
+ fixtureData );
3888
+ }
3622
3889
  }
3623
3890
  } catch ( e ) {
3891
+ console.log( e );
3624
3892
  logger.error( { functionName: 'createCrestPlanogram', error: e } );
3625
- return res.sendError( e.message || 'Internal Server Error', 500 );
3893
+ return false;
3626
3894
  }
3627
3895
  }
3628
3896
 
3629
3897
  export async function updatelayout( req, res ) {
3630
3898
  try {
3631
- let getLayoutTaskDetails = await planoTaskService.find( { date_string: dayjs().format( 'YYYY-MM-DD' ), status: 'incomplete', type: 'layout' } );
3899
+ let getLayoutTaskDetails = await planoTaskService.find( { date_string: { $gte: req.body.date }, status: 'incomplete', type: 'layout' } );
3632
3900
  if ( !getLayoutTaskDetails.length ) {
3633
3901
  return res.sendError( 'No data found', 204 );
3634
3902
  }
@@ -3655,6 +3923,11 @@ export async function updatelayout( req, res ) {
3655
3923
  return acc;
3656
3924
  }, {} );
3657
3925
  Object.entries( elementsGroup ).forEach( async ( [ key, values ] ) => {
3926
+ let removeFixtures = layoutAnswer.wronglyLocatedFixtures.filter( ( rmFx ) => {
3927
+ if ( rmFx.fixtureElement == key && rmFx.location != key ) {
3928
+ return rmFx;
3929
+ }
3930
+ } ).map( ( fxtu ) => fxtu.fixtureId );
3658
3931
  let matchingFixtures = [];
3659
3932
  let maxFixtureNumber = 0;
3660
3933
  let elementType = '';
@@ -3675,6 +3948,7 @@ export async function updatelayout( req, res ) {
3675
3948
  }
3676
3949
  if ( matchingFixtures.length ) {
3677
3950
  matchingFixtures.sort( ( a, b ) => a.associatedElementFixtureNumber - b.associatedElementFixtureNumber );
3951
+ matchingFixtures = matchingFixtures.filter( ( fxt ) => !removeFixtures.includes( fxt._id.toString() ) );
3678
3952
  maxFixtureNumber = Math.max(
3679
3953
  ...matchingFixtures.map( ( f ) => f.associatedElementFixtureNumber ),
3680
3954
  );
@@ -3844,3 +4118,185 @@ export async function updatelayout( req, res ) {
3844
4118
  }
3845
4119
  }
3846
4120
 
4121
+
4122
+ export async function downloadPlanoImage( req, res ) {
4123
+ try {
4124
+ let query = [
4125
+ {
4126
+ $match: {
4127
+ date_string: { $gte: req.body.fromDate, $lte: req.body.toDate },
4128
+ type: 'layout',
4129
+ status: 'incomplete',
4130
+ },
4131
+ },
4132
+ {
4133
+ $lookup: {
4134
+ from: 'planograms',
4135
+ let: { plano_id: '$planoId' },
4136
+ pipeline: [
4137
+ {
4138
+ $match: {
4139
+ $expr: {
4140
+ $and: [
4141
+ { $eq: [ '$_id', '$$plano_id' ] },
4142
+ ],
4143
+ },
4144
+ },
4145
+ },
4146
+ {
4147
+ $project: {
4148
+ storeName: 1,
4149
+ _id: 0,
4150
+ },
4151
+ },
4152
+ ],
4153
+ as: 'planogram',
4154
+ },
4155
+ },
4156
+ { $unwind: { path: '$planogram', preserveNullAndEmptyArrays: true } },
4157
+ {
4158
+ $project: {
4159
+ storeName: '$planogram.storeName',
4160
+ answers: 1,
4161
+ type: 1,
4162
+ status: 1,
4163
+ planoId: 1,
4164
+ floorId: 1,
4165
+ },
4166
+ },
4167
+ ];
4168
+
4169
+ let taskDetails = await planoTaskService.aggregate( query );
4170
+ if ( !taskDetails.length ) {
4171
+ return res.sendError( 'No data found', 204 );
4172
+ }
4173
+ let planoList = taskDetails.map( ( ele ) => ele.planoId );
4174
+ let storeList = taskDetails.map( ( ele ) => ele.storeName );
4175
+ async function sleep( ms ) {
4176
+ return new Promise( ( resolve ) => setTimeout( resolve, ms ) );
4177
+ }
4178
+
4179
+ async function openPlanoUrls( planoList ) {
4180
+ for ( let id of planoList ) {
4181
+ const url = `http://localhost:8080/#/plano?planoId=${id}&token&url=http://localhost:3008`;
4182
+ const driver = await new Builder().forBrowser( 'chrome' ).build();
4183
+
4184
+ try {
4185
+ await driver.get( url );
4186
+ await sleep( 20000 );
4187
+ } catch ( err ) {
4188
+ console.error( `Error while opening planoId ${id}:`, err );
4189
+ } finally {
4190
+ try {
4191
+ if ( driver && await driver.getSession() ) {
4192
+ await driver.quit();
4193
+ }
4194
+ } catch ( quitErr ) {
4195
+ console.warn( `Error while quitting driver for planoId ${id}:`, quitErr );
4196
+ }
4197
+ }
4198
+ }
4199
+ }
4200
+ if ( !req.body?.merge ) {
4201
+ const downloadsPath = path.join( os.homedir(), 'Downloads' );
4202
+ const targetFolder = path.join( __dirname, '..', '..', `${req.body.file}Images` );
4203
+ await openPlanoUrls( planoList );
4204
+ if ( !fs.existsSync( targetFolder ) ) {
4205
+ fs.mkdirSync( targetFolder, { recursive: true } );
4206
+ console.log( 'Created folder:', targetFolder );
4207
+ }
4208
+ fs.readdir( downloadsPath, async ( err, files ) => {
4209
+ if ( err ) {
4210
+ return console.error( 'Failed to read Downloads folder:', err );
4211
+ }
4212
+ console.log( files );
4213
+ for ( let file of files ) {
4214
+ let fileName = file.split( '.' )[0];
4215
+ const sourcePath = path.join( downloadsPath, file );
4216
+ const targetPath = path.join( targetFolder, file );
4217
+ if ( storeList.includes( fileName ) ) {
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
+ }
4242
+ } else {
4243
+ console.warn( 'File not found in Downloads:', fileName );
4244
+ }
4245
+ }
4246
+ }
4247
+ } );
4248
+ }
4249
+
4250
+ if ( req.body?.merge ) {
4251
+ const targetFolder = path.join( __dirname, '..', '..', `mergedImages` );
4252
+ if ( !fs.existsSync( targetFolder ) ) {
4253
+ fs.mkdirSync( targetFolder, { recursive: true } );
4254
+ console.log( 'Created folder:', targetFolder );
4255
+ }
4256
+ for ( let store of storeList ) {
4257
+ if ( store != undefined ) {
4258
+ const image1 = path.join( __dirname, '..', '..', `oldImages/${store}.png` );
4259
+ const image2 = path.join( __dirname, '..', '..', `newImages/${store}.png` );
4260
+
4261
+ const output = path.join( __dirname, '..', '..', `mergedImages/${store}merged.png` );
4262
+
4263
+
4264
+ const [ img1, img2 ] = await Promise.all( [
4265
+ sharp( image1 ),
4266
+ sharp( image2 ),
4267
+ ] );
4268
+
4269
+ const [ meta1, meta2 ] = await Promise.all( [ img1.metadata(), img2.metadata() ] );
4270
+
4271
+ const canvasWidth = meta1.width + meta2.width;
4272
+ const canvasHeight = Math.max( meta1.height, meta2.height );
4273
+
4274
+ const [ img1Buffer, img2Buffer ] = await Promise.all( [
4275
+ img1.toBuffer(),
4276
+ img2.toBuffer(),
4277
+ ] );
4278
+
4279
+ await sharp( {
4280
+ create: {
4281
+ width: canvasWidth,
4282
+ height: canvasHeight,
4283
+ channels: 3,
4284
+ background: { r: 255, g: 255, b: 255 },
4285
+ },
4286
+ } )
4287
+ .composite( [
4288
+ { input: img1Buffer, top: 0, left: 0 },
4289
+ { input: img2Buffer, top: 0, left: meta1.width },
4290
+ ] )
4291
+ .toFile( output );
4292
+
4293
+ console.log( 'Images merged successfully!' );
4294
+ }
4295
+ }
4296
+ }
4297
+ return res.sendSuccess( 'Image Generated SuccessFully' );
4298
+ } catch ( e ) {
4299
+ console.log( e );
4300
+ return res.sendError( e, 500 );
4301
+ }
4302
+ }