tango-app-api-store-builder 1.0.0-beta-75 → 1.0.0-beta-77

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.
@@ -15,6 +15,9 @@ import * as planoTaskService from '../service/planoTask.service.js';
15
15
  import * as fixtureConfigService from '../service/fixtureConfig.service.js';
16
16
  import mongoose from 'mongoose';
17
17
  import JSZip from 'jszip';
18
+ import { signedUrl } from 'tango-app-api-middleware';
19
+ import fs from 'fs';
20
+ import https from 'https';
18
21
 
19
22
 
20
23
  export async function getStoreNames( req, res ) {
@@ -1777,6 +1780,28 @@ export async function getProdTaskData( req, res ) {
1777
1780
  }
1778
1781
  }
1779
1782
 
1783
+ export async function extractZipFileNames( req, res ) {
1784
+ try {
1785
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
1786
+ return res.sendError( 'Unauthorized', 401 );
1787
+ }
1788
+
1789
+ if ( !req.files.file ) {
1790
+ return res.sendError( 'No file uploaded', 400 );
1791
+ }
1792
+
1793
+ const zip = new JSZip();
1794
+ const zipContents = await zip.loadAsync( req.files.file.data );
1795
+
1796
+ const fileNames = Object.keys( zipContents.files );
1797
+
1798
+ return res.sendSuccess( { fileNames } );
1799
+ } catch ( e ) {
1800
+ logger.error( { functionName: 'extractZipFileNames', error: e } );
1801
+ return res.sendError( e.message || 'Internal Server Error', 500 );
1802
+ }
1803
+ }
1804
+
1780
1805
  export async function updatelayoutFeedback( req, res ) {
1781
1806
  try {
1782
1807
  if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
@@ -1825,6 +1850,9 @@ export async function updatelayoutFeedback( req, res ) {
1825
1850
  case 'Wall 3':
1826
1851
  rightFixtures.push( {} );
1827
1852
  break;
1853
+ case 'centre':
1854
+ floorFixtures.push( {} );
1855
+ break;
1828
1856
 
1829
1857
  default:
1830
1858
  break;
@@ -1939,28 +1967,6 @@ export async function updatelayoutFeedback( req, res ) {
1939
1967
  }
1940
1968
  }
1941
1969
 
1942
- export async function extractZipFileNames( req, res ) {
1943
- try {
1944
- if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
1945
- return res.sendError( 'Unauthorized', 401 );
1946
- }
1947
-
1948
- if ( !req.files.file ) {
1949
- return res.sendError( 'No file uploaded', 400 );
1950
- }
1951
-
1952
- const zip = new JSZip();
1953
- const zipContents = await zip.loadAsync( req.files.file.data );
1954
-
1955
- const fileNames = Object.keys( zipContents.files );
1956
-
1957
- return res.sendSuccess( { fileNames } );
1958
- } catch ( e ) {
1959
- logger.error( { functionName: 'extractZipFileNames', error: e } );
1960
- return res.sendError( e.message || 'Internal Server Error', 500 );
1961
- }
1962
- }
1963
-
1964
1970
  export async function updateFixtureFeedback( req, res ) {
1965
1971
  try {
1966
1972
  if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
@@ -1987,7 +1993,7 @@ export async function updateFixtureFeedback( req, res ) {
1987
1993
 
1988
1994
  const planogram = await planoService.findOne( { storeName: store.storeName } );
1989
1995
 
1990
- const fixtureTaskList = await planoTaskService.find( { planoId: planogram.toObject()._id, type: 'fixture' } );
1996
+ const fixtureTaskList = await planoTaskService.find( { planoId: planogram.toObject()._id, type: 'fixture', date_string: store.date } );
1991
1997
 
1992
1998
  for ( let j = 0; j < fixtureTaskList.length; j++ ) {
1993
1999
  const fixtureTask = fixtureTaskList[j].toObject();
@@ -2002,6 +2008,38 @@ export async function updateFixtureFeedback( req, res ) {
2002
2008
 
2003
2009
  const fixtureDoc = fixture?.toObject();
2004
2010
 
2011
+ if ( q1.issues.includes( 'Fixture size is wrong' ) ) {
2012
+ const fixtureConfig = await fixtureConfigService.findOne( { 'fixtureLength.value': q1.data.fixtureSize.value } );
2013
+
2014
+ if ( fixtureConfig && fixtureConfig.toObject()?.fixtureCode ) {
2015
+ await storeFixtureService.updateOne( { _id: fixtureDoc._id }, { fixtureCode: fixtureConfig.toObject().fixtureCode } );
2016
+ }
2017
+ }
2018
+
2019
+ if ( q1.issues.includes( 'Fixture type is wrong' ) ) {
2020
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: q1.data.fixtureType } );
2021
+
2022
+ if ( fixtureConfig && fixtureConfig.toObject().fixtureCode ) {
2023
+ await storeFixtureService.updateOne( { _id: fixtureDoc._id }, { fixtureCode: fixtureConfig.toObject().fixtureCode } );
2024
+ }
2025
+ }
2026
+
2027
+ if ( q1.issues.includes( 'Fixture brand is wrong' ) ) {
2028
+ const fixtureBrand = q1.data.fixtureBrand;
2029
+
2030
+ if ( fixtureBrand?.length ) {
2031
+ const formattedfixtureBrand = fixtureBrand.length ? ( fixtureBrand.length > 1 ? fixtureBrand.join( ' + ' ) : fixtureBrand[0] ) : undefined;
2032
+
2033
+ await storeFixtureService.updateOne( { _id: fixtureDoc._id }, { fixtureName: formattedfixtureBrand, fixtureBrandCategory: formattedfixtureBrand } );
2034
+ }
2035
+ }
2036
+
2037
+ if ( q1.issues.includes( 'Fixture not in the store' ) ) {
2038
+ await storeFixtureService.deleteOne( { _id: fixtureDoc._id } );
2039
+ await fixtureShelfService.deleteMany( { fixtureId: fixtureDoc._id } );
2040
+ await planoMappingService.deleteMany( { fixtureId: fixtureDoc._id } );
2041
+ }
2042
+
2005
2043
 
2006
2044
  if ( q1.issues.includes( 'Shelves count/Product Category/Capacity is wrong' ) ) {
2007
2045
  const taskShelves = q1.data.shelves;
@@ -2022,7 +2060,6 @@ export async function updateFixtureFeedback( req, res ) {
2022
2060
  const section = taskShelf.section;
2023
2061
  const subBrand = taskShelf.subBrand;
2024
2062
  const formattedsubBrand = subBrand.length ? ( subBrand.length > 1 ? subBrand.join( ' + ' ) : subBrand[0] ) : undefined;
2025
- // const formattedsubBrand = subBrand ? subBrand : undefined;
2026
2063
 
2027
2064
  if ( taskShelves.length === fixtureShelves.length ) {
2028
2065
  const fixtureShelf = fixtureShelves.filter( ( shelf ) => {
@@ -2037,18 +2074,17 @@ export async function updateFixtureFeedback( req, res ) {
2037
2074
  return shelf.toObject().shelfNumber === k+1;
2038
2075
  } );
2039
2076
 
2040
-
2041
2077
  const updateShelf = await fixtureShelfService.updateOne( { _id: fixtureShelf?.[0].toObject()._id }, { shelfCapacity: productCapacity, sectionName: formattedsubBrand, sectionZone: section } );
2042
2078
 
2043
2079
  console.log( updateShelf );
2044
2080
 
2045
-
2046
2081
  const shelfDifference = fixtureShelves.length - taskShelves.length;
2047
2082
 
2048
2083
  const shelvesToDelete = fixtureShelves.slice( -shelfDifference );
2049
2084
 
2050
2085
  shelvesToDelete.map( async ( shelf ) => {
2051
2086
  await fixtureShelfService.deleteOne( { _id: shelf.toObject()._id } );
2087
+ await planoMappingService.deleteMany( { shelfId: shelf.toObject()._id } );
2052
2088
  } );
2053
2089
  } else if ( taskShelves.length > fixtureShelves.length ) {
2054
2090
  if ( k + 1 <= fixtureShelves.length ) {
@@ -2082,11 +2118,1179 @@ export async function updateFixtureFeedback( req, res ) {
2082
2118
  }
2083
2119
  }
2084
2120
  }
2121
+
2122
+ const vmTaskList = await planoTaskService.find( { planoId: planogram.toObject()._id, type: 'vm', date_string: store.date } );
2123
+
2124
+ for ( let j = 0; j < vmTaskList.length; j++ ) {
2125
+ const vmTask = vmTaskList[j].toObject();
2126
+
2127
+ const [ q1, q2 ] = vmTask.answers;
2128
+
2129
+ if ( q1.value ) continue;
2130
+
2131
+ const removeVms = q1.selectedVMs.forEach( async ( vmId ) => {
2132
+ if ( !vmId ) return;
2133
+ const vmObjectId = new mongoose.Types.ObjectId( vmId );
2134
+
2135
+ const deletedVm = await planoMappingService.deleteOne( { _id: vmObjectId } );
2136
+
2137
+ return deletedVm;
2138
+ } );
2139
+
2140
+ console.log( removeVms, 'removed vms' );
2141
+
2142
+ const newVms = q1.newVmsType.forEach( async ( vmType ) => {
2143
+ const vm = await planoProductService.findOne( { type: 'vm', productName: vmType } );
2144
+
2145
+ if ( !vm ) return;
2146
+
2147
+ const insertData = {
2148
+ 'clientId': planogram.toObject().clientId,
2149
+ 'storeName': planogram.toObject().storeName,
2150
+ 'storeId': planogram.toObject().storeId,
2151
+ 'type': 'vm',
2152
+ 'planoId': planogram.toObject()._id,
2153
+ 'floorId': vmTask.floorId,
2154
+ 'fixtureId': vmTask.fixtureId,
2155
+ 'productId': vm.toObject()._id,
2156
+ };
2157
+
2158
+ const insertedVm = await planoMappingService.create( insertData );
2159
+
2160
+ return insertedVm;
2161
+ } );
2162
+
2163
+ console.log( newVms, 'new vms' );
2164
+ }
2085
2165
  }
2086
2166
 
2087
2167
  res.sendSuccess( 'Updated successfully' );
2088
2168
  } catch ( e ) {
2089
- logger.error( { functionName: 'updatelayoutFeedback', error: e } );
2169
+ logger.error( { functionName: 'updateFixtureFeedback', error: e } );
2170
+ return res.sendError( e.message || 'Internal Server Error', 500 );
2171
+ }
2172
+ }
2173
+
2174
+ export async function getVmTaskData( req, res ) {
2175
+ try {
2176
+ const { storeName, date } = req.body;
2177
+
2178
+ const planogram = await planoService.findOne( { storeName: storeName } );
2179
+
2180
+ const vmTaskList = await planoTaskService.find( { planoId: planogram.toObject()._id, type: 'vm', date_string: date } );
2181
+
2182
+ if ( !vmTaskList?.length ) {
2183
+ return res.sendError( 'No data', 204 );
2184
+ }
2185
+
2186
+ const storefixtures = await storeFixtureService.findAndSort( { planoId: planogram.toObject()._id, fixtureType: { $ne: 'other' } }, { fixtureName: 1, fixtureNumber: 1, _id: 1 }, { fixtureNumber: 1 } );
2187
+
2188
+ const fixtureVmData = await Promise.all(
2189
+ storefixtures.map( async ( fixture ) => {
2190
+ const fixtureDoc = fixture.toObject();
2191
+ const vmTasks = await planoTaskService.find( { fixtureId: fixture._id, type: 'vm' } );
2192
+
2193
+ const q2 = vmTasks[0].toObject().answers?.[1];
2194
+
2195
+ const params = {
2196
+ Bucket: JSON.parse( process.env.BUCKET ).storeBuilder,
2197
+ file_path: q2?.image || null,
2198
+ };
2199
+
2200
+ const fixtureImage = await signedUrl( params );
2201
+
2202
+ const vmTaskData = await Promise.all(
2203
+ vmTasks.flatMap( ( task ) => {
2204
+ const q1 = task.toObject().answers?.[0];
2205
+
2206
+ if ( !q1?.newVmsType || !q1?.newVms ) return [];
2207
+
2208
+ return q1.newVmsType.map( async ( vmtype, k ) => {
2209
+ const params = {
2210
+ Bucket: JSON.parse( process.env.BUCKET ).storeBuilder,
2211
+ file_path: q1.newVms[k]?.imageUrl || null,
2212
+ };
2213
+ const signedImg = await signedUrl( params );
2214
+
2215
+ return {
2216
+ vmtype,
2217
+ vmImg: signedImg,
2218
+ };
2219
+ } );
2220
+ } ),
2221
+ );
2222
+
2223
+ return {
2224
+ vms: vmTaskData,
2225
+ fixtureImg: fixtureImage,
2226
+ ...fixtureDoc,
2227
+ };
2228
+ } ),
2229
+ );
2230
+ return res.sendSuccess( fixtureVmData );
2231
+ } catch ( e ) {
2232
+ logger.error( { functionName: 'getVmTaskData', error: e } );
2233
+ return res.sendError( e.message || 'Internal Server Error', 500 );
2234
+ }
2235
+ }
2236
+
2237
+
2238
+ export async function updateVmData( req, res ) {
2239
+ try {
2240
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
2241
+ return res.sendError( 'Unauthorized', 401 );
2242
+ }
2243
+
2244
+ if ( !req.files.file ) {
2245
+ return res.sendError( 'Excel file is required', 400 );
2246
+ }
2247
+
2248
+ const workbook = xlsx.read( req.files.file.data, { type: 'buffer' } );
2249
+ const sheetName = 'Basha';
2250
+ const raw = xlsx.utils.sheet_to_json( workbook.Sheets[sheetName] );
2251
+
2252
+ let initId = 81;
2253
+
2254
+ for ( let i = 0; i < raw.length; i++ ) {
2255
+ const vmData = raw[i];
2256
+
2257
+ const vmInsertData = {
2258
+ 'clientId': '11',
2259
+ 'type': 'vm',
2260
+ 'productId': 'VM' + initId,
2261
+ 'productName': vmData?.['VM Categories '],
2262
+ 'productHeight': {
2263
+ 'value': vmData?.['VM Height mm'],
2264
+ 'unit': 'mm',
2265
+ },
2266
+ 'productWidth': {
2267
+ 'value': vmData?.['VM Width mm'],
2268
+ 'unit': 'mm',
2269
+ },
2270
+ 'startYPosition': vmData?.['StartPosition '],
2271
+ 'endYPosition': vmData?.['End Position'],
2272
+ 'xZone': vmData?.['Start Zone '],
2273
+ };
2274
+
2275
+ const createdVm = await planoProductService.create( vmInsertData );
2276
+
2277
+ initId += 1;
2278
+
2279
+ const fixture = await storeFixtureService.findOne( { storeName: vmData?.['Store name '], fixtureNumber: vmData?.['Fixture Number'] } );
2280
+
2281
+ const fixtureDoc = fixture?.toObject();
2282
+
2283
+ if ( !fixture ) {
2284
+ continue;
2285
+ }
2286
+
2287
+ const mappingData = {
2288
+ 'clientId': '11',
2289
+ 'storeName': fixtureDoc.storeName,
2290
+ 'storeId': fixtureDoc.storeId,
2291
+ 'type': 'vm',
2292
+ 'planoId': fixtureDoc.planoId,
2293
+ 'floorId': fixtureDoc.floorId,
2294
+ 'fixtureId': fixtureDoc._id,
2295
+ 'productId': createdVm.toObject()._id,
2296
+ };
2297
+
2298
+ await planoMappingService.create( mappingData );
2299
+ }
2300
+
2301
+ res.sendSuccess( 'Updated Successfully' );
2302
+ } catch ( e ) {
2303
+ logger.error( { functionName: 'getVmTaskData', error: e } );
2090
2304
  return res.sendError( e.message || 'Internal Server Error', 500 );
2091
2305
  }
2092
2306
  }
2307
+
2308
+
2309
+ async function scrapeCrest() {
2310
+ const storeIds = [];
2311
+ const apiUrl = 'https://api.getcrest.ai/api/ms_shelfsensei/layout/';
2312
+ const bearerToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzQzNjY5ODIyLCJpYXQiOjE3NDM2NjYyMjIsImp0aSI6IjA5ZDRjYTVhZGRiNzQxMDVhYjhjOWVjMmU3MjZiM2NiIiwidXNlcl9pZCI6MTA4NSwiaWQiOjEwODUsImN1c3RvbWVyX2dyb3VwIjozOTgsImxpY2VuY2Vfc2NvcGVzIjpbeyJyZXNvdXJjZV9zZXQiOiJwcF9zZXQiLCJzY29wZV9yb2xlIjoiY29udHJpYnV0b3IifSx7InJlc291cmNlX3NldCI6ImRwX3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9LHsicmVzb3VyY2Vfc2V0IjoiZGZfc2V0Iiwic2NvcGVfcm9sZSI6ImNvbnRyaWJ1dG9yIn0seyJyZXNvdXJjZV9zZXQiOiJkZWZhdWx0X3NldCIsInNjb3BlX3JvbGUiOiJjb250cmlidXRvciJ9XX0.C3wLXzbv0bTDGiZqs8jSA3up0cq0wqA5PIMw45_T4Wg';
2313
+ const filePath = 'response.json';
2314
+ let allResults = [];
2315
+
2316
+ if ( fs.existsSync( filePath ) ) {
2317
+ try {
2318
+ const existingData = fs.readFileSync( filePath, 'utf8' );
2319
+ allResults = JSON.parse( existingData );
2320
+ if ( !Array.isArray( allResults ) ) {
2321
+ allResults = [];
2322
+ }
2323
+ } catch ( error ) {
2324
+ console.error( 'Error reading existing JSON file:', error.message );
2325
+ allResults = [];
2326
+ }
2327
+ }
2328
+
2329
+ for ( const storeId of storeIds ) {
2330
+ try {
2331
+ const result = await new Promise( ( resolve ) => {
2332
+ const payload = JSON.stringify( { store_id: storeId } );
2333
+ const options = {
2334
+ method: 'POST',
2335
+ headers: {
2336
+ 'Authorization': `Bearer ${bearerToken}`,
2337
+ 'Content-Type': 'application/json',
2338
+ 'Content-Length': Buffer.byteLength( payload ),
2339
+ },
2340
+ };
2341
+
2342
+ const req = https.request( apiUrl, options, ( res ) => {
2343
+ let data = '';
2344
+ res.on( 'data', ( chunk ) => {
2345
+ data += chunk;
2346
+ } );
2347
+ res.on( 'end', () => {
2348
+ try {
2349
+ const jsonData = JSON.parse( data );
2350
+ const result = { storeName: storeId, data: jsonData };
2351
+ allResults.push( result );
2352
+ fs.writeFileSync( filePath, JSON.stringify( allResults, null, 2 ) );
2353
+ console.log( 'Received Data:', result );
2354
+ resolve( result );
2355
+ } catch ( error ) {
2356
+ console.error( `Error parsing JSON for ${storeId}:`, error.message );
2357
+ resolve( { storeName: storeId, data: null } );
2358
+ }
2359
+ } );
2360
+ } );
2361
+
2362
+ req.on( 'error', ( error ) => {
2363
+ console.error( `Error fetching data for ${storeId}:`, error.message );
2364
+ resolve( { storeName: storeId, data: null } );
2365
+ } );
2366
+
2367
+ req.write( payload );
2368
+ req.end();
2369
+ } );
2370
+ } catch ( error ) {
2371
+ console.error( `Unexpected error for ${storeId}:`, error.message );
2372
+ }
2373
+ await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) );
2374
+ }
2375
+ }
2376
+
2377
+ export async function createCrestPlanogram( req, res ) {
2378
+ try {
2379
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
2380
+ return res.sendError( 'Unauthorized', 401 );
2381
+ }
2382
+
2383
+ if ( !req.files || !req.files.file ) {
2384
+ return res.sendError( 'JSON file is required', 400 );
2385
+ }
2386
+
2387
+ const data = JSON.parse( req.files.file.data.toString( 'utf8' ) );
2388
+
2389
+ const crestData = data.filter( ( item ) => item.data.message === 'SUCCESS' );
2390
+
2391
+ const constantFixtureLength = 1220;
2392
+ const constantDetailedFixtureLength = 1220;
2393
+
2394
+ const constantFixtureWidth = 610;
2395
+ const constantDetailedFixtureWidth = 1524;
2396
+
2397
+ const mmToFeet = 305;
2398
+
2399
+ function roundToTwo( num ) {
2400
+ return Math.round( num * 100 ) / 100;
2401
+ }
2402
+
2403
+ for ( let i = 0; i < crestData.length; i++ ) {
2404
+ const storeData = crestData[i];
2405
+
2406
+ const storeDetails = await storeService.findOne( { storeName: storeData.storeName } );
2407
+
2408
+ const planoInsertData = {
2409
+ storeName: storeData.storeName,
2410
+ storeId: storeDetails?.toObject()?.storeId ? storeDetails.toObject().storeId : 'nil',
2411
+ layoutName: `${storeData.storeName} - Layout`,
2412
+ clientId: '11',
2413
+ attachments: [],
2414
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
2415
+ createdByName: 'Bejan',
2416
+ createdByEmail: 'bejan@tangotech.co.in',
2417
+ status: 'completed',
2418
+ floorNumber: 1,
2419
+ productResolutionLevel: 'L2',
2420
+ scanType: 'qr',
2421
+ };
2422
+
2423
+ const insertedPlano = await planoService.upsertOne( { storeName: storeData.storeName }, planoInsertData );
2424
+
2425
+ const planoDoc = insertedPlano.toObject();
2426
+
2427
+ const leftWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'LEFT WALL' );
2428
+ const leftFixtures = leftWall.flatMap( ( wall ) => wall.fixtures );
2429
+ const rightWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT WALL' );
2430
+ const rightFixtures = rightWall.flatMap( ( wall ) => wall.fixtures );
2431
+ const backWall = storeData.data.result.filter( ( entry ) => entry['main'] === 'RIGHT VERTICAL WALL' );
2432
+ const backFixtures = backWall.flatMap( ( wall ) => wall.fixtures );
2433
+ const floorFixtures = storeData.data.result.filter( ( entry ) => entry['main'] === 'Euro Center' || entry['main'] === 'Euro Center Dr' );
2434
+
2435
+ const leftXDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
2436
+ const leftXDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( leftFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
2437
+
2438
+ const leftYDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantFixtureWidth / mmToFeet ) ) ) : 0;
2439
+ const leftYDetailedDistanceFeet = leftFixtures.length ? roundToTwo( ( ( constantDetailedFixtureWidth / mmToFeet ) ) ) : 0;
2440
+
2441
+ const rightXDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantFixtureLength / mmToFeet ) ) ) : 0;
2442
+ const rightXDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( rightFixtures.length * ( constantDetailedFixtureLength / mmToFeet ) ) ) : 0;
2443
+
2444
+ const rightYDistanceFeet = rightFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
2445
+ const rightYDetailedDistanceFeet = rightFixtures.length ? roundToTwo( ( constantDetailedFixtureWidth / mmToFeet ) ): 0;
2446
+
2447
+ const maxFixturesPerRow = floorFixtures.length/2;
2448
+ const totalRows = 2;
2449
+
2450
+ const floorXDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantFixtureLength / mmToFeet ) ) ) : 0;
2451
+ const floorXDetailedDistanceFeet = floorFixtures.length ? roundToTwo( ( ( floorFixtures.length/2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ): 0;
2452
+
2453
+ const floorYDistanceFeet = floorFixtures.length ? roundToTwo( ( 2 * ( constantFixtureWidth/ mmToFeet ) ) ): 0;
2454
+ const floorYDetailedDistanceFeet = floorFixtures.length ? roundToTwo( 2 * ( constantDetailedFixtureWidth/mmToFeet ) ): 0;
2455
+
2456
+ const backXDistanceFeet = backFixtures.length ? roundToTwo( ( constantFixtureWidth / mmToFeet ) ) : 0;
2457
+ const backXDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( constantDetailedFixtureLength / mmToFeet ) ) : 0;
2458
+
2459
+ const backYDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantFixtureLength / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantFixtureWidth )/mmToFeet ) ) ) : 0;
2460
+ const backYDetailedDistanceFeet = backFixtures.length ? roundToTwo( ( ( backFixtures.length * ( constantDetailedFixtureWidth / mmToFeet ) ) + ( ( ( leftFixtures.length ? 1 : 0 ) + ( rightFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth )/mmToFeet ) ) ): 0;
2461
+
2462
+ const maxXDistance = Math.max( leftXDistanceFeet, rightXDistanceFeet, floorXDistanceFeet );
2463
+ const maxXDetailedDistance = Math.max( leftXDetailedDistanceFeet, rightXDetailedDistanceFeet, floorXDetailedDistanceFeet );
2464
+
2465
+ const maxYDistance = Math.max( floorYDistanceFeet, backYDistanceFeet );
2466
+ const maxYDetailedDistance = Math.max( floorYDetailedDistanceFeet, backYDetailedDistanceFeet );
2467
+
2468
+ const finalXDistance = roundToTwo( ( maxXDistance < ( backXDistanceFeet + floorXDistanceFeet )? ( ( backXDistanceFeet + floorXDistanceFeet ) + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDistance + ( ( 2 * constantFixtureLength )/mmToFeet ) ) : maxXDistance ) );
2469
+ const finalXDetailedDistance = roundToTwo( ( maxXDetailedDistance < ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet )? ( ( backXDetailedDistanceFeet + floorXDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : ( floorFixtures.length && backFixtures.length ) ? ( maxXDetailedDistance + ( ( 2 * constantDetailedFixtureLength )/mmToFeet ) ) : maxXDetailedDistance ) );
2470
+
2471
+ const finalYDistance = roundToTwo( ( maxYDistance < ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) ? ( ( leftYDistanceFeet + rightYDistanceFeet + floorYDistanceFeet ) + ( ( 2 * constantFixtureWidth )/mmToFeet ) ) : ( maxYDistance + ( ( constantFixtureWidth )/mmToFeet ) ) ) );
2472
+ const finalYDetailedDistance = roundToTwo( ( maxYDetailedDistance < ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) ? ( ( leftYDetailedDistanceFeet + rightYDetailedDistanceFeet + floorYDetailedDistanceFeet ) + ( ( 2 * constantDetailedFixtureWidth )/mmToFeet ) ) : ( maxYDetailedDistance + ( ( constantDetailedFixtureWidth )/mmToFeet ) ) ) );
2473
+
2474
+ const floorInsertData = {
2475
+ storeName: planoDoc.storeName,
2476
+ storeId: planoDoc.storeId,
2477
+ layoutName: `${planoDoc.storeName} - Layout`,
2478
+ clientId: '11',
2479
+ floorNumber: 1,
2480
+ floorName: 'floor 1',
2481
+ layoutPolygon: [
2482
+ {
2483
+ elementType: 'wall',
2484
+ distance: finalXDistance,
2485
+ unit: 'ft',
2486
+ direction: 'right',
2487
+ angle: 90,
2488
+ elementNumber: 1,
2489
+ detailedDistance: finalXDetailedDistance,
2490
+ },
2491
+ {
2492
+ elementType: 'wall',
2493
+ distance: finalYDistance,
2494
+ unit: 'ft',
2495
+ direction: 'down',
2496
+ angle: 90,
2497
+ elementNumber: 2,
2498
+ detailedDistance: finalYDetailedDistance,
2499
+ },
2500
+ {
2501
+ elementType: 'wall',
2502
+ distance: finalXDistance,
2503
+ unit: 'ft',
2504
+ direction: 'left',
2505
+ angle: 90,
2506
+ elementNumber: 3,
2507
+ detailedDistance: finalXDetailedDistance,
2508
+ },
2509
+ {
2510
+ elementType: 'wall',
2511
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
2512
+ unit: 'ft',
2513
+ direction: 'up',
2514
+ angle: 90,
2515
+ elementNumber: 4,
2516
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
2517
+ },
2518
+ {
2519
+ elementType: 'entrance',
2520
+ distance: roundToTwo( ( ( finalYDistance * 20 ) / 100 ) ),
2521
+ unit: 'ft',
2522
+ direction: 'up',
2523
+ angle: 90,
2524
+ elementNumber: 1,
2525
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 30 ) / 100 ) ),
2526
+ },
2527
+ {
2528
+ elementType: 'wall',
2529
+ distance: roundToTwo( ( ( finalYDistance * 40 ) / 100 ) ),
2530
+ unit: 'ft',
2531
+ direction: 'up',
2532
+ angle: 90,
2533
+ elementNumber: 5,
2534
+ detailedDistance: roundToTwo( ( ( finalYDetailedDistance * 35 ) / 100 ) ),
2535
+ },
2536
+ ],
2537
+ createdBy: new mongoose.Types.ObjectId( '66a78cd82734f4f857cd6db6' ),
2538
+ createdByName: 'Bejan',
2539
+ createdByEmail: 'bejan@tangotech.co.in',
2540
+ status: 'completed',
2541
+ planoId: planoDoc._id,
2542
+ };
2543
+
2544
+ const layoutDoc = await storeBuilderService.upsertOne( { planoId: planoDoc._id }, floorInsertData );
2545
+
2546
+ let fixtureCounter = 1;
2547
+
2548
+ for ( let index = 0; index < leftFixtures.length; index++ ) {
2549
+ const fixture = leftFixtures[index];
2550
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
2551
+ const fixtureConfigDoc = fixtureConfig.toObject();
2552
+
2553
+ const fixtureData = {
2554
+ 'clientId': layoutDoc.clientId,
2555
+ 'storeName': layoutDoc.storeName,
2556
+ 'storeId': layoutDoc.storeId,
2557
+ 'planoId': layoutDoc.planoId,
2558
+ 'floorId': layoutDoc._id,
2559
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
2560
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
2561
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2562
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2563
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
2564
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
2565
+ 'fixtureType': 'wall',
2566
+ 'fixtureHeight': {
2567
+ 'value': 0,
2568
+ 'unit': 'mm',
2569
+ },
2570
+ 'fixtureLength': {
2571
+ 'value': constantFixtureLength,
2572
+ 'unit': 'mm',
2573
+ },
2574
+ 'fixtureWidth': {
2575
+ 'value': constantFixtureWidth,
2576
+ 'unit': 'mm',
2577
+ },
2578
+ 'associatedElementType': 'wall',
2579
+ 'associatedElementNumber': 1,
2580
+ 'relativePosition': {
2581
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
2582
+ 'y': 0,
2583
+ 'unit': 'ft',
2584
+ },
2585
+ 'fixtureNumber': fixtureCounter,
2586
+ 'detailedFixtureLength': {
2587
+ 'value': constantDetailedFixtureLength,
2588
+ 'unit': 'mm',
2589
+ },
2590
+ 'detailedFixtureWidth': {
2591
+ 'value': constantDetailedFixtureWidth,
2592
+ 'unit': 'mm',
2593
+ },
2594
+ 'relativeDetailedPosition': {
2595
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
2596
+ 'y': 0,
2597
+ 'unit': 'ft',
2598
+ },
2599
+ 'productResolutionLevel': 'L2',
2600
+ 'associatedElementFixtureNumber': index+1,
2601
+ 'header': fixture.header,
2602
+ 'footer': fixture.footer,
2603
+ 'fixtureConfigId': fixtureConfigDoc._id,
2604
+ };
2605
+
2606
+ const createdFixture = await storeFixtureService.upsertOne(
2607
+ {
2608
+ floorId: layoutDoc._id,
2609
+ fixtureNumber: fixtureCounter,
2610
+ },
2611
+ fixtureData );
2612
+
2613
+ fixtureCounter +=1;
2614
+
2615
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
2616
+
2617
+
2618
+ for ( let j = 0; j < fixtureConfigDoc.shelfConfig.length; j++ ) {
2619
+ const configShelf = fixtureConfigDoc.shelfConfig[j];
2620
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
2621
+
2622
+ const shelfSection = shelfZone.products.find( ( product ) => product.isMerchandisingElement === false );
2623
+
2624
+ const shelfData = {
2625
+ 'clientId': '11',
2626
+ 'storeName': layoutDoc.storeName,
2627
+ 'storeId': layoutDoc.storeId,
2628
+ 'planoId': layoutDoc.planoId,
2629
+ 'floorId': layoutDoc._id,
2630
+ 'fixtureId': createdFixture._id,
2631
+ 'shelfNumber': j + 1,
2632
+ 'shelfOrder': 'LTR',
2633
+ 'shelfCapacity': configShelf.shelfCapacity,
2634
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
2635
+ 'sectionZone': configShelf.shelfZone,
2636
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
2637
+ };
2638
+
2639
+ await fixtureShelfService.upsertOne(
2640
+ {
2641
+ fixtureId: createdFixture._id,
2642
+ shelfNumber: j + 1,
2643
+ },
2644
+ shelfData,
2645
+ );
2646
+ }
2647
+
2648
+ for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2649
+ const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2650
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2651
+
2652
+ for ( const vm of vms ) {
2653
+ let vmTemplate = await planoProductService.findOne( { productName: vm.productName, fixtureConfigId: fixtureConfig._id } );
2654
+ if ( !vmTemplate ) {
2655
+ let configData = vmConfig[0];
2656
+
2657
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2658
+ configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2659
+ }
2660
+
2661
+ if ( vm.productName !== 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2662
+ configData = vmConfig.find( ( config ) => config.vmNumber === 2 );
2663
+ }
2664
+
2665
+ const insertData = {
2666
+ 'clientId': '11',
2667
+ 'productId': 'VMCR',
2668
+ 'type': 'vm',
2669
+ 'productName': vm.productName,
2670
+ 'productHeight': {
2671
+ 'value': configData.vmHeightmm,
2672
+ 'unit': 'mm',
2673
+ },
2674
+ 'productWidth': {
2675
+ 'value': configData.vmWidthmm,
2676
+ 'unit': 'mm',
2677
+ },
2678
+ 'startYPosition': configData.startShelf,
2679
+ 'endYPosition': configData.endShelf,
2680
+ 'xZone': configData.zone,
2681
+ 'fixtureConfigId': fixtureConfig._id,
2682
+ };
2683
+
2684
+ vmTemplate = await planoProductService.upsertOne(
2685
+ { productName: vm.productName, fixtureConfigId: fixtureConfig._id },
2686
+ insertData );
2687
+ }
2688
+
2689
+ const vmData = {
2690
+ 'clientId': layoutDoc.clientId,
2691
+ 'storeName': layoutDoc.storeName,
2692
+ 'storeId': layoutDoc.storeId,
2693
+ 'planoId': layoutDoc.planoId,
2694
+ 'floorId': layoutDoc._id,
2695
+ 'type': 'vm',
2696
+ 'fixtureId': createdFixture._id,
2697
+ 'productId': vmTemplate._id,
2698
+ };
2699
+
2700
+ await planoMappingService.upsertOne(
2701
+ {
2702
+ fixtureId: createdFixture._id,
2703
+ productId: vmTemplate._id,
2704
+ },
2705
+ vmData,
2706
+ );
2707
+ }
2708
+ }
2709
+ }
2710
+
2711
+ for ( let index = 0; index < backFixtures.length; index++ ) {
2712
+ const fixture = backFixtures[index];
2713
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
2714
+ const fixtureConfigDoc = fixtureConfig.toObject();
2715
+
2716
+ const fixtureData = {
2717
+ 'clientId': layoutDoc.clientId,
2718
+ 'storeName': layoutDoc.storeName,
2719
+ 'storeId': layoutDoc.storeId,
2720
+ 'planoId': layoutDoc.planoId,
2721
+ 'floorId': layoutDoc._id,
2722
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
2723
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
2724
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2725
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2726
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
2727
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
2728
+ 'fixtureType': 'wall',
2729
+ 'fixtureHeight': {
2730
+ 'value': 0,
2731
+ 'unit': 'mm',
2732
+ },
2733
+ 'fixtureLength': {
2734
+ 'value': constantFixtureWidth,
2735
+ 'unit': 'mm',
2736
+ },
2737
+ 'fixtureWidth': {
2738
+ 'value': constantFixtureLength,
2739
+ 'unit': 'mm',
2740
+ },
2741
+ 'associatedElementType': 'wall',
2742
+ 'associatedElementNumber': 2,
2743
+ 'relativePosition': {
2744
+ 'x': roundToTwo( ( finalXDistance - ( constantFixtureWidth/mmToFeet ) ) ),
2745
+ 'y': roundToTwo( ( ( index * ( ( constantFixtureLength/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantFixtureWidth/mmToFeet ) ) ),
2746
+ 'unit': 'ft',
2747
+ },
2748
+ 'fixtureNumber': fixtureCounter,
2749
+ 'detailedFixtureLength': {
2750
+ 'value': constantDetailedFixtureLength,
2751
+ 'unit': 'mm',
2752
+ },
2753
+ 'detailedFixtureWidth': {
2754
+ 'value': constantDetailedFixtureWidth,
2755
+ 'unit': 'mm',
2756
+ },
2757
+ 'relativeDetailedPosition': {
2758
+ 'x': roundToTwo( ( finalXDetailedDistance - ( constantDetailedFixtureLength/mmToFeet ) ) ),
2759
+ 'y': roundToTwo( ( ( index * ( ( constantDetailedFixtureWidth/mmToFeet ) ) ) + ( ( leftFixtures.length ? 1 : 0 ) * constantDetailedFixtureWidth/mmToFeet ) ) ),
2760
+ 'unit': 'ft',
2761
+ },
2762
+ 'productResolutionLevel': 'L2',
2763
+ 'associatedElementFixtureNumber': index+1,
2764
+ 'header': fixture.header,
2765
+ 'footer': fixture.footer,
2766
+ 'fixtureConfigId': fixtureConfigDoc._id,
2767
+ };
2768
+
2769
+ const createdFixture = await storeFixtureService.upsertOne(
2770
+ {
2771
+ floorId: layoutDoc._id,
2772
+ fixtureNumber: fixtureCounter,
2773
+ },
2774
+ fixtureData );
2775
+
2776
+ fixtureCounter +=1;
2777
+
2778
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
2779
+
2780
+ for ( let j = 0; j < fixtureConfigDoc.shelfConfig.length; j++ ) {
2781
+ const configShelf = fixtureConfigDoc.shelfConfig[j];
2782
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
2783
+
2784
+ const shelfSection = shelfZone.products.find( ( product ) => product.isMerchandisingElement === false );
2785
+
2786
+ const shelfData = {
2787
+ 'clientId': '11',
2788
+ 'storeName': layoutDoc.storeName,
2789
+ 'storeId': layoutDoc.storeId,
2790
+ 'planoId': layoutDoc.planoId,
2791
+ 'floorId': layoutDoc._id,
2792
+ 'fixtureId': createdFixture._id,
2793
+ 'shelfNumber': j + 1,
2794
+ 'shelfOrder': 'LTR',
2795
+ 'shelfCapacity': configShelf.shelfCapacity,
2796
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
2797
+ 'sectionZone': configShelf.shelfZone,
2798
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
2799
+ };
2800
+
2801
+ await fixtureShelfService.upsertOne(
2802
+ {
2803
+ fixtureId: createdFixture._id,
2804
+ shelfNumber: j + 1,
2805
+ },
2806
+ shelfData,
2807
+ );
2808
+ }
2809
+
2810
+ for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2811
+ const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2812
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2813
+
2814
+ for ( const vm of vms ) {
2815
+ let vmTemplate = await planoProductService.findOne( { productName: vm.productName, fixtureConfigId: fixtureConfig._id } );
2816
+ if ( !vmTemplate ) {
2817
+ let configData = vmConfig[0];
2818
+
2819
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2820
+ configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2821
+ }
2822
+
2823
+ if ( vm.productName !== 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2824
+ configData = vmConfig.find( ( config ) => config.vmNumber === 2 );
2825
+ }
2826
+
2827
+ const insertData = {
2828
+ 'clientId': '11',
2829
+ 'productId': 'VMCR',
2830
+ 'type': 'vm',
2831
+ 'productName': vm.productName,
2832
+ 'productHeight': {
2833
+ 'value': configData.vmHeightmm,
2834
+ 'unit': 'mm',
2835
+ },
2836
+ 'productWidth': {
2837
+ 'value': configData.vmWidthmm,
2838
+ 'unit': 'mm',
2839
+ },
2840
+ 'startYPosition': configData.startShelf,
2841
+ 'endYPosition': configData.endShelf,
2842
+ 'xZone': configData.zone,
2843
+ 'fixtureConfigId': fixtureConfig._id,
2844
+ };
2845
+
2846
+ vmTemplate = await planoProductService.upsertOne(
2847
+ { productName: vm.productName, fixtureConfigId: fixtureConfig._id },
2848
+ insertData );
2849
+ }
2850
+
2851
+ const vmData = {
2852
+ 'clientId': layoutDoc.clientId,
2853
+ 'storeName': layoutDoc.storeName,
2854
+ 'storeId': layoutDoc.storeId,
2855
+ 'planoId': layoutDoc.planoId,
2856
+ 'floorId': layoutDoc._id,
2857
+ 'type': 'vm',
2858
+ 'fixtureId': createdFixture._id,
2859
+ 'productId': vmTemplate._id,
2860
+ };
2861
+
2862
+ await planoMappingService.upsertOne(
2863
+ {
2864
+ fixtureId: createdFixture._id,
2865
+ productId: vmTemplate._id,
2866
+ },
2867
+ vmData,
2868
+ );
2869
+ }
2870
+ }
2871
+ }
2872
+
2873
+ for ( let index = 0; index < rightFixtures.length; index++ ) {
2874
+ const fixture = rightFixtures[index];
2875
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.fixtureType } );
2876
+ const fixtureConfigDoc = fixtureConfig.toObject();
2877
+
2878
+ const fixtureData = {
2879
+ 'clientId': layoutDoc.clientId,
2880
+ 'storeName': layoutDoc.storeName,
2881
+ 'storeId': layoutDoc.storeId,
2882
+ 'planoId': layoutDoc.planoId,
2883
+ 'floorId': layoutDoc._id,
2884
+ 'fixtureName': `Fixture ${index+1} - ${fixture.fixtureType}`,
2885
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
2886
+ 'fixtureBrandCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2887
+ 'fixtureBrandSubCategory': fixture.fixtureSubname.length ? ( fixture.fixtureSubname.length > 1 ? fixture.fixtureSubname.join( ' + ' ) : fixture.fixtureSubname[0] ) : undefined,
2888
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
2889
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
2890
+ 'fixtureType': 'wall',
2891
+ 'fixtureHeight': {
2892
+ 'value': 0,
2893
+ 'unit': 'mm',
2894
+ },
2895
+ 'fixtureLength': {
2896
+ 'value': constantFixtureLength,
2897
+ 'unit': 'mm',
2898
+ },
2899
+ 'fixtureWidth': {
2900
+ 'value': constantFixtureWidth,
2901
+ 'unit': 'mm',
2902
+ },
2903
+ 'associatedElementType': 'wall',
2904
+ 'associatedElementNumber': 3,
2905
+ 'relativePosition': {
2906
+ 'x': roundToTwo( ( index * ( constantFixtureLength / mmToFeet ) ) ),
2907
+ 'y': roundToTwo( ( finalYDistance - ( constantFixtureWidth / mmToFeet ) ) ),
2908
+ 'unit': 'ft',
2909
+ },
2910
+ 'fixtureNumber': fixtureCounter,
2911
+ 'detailedFixtureLength': {
2912
+ 'value': constantDetailedFixtureLength,
2913
+ 'unit': 'mm',
2914
+ },
2915
+ 'detailedFixtureWidth': {
2916
+ 'value': constantDetailedFixtureWidth,
2917
+ 'unit': 'mm',
2918
+ },
2919
+ 'relativeDetailedPosition': {
2920
+ 'x': roundToTwo( ( index * ( constantDetailedFixtureLength / mmToFeet ) ) ),
2921
+ 'y': roundToTwo( ( finalYDetailedDistance - ( constantDetailedFixtureWidth / mmToFeet ) ) ),
2922
+ 'unit': 'ft',
2923
+ },
2924
+ 'productResolutionLevel': 'L2',
2925
+ 'associatedElementFixtureNumber': index+1,
2926
+ 'header': fixture.header,
2927
+ 'footer': fixture.footer,
2928
+ 'fixtureConfigId': fixtureConfigDoc._id,
2929
+ };
2930
+
2931
+ const createdFixture = await storeFixtureService.upsertOne(
2932
+ {
2933
+ floorId: layoutDoc._id,
2934
+ fixtureNumber: fixtureCounter,
2935
+ },
2936
+ fixtureData );
2937
+
2938
+ fixtureCounter +=1;
2939
+
2940
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
2941
+
2942
+ for ( let j = 0; j < fixtureConfigDoc.shelfConfig.length; j++ ) {
2943
+ const configShelf = fixtureConfigDoc.shelfConfig[j];
2944
+
2945
+ const shelfZone = fixture.productZones.find( ( zone ) => zone.zoneName === configShelf.shelfZone );
2946
+ const shelfSection = shelfZone.products.find( ( product ) => product.isMerchandisingElement === false );
2947
+
2948
+ const shelfData = {
2949
+ 'clientId': '11',
2950
+ 'storeName': layoutDoc.storeName,
2951
+ 'storeId': layoutDoc.storeId,
2952
+ 'planoId': layoutDoc.planoId,
2953
+ 'floorId': layoutDoc._id,
2954
+ 'fixtureId': createdFixture._id,
2955
+ 'shelfNumber': j + 1,
2956
+ 'shelfOrder': 'LTR',
2957
+ 'shelfCapacity': configShelf.shelfCapacity,
2958
+ 'sectionName': shelfSection?.productName ? shelfSection.productName : 'Unknown',
2959
+ 'sectionZone': configShelf.shelfZone,
2960
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
2961
+ };
2962
+
2963
+ await fixtureShelfService.upsertOne(
2964
+ {
2965
+ fixtureId: createdFixture._id,
2966
+ shelfNumber: j + 1,
2967
+ },
2968
+ shelfData,
2969
+ );
2970
+ }
2971
+
2972
+ for ( let i = 0; i < fixture.productZones?.length; i++ ) {
2973
+ const vms = fixture.productZones[i].products.filter( ( vm ) => vm.isMerchandisingElement );
2974
+ const vmConfig = fixtureConfigDoc.vmConfig.filter( ( vm ) => vm.position === fixture.productZones[i].zoneName );
2975
+
2976
+ for ( const vm of vms ) {
2977
+ let vmTemplate = await planoProductService.findOne( { productName: vm.productName, fixtureConfigId: fixtureConfig._id } );
2978
+ if ( !vmTemplate ) {
2979
+ let configData = vmConfig[0];
2980
+
2981
+ if ( vm.productName === 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2982
+ configData = vmConfig.find( ( config ) => config.vmNumber === 3 );
2983
+ }
2984
+
2985
+ if ( vm.productName !== 'Creatr' && fixture.productZones[i].zoneName === 'Mid' ) {
2986
+ configData = vmConfig.find( ( config ) => config.vmNumber === 2 );
2987
+ }
2988
+
2989
+ const insertData = {
2990
+ 'clientId': '11',
2991
+ 'productId': 'VMCR',
2992
+ 'type': 'vm',
2993
+ 'productName': vm.productName,
2994
+ 'productHeight': {
2995
+ 'value': configData.vmHeightmm,
2996
+ 'unit': 'mm',
2997
+ },
2998
+ 'productWidth': {
2999
+ 'value': configData.vmWidthmm,
3000
+ 'unit': 'mm',
3001
+ },
3002
+ 'startYPosition': configData.startShelf,
3003
+ 'endYPosition': configData.endShelf,
3004
+ 'xZone': configData.zone,
3005
+ 'fixtureConfigId': fixtureConfig._id,
3006
+ };
3007
+
3008
+ vmTemplate = await planoProductService.upsertOne(
3009
+ { productName: vm.productName, fixtureConfigId: fixtureConfig._id },
3010
+ insertData );
3011
+ }
3012
+
3013
+ const vmData = {
3014
+ 'clientId': layoutDoc.clientId,
3015
+ 'storeName': layoutDoc.storeName,
3016
+ 'storeId': layoutDoc.storeId,
3017
+ 'planoId': layoutDoc.planoId,
3018
+ 'floorId': layoutDoc._id,
3019
+ 'type': 'vm',
3020
+ 'fixtureId': createdFixture._id,
3021
+ 'productId': vmTemplate._id,
3022
+ };
3023
+
3024
+ await planoMappingService.upsertOne(
3025
+ {
3026
+ fixtureId: createdFixture._id,
3027
+ productId: vmTemplate._id,
3028
+ },
3029
+ vmData,
3030
+ );
3031
+ }
3032
+ }
3033
+ }
3034
+
3035
+ for ( let index = 0; index < floorFixtures.length; index++ ) {
3036
+ const fixture = floorFixtures[index];
3037
+ const centerRow = Math.floor( totalRows / 2 );
3038
+
3039
+ const startingX =roundToTwo( ( ( finalXDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantFixtureLength / mmToFeet ) ) ) );
3040
+ const detailedStartingX = roundToTwo( ( ( finalXDetailedDistance / 2 ) - ( ( maxFixturesPerRow / 2 ) * ( constantDetailedFixtureLength / mmToFeet ) ) ) );
3041
+
3042
+ const startingY = ( finalYDistance / 2 ) - ( centerRow * ( constantFixtureWidth / mmToFeet ) );
3043
+ const detailedStartingY = ( finalYDetailedDistance / 2 ) - ( centerRow * ( constantDetailedFixtureWidth / mmToFeet ) );
3044
+
3045
+ const colIndex = Math.floor( index / 2 );
3046
+ const rowIndex = index % 2 === 0 ? 1 : 0;
3047
+
3048
+
3049
+ const xPos = roundToTwo( ( startingX + colIndex * ( constantFixtureLength / mmToFeet ) ) );
3050
+ const yPos = roundToTwo( ( startingY + rowIndex * ( constantFixtureWidth / mmToFeet ) ) );
3051
+
3052
+ const detailedXPos = roundToTwo( ( detailedStartingX + colIndex * ( constantDetailedFixtureLength / mmToFeet ) ) );
3053
+ const detailedYPos = roundToTwo( ( detailedStartingY + rowIndex * ( constantDetailedFixtureWidth / mmToFeet ) ) );
3054
+
3055
+ const fixtureConfig = await fixtureConfigService.findOne( { fixtureCategory: fixture.main } );
3056
+ const fixtureConfigDoc = fixtureConfig.toObject();
3057
+
3058
+ const fixtureData = {
3059
+ 'clientId': layoutDoc.clientId,
3060
+ 'storeName': layoutDoc.storeName,
3061
+ 'storeId': layoutDoc.storeId,
3062
+ 'planoId': layoutDoc.planoId,
3063
+ 'floorId': layoutDoc._id,
3064
+ 'fixtureName': `Fixture ${index+1} - ${fixture.main}`,
3065
+ 'fixtureCategory': fixtureConfigDoc.fixtureConfigType,
3066
+ 'fixtureBrandCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
3067
+ 'fixtureBrandSubCategory': fixture.centerSubMain ? fixture.centerSubMain : undefined,
3068
+ 'fixtureCode': fixtureConfigDoc?.fixtureCode,
3069
+ 'fixtureCapacity': fixtureConfigDoc?.fixtureCapacity,
3070
+ 'fixtureType': 'floor',
3071
+ 'fixtureHeight': {
3072
+ 'value': 0,
3073
+ 'unit': 'mm',
3074
+ },
3075
+ 'fixtureLength': {
3076
+ 'value': constantFixtureLength,
3077
+ 'unit': 'mm',
3078
+ },
3079
+ 'fixtureWidth': {
3080
+ 'value': constantFixtureWidth,
3081
+ 'unit': 'mm',
3082
+ },
3083
+ 'relativePosition': {
3084
+ 'x': xPos,
3085
+ 'y': yPos,
3086
+ 'unit': 'ft',
3087
+ },
3088
+ 'fixtureNumber': fixtureCounter,
3089
+ 'detailedFixtureLength': {
3090
+ 'value': constantDetailedFixtureLength,
3091
+ 'unit': 'mm',
3092
+ },
3093
+ 'detailedFixtureWidth': {
3094
+ 'value': constantDetailedFixtureWidth,
3095
+ 'unit': 'mm',
3096
+ },
3097
+ 'relativeDetailedPosition': {
3098
+ 'x': detailedXPos,
3099
+ 'y': detailedYPos,
3100
+ 'unit': 'ft',
3101
+ },
3102
+ 'productResolutionLevel': 'L2',
3103
+ 'associatedElementFixtureNumber': index+1,
3104
+ 'fixtureConfigId': fixtureConfigDoc._id,
3105
+ };
3106
+
3107
+ const createdFixture = await storeFixtureService.upsertOne(
3108
+ {
3109
+ floorId: layoutDoc._id,
3110
+ fixtureNumber: fixtureCounter,
3111
+ },
3112
+ fixtureData );
3113
+
3114
+ fixtureCounter +=1;
3115
+
3116
+ if ( !fixtureConfigDoc.shelfConfig.length || fixture.header === 'CL' || fixture.fixtureSubname?.includes( 'CL' ) ) continue;
3117
+
3118
+ for ( let j = 0; j < fixtureConfigDoc.shelfConfig.length; j++ ) {
3119
+ const configShelf = fixtureConfigDoc.shelfConfig[j];
3120
+
3121
+ const shelfSection = fixture.centerSuperSubMain.find( ( product ) => product.isVisualMerchandiser === false || product.isVisualMerchandiser === true );
3122
+
3123
+ const shelfData = {
3124
+ 'clientId': '11',
3125
+ 'storeName': layoutDoc.storeName,
3126
+ 'storeId': layoutDoc.storeId,
3127
+ 'planoId': layoutDoc.planoId,
3128
+ 'floorId': layoutDoc._id,
3129
+ 'fixtureId': createdFixture._id,
3130
+ 'shelfNumber': j + 1,
3131
+ 'shelfOrder': 'LTR',
3132
+ 'shelfCapacity': configShelf.shelfCapacity,
3133
+ 'sectionName': fixture.centerSuperSubMain.find( ( product ) => product.isVisualMerchandiser === true ) ? shelfSection?.name + ' PIDs' : shelfSection?.name,
3134
+ 'shelfSplitup': configShelf?.shelfSplitup ? configShelf.shelfSplitup : 0,
3135
+ };
3136
+
3137
+ await fixtureShelfService.upsertOne(
3138
+ {
3139
+ fixtureId: createdFixture._id,
3140
+ shelfNumber: j + 1,
3141
+ },
3142
+ shelfData,
3143
+ );
3144
+ }
3145
+
3146
+
3147
+ const vm = fixture.centerSuperSubMain.find( ( vm ) => vm.isVisualMerchandiser );
3148
+ const vmConfig = fixtureConfigDoc.vmConfig;
3149
+
3150
+ if ( vm ) {
3151
+ let vmTemplate1 = await planoProductService.findOne( { productName: vm.name, fixtureConfigId: fixtureConfig._id } );
3152
+ if ( !vmTemplate1 ) {
3153
+ const configData1 = vmConfig[0];
3154
+
3155
+
3156
+ const insertData1 = {
3157
+ 'clientId': '11',
3158
+ 'productId': 'VMCR',
3159
+ 'type': 'vm',
3160
+ 'productName': vm.name,
3161
+ 'productHeight': {
3162
+ 'value': configData1.vmHeightmm,
3163
+ 'unit': 'mm',
3164
+ },
3165
+ 'productWidth': {
3166
+ 'value': configData1.vmWidthmm,
3167
+ 'unit': 'mm',
3168
+ },
3169
+ 'startYPosition': configData1.startShelf,
3170
+ 'endYPosition': configData1.endShelf,
3171
+ 'xZone': configData1.zone,
3172
+ 'fixtureConfigId': fixtureConfig._id,
3173
+ };
3174
+
3175
+ vmTemplate1 = await planoProductService.upsertOne(
3176
+ { productName: vm.productName, fixtureConfigId: fixtureConfig._id },
3177
+ insertData1 );
3178
+ }
3179
+
3180
+ const vmData1 = {
3181
+ 'clientId': layoutDoc.clientId,
3182
+ 'storeName': layoutDoc.storeName,
3183
+ 'storeId': layoutDoc.storeId,
3184
+ 'planoId': layoutDoc.planoId,
3185
+ 'floorId': layoutDoc._id,
3186
+ 'type': 'vm',
3187
+ 'fixtureId': createdFixture._id,
3188
+ 'productId': vmTemplate1._id,
3189
+ };
3190
+
3191
+ await planoMappingService.upsertOne(
3192
+ {
3193
+ fixtureId: createdFixture._id,
3194
+ productId: vmTemplate1._id,
3195
+ },
3196
+ vmData1,
3197
+ );
3198
+
3199
+ let vmTemplate2 = await planoProductService.findOne( { productName: ' ', fixtureConfigId: fixtureConfig._id } );
3200
+ if ( !vmTemplate2 ) {
3201
+ const configData2 = vmConfig[1];
3202
+
3203
+
3204
+ const insertData2 = {
3205
+ 'clientId': '11',
3206
+ 'productId': 'VMCR',
3207
+ 'type': 'vm',
3208
+ 'productName': ' ',
3209
+ 'productHeight': {
3210
+ 'value': configData2.vmHeightmm,
3211
+ 'unit': 'mm',
3212
+ },
3213
+ 'productWidth': {
3214
+ 'value': configData2.vmWidthmm,
3215
+ 'unit': 'mm',
3216
+ },
3217
+ 'startYPosition': configData2.startShelf,
3218
+ 'endYPosition': configData2.endShelf,
3219
+ 'xZone': configData2.zone,
3220
+ 'fixtureConfigId': fixtureConfig._id,
3221
+ };
3222
+
3223
+ vmTemplate2 = await planoProductService.upsertOne(
3224
+ { productName: ' ', fixtureConfigId: fixtureConfig._id },
3225
+ insertData2 );
3226
+ }
3227
+
3228
+ const vmData2 = {
3229
+ 'clientId': layoutDoc.clientId,
3230
+ 'storeName': layoutDoc.storeName,
3231
+ 'storeId': layoutDoc.storeId,
3232
+ 'planoId': layoutDoc.planoId,
3233
+ 'floorId': layoutDoc._id,
3234
+ 'type': 'vm',
3235
+ 'fixtureId': createdFixture._id,
3236
+ 'productId': vmTemplate2._id,
3237
+ };
3238
+
3239
+ await planoMappingService.upsertOne(
3240
+ {
3241
+ fixtureId: createdFixture._id,
3242
+ productId: vmTemplate2._id,
3243
+ },
3244
+ vmData2,
3245
+ );
3246
+ }
3247
+ }
3248
+
3249
+ console.log( storeData.storeName );
3250
+ }
3251
+
3252
+ res.sendSuccess( 'Updated Successfully' );
3253
+ } catch ( e ) {
3254
+ logger.error( { functionName: 'createCrestPlanogram', error: e } );
3255
+ return res.sendError( e.message || 'Internal Server Error', 500 );
3256
+ }
3257
+ }
3258
+
3259
+ export async function updateCrestVms( req, res ) {
3260
+ try {
3261
+ if ( req?.headers?.authorization?.split( ' ' )[1] !== 'hwjXfCD6TgMvc82cuSGZ9bNv9MuXsaiQ6uvx' ) {
3262
+ return res.sendError( 'Unauthorized', 401 );
3263
+ }
3264
+
3265
+ if ( !req.files || !req.files.file ) {
3266
+ return res.sendError( 'JSON file is required', 400 );
3267
+ }
3268
+
3269
+ const data = JSON.parse( req.files.file.data.toString( 'utf8' ) );
3270
+
3271
+ const crestData = data.filter( ( item ) => item.data.message === 'FAILURE' );
3272
+
3273
+
3274
+ const returnSet = new Set();
3275
+
3276
+
3277
+ crestData.forEach( ( store ) => {
3278
+ returnSet.add( store.storeName );
3279
+ // store.data.result.forEach( ( wall ) => {
3280
+ // wall.fixtures?.forEach( ( fixture ) => {
3281
+ // fixture.productZones.forEach( ( zone ) => {
3282
+ // zone.products.forEach( ( product ) => {
3283
+
3284
+ // } );
3285
+ // } );
3286
+ // } );
3287
+ // } );
3288
+ } );
3289
+
3290
+ return res.sendSuccess( Array.from( returnSet ) );
3291
+ } catch ( e ) {
3292
+ logger.error( { functionName: 'createCrestPlanogram', error: e } );
3293
+ return res.sendError( e.message || 'Internal Server Error', 500 );
3294
+ }
3295
+ }
3296
+