tango-app-api-store-builder 1.0.0-beta-97 → 1.0.0-beta-99

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.
@@ -7,7 +7,6 @@ import * as planoService from '../service/planogram.service.js';
7
7
  import * as storeFixtureService from '../service/storeFixture.service.js';
8
8
  import * as fixtureShelfService from '../service/fixtureShelf.service.js';
9
9
  import * as planoProductService from '../service/planoProduct.service.js';
10
- import * as planoVmService from '../service/planoVm.service.js';
11
10
  import * as planoMappingService from '../service/planoMapping.service.js';
12
11
  import * as planoTaskService from '../service/planoTask.service.js';
13
12
  import * as processedTaskService from '../service/processedTaskservice.js';
@@ -15,12 +14,11 @@ import * as processedTaskService from '../service/processedTaskservice.js';
15
14
  // import * as planoTaskComplianceService from '../service/planoTask.service.js';
16
15
  // import * as planoQrConversionRequestService from '../service/planoQrConversionRequest.service.js';
17
16
  import * as fixtureConfigService from '../service/fixtureConfig.service.js';
18
- import * as fixtureLibraryService from '../service/planoLibrary.service.js';
19
17
  import mongoose from 'mongoose';
20
18
  import JSZip from 'jszip';
21
19
  import { signedUrl } from 'tango-app-api-middleware';
22
20
  import fs from 'fs';
23
- // import https from 'https';
21
+ import https from 'https';
24
22
  import os from 'os';
25
23
  import { fileURLToPath } from 'url';
26
24
  import path from 'path';
@@ -1137,7 +1135,7 @@ export async function updateFixturesShelves( req, res ) {
1137
1135
 
1138
1136
  const createdFixture = await storeFixtureService.findOneAndUpdate2( { storeName: layoutDoc.storeName, fixtureNumber: fixture?.['fixtureNumber'] }, { fixtureCode: fixture?.['Fixture ID'] } );
1139
1137
 
1140
- console.log( 'Fixture Data', fixtureData );
1138
+ // console.log( 'Fixture Data', fixtureData );
1141
1139
 
1142
1140
 
1143
1141
  const vms = typeof fixture?.['VM Template ID'] === 'string' ? fixture?.['VM Template ID']?.split( ', ' ).map( ( item ) => item.trim() ) : [];
@@ -1253,7 +1251,7 @@ export async function updateFixturesShelves( req, res ) {
1253
1251
 
1254
1252
  const createdFixture = await storeFixtureService.findOneAndUpdate2( { storeName: layoutDoc.storeName, fixtureNumber: fixture?.['fixtureNumber'] }, { fixtureCode: fixture?.['Fixture ID'] } );
1255
1253
 
1256
- console.log( 'Fixture Data', fixtureData );
1254
+ // console.log( 'Fixture Data', fixtureData );
1257
1255
 
1258
1256
  const vms = typeof fixture?.['VM Template ID'] === 'string' ? fixture?.['VM Template ID']?.split( ', ' ).map( ( item ) => item.trim() ) : [];
1259
1257
 
@@ -1302,7 +1300,7 @@ export async function updateFixturesShelves( req, res ) {
1302
1300
 
1303
1301
  const createdShelf = await fixtureShelfService.create( shelfData );
1304
1302
 
1305
- console.log( 'Shelf Data:', createdShelf );
1303
+ // console.log( 'Shelf Data:', createdShelf );
1306
1304
 
1307
1305
  shelfIndex++;
1308
1306
  }
@@ -1364,7 +1362,7 @@ export async function updateFixturesShelves( req, res ) {
1364
1362
 
1365
1363
  const createdFixture = await storeFixtureService.findOneAndUpdate2( { storeName: layoutDoc.storeName, fixtureNumber: fixture?.['fixtureNumber'] }, { fixtureCode: fixture?.['Fixture ID'] } );
1366
1364
 
1367
- console.log( 'Fixture Data', fixtureData );
1365
+ // console.log( 'Fixture Data', fixtureData );
1368
1366
 
1369
1367
  const vms = typeof fixture?.['VM Template ID'] === 'string' ? fixture?.['VM Template ID']?.split( ', ' ).map( ( item ) => item.trim() ) : [];
1370
1368
 
@@ -1489,7 +1487,7 @@ export async function updateFixturesShelves( req, res ) {
1489
1487
  };
1490
1488
 
1491
1489
  const createdFixture = await storeFixtureService.findOneAndUpdate2( { storeName: layoutDoc.storeName, fixtureNumber: fixture?.['fixtureNumber'] }, { fixtureCode: fixture?.['Fixture ID'] } );
1492
- console.log( 'Fixture Data', fixtureData );
1490
+ // console.log( 'Fixture Data', fixtureData );
1493
1491
 
1494
1492
  const vms = typeof fixture?.['VM Template ID'] === 'string' ? fixture?.['VM Template ID']?.split( ', ' ).map( ( item ) => item.trim() ) : [];
1495
1493
 
@@ -1702,7 +1700,6 @@ export async function updateInventory( req, res ) {
1702
1700
  console.log( updateData );
1703
1701
 
1704
1702
  const product = await planoProductService.create( updateData );
1705
- console.log( product );
1706
1703
  }
1707
1704
 
1708
1705
 
@@ -1827,7 +1824,6 @@ export async function updatelayoutFeedback( req, res ) {
1827
1824
  const layoutDoc = layoutFeedbacks[i].toObject();
1828
1825
 
1829
1826
  const [ q1, q2, q3 ] = layoutDoc.answers;
1830
- console.log( q3 );
1831
1827
 
1832
1828
  if ( q1.value === false ) {
1833
1829
  const floor = await storeBuilderService.findOne( { _id: layoutDoc.floorId } );
@@ -2140,7 +2136,6 @@ export async function updateFixtureFeedback( req, res ) {
2140
2136
  const vmTask = vmTaskList[j].toObject();
2141
2137
 
2142
2138
  const [ q1, q2 ] = vmTask.answers;
2143
- console.log( q2 );
2144
2139
 
2145
2140
  if ( q1.value ) continue;
2146
2141
 
@@ -2322,73 +2317,73 @@ export async function updateVmData( req, res ) {
2322
2317
  }
2323
2318
 
2324
2319
 
2325
- // async function scrapeCrest() {
2326
- // const storeIds = [ 'LKST682' ];
2327
- // const apiUrl = 'https://api.getcrest.ai/api/ms_shelfsensei/layout/';
2328
- // const bearerToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ4ODUwMzMyLCJpYXQiOjE3NDg4NDY3MzIsImp0aSI6ImNkNmRmNWZhYTg4ZDRmMjQ4YmZkYzFkMzkzZWYzMTg5IiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.8fclGcH6koHsKVmtGAQLscS80yNaVqPRkcpLhI3cnsk';
2329
- // const filePath = 'response.json';
2330
- // let allResults = [];
2331
-
2332
- // if ( fs.existsSync( filePath ) ) {
2333
- // try {
2334
- // const existingData = fs.readFileSync( filePath, 'utf8' );
2335
- // allResults = JSON.parse( existingData );
2336
- // if ( !Array.isArray( allResults ) ) {
2337
- // allResults = [];
2338
- // }
2339
- // } catch ( error ) {
2340
- // console.error( 'Error reading existing JSON file:', error.message );
2341
- // allResults = [];
2342
- // }
2343
- // }
2344
-
2345
- // for ( const storeId of storeIds ) {
2346
- // try {
2347
- // const result = await new Promise( ( resolve ) => {
2348
- // const payload = JSON.stringify( { store_id: storeId } );
2349
- // const options = {
2350
- // method: 'POST',
2351
- // headers: {
2352
- // 'Authorization': `Bearer ${bearerToken}`,
2353
- // 'Content-Type': 'application/json',
2354
- // 'Content-Length': Buffer.byteLength( payload ),
2355
- // },
2356
- // };
2357
-
2358
- // const req = https.request( apiUrl, options, ( res ) => {
2359
- // let data = '';
2360
- // res.on( 'data', ( chunk ) => {
2361
- // data += chunk;
2362
- // } );
2363
- // res.on( 'end', () => {
2364
- // try {
2365
- // const jsonData = JSON.parse( data );
2366
- // const result = { storeName: storeId, data: jsonData };
2367
- // allResults.push( result );
2368
- // fs.writeFileSync( filePath, JSON.stringify( allResults, null, 2 ) );
2369
- // console.log( 'Received Data:', result );
2370
- // resolve( result );
2371
- // } catch ( error ) {
2372
- // console.error( `Error parsing JSON for ${storeId}:`, error.message );
2373
- // resolve( { storeName: storeId, data: null } );
2374
- // }
2375
- // } );
2376
- // } );
2377
-
2378
- // req.on( 'error', ( error ) => {
2379
- // console.error( `Error fetching data for ${storeId}:`, error.message );
2380
- // resolve( { storeName: storeId, data: null } );
2381
- // } );
2382
-
2383
- // req.write( payload );
2384
- // req.end();
2385
- // } );
2386
- // } catch ( error ) {
2387
- // console.error( `Unexpected error for ${storeId}:`, error.message );
2388
- // }
2389
- // await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
2390
- // }
2391
- // }
2320
+ async function scrapeCrest() {
2321
+ const storeIds = [ 'LKST2566' ];
2322
+ const apiUrl = 'https://api.getcrest.ai/api/ms_shelfsensei/layout/';
2323
+ const bearerToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ5MDIyMjc4LCJpYXQiOjE3NDkwMTg2NzgsImp0aSI6ImYwZjY3OGU2NDliZTRhZGU4ZTY4MGNhMGM3YmUxOWJhIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.eqMyUVVB4lvBLy_YXbPBLE8fbGTvTjGkrVw9Hi0HJMI';
2324
+ const filePath = 'response.json';
2325
+ let allResults = [];
2326
+
2327
+ if ( fs.existsSync( filePath ) ) {
2328
+ try {
2329
+ const existingData = fs.readFileSync( filePath, 'utf8' );
2330
+ allResults = JSON.parse( existingData );
2331
+ if ( !Array.isArray( allResults ) ) {
2332
+ allResults = [];
2333
+ }
2334
+ } catch ( error ) {
2335
+ console.error( 'Error reading existing JSON file:', error.message );
2336
+ allResults = [];
2337
+ }
2338
+ }
2339
+
2340
+ for ( const storeId of storeIds ) {
2341
+ try {
2342
+ const result = await new Promise( ( resolve ) => {
2343
+ const payload = JSON.stringify( { store_id: storeId } );
2344
+ const options = {
2345
+ method: 'POST',
2346
+ headers: {
2347
+ 'Authorization': `Bearer ${bearerToken}`,
2348
+ 'Content-Type': 'application/json',
2349
+ 'Content-Length': Buffer.byteLength( payload ),
2350
+ },
2351
+ };
2352
+
2353
+ const req = https.request( apiUrl, options, ( res ) => {
2354
+ let data = '';
2355
+ res.on( 'data', ( chunk ) => {
2356
+ data += chunk;
2357
+ } );
2358
+ res.on( 'end', () => {
2359
+ try {
2360
+ const jsonData = JSON.parse( data );
2361
+ const result = { storeName: storeId, data: jsonData };
2362
+ allResults.push( result );
2363
+ fs.writeFileSync( filePath, JSON.stringify( allResults, null, 2 ) );
2364
+ console.log( 'Received Data:', result );
2365
+ resolve( result );
2366
+ } catch ( error ) {
2367
+ console.error( `Error parsing JSON for ${storeId}:`, error.message );
2368
+ resolve( { storeName: storeId, data: null } );
2369
+ }
2370
+ } );
2371
+ } );
2372
+
2373
+ req.on( 'error', ( error ) => {
2374
+ console.error( `Error fetching data for ${storeId}:`, error.message );
2375
+ resolve( { storeName: storeId, data: null } );
2376
+ } );
2377
+
2378
+ req.write( payload );
2379
+ req.end();
2380
+ } );
2381
+ } catch ( error ) {
2382
+ console.error( `Unexpected error for ${storeId}:`, error.message );
2383
+ }
2384
+ await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
2385
+ }
2386
+ }
2392
2387
 
2393
2388
  // scrapeCrest()
2394
2389
 
@@ -3324,248 +3319,246 @@ export async function updateCrestVms( req, res ) {
3324
3319
  }
3325
3320
 
3326
3321
 
3327
- // async function filterStores() {
3328
- // const stores = [
3329
- // 'ST338', 'LKST1304', 'ST303', 'LKST1228', 'LKST499', 'LKST479', 'ST320',
3330
- // 'LKST515', 'LKST406', 'ST392', 'ST328', 'ST332', 'LKST487', 'ST312',
3331
- // 'LKST615', 'LKST352', 'LKST457', 'LKST439', 'LKST347', 'LKST1084',
3332
- // 'LKST380', 'ST298', 'LKST356', 'LKST223', 'LKST480', 'ST30', 'ST285',
3333
- // 'LKST500', 'LKST466', 'LKST321', 'LKST678', 'LKST383', 'LKST365',
3334
- // 'LKST374', 'ST302', 'LKST420', 'LKST394', 'LKST444', 'LKST314',
3335
- // 'LKST01', 'LKST357', 'LKST465', 'LKST331', 'LKST440', 'LKST345',
3336
- // 'LKST389', 'ST330', 'LKST299', 'ST244', 'LKST294', 'ST314', 'LKST361',
3337
- // 'LKST377', 'LKST390', 'ST335', 'LKST416', 'ST293', 'LKST341', 'LKST501',
3338
- // 'LKST408', 'LKST227', 'LKST353', 'LKST364', 'ST318', 'LKST326',
3339
- // 'LKST344', 'ST321', 'LKST384', 'LKST496', 'LKST427', 'LKST325',
3340
- // 'LKST282', 'ST197', 'LKST388', 'LKST338', 'LKST371', 'ST326', 'LKST428',
3341
- // 'LKST112', 'LKST334', 'ST319', 'LKST464', 'LKST490', 'LKST11',
3342
- // 'LKST502', 'LKST1438',
3343
- // ];
3322
+ async function filterStores() {
3323
+ const stores = [
3324
+ 'ST338', 'LKST1304', 'ST303', 'LKST1228', 'LKST499', 'LKST479', 'ST320',
3325
+ 'LKST515', 'LKST406', 'ST392', 'ST328', 'ST332', 'LKST487', 'ST312',
3326
+ 'LKST615', 'LKST352', 'LKST457', 'LKST439', 'LKST347', 'LKST1084',
3327
+ 'LKST380', 'ST298', 'LKST356', 'LKST223', 'LKST480', 'ST30', 'ST285',
3328
+ 'LKST500', 'LKST466', 'LKST321', 'LKST678', 'LKST383', 'LKST365',
3329
+ 'LKST374', 'ST302', 'LKST420', 'LKST394', 'LKST444', 'LKST314',
3330
+ 'LKST01', 'LKST357', 'LKST465', 'LKST331', 'LKST440', 'LKST345',
3331
+ 'LKST389', 'ST330', 'LKST299', 'ST244', 'LKST294', 'ST314', 'LKST361',
3332
+ 'LKST377', 'LKST390', 'ST335', 'LKST416', 'ST293', 'LKST341', 'LKST501',
3333
+ 'LKST408', 'LKST227', 'LKST353', 'LKST364', 'ST318', 'LKST326',
3334
+ 'LKST344', 'ST321', 'LKST384', 'LKST496', 'LKST427', 'LKST325',
3335
+ 'LKST282', 'ST197', 'LKST388', 'LKST338', 'LKST371', 'ST326', 'LKST428',
3336
+ 'LKST112', 'LKST334', 'ST319', 'LKST464', 'LKST490', 'LKST11',
3337
+ 'LKST502', 'LKST1438',
3338
+ ];
3339
+
3340
+ const rawData = fs.readFileSync( 'crest_scrap_v1.json', 'utf8' );
3341
+ const allStores = JSON.parse( rawData );
3342
+
3343
+ const filteredStores = allStores.filter( ( store ) => stores.includes( store.storeName ) );
3344
+
3345
+ fs.writeFileSync( 'crest_filtered.json', JSON.stringify( filteredStores, null, 2 ) );
3346
+ }
3347
+
3348
+ import fsp from 'fs/promises';
3349
+
3350
+ import sharp from 'sharp';
3344
3351
 
3345
- // const rawData = fs.readFileSync( 'crest_scrap_v1.json', 'utf8' );
3346
- // const allStores = JSON.parse( rawData );
3347
3352
 
3348
- // const filteredStores = allStores.filter( ( store ) => stores.includes( store.storeName ) );
3353
+ const stitchImagesFromZips = async () => {
3354
+ const zip1Path = 'crest_plano.zip';
3355
+ const zip2Path = 'tango_plano.zip';
3356
+ const outputDir = 'stitched';
3349
3357
 
3350
- // fs.writeFileSync( 'crest_filtered.json', JSON.stringify( filteredStores, null, 2 ) );
3351
- // }
3358
+ const loadZip = async ( zipPath ) => {
3359
+ const buffer = await fsp.readFile( zipPath );
3360
+ return await JSZip.loadAsync( buffer );
3361
+ };
3352
3362
 
3353
- // import fsp from 'fs/promises';
3363
+ const extractImages = async ( zip ) => {
3364
+ const imageFiles = {};
3365
+ const imageRegex = /\.(png|jpe?g)$/i;
3354
3366
 
3355
- import sharp from 'sharp';
3367
+ for ( const [ name, file ] of Object.entries( zip.files ) ) {
3368
+ const base = path.basename( name );
3369
+ if ( !file.dir && imageRegex.test( base ) ) {
3370
+ imageFiles[base] = await file.async( 'nodebuffer' );
3371
+ }
3372
+ }
3373
+
3374
+ return imageFiles;
3375
+ };
3376
+
3377
+ const stitchOrCenter = async ( buffer1, buffer2, outputPath ) => {
3378
+ const totalWidth = 7000;
3379
+ const width1 = Math.round( totalWidth * 0.3 );
3380
+ const width2 = Math.round( totalWidth * 0.7 );
3381
+
3382
+ let img1 = buffer1 ? await sharp( buffer1 ).resize( { width: width1 } ).toBuffer() : null;
3383
+ let img2 = buffer2 ? await sharp( buffer2 ).resize( { width: width2 } ).toBuffer() : null;
3384
+
3385
+ const [ meta1, meta2 ] = await Promise.all( [
3386
+ img1 ? sharp( img1 ).metadata() : Promise.resolve( { height: 0 } ),
3387
+ img2 ? sharp( img2 ).metadata() : Promise.resolve( { height: 0 } ),
3388
+ ] );
3389
+
3390
+ const maxHeight = Math.max( meta1.height, meta2.height );
3391
+
3392
+ const composites = [];
3393
+ if ( img1 ) composites.push( { input: img1, top: 0, left: 0 } );
3394
+ if ( img2 ) composites.push( { input: img2, top: 0, left: width1 } );
3395
+
3396
+ await sharp( {
3397
+ create: {
3398
+ width: totalWidth,
3399
+ height: maxHeight,
3400
+ channels: 4,
3401
+ background: { r: 255, g: 255, b: 255, alpha: 0 },
3402
+ },
3403
+ } )
3404
+ .composite( composites )
3405
+ .png()
3406
+ .toFile( outputPath );
3407
+ };
3408
+
3409
+ try {
3410
+ await fsp.mkdir( outputDir, { recursive: true } );
3411
+
3412
+ const [ zip1, zip2 ] = await Promise.all( [ loadZip( zip1Path ), loadZip( zip2Path ) ] );
3413
+ const [ images1, images2 ] = await Promise.all( [ extractImages( zip1 ), extractImages( zip2 ) ] );
3356
3414
 
3415
+ const allFilenames = new Set( [ ...Object.keys( images1 ), ...Object.keys( images2 ) ] );
3357
3416
 
3358
- // const stitchImagesFromZips = async () => {
3359
- // const zip1Path = 'crest_plano.zip';
3360
- // const zip2Path = 'tango_plano.zip';
3361
- // const outputDir = 'stitched';
3362
-
3363
- // const loadZip = async ( zipPath ) => {
3364
- // const buffer = await fsp.readFile( zipPath );
3365
- // return await JSZip.loadAsync( buffer );
3366
- // };
3367
-
3368
- // const extractImages = async ( zip ) => {
3369
- // const imageFiles = {};
3370
- // const imageRegex = /\.(png|jpe?g)$/i;
3371
-
3372
- // for ( const [ name, file ] of Object.entries( zip.files ) ) {
3373
- // const base = path.basename( name );
3374
- // if ( !file.dir && imageRegex.test( base ) ) {
3375
- // imageFiles[base] = await file.async( 'nodebuffer' );
3376
- // }
3377
- // }
3378
-
3379
- // return imageFiles;
3380
- // };
3381
-
3382
- // const stitchOrCenter = async ( buffer1, buffer2, outputPath ) => {
3383
- // const totalWidth = 7000;
3384
- // const width1 = Math.round( totalWidth * 0.3 );
3385
- // const width2 = Math.round( totalWidth * 0.7 );
3386
-
3387
- // let img1 = buffer1 ? await sharp( buffer1 ).resize( { width: width1 } ).toBuffer() : null;
3388
- // let img2 = buffer2 ? await sharp( buffer2 ).resize( { width: width2 } ).toBuffer() : null;
3389
-
3390
- // const [ meta1, meta2 ] = await Promise.all( [
3391
- // img1 ? sharp( img1 ).metadata() : Promise.resolve( { height: 0 } ),
3392
- // img2 ? sharp( img2 ).metadata() : Promise.resolve( { height: 0 } ),
3393
- // ] );
3394
-
3395
- // const maxHeight = Math.max( meta1.height, meta2.height );
3396
-
3397
- // const composites = [];
3398
- // if ( img1 ) composites.push( { input: img1, top: 0, left: 0 } );
3399
- // if ( img2 ) composites.push( { input: img2, top: 0, left: width1 } );
3400
-
3401
- // await sharp( {
3402
- // create: {
3403
- // width: totalWidth,
3404
- // height: maxHeight,
3405
- // channels: 4,
3406
- // background: { r: 255, g: 255, b: 255, alpha: 0 },
3407
- // },
3408
- // } )
3409
- // .composite( composites )
3410
- // .png()
3411
- // .toFile( outputPath );
3412
- // };
3413
-
3414
- // try {
3415
- // await fsp.mkdir( outputDir, { recursive: true } );
3416
-
3417
- // const [ zip1, zip2 ] = await Promise.all( [ loadZip( zip1Path ), loadZip( zip2Path ) ] );
3418
- // const [ images1, images2 ] = await Promise.all( [ extractImages( zip1 ), extractImages( zip2 ) ] );
3419
-
3420
- // const allFilenames = new Set( [ ...Object.keys( images1 ), ...Object.keys( images2 ) ] );
3421
-
3422
- // for ( const name of allFilenames ) {
3423
- // const buffer1 = images1[name] || null;
3424
- // const buffer2 = images2[name] || null;
3425
- // const outputPath = path.join( outputDir, `${name.replace( /\.[^/.]+$/, '' )}.png` );
3426
-
3427
- // try {
3428
- // await stitchOrCenter( buffer1, buffer2, outputPath );
3429
- // console.log( ` Processed: ${name}` );
3430
- // } catch ( err ) {
3431
- // console.error( ` Error processing ${name}:`, err.message );
3432
- // }
3433
- // }
3434
- // } catch ( err ) {
3435
- // console.error( ' Unexpected error:', err.message );
3436
- // }
3437
- // };
3417
+ for ( const name of allFilenames ) {
3418
+ const buffer1 = images1[name] || null;
3419
+ const buffer2 = images2[name] || null;
3420
+ const outputPath = path.join( outputDir, `${name.replace( /\.[^/.]+$/, '' )}.png` );
3421
+
3422
+ try {
3423
+ await stitchOrCenter( buffer1, buffer2, outputPath );
3424
+ console.log( ` Processed: ${name}` );
3425
+ } catch ( err ) {
3426
+ console.error( ` Error processing ${name}:`, err.message );
3427
+ }
3428
+ }
3429
+ } catch ( err ) {
3430
+ console.error( ' Unexpected error:', err.message );
3431
+ }
3432
+ };
3438
3433
 
3439
3434
  // stitchImagesFromZips();
3440
3435
 
3441
3436
 
3442
- import { Builder } from 'selenium-webdriver';
3443
- // import chrome from 'selenium-webdriver/chrome.js';
3437
+ import { Builder, By, until } from 'selenium-webdriver';
3438
+ import chrome from 'selenium-webdriver/chrome.js';
3444
3439
  import fetch from 'node-fetch';
3445
3440
 
3446
3441
  import fetchCookie from 'fetch-cookie';
3447
3442
 
3448
3443
 
3449
- // async function downloadCrestImages() {
3450
- // const storeList = await planoService.find( {} );
3451
- // // const storeIds = storeList.map( ( store ) => store.toObject().storeName );
3452
- // const storeIds = [ 'LKST1304' ];
3453
-
3454
-
3455
- // const invalidateUrl = 'https://app.getcrest.ai/api/ms_iam/user/session/override/';
3456
- // const tokenUrl = 'https://app.getcrest.ai/api/ms_iam/token/';
3457
-
3458
- // let authToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ3NTEwNDAxLCJpYXQiOjE3NDc1MDY4MDEsImp0aSI6IjQ0YzNjOWNkZjUzYjQ5ZWE5OGQ3NWQxOTI1NGMxMGRkIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.5OYkUq4kIWDUXothNCCfk6GIQHlhiMdOuHzuczWt6QM';
3459
-
3460
- // const fetchWithCookies = fetchCookie( fetch );
3461
-
3462
- // async function fetchNewToken() {
3463
- // const invalidate = await fetchWithCookies( invalidateUrl, {
3464
- // 'method': 'POST',
3465
- // 'headers': { 'Content-Type': 'application/json' },
3466
- // 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3467
- // } );
3468
-
3469
- // const invalidateData = await invalidate.json();
3470
-
3471
- // console.log( invalidateData );
3472
-
3473
- // console.log( 'Fetching new token...' );
3474
- // const res = await fetchWithCookies( tokenUrl, {
3475
- // 'method': 'POST',
3476
- // 'Accept': 'application/json, text/javascript, */*; q=0.01',
3477
- // 'headers': { 'Content-Type': 'application/json' },
3478
- // 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3479
- // } );
3480
-
3481
- // if ( !res.ok ) {
3482
- // throw new Error( `Failed to fetch token: ${res.status}` );
3483
- // }
3484
-
3485
- // const data = await res.json();
3486
- // console.log( data );
3487
- // authToken = data.access;
3488
- // return authToken;
3489
- // }
3490
-
3491
- // async function runAutomation( token, storeId, retries = 3 ) {
3492
- // let attempts = 0;
3493
-
3494
- // while ( attempts < retries ) {
3495
- // const options = new chrome.Options();
3496
- // // options.addArguments( 'headless' );
3497
- // options.addArguments( 'disable-gpu' );
3498
-
3499
- // const driver = await new Builder()
3500
- // .forBrowser( 'chrome' )
3501
- // .setChromeOptions( options )
3502
- // .build();
3503
-
3504
- // try {
3505
- // const url = `https://app.getcrest.ai/pvt/?auth=${token}&module=planno&store_id=${storeId}`;
3506
- // await driver.get( url );
3507
- // const currentUrl = await driver.getCurrentUrl();
3508
- // if ( currentUrl.includes( '/login' ) ) {
3509
- // console.warn( `Redirected to login for store ${storeId}. Retrying with new token...` );
3510
- // await driver.quit();
3511
- // const newToken = await fetchNewToken();
3512
- // return await runAutomation( newToken, storeId, retries );
3513
- // }
3514
-
3515
- // const button = await driver.wait( until.elementLocated(
3516
- // 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")]' ),
3517
- // ), 10000 );
3518
- // await button.click();
3519
-
3520
- // const checkbox = await driver.wait(
3521
- // until.elementLocated(
3522
- // By.xpath( '//*[contains(@class, "MuiCheckbox-root") and contains(@class, "MuiIconButton-root")]//input[@type="checkbox"]' ),
3523
- // ),
3524
- // 10000,
3525
- // );
3526
- // await checkbox.click();
3527
-
3528
- // const downloadIcon = await driver.wait(
3529
- // until.elementLocated(
3530
- // By.xpath( '//button[contains(@class, "cool-tooltip")]' ),
3531
- // ),
3532
- // 10000,
3533
- // );
3534
- // await downloadIcon.click();
3535
-
3536
-
3537
- // console.log( `Download triggered for store: ${storeId}` );
3538
- // await driver.sleep( 5000 );
3539
- // return;
3540
- // } catch ( err ) {
3541
- // attempts++;
3542
- // console.error( `Error for store ${storeId}, attempt ${attempts}: ${err.message}` );
3543
- // if ( attempts >= retries ) {
3544
- // console.error( `Failed for store ${storeId} after ${retries} attempts` );
3545
- // } else {
3546
- // console.log( `Retrying for store ${storeId}, attempt ${attempts + 1}` );
3547
- // }
3548
- // } finally {
3549
- // try {
3550
- // if ( driver && ( await driver.getSession() ) ) {
3551
- // await driver.quit();
3552
- // }
3553
- // } catch ( e ) {
3554
-
3555
- // }
3556
- // }
3557
- // }
3558
- // }
3559
-
3560
- // for ( const storeId of storeIds ) {
3561
- // try {
3562
- // console.log( `Starting automation for store: ${storeId}` );
3563
- // await runAutomation( authToken, storeId );
3564
- // } catch ( error ) {
3565
- // console.error( `Automation failed for store ${storeId}: ${error.message}` );
3566
- // }
3567
- // }
3568
- // }
3444
+ async function downloadCrestImages() {
3445
+ const storeList = await planoService.find( {} );
3446
+ const storeIds = storeList.map( ( store ) => store.toObject().storeName );
3447
+
3448
+ const invalidateUrl = 'https://app.getcrest.ai/api/ms_iam/user/session/override/';
3449
+ const tokenUrl = 'https://app.getcrest.ai/api/ms_iam/token/';
3450
+
3451
+ let authToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ0NzE4MjUzLCJpYXQiOjE3NDQ3MTQ2NTMsImp0aSI6Ijk5ZTAyYjU4ODg2NjQ3MDk4Y2NlY2NmODZlYzYzYTU4IiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.7g1XS48l7mVsOcDXHLC7VFLFyJ-p13e2kkJlb8uFc_g';
3452
+
3453
+ const fetchWithCookies = fetchCookie( fetch );
3454
+
3455
+ async function fetchNewToken() {
3456
+ const invalidate = await fetchWithCookies( invalidateUrl, {
3457
+ 'method': 'POST',
3458
+ 'headers': { 'Content-Type': 'application/json' },
3459
+ 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3460
+ } );
3461
+
3462
+ const invalidateData = await invalidate.json();
3463
+
3464
+ console.log( invalidateData );
3465
+
3466
+ console.log( 'Fetching new token...' );
3467
+ const res = await fetchWithCookies( tokenUrl, {
3468
+ 'method': 'POST',
3469
+ 'Accept': 'application/json, text/javascript, */*; q=0.01',
3470
+ 'headers': { 'Content-Type': 'application/json' },
3471
+ 'body': JSON.stringify( { 'email': 'tango.lenskart@getcrest.ai', 'password': 'Tangolenskart@123' } ),
3472
+ } );
3473
+
3474
+ if ( !res.ok ) {
3475
+ throw new Error( `Failed to fetch token: ${res.status}` );
3476
+ }
3477
+
3478
+ const data = await res.json();
3479
+ console.log( data );
3480
+ authToken = data.access;
3481
+ return authToken;
3482
+ }
3483
+
3484
+ async function runAutomation( token, storeId, retries = 3 ) {
3485
+ let attempts = 0;
3486
+
3487
+ while ( attempts < retries ) {
3488
+ const options = new chrome.Options();
3489
+ options.addArguments( 'headless' );
3490
+ options.addArguments( 'disable-gpu' );
3491
+
3492
+ const driver = await new Builder()
3493
+ .forBrowser( 'chrome' )
3494
+ .setChromeOptions( options )
3495
+ .build();
3496
+
3497
+ try {
3498
+ const url = `https://app.getcrest.ai/pvt/?auth=${token}&module=planno&store_id=${storeId}`;
3499
+ await driver.get( url );
3500
+ const currentUrl = await driver.getCurrentUrl();
3501
+ if ( currentUrl.includes( '/login' ) ) {
3502
+ console.warn( `Redirected to login for store ${storeId}. Retrying with new token...` );
3503
+ await driver.quit();
3504
+ const newToken = await fetchNewToken();
3505
+ return await runAutomation( newToken, storeId, retries );
3506
+ }
3507
+
3508
+ const button = await driver.wait( until.elementLocated(
3509
+ 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")]' ),
3510
+ ), 10000 );
3511
+ await button.click();
3512
+
3513
+ const checkbox = await driver.wait(
3514
+ until.elementLocated(
3515
+ By.xpath( '//*[contains(@class, "MuiCheckbox-root") and contains(@class, "MuiIconButton-root")]//input[@type="checkbox"]' ),
3516
+ ),
3517
+ 10000,
3518
+ );
3519
+ await checkbox.click();
3520
+
3521
+ const downloadIcon = await driver.wait(
3522
+ until.elementLocated(
3523
+ By.xpath( '//button[contains(@class, "cool-tooltip")]' ),
3524
+ ),
3525
+ 10000,
3526
+ );
3527
+ await downloadIcon.click();
3528
+
3529
+
3530
+ console.log( `Download triggered for store: ${storeId}` );
3531
+ await driver.sleep( 5000 );
3532
+ return;
3533
+ } catch ( err ) {
3534
+ attempts++;
3535
+ console.error( `Error for store ${storeId}, attempt ${attempts}: ${err.message}` );
3536
+ if ( attempts >= retries ) {
3537
+ console.error( `Failed for store ${storeId} after ${retries} attempts` );
3538
+ } else {
3539
+ console.log( `Retrying for store ${storeId}, attempt ${attempts + 1}` );
3540
+ }
3541
+ } finally {
3542
+ try {
3543
+ if ( driver && ( await driver.getSession() ) ) {
3544
+ await driver.quit();
3545
+ }
3546
+ } catch ( e ) {
3547
+
3548
+ }
3549
+ }
3550
+ }
3551
+ }
3552
+
3553
+ for ( const storeId of storeIds ) {
3554
+ try {
3555
+ console.log( `Starting automation for store: ${storeId}` );
3556
+ await runAutomation( authToken, storeId );
3557
+ } catch ( error ) {
3558
+ console.error( `Automation failed for store ${storeId}: ${error.message}` );
3559
+ }
3560
+ }
3561
+ }
3569
3562
 
3570
3563
  // downloadCrestImages();
3571
3564
  export async function updatePlanoFixtureLayout( planoId, floorId ) {
@@ -4140,12 +4133,36 @@ export async function downloadPlanoImage( req, res ) {
4140
4133
  date_string: { $gte: req.body.fromDate, $lte: req.body.toDate },
4141
4134
  type: 'layout',
4142
4135
  status: 'incomplete',
4143
- storeName: { $in: req.body.store },
4144
4136
  },
4145
4137
  },
4138
+ {
4139
+ $lookup: {
4140
+ from: 'planograms',
4141
+ let: { plano_id: '$planoId' },
4142
+ pipeline: [
4143
+ {
4144
+ $match: {
4145
+ $expr: {
4146
+ $and: [
4147
+ { $eq: [ '$_id', '$$plano_id' ] },
4148
+ ],
4149
+ },
4150
+ },
4151
+ },
4152
+ {
4153
+ $project: {
4154
+ storeName: 1,
4155
+ _id: 0,
4156
+ },
4157
+ },
4158
+ ],
4159
+ as: 'planogram',
4160
+ },
4161
+ },
4162
+ { $unwind: { path: '$planogram', preserveNullAndEmptyArrays: true } },
4146
4163
  {
4147
4164
  $project: {
4148
- storeName: 1,
4165
+ storeName: '$planogram.storeName',
4149
4166
  answers: 1,
4150
4167
  type: 1,
4151
4168
  status: 1,
@@ -4159,18 +4176,17 @@ export async function downloadPlanoImage( req, res ) {
4159
4176
  if ( !taskDetails.length ) {
4160
4177
  return res.sendError( 'No data found', 204 );
4161
4178
  }
4162
- let planoList = [ ...new Set( taskDetails.map( ( ele ) => ele.planoId ) ) ];
4163
- console.log( planoList );
4164
- let storeList = [ ...new Set( taskDetails.map( ( ele ) => ele.storeName ) ) ];
4165
- console.log( storeList );
4179
+ let planoList = taskDetails.map( ( ele ) => ele.planoId );
4180
+ let storeList = taskDetails.map( ( ele ) => ele.storeName );
4166
4181
  async function sleep( ms ) {
4167
4182
  return new Promise( ( resolve ) => setTimeout( resolve, ms ) );
4168
4183
  }
4169
4184
 
4170
4185
  async function openPlanoUrls( planoList ) {
4171
4186
  for ( let id of planoList ) {
4172
- const url = `https://plano-builder.tangoeye.ai/#/plano?planoId=${id}&token&download=1&url=http://localhost:3008`;
4187
+ const url = `http://localhost:8080/#/plano?planoId=${id}&token&url=http://localhost:3008`;
4173
4188
  const driver = await new Builder().forBrowser( 'chrome' ).build();
4189
+
4174
4190
  try {
4175
4191
  await driver.get( url );
4176
4192
  await sleep( 20000 );
@@ -4190,7 +4206,6 @@ export async function downloadPlanoImage( req, res ) {
4190
4206
  if ( !req.body?.merge ) {
4191
4207
  const downloadsPath = path.join( os.homedir(), 'Downloads' );
4192
4208
  const targetFolder = path.join( __dirname, '..', '..', `${req.body.file}Images` );
4193
- console.log( 'test' );
4194
4209
  await openPlanoUrls( planoList );
4195
4210
  if ( !fs.existsSync( targetFolder ) ) {
4196
4211
  fs.mkdirSync( targetFolder, { recursive: true } );
@@ -5707,7 +5722,7 @@ export async function getVideoLinks( req, res ) {
5707
5722
  continue;
5708
5723
  }
5709
5724
  const [ q1, q2, q3 ] = data.answers;
5710
- console.log( q1, q2 );
5725
+
5711
5726
  const params = {
5712
5727
  Bucket: 'tango-planogram',
5713
5728
  file_path: q3?.video || null,
@@ -7000,28 +7015,28 @@ export async function updateExcelPlanogram( req, res ) {
7000
7015
  }
7001
7016
  }
7002
7017
 
7003
- // async function downloadImage() {
7004
- // const url = 'https://api.getcrest.ai/api/ms_data_preparation/master_data/attachment/?preview=0&attachment_id=2934';
7018
+ async function downloadImage() {
7019
+ const url = 'https://api.getcrest.ai/api/ms_data_preparation/master_data/attachment/?preview=0&attachment_id=2934';
7005
7020
 
7006
- // try {
7007
- // const response = await fetch( url, {
7008
- // headers: {
7009
- // Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ3MjE0MjcxLCJpYXQiOjE3NDcyMTA2NzEsImp0aSI6ImM4ZjQ4ZDY2YWJkYzRmNDU4MWI4OGE4MTMwODVjOTUwIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.IOw_0yNA6CMBCIn7cxjPR0FqHI949WplCKzlkr8aK7g',
7010
- // Cookie: 'prod_session_key=w144dqljxlh096487nc33rm09vwtossh; prod_session_key=7mljy9k7niwpw4btbbyvuhkz7otbdh6v',
7011
- // },
7012
- // } );
7021
+ try {
7022
+ const response = await fetch( url, {
7023
+ headers: {
7024
+ Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ3MjE0MjcxLCJpYXQiOjE3NDcyMTA2NzEsImp0aSI6ImM4ZjQ4ZDY2YWJkYzRmNDU4MWI4OGE4MTMwODVjOTUwIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.IOw_0yNA6CMBCIn7cxjPR0FqHI949WplCKzlkr8aK7g',
7025
+ Cookie: 'prod_session_key=w144dqljxlh096487nc33rm09vwtossh; prod_session_key=7mljy9k7niwpw4btbbyvuhkz7otbdh6v',
7026
+ },
7027
+ } );
7013
7028
 
7014
- // if ( !response.ok ) throw new Error( `HTTP error! Status: ${response.status}` );
7029
+ if ( !response.ok ) throw new Error( `HTTP error! Status: ${response.status}` );
7015
7030
 
7016
- // const dest = fs.createWriteStream( '2934.png' );
7017
- // response.body.pipe( dest );
7031
+ const dest = fs.createWriteStream( '2934.png' );
7032
+ response.body.pipe( dest );
7018
7033
 
7019
- // dest.on( 'finish', () => console.log( 'Image saved as image.jpg' ) );
7020
- // dest.on( 'error', ( err ) => console.error( 'File write error:', err ) );
7021
- // } catch ( err ) {
7022
- // console.error( 'Fetch error:', err );
7023
- // }
7024
- // }
7034
+ dest.on( 'finish', () => console.log( 'Image saved as image.jpg' ) );
7035
+ dest.on( 'error', ( err ) => console.error( 'File write error:', err ) );
7036
+ } catch ( err ) {
7037
+ console.error( 'Fetch error:', err );
7038
+ }
7039
+ }
7025
7040
 
7026
7041
  // downloadImage();
7027
7042
 
@@ -7068,1416 +7083,73 @@ export async function recorrectTaskData( req, res ) {
7068
7083
  }
7069
7084
 
7070
7085
 
7071
- export async function migrateCrestv1( req, res ) {
7072
- try {
7073
- if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
7074
- return res.sendError( 'Unauthorized', 401 );
7075
- }
7076
-
7077
- const startTime = Date.now();
7078
-
7079
- const layoutApiUrl = 'https://api.getcrest.ai/api/ms_shelfsensei/layout/';
7080
- let staticToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQ1NTE3MjQxLCJpYXQiOjE3NDU1MTM2NDEsImp0aSI6Ijg3MWVlNTA3ODY2OTQ5OTVhMTQ0YTk4NzQyNzY0MzEzIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImlzX21lZXNlZWtfYWNjb3VudCI6ZmFsc2UsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.eGzTMGwwstr13M0Hu1Ls5-gkE_oSPMJJBL2wgygT6Ac';
7081
- const fetchWithCookies = fetchCookie( fetch );
7082
-
7083
-
7084
- async function fetchStoreData( store, bearerToken, res ) {
7085
- const payload = JSON.stringify( { store_id: store.toObject().storeName?.toUpperCase() } );
7086
-
7087
- try {
7088
- const response = await fetch( layoutApiUrl, {
7089
- method: 'POST',
7090
- headers: {
7091
- 'Authorization': `Bearer ${bearerToken}`,
7092
- 'Content-Type': 'application/json',
7093
- 'Content-Length': Buffer.byteLength( payload ),
7094
- },
7095
- body: payload,
7096
- } );
7097
-
7098
- const data = await response.text();
7099
- let jsonData = null;
7086
+ function fillFeedbackFromJson( excelPath, jsonData, outputPath ) {
7087
+ const workbook = xlsx.readFile( excelPath );
7088
+ const sheetName = workbook.SheetNames[0];
7089
+ const sheet = workbook.Sheets[sheetName];
7100
7090
 
7101
- try {
7102
- jsonData = JSON.parse( data );
7103
- } catch ( parseError ) {
7104
- logger.error( { functionName: `Warning: Received invalid JSON for store ${store.toObject().storeName}`, error: parseError } );
7105
- console.warn( `Warning: Received invalid JSON for store ${store.toObject().storeName}` );
7106
- return { storeName: store.toObject().storeName, data: null };
7107
- }
7091
+ const data = xlsx.utils.sheet_to_json( sheet, { defval: 'Transformed by Data.Page' } );
7108
7092
 
7109
- if ( jsonData.result === 'Token is invalid or expired' ) {
7110
- console.log( 'Token expired, retrying...' );
7111
- try {
7112
- const newToken = await fetchNewToken();
7113
- staticToken = newToken;
7114
- return await fetchStoreData( store, newToken, res );
7115
- } catch ( retryError ) {
7116
- logger.error( { functionName: 'Failed to refresh token', error: retryError } );
7117
- console.log( retryError );
7118
- return res.sendError( 'Failed to refresh token', 401 );
7119
- }
7120
- }
7093
+ const feedbackMap = {};
7094
+ jsonData.forEach( ( entry ) => {
7095
+ feedbackMap[entry.store] = entry.videoUrl;
7096
+ } );
7121
7097
 
7122
- return { storeName: store.toObject().storeName, data: jsonData };
7123
- } catch ( error ) {
7124
- logger.error( { functionName: `Error fetching data for ${store.toObject().storeName}:`, error } );
7125
- console.error( `Error fetching data for ${store.toObject().storeName}:`, error.message );
7126
- return { storeName: store.toObject().storeName, data: null };
7127
- }
7098
+ const updatedData = data.map( ( row ) => {
7099
+ const store = row.storeName;
7100
+ if ( feedbackMap[store] ) {
7101
+ row.FeedBack = feedbackMap[store];
7128
7102
  }
7103
+ return row;
7104
+ } );
7129
7105
 
7106
+ const newSheet = xlsx.utils.json_to_sheet( updatedData );
7130
7107
 
7131
- const fetchNewToken = async () => {
7132
- const email = 'tango.lenskart@getcrest.ai';
7133
- const password = 'Tangolenskart@123';
7134
-
7135
- const credentials = JSON.stringify( { email, password } );
7136
-
7137
- const invalidateUrl = 'https://app.getcrest.ai/api/ms_iam/user/session/override/';
7138
- const tokenUrl = 'https://app.getcrest.ai/api/ms_iam/token/';
7139
-
7140
- try {
7141
- const invalidateRes = await fetchWithCookies( invalidateUrl, {
7142
- method: 'POST',
7143
- headers: {
7144
- 'Content-Type': 'application/json',
7145
- },
7146
- body: credentials,
7147
- } );
7148
-
7149
- const invalidateData = await invalidateRes.json();
7150
- console.log( 'Invalidate response:', invalidateData );
7151
-
7152
- console.log( 'Fetching new token...' );
7153
- const tokenRes = await fetchWithCookies( tokenUrl, {
7154
- method: 'POST',
7155
- headers: {
7156
- 'Content-Type': 'application/json',
7157
- 'Accept': 'application/json, text/javascript, */*; q=0.01',
7158
- },
7159
- body: credentials,
7160
- } );
7161
-
7162
- const tokenData = await tokenRes.json();
7163
- console.log( 'Token response:', tokenData );
7164
-
7165
- return tokenData.access;
7166
- } catch ( error ) {
7167
- console.error( 'Error fetching new token:', error );
7168
- throw error;
7169
- }
7170
- };
7108
+ workbook.Sheets[sheetName] = newSheet;
7171
7109
 
7172
- const fetchVmImage = async ( attachmentId ) => {
7173
- try {
7174
- const response = await fetchWithCookies( `https://api.getcrest.ai/api/ms_data_preparation/master_data/attachment/?preview=0&attachment_id=${attachmentId}`, {
7175
- method: 'GET',
7176
- headers: {
7177
- 'Authorization': `Bearer ${staticToken}`,
7178
- 'Cookie': 'prod_session_key=w144dqljxlh096487nc33rm09vwtossh',
7179
- },
7180
- } );
7110
+ xlsx.writeFile( workbook, outputPath );
7111
+ }
7181
7112
 
7113
+ // fillFeedbackFromJson('input.xlsx', feedbackJson, 'output.xlsx');
7182
7114
 
7183
- if ( !response.ok ) {
7184
- return;
7185
- // throw new Error( `Failed to fetch image: ${response.status}` );
7186
- }
7187
7115
 
7188
- // const dest = fs.createWriteStream( `${attachmentId}.png` );
7189
- // response.body.pipe( dest );
7116
+ function exportFixtureJsonToExcel( fixtures, filePath ) {
7117
+ const fixtureInfoArr = [];
7118
+ const shelfConfigArr = [];
7119
+ const vmConfigArr = [];
7190
7120
 
7191
- return await response.buffer();
7192
- } catch ( error ) {
7193
- console.error( 'Error fetching image buffer:', error.message );
7194
- throw error;
7195
- }
7196
- };
7121
+ for ( const fixture of fixtures ) {
7122
+ fixtureInfoArr.push( {
7123
+ clientId: fixture.clientId,
7124
+ fixtureCode: fixture.fixtureCode,
7125
+ fixtureCategory: fixture.fixtureCategory,
7126
+ fixtureConfigType: fixture.fixtureConfigType,
7127
+ fixtureLength: `${fixture.fixtureLength?.value} ${fixture.fixtureLength?.unit}`,
7128
+ fixtureCapacity: fixture.fixtureCapacity,
7129
+ } );
7197
7130
 
7198
- const getImageMetadata = async ( imageBuffer ) => {
7199
- try {
7200
- const metadata = await sharp( imageBuffer ).metadata();
7201
- const { width, height, format } = metadata;
7131
+ ( fixture.shelfConfig || [] ).forEach( ( shelf ) => {
7132
+ shelfConfigArr.push( {
7133
+ fixtureCode: fixture.fixtureCode,
7134
+ ...shelf,
7135
+ } );
7136
+ } );
7202
7137
 
7203
- if ( !width || !height || !format ) throw new Error( 'Invalid image metadata' );
7138
+ ( fixture.vmConfig || [] ).forEach( ( vm ) => {
7139
+ vmConfigArr.push( {
7140
+ fixtureCode: fixture.fixtureCode,
7141
+ ...vm,
7142
+ } );
7143
+ } );
7144
+ }
7204
7145
 
7205
- const ratio = width / height;
7206
- const normalizedRatio = ratio > 1 ? ratio : 1 / ratio;
7207
- const squareThreshold = 1.2;
7208
- const imageShape = normalizedRatio <= squareThreshold ? 'square' : 'rectangle';
7146
+ const workbook = xlsx.utils.book_new();
7147
+ xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( fixtureInfoArr ), 'Fixture Info' );
7148
+ xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( shelfConfigArr ), 'Shelf Config' );
7149
+ xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( vmConfigArr ), 'VM Config' );
7209
7150
 
7210
- const fileExtension = format === 'jpeg' ? 'jpg' : format;
7211
- const contentType = `image/${format}`;
7212
-
7213
- return {
7214
- imageShape,
7215
- width,
7216
- height,
7217
- fileExtension,
7218
- contentType,
7219
- };
7220
- } catch ( error ) {
7221
- console.error( 'Error processing image buffer:', error.message );
7222
- throw error;
7223
- }
7224
- };
7225
-
7226
-
7227
- async function generateFixtureTemplateName( baseName, fixtureWidth ) {
7228
- function escapeRegex( str ) {
7229
- return str.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
7230
- }
7231
-
7232
- const escapedBase = escapeRegex( baseName );
7233
- const regexPattern = new RegExp( `^Template-(\\d+)-${escapedBase}$` );
7234
-
7235
- const existingFixtures = await fixtureConfigService.find( {
7236
- fixtureName: { $regex: new RegExp( `^Template-(\\d+)-${escapedBase}$` ) },
7237
- fixtureWidth: fixtureWidth,
7238
- } );
7239
-
7240
- const usedNumbers = existingFixtures
7241
- .map( ( doc ) => {
7242
- const match = doc.fixtureName.match( regexPattern );
7243
- return match ? parseInt( match[1], 10 ) : null;
7244
- } )
7245
- .filter( ( num ) => num !== null );
7246
-
7247
- const nextNumber = usedNumbers.length > 0 ? Math.max( ...usedNumbers ) + 1 : 1;
7248
-
7249
- return `Template-${nextNumber}-${baseName}`;
7250
- }
7251
-
7252
-
7253
- if ( !req?.body?.storeName ) {
7254
- return res.sendError( 'No store supplied', 200 );
7255
- }
7256
-
7257
- let storeQuery = {
7258
- clientId: '11',
7259
- $and: [
7260
- { storeName: req.body.storeName },
7261
- // { storeName: { $in: [ 'LKST98' ] } },
7262
- // { storeName: { $nin: [ 'LKST98', 'LKST1193' ] } },
7263
- ],
7264
- };
7265
-
7266
- let storeList = await storeService.find( storeQuery );
7267
-
7268
- const constantFixtureLength = 1220;
7269
- const constantDetailedFixtureLength = 1220;
7270
-
7271
- const constantFixtureWidth = 610;
7272
- const constantDetailedFixtureWidth = 1524;
7273
-
7274
- const mmToFeet = 305;
7275
-
7276
- function roundToTwo( num ) {
7277
- return Math.round( num * 100 ) / 100;
7278
- }
7279
-
7280
-
7281
- for ( let i = 0; i < storeList.length; i++ ) {
7282
- const storeData = await fetchStoreData( storeList[i], staticToken, res );
7283
-
7284
- if ( storeData?.data?.message !== 'SUCCESS' ) continue;
7285
-
7286
-
7287
- const storeDetails = storeList[i];
7288
-
7289
- const existingPlanogram = await planoService.findOne( { storeName: storeData.storeName } );
7290
-
7291
- if ( existingPlanogram ) {
7292
- const checkTaskSubmitted = await planoTaskService.findOne( { planoId: existingPlanogram.toObject()._id } );
7293
-
7294
- const checkTaskCreated = await processedTaskService.findOne( { storeName: storeData.storeName, date_string: dayjs().format( 'YYYY-MM-DD' ), isPlano: true } );
7295
-
7296
- if ( checkTaskSubmitted || checkTaskCreated ) {
7297
- continue;
7298
- }
7299
- }
7300
-
7301
-
7302
- if ( existingPlanogram?.toObject()?._id && mongoose.Types.ObjectId.isValid( existingPlanogram?.toObject()?._id ) ) {
7303
- await Promise.all( [ planoService.deleteOne( { _id: existingPlanogram?.toObject()?._id } ), storeBuilderService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
7304
- storeFixtureService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ), fixtureShelfService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
7305
- planoMappingService.deleteMany( { planoId: existingPlanogram?.toObject()?._id } ),
7306
- ] );
7307
- }
7308
-
7309
-
7310
- const planoInsertData = {
7311
- storeName: storeData.storeName,
7312
- storeId: storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7313
- layoutName: `${storeData.storeName} - Layout`,
7314
- clientId: '11',
7315
- attachments: [],
7316
- createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
7317
- createdByName: 'Bejan',
7318
- createdByEmail: 'bejan@tangotech.co.in',
7319
- status: 'completed',
7320
- floorNumber: 1,
7321
- productResolutionLevel: 'L2',
7322
- scanType: 'qr',
7323
- };
7324
-
7325
- const insertedPlano = await planoService.upsertOne( { storeName: storeData.storeName }, planoInsertData );
7326
- const planoDoc = insertedPlano.toObject();
7327
-
7328
- const floors = new Set();
7329
-
7330
- for ( const item of storeData.data.result ) {
7331
- if ( item.floor ) {
7332
- floors.add( item.floor );
7333
- }
7334
-
7335
- if ( Array.isArray( item.fixtures ) ) {
7336
- for ( const fixture of item.fixtures ) {
7337
- if ( fixture.floor ) {
7338
- floors.add( fixture.floor );
7339
- }
7340
- }
7341
- }
7342
- }
7343
-
7344
- const floorArray = Array.from( floors );
7345
-
7346
- let isFloorKeyExist = true;
7347
-
7348
- if ( !floorArray.length ) {
7349
- isFloorKeyExist = false;
7350
- floorArray.push( 'GROUND' );
7351
- }
7352
-
7353
- for ( let floorIndex = 0; floorIndex < floorArray.length; floorIndex++ ) {
7354
- const leftWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'LEFT WALL' );
7355
- let leftFixtures = leftWall.flatMap( ( wall ) => wall.fixtures );
7356
- if ( isFloorKeyExist ) {
7357
- leftFixtures = leftFixtures.filter( ( fixture ) => fixture.floor === floorArray[floorIndex] );
7358
- }
7359
- const rightWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT WALL' );
7360
- let rightFixtures = rightWall.flatMap( ( wall ) => wall.fixtures );
7361
- if ( isFloorKeyExist ) {
7362
- rightFixtures = rightFixtures.filter( ( fixture ) => fixture.floor === floorArray[floorIndex] );
7363
- }
7364
- const backWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT VERTICAL WALL' );
7365
- let backFixtures = backWall.flatMap( ( wall ) => wall.fixtures );
7366
- if ( isFloorKeyExist ) {
7367
- backFixtures = backFixtures.filter( ( fixture ) => fixture.floor === floorArray[floorIndex] );
7368
- }
7369
- let floorFixtures = storeData.data.result.filter(
7370
- ( entry ) => entry['main'] === 'Euro Center' || entry['main'] === 'Euro Center Dr',
7371
- );
7372
- if ( isFloorKeyExist ) {
7373
- floorFixtures = floorFixtures.filter( ( fixture ) => fixture.floor === floorArray[floorIndex] );
7374
- }
7375
-
7376
- const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
7377
- const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
7378
-
7379
- const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
7380
- const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
7381
-
7382
- const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
7383
- const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
7384
-
7385
- const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
7386
- const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
7387
-
7388
- const maxFixturesPerRow = floorFixtures.length/2;
7389
- const totalRows = 2;
7390
-
7391
- const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
7392
- const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
7393
-
7394
- const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
7395
- const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
7396
-
7397
- const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
7398
- const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
7399
-
7400
- const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
7401
- const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
7402
-
7403
- const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
7404
- const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
7405
-
7406
- const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet );
7407
- const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet );
7408
-
7409
- const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
7410
- const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
7411
-
7412
- const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
7413
- const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
7414
-
7415
-
7416
- const floorInsertData = {
7417
- storeName: planoDoc.storeName,
7418
- storeId: storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7419
- layoutName: `${planoDoc.storeName} - Layout`,
7420
- clientId: '11',
7421
- floorNumber: floorIndex + 1,
7422
- floorName: `${floorArray[floorIndex].toLowerCase()} floor`,
7423
- crestLayout: true,
7424
- layoutPolygon: [
7425
- {
7426
- elementType: 'wall',
7427
- distance: finalXDistance,
7428
- unit: 'ft',
7429
- direction: 'right',
7430
- angle: 90,
7431
- elementNumber: 1,
7432
- detailedDistance: finalXDetailedDistance,
7433
- },
7434
- {
7435
- elementType: 'wall',
7436
- distance: finalYDistance,
7437
- unit: 'ft',
7438
- direction: 'down',
7439
- angle: 90,
7440
- elementNumber: 2,
7441
- detailedDistance: finalYDetailedDistance,
7442
- },
7443
- {
7444
- elementType: 'wall',
7445
- distance: finalXDistance,
7446
- unit: 'ft',
7447
- direction: 'left',
7448
- angle: 90,
7449
- elementNumber: 3,
7450
- detailedDistance: finalXDetailedDistance,
7451
- },
7452
- {
7453
- elementType: 'wall',
7454
- distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
7455
- unit: 'ft',
7456
- direction: 'up',
7457
- angle: 90,
7458
- elementNumber: 4,
7459
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
7460
- },
7461
- {
7462
- elementType: 'entrance',
7463
- distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
7464
- unit: 'ft',
7465
- direction: 'up',
7466
- angle: 90,
7467
- elementNumber: 1,
7468
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
7469
- },
7470
- {
7471
- elementType: 'wall',
7472
- distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
7473
- unit: 'ft',
7474
- direction: 'up',
7475
- angle: 90,
7476
- elementNumber: 5,
7477
- detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
7478
- },
7479
- ],
7480
- createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
7481
- createdByName: 'Bejan',
7482
- createdByEmail: 'bejan@tangotech.co.in',
7483
- status: 'completed',
7484
- planoId: planoDoc._id,
7485
- };
7486
-
7487
- const layoutDoc = await storeBuilderService.upsertOne( { planoId: planoDoc._id, floorNumber: floorIndex + 1 }, floorInsertData );
7488
-
7489
- let fixtureCounter = 1;
7490
-
7491
-
7492
- for ( let index = 0; index < leftFixtures.length; index++ ) {
7493
- const fixture = leftFixtures[index];
7494
-
7495
- const fixtureConfig = await fixtureLibraryService.findOne( { fixtureCategory: fixture.fixtureType } );
7496
- if ( !fixtureConfig ) continue;
7497
- const fixtureConfigDoc = fixtureConfig.toObject();
7498
-
7499
- let mapKey = `${fixtureConfigDoc.fixtureCategory}${fixtureConfigDoc.fixtureWidth.value}${fixtureConfigDoc.fixtureWidth.unit},${fixture.header}`;
7500
-
7501
- const fixtureProductSubBrandName = new Set();
7502
-
7503
-
7504
- const shelfTemplate = fixtureConfigDoc.shelfConfig.map( ( configShelf, j ) => {
7505
- const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
7506
- const shelfSection = shelfZone?.products.find( ( product ) => !product.isMerchandisingElement );
7507
-
7508
- const shelfIdentifier = `shelf${j + 1}=${shelfSection?.productName}`;
7509
-
7510
- mapKey += ','+shelfIdentifier;
7511
-
7512
- const productSubBrandName = shelfSection?.productName?.replace( /\s*PIDs\b/g, '' )?.split( /\s*\+\s*/ ) || [];
7513
-
7514
- productSubBrandName.forEach( ( item ) => fixtureProductSubBrandName.add( item ) );
7515
-
7516
- return {
7517
- shelfNumber: j+1,
7518
- shelfType: configShelf?.shelfType,
7519
- productPerShelf: configShelf?.productPerShelf,
7520
- trayRows: configShelf?.trayRows,
7521
- productBrandName: productSubBrandName,
7522
- zone: configShelf.shelfZone,
7523
- };
7524
- } );
7525
-
7526
- const vmConfig = fixture.productZones?.flatMap( ( zone ) => {
7527
- const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
7528
- const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
7529
- const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
7530
-
7531
- return vms.map( ( vm, k ) => {
7532
- let configData = vmConfig[0];
7533
-
7534
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
7535
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
7536
- configData.zone = 'stretch';
7537
- }
7538
-
7539
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
7540
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
7541
- }
7542
-
7543
- if ( !configData ) return;
7544
-
7545
- const vmIdentifier = `vm${k+1}=${vm.productName}+${configData.vmHeightmm}+${configData.vmWidthmm}+${configData.startShelf}+${configData.endShelf}+${configData.zone}`;
7546
-
7547
- mapKey += ','+vmIdentifier;
7548
-
7549
- return {
7550
- startYPosition: configData.startShelf,
7551
- endYPosition: configData.endShelf,
7552
- xZone: configData.zone,
7553
- vmName: vm.productName,
7554
- vmHeight: configData.vmHeightmm,
7555
- vmWidth: configData.vmWidthmm,
7556
- imageUrl: zone?.actual_image_url,
7557
- };
7558
- } );
7559
- } );
7560
-
7561
- const vmTemplate = await Promise.all( vmConfig.map( async ( vmTemplate ) => {
7562
- const vmInsertData = {
7563
- clientId: '11',
7564
- vmName: vmTemplate.vmName,
7565
- vmHeight: {
7566
- value: vmTemplate.vmHeight,
7567
- unit: 'mm',
7568
- },
7569
- vmWidth: {
7570
- value: vmTemplate.vmWidth,
7571
- unit: 'mm',
7572
- },
7573
- status: 'complete',
7574
- vmBrand: vmTemplate.vmBrand,
7575
- };
7576
- if ( vmTemplate?.imageUrl ) {
7577
- const parsedUrl = new URL( vmTemplate.imageUrl );
7578
- const attachmentId = parsedUrl.searchParams.get( 'attachment_id' );
7579
-
7580
- const isVmImageExist = await planoVmService.findOne( { crestImageId: attachmentId } );
7581
-
7582
- if ( !isVmImageExist ) {
7583
- const vmImageData = await fetchVmImage( attachmentId );
7584
-
7585
- const imageMeta = await getImageMetadata( vmImageData );
7586
-
7587
- const params = {
7588
- Bucket: JSON.parse( process.env.BUCKET ).storeBuilder,
7589
- Key: `vmType/`,
7590
- fileName: `${attachmentId}.${imageMeta.fileExtension}`,
7591
- ContentType: imageMeta.contentType,
7592
- body: vmImageData,
7593
- };
7594
-
7595
- const imgUpload = await fileUpload( params );
7596
-
7597
- vmInsertData.crestImageId = attachmentId;
7598
- vmInsertData.vmImageUrl = imgUpload.Key;
7599
-
7600
-
7601
- if ( imageMeta.imageShape === 'square' ) {
7602
- vmInsertData.vmHeight.value = 100;
7603
- vmInsertData.vmWidth.value = 230;
7604
- }
7605
- } else {
7606
- vmInsertData.crestImageId = attachmentId;
7607
- vmInsertData.vmImageUrl = isVmImageExist.toObject().vmImageUrl;
7608
- }
7609
- }
7610
-
7611
- const vmDetails = await planoVmService.upsertOne(
7612
- {
7613
- 'productName': vmInsertData.vmName,
7614
- },
7615
- vmInsertData,
7616
- );
7617
-
7618
- return {
7619
- vmId: vmDetails.toObject()._id,
7620
- startYPosition: vmTemplate.startYPosition,
7621
- endYPosition: vmTemplate.endYPosition,
7622
- xZone: vmTemplate.xZone,
7623
- };
7624
- } ) );
7625
-
7626
- const baseFixtureName = `${fixtureConfigDoc.fixtureCategory}`;
7627
- const uniqueFixtureName = await generateFixtureTemplateName( baseFixtureName, fixtureConfigDoc.fixtureWidth );
7628
-
7629
-
7630
- const fixtureTemplateData = {
7631
- ...fixtureConfigDoc,
7632
- 'shelfConfig': shelfTemplate,
7633
- 'vmConfig': vmTemplate,
7634
- 'clientId': fixtureConfigDoc.clientId,
7635
- 'fixtureName': uniqueFixtureName,
7636
- 'header': {
7637
- label: fixture.header ? fixture.header : fixture.fixtureSubname[0],
7638
- isEnabled: true,
7639
- },
7640
- 'footer': {
7641
- label: fixture.footer,
7642
- isEnabled: true,
7643
- },
7644
- 'isBodyEnabled': true,
7645
- 'productResolutionLevel': 'L3',
7646
- 'productBrandName': [ ...fixtureProductSubBrandName ],
7647
- 'fixtureLibraryId': fixtureConfigDoc._id,
7648
- 'crestMapKey': mapKey,
7649
- };
7650
-
7651
- delete fixtureTemplateData._id;
7652
-
7653
-
7654
- const fixtureTemplate = await fixtureConfigService.upsertOne(
7655
- { crestMapKey: mapKey },
7656
- fixtureTemplateData,
7657
- );
7658
-
7659
- const fixtureData = {
7660
- ...fixtureTemplate.toObject(),
7661
- 'storeName': layoutDoc.storeName,
7662
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7663
- 'planoId': layoutDoc.planoId,
7664
- 'floorId': layoutDoc._id,
7665
- 'associatedElementType': 'wall',
7666
- 'associatedElementNumber': 1,
7667
- 'relativePosition': {
7668
- 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
7669
- 'y': 0,
7670
- 'unit': 'ft',
7671
- },
7672
- 'fixtureNumber': fixtureCounter,
7673
- 'relativeDetailedPosition': {
7674
- 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
7675
- 'y': 0,
7676
- 'unit': 'ft',
7677
- },
7678
- 'associatedElementFixtureNumber': index+1,
7679
- 'fixtureConfigId': fixtureTemplate.toObject()._id,
7680
- };
7681
-
7682
- delete fixtureData._id;
7683
- delete fixtureData.shelfConfig;
7684
-
7685
- const createdFixture = await storeFixtureService.upsertOne(
7686
- {
7687
- floorId: layoutDoc._id,
7688
- fixtureNumber: fixtureCounter++,
7689
- },
7690
- fixtureData,
7691
- );
7692
-
7693
- if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
7694
-
7695
- fixtureTemplate.shelfConfig.forEach( async ( configShelf, j ) => {
7696
- const shelfData = {
7697
- 'clientId': '11',
7698
- 'storeName': layoutDoc.storeName,
7699
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7700
- 'planoId': layoutDoc.planoId,
7701
- 'floorId': layoutDoc._id,
7702
- 'fixtureId': createdFixture._id,
7703
- 'shelfNumber': j + 1,
7704
- 'shelfOrder': 'LTR',
7705
- 'shelfCapacity': configShelf.shelfCapacity,
7706
- 'productBrandName': configShelf.productBrandName,
7707
- 'shelfType': configShelf.shelfType,
7708
- 'productPerShelf': configShelf.productPerShelf,
7709
- 'trayRows': configShelf.trayRows,
7710
- 'productPerTray': configShelf.productPerTray,
7711
- 'zone': configShelf.zone,
7712
- };
7713
-
7714
- await fixtureShelfService.upsertOne(
7715
- {
7716
- fixtureId: createdFixture._id,
7717
- shelfNumber: j + 1,
7718
- },
7719
- shelfData,
7720
- );
7721
- } );
7722
- }
7723
-
7724
- for ( let index = 0; index < backFixtures.length; index++ ) {
7725
- const fixture = backFixtures[index];
7726
-
7727
- const fixtureConfig = await fixtureLibraryService.findOne( { fixtureCategory: fixture.fixtureType } );
7728
- if ( !fixtureConfig ) continue;
7729
- const fixtureConfigDoc = fixtureConfig.toObject();
7730
-
7731
- let mapKey = `${fixtureConfigDoc.fixtureCategory}${fixtureConfigDoc.fixtureWidth.value}${fixtureConfigDoc.fixtureWidth.unit},${fixture.header}`;
7732
-
7733
- const fixtureProductSubBrandName = new Set();
7734
-
7735
-
7736
- const shelfTemplate = fixtureConfigDoc.shelfConfig.map( ( configShelf, j ) => {
7737
- const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
7738
- const shelfSection = shelfZone?.products.find( ( product ) => !product.isMerchandisingElement );
7739
-
7740
- const shelfIdentifier = `shelf${j + 1}=${shelfSection?.productName}`;
7741
-
7742
- mapKey += ','+shelfIdentifier;
7743
-
7744
- const productSubBrandName = shelfSection?.productName?.replace( /\s*PIDs\b/g, '' )?.split( /\s*\+\s*/ ) || [];
7745
-
7746
- productSubBrandName.forEach( ( item ) => fixtureProductSubBrandName.add( item ) );
7747
-
7748
- return {
7749
- shelfNumber: j+1,
7750
- shelfType: configShelf?.shelfType,
7751
- productPerShelf: configShelf?.productPerShelf,
7752
- trayRows: configShelf?.trayRows,
7753
- productBrandName: productSubBrandName,
7754
- zone: configShelf.shelfZone,
7755
- };
7756
- } );
7757
-
7758
- const vmConfig = fixture.productZones?.flatMap( ( zone ) => {
7759
- const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
7760
- const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
7761
- const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
7762
-
7763
- return vms.map( ( vm, k ) => {
7764
- let configData = vmConfig[0];
7765
-
7766
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
7767
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
7768
- configData.zone = 'stretch';
7769
- }
7770
-
7771
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
7772
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
7773
- }
7774
-
7775
- if ( !configData ) return;
7776
-
7777
- const vmIdentifier = `vm${k+1}=${vm.productName}+${configData.vmHeightmm}+${configData.vmWidthmm}+${configData.startShelf}+${configData.endShelf}+${configData.zone}`;
7778
-
7779
- mapKey += ','+vmIdentifier;
7780
-
7781
- return {
7782
- startYPosition: configData.startShelf,
7783
- endYPosition: configData.endShelf,
7784
- xZone: configData.zone,
7785
- vmName: vm.productName,
7786
- vmHeight: configData.vmHeightmm,
7787
- vmWidth: configData.vmWidthmm,
7788
- imageUrl: zone?.actual_image_url,
7789
- };
7790
- } );
7791
- } );
7792
-
7793
- const vmTemplate = await Promise.all( vmConfig.map( async ( vmTemplate ) => {
7794
- const vmInsertData = {
7795
- clientId: '11',
7796
- vmName: vmTemplate.vmName,
7797
- vmHeight: {
7798
- value: vmTemplate.vmHeight,
7799
- unit: 'mm',
7800
- },
7801
- vmWidth: {
7802
- value: vmTemplate.vmWidth,
7803
- unit: 'mm',
7804
- },
7805
- status: 'complete',
7806
- vmBrand: vmTemplate.vmBrand,
7807
- };
7808
- if ( vmTemplate?.imageUrl ) {
7809
- const parsedUrl = new URL( vmTemplate.imageUrl );
7810
- const attachmentId = parsedUrl.searchParams.get( 'attachment_id' );
7811
-
7812
- const isVmImageExist = await planoVmService.findOne( { crestImageId: attachmentId } );
7813
-
7814
- if ( !isVmImageExist ) {
7815
- const vmImageData = await fetchVmImage( attachmentId );
7816
-
7817
- const imageMeta = await getImageMetadata( vmImageData );
7818
-
7819
- const params = {
7820
- Bucket: JSON.parse( process.env.BUCKET ).storeBuilder,
7821
- Key: `vmType/`,
7822
- fileName: `${attachmentId}.${imageMeta.fileExtension}`,
7823
- ContentType: imageMeta.contentType,
7824
- body: vmImageData,
7825
- };
7826
-
7827
- const imgUpload = await fileUpload( params );
7828
-
7829
-
7830
- vmInsertData.crestImageId = attachmentId;
7831
- vmInsertData.vmImageUrl = imgUpload.Key;
7832
-
7833
-
7834
- if ( imageMeta.imageShape === 'square' ) {
7835
- vmInsertData.vmHeight.value = 100;
7836
- vmInsertData.vmWidth.value = 230;
7837
- }
7838
- } else {
7839
- vmInsertData.crestImageId = attachmentId;
7840
- vmInsertData.vmImageUrl = isVmImageExist.toObject().vmImageUrl;
7841
- }
7842
- }
7843
-
7844
- const vmDetails = await planoVmService.upsertOne(
7845
- {
7846
- 'productName': vmInsertData.vmName,
7847
- },
7848
- vmInsertData,
7849
- );
7850
-
7851
- return {
7852
- vmId: vmDetails.toObject()._id,
7853
- startYPosition: vmTemplate.startYPosition,
7854
- endYPosition: vmTemplate.endYPosition,
7855
- xZone: vmTemplate.xZone,
7856
- };
7857
- } ) );
7858
-
7859
- const baseFixtureName = `${fixtureConfigDoc.fixtureCategory}`;
7860
- const uniqueFixtureName = await generateFixtureTemplateName( baseFixtureName, fixtureConfigDoc.fixtureWidth );
7861
-
7862
-
7863
- const fixtureTemplateData = {
7864
- ...fixtureConfigDoc,
7865
- 'shelfConfig': shelfTemplate,
7866
- 'vmConfig': vmTemplate,
7867
- 'clientId': fixtureConfigDoc.clientId,
7868
- 'fixtureName': uniqueFixtureName,
7869
- 'header': {
7870
- label: fixture.header ? fixture.header : fixture.fixtureSubname[0],
7871
- isEnabled: true,
7872
- },
7873
- 'footer': {
7874
- label: fixture.footer,
7875
- isEnabled: true,
7876
- },
7877
- 'isBodyEnabled': true,
7878
- 'productResolutionLevel': 'L3',
7879
- 'productBrandName': [ ...fixtureProductSubBrandName ],
7880
- 'fixtureLibraryId': fixtureConfigDoc._id,
7881
- 'crestMapKey': mapKey,
7882
- };
7883
-
7884
- delete fixtureTemplateData._id;
7885
-
7886
-
7887
- const fixtureTemplate = await fixtureConfigService.upsertOne(
7888
- { crestMapKey: mapKey },
7889
- fixtureTemplateData,
7890
- );
7891
-
7892
- const fixtureData = {
7893
- ...fixtureTemplate.toObject(),
7894
- 'storeName': layoutDoc.storeName,
7895
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7896
- 'planoId': layoutDoc.planoId,
7897
- 'floorId': layoutDoc._id,
7898
- 'associatedElementType': 'wall',
7899
- 'associatedElementNumber': 2,
7900
- 'relativePosition': {
7901
- 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
7902
- 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
7903
- 'unit': 'ft',
7904
- },
7905
- 'fixtureNumber': fixtureCounter,
7906
- 'relativeDetailedPosition': {
7907
- 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
7908
- 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
7909
- 'unit': 'ft',
7910
- },
7911
- 'associatedElementFixtureNumber': index+1,
7912
- 'fixtureConfigId': fixtureTemplate.toObject()._id,
7913
- };
7914
-
7915
- delete fixtureData._id;
7916
- delete fixtureData.shelfConfig;
7917
-
7918
- const createdFixture = await storeFixtureService.upsertOne(
7919
- {
7920
- floorId: layoutDoc._id,
7921
- fixtureNumber: fixtureCounter++,
7922
- },
7923
- fixtureData,
7924
- );
7925
-
7926
- if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
7927
-
7928
- fixtureTemplate.shelfConfig.forEach( async ( configShelf, j ) => {
7929
- const shelfData = {
7930
- 'clientId': '11',
7931
- 'storeName': layoutDoc.storeName,
7932
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
7933
- 'planoId': layoutDoc.planoId,
7934
- 'floorId': layoutDoc._id,
7935
- 'fixtureId': createdFixture._id,
7936
- 'shelfNumber': j + 1,
7937
- 'shelfOrder': 'LTR',
7938
- 'shelfCapacity': configShelf.shelfCapacity,
7939
- 'productBrandName': configShelf.productBrandName,
7940
- 'shelfType': configShelf.shelfType,
7941
- 'productPerShelf': configShelf.productPerShelf,
7942
- 'trayRows': configShelf.trayRows,
7943
- 'productPerTray': configShelf.productPerTray,
7944
- 'zone': configShelf.zone,
7945
- };
7946
-
7947
- await fixtureShelfService.upsertOne(
7948
- {
7949
- fixtureId: createdFixture._id,
7950
- shelfNumber: j + 1,
7951
- },
7952
- shelfData,
7953
- );
7954
- } );
7955
- }
7956
-
7957
- for ( let index = 0; index < rightFixtures.length; index++ ) {
7958
- const fixture = rightFixtures[index];
7959
-
7960
- const fixtureConfig = await fixtureLibraryService.findOne( { fixtureCategory: fixture.fixtureType } );
7961
- if ( !fixtureConfig ) continue;
7962
- const fixtureConfigDoc = fixtureConfig.toObject();
7963
-
7964
- let mapKey = `${fixtureConfigDoc.fixtureCategory}${fixtureConfigDoc.fixtureWidth.value}${fixtureConfigDoc.fixtureWidth.unit},${fixture.header}`;
7965
-
7966
- const fixtureProductSubBrandName = new Set();
7967
-
7968
-
7969
- const shelfTemplate = fixtureConfigDoc.shelfConfig.map( ( configShelf, j ) => {
7970
- const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
7971
- const shelfSection = shelfZone?.products.find( ( product ) => !product.isMerchandisingElement );
7972
-
7973
- const shelfIdentifier = `shelf${j + 1}=${shelfSection?.productName}`;
7974
-
7975
- mapKey += ','+shelfIdentifier;
7976
-
7977
- const productSubBrandName = shelfSection?.productName?.replace( /\s*PIDs\b/g, '' )?.split( /\s*\+\s*/ ) || [];
7978
-
7979
- productSubBrandName.forEach( ( item ) => fixtureProductSubBrandName.add( item ) );
7980
-
7981
- return {
7982
- shelfNumber: j+1,
7983
- shelfType: configShelf?.shelfType,
7984
- productPerShelf: configShelf?.productPerShelf,
7985
- trayRows: configShelf?.trayRows,
7986
- productBrandName: productSubBrandName,
7987
- zone: configShelf.shelfZone,
7988
- };
7989
- } );
7990
-
7991
- const vmConfig = fixture.productZones?.flatMap( ( zone ) => {
7992
- const vms = zone.products.filter( ( vm ) => vm.isMerchandisingElement );
7993
- const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === zone.zoneName );
7994
- const pids = zone.products.filter( ( vm ) => !vm.isMerchandisingElement );
7995
-
7996
- return vms.map( ( vm, k ) => {
7997
- let configData = vmConfig[0];
7998
-
7999
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' ) {
8000
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 905 );
8001
- configData.zone = 'stretch';
8002
- }
8003
-
8004
- if ( vm.productName === 'Creatr' && zone.zoneName === 'Mid' && pids.length ) {
8005
- configData = vmConfig.find( ( config ) => config.vmWidthmm === 230 );
8006
- }
8007
-
8008
- if ( !configData ) return;
8009
-
8010
- const vmIdentifier = `vm${k+1}=${vm.productName}+${configData.vmHeightmm}+${configData.vmWidthmm}+${configData.startShelf}+${configData.endShelf}+${configData.zone}`;
8011
-
8012
- mapKey += ','+vmIdentifier;
8013
-
8014
- return {
8015
- startYPosition: configData.startShelf,
8016
- endYPosition: configData.endShelf,
8017
- xZone: configData.zone,
8018
- vmName: vm.productName,
8019
- vmHeight: configData.vmHeightmm,
8020
- vmWidth: configData.vmWidthmm,
8021
- imageUrl: zone?.actual_image_url,
8022
- };
8023
- } );
8024
- } );
8025
-
8026
- const vmTemplate = await Promise.all( vmConfig.map( async ( vmTemplate ) => {
8027
- const vmInsertData = {
8028
- clientId: '11',
8029
- vmName: vmTemplate.vmName,
8030
- vmHeight: {
8031
- value: vmTemplate.vmHeight,
8032
- unit: 'mm',
8033
- },
8034
- vmWidth: {
8035
- value: vmTemplate.vmWidth,
8036
- unit: 'mm',
8037
- },
8038
- status: 'complete',
8039
- vmBrand: vmTemplate.vmBrand,
8040
- };
8041
- if ( vmTemplate?.imageUrl ) {
8042
- const parsedUrl = new URL( vmTemplate.imageUrl );
8043
- const attachmentId = parsedUrl.searchParams.get( 'attachment_id' );
8044
-
8045
- const isVmImageExist = await planoVmService.findOne( { crestImageId: attachmentId } );
8046
-
8047
- if ( !isVmImageExist ) {
8048
- const vmImageData = await fetchVmImage( attachmentId );
8049
-
8050
- const imageMeta = await getImageMetadata( vmImageData );
8051
-
8052
- const params = {
8053
- Bucket: JSON.parse( process.env.BUCKET ).storeBuilder,
8054
- Key: `vmType/`,
8055
- fileName: `${attachmentId}.${imageMeta.fileExtension}`,
8056
- ContentType: imageMeta.contentType,
8057
- body: vmImageData,
8058
- };
8059
-
8060
- const imgUpload = await fileUpload( params );
8061
-
8062
- vmInsertData.crestImageId = attachmentId;
8063
- vmInsertData.vmImageUrl = imgUpload.Key;
8064
-
8065
-
8066
- if ( imageMeta.imageShape === 'square' ) {
8067
- vmInsertData.vmHeight.value = 100;
8068
- vmInsertData.vmWidth.value = 230;
8069
- }
8070
- } else {
8071
- vmInsertData.crestImageId = attachmentId;
8072
- vmInsertData.vmImageUrl = isVmImageExist.toObject().vmImageUrl;
8073
- }
8074
- }
8075
-
8076
- const vmDetails = await planoVmService.upsertOne(
8077
- {
8078
- 'productName': vmInsertData.vmName,
8079
- },
8080
- vmInsertData,
8081
- );
8082
-
8083
- return {
8084
- vmId: vmDetails.toObject()._id,
8085
- startYPosition: vmTemplate.startYPosition,
8086
- endYPosition: vmTemplate.endYPosition,
8087
- xZone: vmTemplate.xZone,
8088
- };
8089
- } ) );
8090
-
8091
- const baseFixtureName = `${fixtureConfigDoc.fixtureCategory}`;
8092
- const uniqueFixtureName = await generateFixtureTemplateName( baseFixtureName, fixtureConfigDoc.fixtureWidth );
8093
-
8094
-
8095
- const fixtureTemplateData = {
8096
- ...fixtureConfigDoc,
8097
- 'shelfConfig': shelfTemplate,
8098
- 'vmConfig': vmTemplate,
8099
- 'clientId': fixtureConfigDoc.clientId,
8100
- 'fixtureName': uniqueFixtureName,
8101
- 'header': {
8102
- label: fixture.header ? fixture.header : fixture.fixtureSubname[0],
8103
- isEnabled: true,
8104
- },
8105
- 'footer': {
8106
- label: fixture.footer,
8107
- isEnabled: true,
8108
- },
8109
- 'isBodyEnabled': true,
8110
- 'productResolutionLevel': 'L3',
8111
- 'productBrandName': [ ...fixtureProductSubBrandName ],
8112
- 'fixtureLibraryId': fixtureConfigDoc._id,
8113
- 'crestMapKey': mapKey,
8114
- };
8115
-
8116
- delete fixtureTemplateData._id;
8117
-
8118
-
8119
- const fixtureTemplate = await fixtureConfigService.upsertOne(
8120
- { crestMapKey: mapKey },
8121
- fixtureTemplateData,
8122
- );
8123
-
8124
- const fixtureData = {
8125
- ...fixtureTemplate.toObject(),
8126
- 'storeName': layoutDoc.storeName,
8127
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
8128
- 'planoId': layoutDoc.planoId,
8129
- 'floorId': layoutDoc._id,
8130
- 'associatedElementType': 'wall',
8131
- 'associatedElementNumber': 3,
8132
- 'relativePosition': {
8133
- 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
8134
- 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
8135
- 'unit': 'ft',
8136
- },
8137
- 'fixtureNumber': fixtureCounter,
8138
- 'relativeDetailedPosition': {
8139
- 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
8140
- 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
8141
- 'unit': 'ft',
8142
- },
8143
- 'associatedElementFixtureNumber': index+1,
8144
- 'fixtureConfigId': fixtureTemplate.toObject()._id,
8145
- };
8146
-
8147
- delete fixtureData._id;
8148
- delete fixtureData.shelfConfig;
8149
-
8150
- const createdFixture = await storeFixtureService.upsertOne(
8151
- {
8152
- floorId: layoutDoc._id,
8153
- fixtureNumber: fixtureCounter++,
8154
- },
8155
- fixtureData,
8156
- );
8157
-
8158
- if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
8159
-
8160
- fixtureTemplate.shelfConfig.forEach( async ( configShelf, j ) => {
8161
- const shelfData = {
8162
- 'clientId': '11',
8163
- 'storeName': layoutDoc.storeName,
8164
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
8165
- 'planoId': layoutDoc.planoId,
8166
- 'floorId': layoutDoc._id,
8167
- 'fixtureId': createdFixture._id,
8168
- 'shelfNumber': j + 1,
8169
- 'shelfOrder': 'LTR',
8170
- 'shelfCapacity': configShelf.shelfCapacity,
8171
- 'productBrandName': configShelf.productBrandName,
8172
- 'shelfType': configShelf.shelfType,
8173
- 'productPerShelf': configShelf.productPerShelf,
8174
- 'trayRows': configShelf.trayRows,
8175
- 'productPerTray': configShelf.productPerTray,
8176
- 'zone': configShelf.zone,
8177
- };
8178
-
8179
- await fixtureShelfService.upsertOne(
8180
- {
8181
- fixtureId: createdFixture._id,
8182
- shelfNumber: j + 1,
8183
- },
8184
- shelfData,
8185
- );
8186
- } );
8187
- }
8188
-
8189
- for ( let index = 0; index < floorFixtures.length; index++ ) {
8190
- const fixture = floorFixtures[index];
8191
-
8192
- const centerRow = Math.floor( totalRows / 2 );
8193
-
8194
- const startingX = roundToTwo( ( finalXDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) );
8195
- const detailedStartingX = roundToTwo( ( finalXDetailedDistance / 2 - ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) );
8196
-
8197
- const startingY = finalYDistance / 2 - centerRow * ( constantFixtureWidth / mmToFeet );
8198
- const detailedStartingY = finalYDetailedDistance / 2 - centerRow * ( constantDetailedFixtureWidth / mmToFeet );
8199
-
8200
- const colIndex = Math.floor( index / 2 );
8201
- const rowIndex = index % 2 === 0 ? 1 : 0;
8202
-
8203
- const xPos = roundToTwo( startingX + colIndex * ( constantFixtureLength / mmToFeet ) );
8204
- const yPos = roundToTwo( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) );
8205
-
8206
- const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
8207
- const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
8208
-
8209
- const fixtureConfig = await fixtureLibraryService.findOne( { fixtureCategory: fixture.main } );
8210
- if ( !fixtureConfig ) continue;
8211
- const fixtureConfigDoc = fixtureConfig.toObject();
8212
-
8213
- let mapKey = `${fixtureConfigDoc.fixtureCategory}${fixtureConfigDoc.fixtureWidth.value}${fixtureConfigDoc.fixtureWidth.unit},${fixture.header}`;
8214
-
8215
- const fixtureProductSubBrandName = new Set();
8216
-
8217
-
8218
- const shelfTemplate = fixtureConfigDoc.shelfConfig.map( ( configShelf, j ) => {
8219
- const shelfSection = fixture?.centerSuperSubMain?.find( ( product ) => !product.isVisualMerchandiser );
8220
-
8221
- const shelfIdentifier = `shelf${j + 1}=${shelfSection?.productName}`;
8222
-
8223
- mapKey += ','+shelfIdentifier;
8224
-
8225
-
8226
- let productSubBrandName = fixture.centerSubMain.replace( /\s*PIDs\b/g, '' )?.split( /\s*\+\s*/ ) || [];
8227
-
8228
- if ( shelfSection ) {
8229
- productSubBrandName = shelfSection.name.replace( /\s*PIDs\b/g, '' )?.split( /\s*\+\s*/ ) || [];
8230
- }
8231
-
8232
- productSubBrandName.forEach( ( item ) => fixtureProductSubBrandName.add( item ) );
8233
-
8234
- return {
8235
- shelfNumber: j+1,
8236
- shelfType: configShelf?.shelfType,
8237
- productPerShelf: configShelf?.productPerShelf,
8238
- trayRows: configShelf?.trayRows,
8239
- productBrandName: productSubBrandName,
8240
- zone: configShelf.shelfZone,
8241
- };
8242
- } );
8243
-
8244
- const vmConfig = fixture.centerSuperSubMain?.flatMap( ( vm ) => {
8245
- if ( !vm?.isVisualMerchandiser ) {
8246
- return [];
8247
- }
8248
- const vmConfig = fixtureConfigDoc.vmConfig;
8249
-
8250
- const [ configData1, configData2 ] = [ vmConfig[0], vmConfig[1] ];
8251
-
8252
- return [
8253
- {
8254
- startYPosition: configData1.startShelf,
8255
- endYPosition: configData1.endShelf,
8256
- xZone: configData1.zone,
8257
- vmName: vm.name + ' - 1',
8258
- vmHeight: configData1.vmHeightmm,
8259
- vmWidth: configData1.vmWidthmm,
8260
- },
8261
- {
8262
- startYPosition: configData2.startShelf,
8263
- endYPosition: configData2.endShelf,
8264
- xZone: configData2.zone,
8265
- vmName: vm.name + ' - 2',
8266
- vmHeight: configData2.vmHeightmm,
8267
- vmWidth: configData2.vmWidthmm,
8268
- },
8269
- ];
8270
- } );
8271
-
8272
- const vmTemplate = await Promise.all( vmConfig.map( async ( vmTemplate ) => {
8273
- const vmInsertData = {
8274
- clientId: '11',
8275
- vmName: vmTemplate.vmName,
8276
- vmHeight: {
8277
- value: vmTemplate.vmHeight,
8278
- unit: 'mm',
8279
- },
8280
- vmWidth: {
8281
- value: vmTemplate.vmWidth,
8282
- unit: 'mm',
8283
- },
8284
- status: 'complete',
8285
- vmBrand: vmTemplate.vmBrand,
8286
- };
8287
-
8288
- const vmDetails = await planoVmService.upsertOne(
8289
- {
8290
- 'vmName': vmInsertData.vmName,
8291
- },
8292
- vmInsertData,
8293
- );
8294
-
8295
- return {
8296
- vmId: vmDetails.toObject()._id,
8297
- startYPosition: vmTemplate.startYPosition,
8298
- endYPosition: vmTemplate.endYPosition,
8299
- xZone: vmTemplate.xZone,
8300
- };
8301
- } ) );
8302
-
8303
- const baseFixtureName = `${fixtureConfigDoc.fixtureCategory}`;
8304
- const uniqueFixtureName = await generateFixtureTemplateName( baseFixtureName, fixtureConfigDoc.fixtureWidth );
8305
-
8306
-
8307
- const fixtureTemplateData = {
8308
- ...fixtureConfigDoc,
8309
- 'shelfConfig': shelfTemplate,
8310
- 'vmConfig': vmTemplate,
8311
- 'clientId': fixtureConfigDoc.clientId,
8312
- 'fixtureName': uniqueFixtureName,
8313
- 'header': {
8314
- label: fixture.centerSubMain,
8315
- isEnabled: true,
8316
- },
8317
- 'footer': {
8318
- label: 'Storage Box',
8319
- isEnabled: true,
8320
- },
8321
- 'isBodyEnabled': true,
8322
- 'productResolutionLevel': 'L3',
8323
- 'productBrandName': [ ...fixtureProductSubBrandName ],
8324
- 'fixtureLibraryId': fixtureConfigDoc._id,
8325
- 'crestMapKey': mapKey,
8326
- };
8327
-
8328
-
8329
- delete fixtureTemplateData._id;
8330
-
8331
-
8332
- const fixtureTemplate = await fixtureConfigService.upsertOne(
8333
- { crestMapKey: mapKey },
8334
- fixtureTemplateData,
8335
- );
8336
-
8337
- const fixtureData = {
8338
- ...fixtureTemplate.toObject(),
8339
- 'storeName': layoutDoc.storeName,
8340
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
8341
- 'planoId': layoutDoc.planoId,
8342
- 'floorId': layoutDoc._id,
8343
- 'relativePosition': {
8344
- 'x': xPos,
8345
- 'y': yPos,
8346
- 'unit': 'ft',
8347
- },
8348
- 'fixtureNumber': fixtureCounter,
8349
- 'relativeDetailedPosition': {
8350
- 'x': detailedXPos,
8351
- 'y': detailedYPos,
8352
- 'unit': 'ft',
8353
- },
8354
- 'associatedElementFixtureNumber': index+1,
8355
- 'fixtureConfigId': fixtureTemplate.toObject()._id,
8356
- };
8357
-
8358
- delete fixtureData._id;
8359
- delete fixtureData.shelfConfig;
8360
-
8361
- const createdFixture = await storeFixtureService.upsertOne(
8362
- {
8363
- floorId: layoutDoc._id,
8364
- fixtureNumber: fixtureCounter++,
8365
- },
8366
- fixtureData,
8367
- );
8368
-
8369
- if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
8370
-
8371
- fixtureTemplate.shelfConfig.forEach( async ( configShelf, j ) => {
8372
- const shelfData = {
8373
- 'clientId': '11',
8374
- 'storeName': layoutDoc.storeName,
8375
- 'storeId': storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
8376
- 'planoId': layoutDoc.planoId,
8377
- 'floorId': layoutDoc._id,
8378
- 'fixtureId': createdFixture._id,
8379
- 'shelfNumber': j + 1,
8380
- 'shelfOrder': 'LTR',
8381
- 'shelfCapacity': configShelf.shelfCapacity,
8382
- 'productBrandName': configShelf.productBrandName,
8383
- 'shelfType': configShelf.shelfType,
8384
- 'productPerShelf': configShelf.productPerShelf,
8385
- 'trayRows': configShelf.trayRows,
8386
- 'productPerTray': configShelf.productPerTray,
8387
- 'zone': configShelf.zone,
8388
- };
8389
-
8390
- await fixtureShelfService.upsertOne(
8391
- {
8392
- fixtureId: createdFixture._id,
8393
- shelfNumber: j + 1,
8394
- },
8395
- shelfData,
8396
- );
8397
- } );
8398
- }
8399
-
8400
-
8401
- const now = Date.now();
8402
- const elapsedMinutes = ( now - startTime ) / 1000 / 60;
8403
- console.log( `Store name: ${storeData.storeName},Floor name: ${floorArray[floorIndex]} Iteration ${i + 1}/${storeList?.length}: total elapsed time = ${elapsedMinutes.toFixed( 2 )} minutes` );
8404
- logger.info( { functionName: 'updateCrestPlanogram', body: `Store name: ${storeData.storeName},Floor name: ${floorArray[floorIndex]} Iteration ${i + 1}/${storeList?.length}: total elapsed time = ${elapsedMinutes.toFixed( 2 )} minutes` } );
8405
- }
8406
- }
8407
-
8408
- res.sendSuccess( 'Updated Successfully' );
8409
- } catch ( e ) {
8410
- logger.error( { functionName: 'updateCrestPlanogram', error: e } );
8411
- return res.sendError( e.message || 'Internal Server Error', 500 );
8412
- }
7151
+ xlsx.writeFile( workbook, filePath );
8413
7152
  }
8414
- // function fillFeedbackFromJson( excelPath, jsonData, outputPath ) {
8415
- // const workbook = xlsx.readFile( excelPath );
8416
- // const sheetName = workbook.SheetNames[0];
8417
- // const sheet = workbook.Sheets[sheetName];
8418
-
8419
- // const data = xlsx.utils.sheet_to_json( sheet, { defval: 'Transformed by Data.Page' } );
8420
-
8421
- // const feedbackMap = {};
8422
- // jsonData.forEach( ( entry ) => {
8423
- // feedbackMap[entry.store] = entry.videoUrl;
8424
- // } );
8425
-
8426
- // const updatedData = data.map( ( row ) => {
8427
- // const store = row.storeName;
8428
- // if ( feedbackMap[store] ) {
8429
- // row.FeedBack = feedbackMap[store];
8430
- // }
8431
- // return row;
8432
- // } );
8433
-
8434
- // const newSheet = xlsx.utils.json_to_sheet( updatedData );
8435
-
8436
- // workbook.Sheets[sheetName] = newSheet;
8437
-
8438
- // xlsx.writeFile( workbook, outputPath );
8439
- // }
8440
-
8441
- // fillFeedbackFromJson('input.xlsx', feedbackJson, 'output.xlsx');
8442
-
8443
-
8444
- // function exportFixtureJsonToExcel( fixtures, filePath ) {
8445
- // const fixtureInfoArr = [];
8446
- // const shelfConfigArr = [];
8447
- // const vmConfigArr = [];
8448
-
8449
- // for ( const fixture of fixtures ) {
8450
- // fixtureInfoArr.push( {
8451
- // clientId: fixture.clientId,
8452
- // fixtureCode: fixture.fixtureCode,
8453
- // fixtureCategory: fixture.fixtureCategory,
8454
- // fixtureConfigType: fixture.fixtureConfigType,
8455
- // fixtureLength: `${fixture.fixtureLength?.value} ${fixture.fixtureLength?.unit}`,
8456
- // fixtureCapacity: fixture.fixtureCapacity,
8457
- // } );
8458
-
8459
- // ( fixture.shelfConfig || [] ).forEach( ( shelf ) => {
8460
- // shelfConfigArr.push( {
8461
- // fixtureCode: fixture.fixtureCode,
8462
- // ...shelf,
8463
- // } );
8464
- // } );
8465
-
8466
- // ( fixture.vmConfig || [] ).forEach( ( vm ) => {
8467
- // vmConfigArr.push( {
8468
- // fixtureCode: fixture.fixtureCode,
8469
- // ...vm,
8470
- // } );
8471
- // } );
8472
- // }
8473
-
8474
- // const workbook = xlsx.utils.book_new();
8475
- // xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( fixtureInfoArr ), 'Fixture Info' );
8476
- // xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( shelfConfigArr ), 'Shelf Config' );
8477
- // xlsx.utils.book_append_sheet( workbook, xlsx.utils.json_to_sheet( vmConfigArr ), 'VM Config' );
8478
-
8479
- // xlsx.writeFile( workbook, filePath );
8480
- // }
8481
7153
 
8482
7154
  // const fixtures = JSON.parse( fs.readFileSync( './input.json', 'utf-8' ) );
8483
7155
  // exportFixtureJsonToExcel( fixtures, 'output.xlsx' );