tango-app-api-store-builder 1.0.0-beta-13 → 1.0.0-beta-15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-store-builder",
3
- "version": "1.0.0-beta-13",
3
+ "version": "1.0.0-beta-15",
4
4
  "description": "storeBuilder",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -23,7 +23,7 @@
23
23
  "joi": "^17.13.3",
24
24
  "mongodb": "^6.12.0",
25
25
  "nodemon": "^3.1.9",
26
- "tango-api-schema": "^2.2.31",
26
+ "tango-api-schema": "^2.2.40",
27
27
  "tango-app-api-middleware": "^3.1.48",
28
28
  "winston": "^3.17.0",
29
29
  "winston-daily-rotate-file": "^5.0.0"
@@ -42,7 +42,7 @@ export async function createStoreBuilder( req, res ) {
42
42
  createdByEmail: req.user.email,
43
43
  planoId: planoId._id,
44
44
  };
45
- for ( let i=1; i<=req.body.floorNumber; i++ ) {
45
+ for ( let i = 1; i <= req.body.floorNumber; i++ ) {
46
46
  data.push( { ...params, floorNumber: i, floorName: `floor ${i}` } );
47
47
  }
48
48
  await storeBuilderService.insertMany( data );
@@ -90,7 +90,7 @@ export async function updateFloor( req, res ) {
90
90
  };
91
91
  let data = [];
92
92
  let num = getLayoutDetails.floorNumber + req.body.floorNumber;
93
- for ( let i=getLayoutDetails.floorNumber + 1; i <= num; i++ ) {
93
+ for ( let i = getLayoutDetails.floorNumber + 1; i <= num; i++ ) {
94
94
  data.push( { ...params, floorNumber: i, floorName: `floor ${i}` } );
95
95
  }
96
96
  getLayoutDetails.floorNumber = num;
@@ -311,7 +311,7 @@ export async function uploadFile( req, res ) {
311
311
  }
312
312
  if ( req.files.file ) {
313
313
  let bucket = JSON.parse( process.env.BUCKET );
314
- let params ={
314
+ let params = {
315
315
  Bucket: bucket.storeBuilder,
316
316
  Key: `${getPlanoDetails.clientId}/${getPlanoDetails.storeName}/attachments/`,
317
317
  fileName: req.files.file.name,
@@ -320,7 +320,7 @@ export async function uploadFile( req, res ) {
320
320
  };
321
321
  let fileuploadRes = await fileUpload( params );
322
322
  if ( getPlanoDetails ) {
323
- let updateRes = await planoService.updateOne( { _id: getPlanoDetails. _id }, { $push: { attachments: fileuploadRes.Key } } );
323
+ let updateRes = await planoService.updateOne( { _id: getPlanoDetails._id }, { $push: { attachments: fileuploadRes.Key } } );
324
324
  if ( updateRes.modifiedCount ) {
325
325
  let params = {
326
326
  Bucket: bucket.storeBuilder,
@@ -348,7 +348,7 @@ export async function getStoreDetails( req, res ) {
348
348
  getStoreDetails = { ...getStoreDetails._doc, cameraBaseImage: '', attachments: [] };
349
349
  const camera = await storeService.findCamera( { storeId: req.body.storeId, isUp: true, isActivated: true }, { thumbnailImage: 1 } );
350
350
  if ( camera.thumbnailImage ) {
351
- const bucket= JSON.parse( process.env.BUCKET );
351
+ const bucket = JSON.parse( process.env.BUCKET );
352
352
  const params = {
353
353
  file_path: camera.thumbnailImage,
354
354
  Bucket: bucket.baseImage,
@@ -365,7 +365,7 @@ export async function getStoreDetails( req, res ) {
365
365
  file_path: attach,
366
366
  };
367
367
  let getSignedUrl = await signedUrl( params );
368
- getStoreDetails.attachments .push( { url: getSignedUrl, name: attach.split( '/' ).pop() } );
368
+ getStoreDetails.attachments.push( { url: getSignedUrl, name: attach.split( '/' ).pop() } );
369
369
  }
370
370
  return res.sendSuccess( getStoreDetails );
371
371
  } catch ( e ) {
@@ -472,22 +472,26 @@ export async function storeFixtures( req, res ) {
472
472
  {
473
473
  $group: {
474
474
  _id: '$fixtureId',
475
- properCount: { $sum: {
476
- $cond: [
477
- {
478
- $and: [
479
- { $eq: [ '$compliance', 'proper' ] },
480
- ],
481
- }, 1, 0 ],
482
- } },
483
- misPlacedCount: { $sum: {
484
- $cond: [
485
- {
486
- $and: [
487
- { $ne: [ '$compliance', 'proper' ] },
488
- ],
489
- }, 1, 0 ],
490
- } },
475
+ properCount: {
476
+ $sum: {
477
+ $cond: [
478
+ {
479
+ $and: [
480
+ { $eq: [ '$compliance', 'proper' ] },
481
+ ],
482
+ }, 1, 0 ],
483
+ },
484
+ },
485
+ misPlacedCount: {
486
+ $sum: {
487
+ $cond: [
488
+ {
489
+ $and: [
490
+ { $ne: [ '$compliance', 'proper' ] },
491
+ ],
492
+ }, 1, 0 ],
493
+ },
494
+ },
491
495
  },
492
496
  },
493
497
  ],
@@ -572,7 +576,8 @@ export async function storeFixturesv1( req, res ) {
572
576
 
573
577
  return {
574
578
  ...fixture.toObject(),
575
- status: productCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
579
+ status: complianceCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
580
+ productCount: productCount,
576
581
  };
577
582
  } ),
578
583
  );
@@ -601,15 +606,19 @@ export async function storeFixturesv1( req, res ) {
601
606
 
602
607
  return {
603
608
  ...fixture.toObject(),
604
- status: productCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
609
+ status: complianceCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
610
+ productCount: productCount,
605
611
  };
606
612
  } ),
607
613
  );
608
614
 
615
+ const productCount = await planoMappingService.count( { floorId: floor._id } );
616
+
609
617
  return {
610
618
  ...floor.toObject(),
611
619
  layoutPolygon: layoutPolygonWithFixtures,
612
620
  centerFixture: centerFixturesWithStatus,
621
+ productCount: productCount,
613
622
  };
614
623
  } ),
615
624
  );
@@ -774,13 +783,87 @@ export async function fixtureShelfProductv1( req, res ) {
774
783
  if ( !planogram ) return res.sendError( 'Planogram not found', 204 );
775
784
  if ( !fixture ) return res.sendError( 'Fixture not found', 204 );
776
785
 
777
- const fixtureShelves = await fixtureShelfService.find( {
778
- fixtureId: new mongoose.Types.ObjectId( fixtureId ),
779
- } );
786
+ if ( fixture.toObject().productResolutionLevel === 'L1' ) {
787
+ const productMappings = await planoMappingService.find( { fixtureId: new mongoose.Types.ObjectId( fixtureId ) } );
788
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
789
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
790
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
780
791
 
781
- if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
792
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
793
+
794
+ const productDetails = await Promise.all(
795
+ productMappings.map( async ( mapping ) => {
796
+ const productData = productMap.get( mapping.productId.toString() ) || {};
797
+ const mappingCompliance = await planoComplianceService.findOne( {
798
+ planoMappingId: mapping._id,
799
+ date: currentDate,
800
+ } );
801
+
802
+ const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
803
+
804
+ return { ...mapping.toObject(), ...productData, status };
805
+ } ),
806
+ );
807
+
808
+ return res.sendSuccess( { ...fixture.toObject(), products: productDetails } );
809
+ }
810
+ if ( fixture.toObject().productResolutionLevel === 'L2' || fixture.toObject().productResolutionLevel === 'L4' ) {
811
+ const fixtureShelves = await fixtureShelfService.find( {
812
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
813
+ } );
814
+
815
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
816
+
817
+ const shelfProducts = await Promise.all(
818
+ fixtureShelves.map( async ( shelf ) => {
819
+ const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
820
+
821
+ if ( !productMappings.length ) {
822
+ return { ...shelf.toObject(), products: [] };
823
+ }
824
+
825
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
826
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
827
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
828
+
829
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
830
+
831
+ const productDetails = await Promise.all(
832
+ productMappings.map( async ( mapping ) => {
833
+ const productData = productMap.get( mapping.productId.toString() );
834
+ if ( !productData ) {
835
+ return { ...mapping.toObject(), status: '' };
836
+ }
782
837
 
783
- if ( planogram.toObject().productResolutionLevel === 'L3' ) {
838
+ const mappingCompliance = await planoComplianceService.findOne( {
839
+ planoMappingId: mapping._id,
840
+ date: currentDate,
841
+ } );
842
+
843
+ const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
844
+
845
+ return {
846
+ ...mapping.toObject(),
847
+ ...productData,
848
+ status,
849
+ };
850
+ } ),
851
+ );
852
+
853
+ return {
854
+ ...shelf.toObject(),
855
+ products: productDetails,
856
+ };
857
+ } ),
858
+ );
859
+
860
+ return res.sendSuccess( { ...fixture.toObject(), shelves: shelfProducts } );
861
+ } else if ( fixture.toObject().productResolutionLevel === 'L3' ) {
862
+ const fixtureShelves = await fixtureShelfService.find( {
863
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
864
+ } );
865
+
866
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
784
867
  const groupedShelves = await ( async () => {
785
868
  const shelfProducts = await Promise.all(
786
869
  fixtureShelves.map( async ( shelf ) => {
@@ -804,8 +887,7 @@ export async function fixtureShelfProductv1( req, res ) {
804
887
  }
805
888
 
806
889
  const mappingCompliance = await planoComplianceService.findOne( {
807
- shelfId: mapping.shelfId,
808
- shelfPosition: mapping.shelfPosition,
890
+ planoMappingId: mapping._id,
809
891
  date: currentDate,
810
892
  } );
811
893
 
@@ -836,52 +918,8 @@ export async function fixtureShelfProductv1( req, res ) {
836
918
  }, {} );
837
919
  } )();
838
920
  return res.sendSuccess( { ...fixture.toObject(), categories: groupedShelves } );
839
- } else if ( planogram.toObject().productResolutionLevel === 'L4' || planogram.toObject().productResolutionLevel === 'L5' ) {
840
- const shelfProducts = await Promise.all(
841
- fixtureShelves.map( async ( shelf ) => {
842
- const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
843
-
844
- if ( !productMappings.length ) {
845
- return { ...shelf.toObject(), products: [] };
846
- }
847
-
848
- const productIds = productMappings.map( ( mapping ) => mapping.productId );
849
- const products = await planoProductService.find( { _id: { $in: productIds } } );
850
- const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
851
-
852
- const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
853
-
854
- const productDetails = await Promise.all(
855
- productMappings.map( async ( mapping ) => {
856
- const productData = productMap.get( mapping.productId.toString() );
857
- if ( !productData ) {
858
- return { ...mapping.toObject(), status: '' };
859
- }
860
-
861
- const mappingCompliance = await planoComplianceService.findOne( {
862
- shelfId: mapping.shelfId,
863
- shelfPosition: mapping.shelfPosition,
864
- date: currentDate,
865
- } );
866
-
867
- const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
868
-
869
- return {
870
- ...mapping.toObject(),
871
- ...productData,
872
- status,
873
- };
874
- } ),
875
- );
876
-
877
- return {
878
- ...shelf.toObject(),
879
- products: productDetails,
880
- };
881
- } ),
882
- );
883
-
884
- return res.sendSuccess( { ...fixture.toObject(), shelves: shelfProducts } );
921
+ } else {
922
+ return res.sendError( 'Incorrect resolution level', 400 );
885
923
  }
886
924
  } catch ( e ) {
887
925
  logger.error( { functionName: 'fixtureShelfProductv1', error: e, message: req.body } );
@@ -924,7 +962,7 @@ export async function scan( req, res ) {
924
962
  shelfId = req.body.shelfId;
925
963
  req.body.shelfId = shelfDetails.map( ( ele ) => ele._id );
926
964
  }
927
- let productCheck= await planoMappingService.findOne( { rfId: req.body.rfId } );
965
+ let productCheck = await planoMappingService.findOne( { rfId: req.body.rfId } );
928
966
  if ( !productCheck ) {
929
967
  return res.sendError( 'Product not found', 400 );
930
968
  }
@@ -1026,24 +1064,131 @@ export async function scan( req, res ) {
1026
1064
 
1027
1065
  export async function scanv1( req, res ) {
1028
1066
  try {
1029
- const planogram = await planoService.findOne(
1030
- { _id: new mongoose.Types.ObjectId( req.body.planoId ) },
1067
+ const fixture = await storeFixtureService.findOne(
1068
+ { _id: new mongoose.Types.ObjectId( req.body.fixtureId ) },
1031
1069
  { storeId: 1, storeName: 1, planoId: '$_id', productResolutionLevel: 1 },
1032
1070
  );
1033
1071
 
1034
- if ( !planogram ) return res.sendError( 'No data found', 204 );
1072
+ if ( !fixture ) return res.sendError( 'No data found', 204 );
1035
1073
 
1036
- if ( planogram.productResolutionLevel === 'L3' ) {
1074
+ if ( fixture.productResolutionLevel === 'L1' ) {
1037
1075
  if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1038
1076
 
1077
+ if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1078
+
1039
1079
  if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1040
1080
 
1081
+ const mappingQuery = {
1082
+ planoId: req.body.planoId,
1083
+ floorId: req.body.floorId,
1084
+ fixtureId: req.body.fixtureId,
1085
+ rfId: req.body.rfId,
1086
+ };
1087
+
1088
+ const productMapping = await planoMappingService.findOne( mappingQuery );
1089
+
1090
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1091
+
1092
+ if ( !productMapping ) {
1093
+ const misplacedQuery = {
1094
+ planoId: req.body.planoId,
1095
+ floorId: req.body.floorId,
1096
+ rfId: req.body.rfId,
1097
+ };
1098
+ const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1099
+
1100
+ if ( !misplacedProductMapping ) {
1101
+ return res.sendSuccess( { data: 'missing', status: false } );
1102
+ }
1103
+
1104
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1105
+ delete complianceData._id;
1106
+
1107
+ let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1108
+
1109
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1110
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1111
+ }
1112
+
1113
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1114
+ delete complianceData._id;
1115
+
1116
+ let productDetails = await planoProductService.findOne( { _id: mappingQuery.productId } );
1117
+
1118
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1119
+
1120
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1121
+ } else if ( fixture.productResolutionLevel === 'L2' ) {
1122
+ if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1123
+
1041
1124
  if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1042
1125
 
1126
+ if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1127
+
1043
1128
  if ( !req.body.shelfId && req.body.rfId ) {
1044
1129
  const shelf = await fixtureShelfService.findOne( { planoId: req.body.planoId, floorId: req.body.floorId, fixtureId: req.body.fixtureId, rfId: req.body.rfId } );
1045
1130
  if ( !shelf ) return res.sendError( 'No matching shelf for the rfId', 400 );
1046
- return res.sendSuccess( shelf.toObject()._id );
1131
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1132
+ }
1133
+
1134
+ if ( !req.body.shelfId ) return res.sendError( 'Shelf id is required', 400 );
1135
+
1136
+ const mappingQuery = {
1137
+ planoId: req.body.planoId,
1138
+ floorId: req.body.floorId,
1139
+ fixtureId: req.body.fixtureId,
1140
+ shelfId: req.body.shelfId,
1141
+ rfId: req.body.rfId,
1142
+ };
1143
+
1144
+ const productMapping = await planoMappingService.findOne( mappingQuery );
1145
+
1146
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1147
+
1148
+ if ( !productMapping ) {
1149
+ const misplacedQuery = {
1150
+ planoId: req.body.planoId,
1151
+ floorId: req.body.floorId,
1152
+ rfId: req.body.rfId,
1153
+ };
1154
+ const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1155
+
1156
+ if ( !misplacedProductMapping ) {
1157
+ const shelf = await fixtureShelfService.findOne( misplacedQuery );
1158
+ if ( !shelf ) {
1159
+ return res.sendSuccess( { data: 'missing', status: false } );
1160
+ }
1161
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1162
+ }
1163
+
1164
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1165
+ delete complianceData._id;
1166
+
1167
+ let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1168
+
1169
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1170
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1171
+ }
1172
+
1173
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1174
+ delete complianceData._id;
1175
+
1176
+ let productDetails = await planoProductService.findOne( { _id: productMapping.toObject().productId } );
1177
+
1178
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1179
+
1180
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1181
+ } else if ( fixture.productResolutionLevel === 'L3' ) {
1182
+ if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1183
+
1184
+ if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1185
+
1186
+ if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1187
+
1188
+ if ( !req.body.shelfId && req.body.rfId ) {
1189
+ const shelf = await fixtureShelfService.findOne( { planoId: req.body.planoId, floorId: req.body.floorId, fixtureId: req.body.fixtureId, rfId: req.body.rfId } );
1190
+ if ( !shelf ) return res.sendError( 'No matching shelf for the rfId', 400 );
1191
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1047
1192
  }
1048
1193
 
1049
1194
  if ( !req.body.shelfId ) return res.sendError( 'Shelf id is required', 400 );
@@ -1073,24 +1218,35 @@ export async function scanv1( req, res ) {
1073
1218
  };
1074
1219
  const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1075
1220
 
1221
+
1076
1222
  if ( !misplacedProductMapping ) {
1077
- return res.sendError( 'No product found for the RFID', 400 );
1223
+ const shelf = await fixtureShelfService.findOne( misplacedQuery );
1224
+ if ( !shelf ) {
1225
+ return res.sendSuccess( { data: 'missing', status: false } );
1226
+ }
1227
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1078
1228
  }
1079
1229
 
1230
+
1231
+ const misplacedProductShelf = await fixtureShelfService.findOne( { _id: misplacedProductMapping.toObject().shelfId } );
1232
+
1080
1233
  let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1081
1234
 
1082
- if ( shelf.toObject().sectionName === misplacedProductMapping.toObject().category ) {
1083
- const complianceData = { ...misplacedProductMapping.toObject(), compliance: 'proper' };
1235
+ if ( shelf.toObject().sectionName === misplacedProductShelf.toObject().sectionName ) {
1236
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'proper' };
1084
1237
  delete complianceData._id;
1085
1238
 
1086
1239
  await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1087
- return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject(): {} ) }, status: true } );
1240
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: true } );
1088
1241
  } else {
1089
- const complianceData = { ...misplacedProductMapping.toObject(), compliance: 'misplaced' };
1242
+ if ( shelf.toObject()._id.toString() !== misplacedProductShelf.toObject()._id.toString() ) {
1243
+ return res.sendError( 'RFID conflict with section', 400 );
1244
+ }
1245
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1090
1246
  delete complianceData._id;
1091
1247
 
1092
1248
  await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1093
- return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject(): {} ) }, status: false } );
1249
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1094
1250
  }
1095
1251
  }
1096
1252
 
@@ -1098,10 +1254,12 @@ export async function scanv1( req, res ) {
1098
1254
  const complianceData = { ...productMapping.toObject(), compliance: 'proper' };
1099
1255
  delete complianceData._id;
1100
1256
 
1101
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1257
+ let productDetails = await planoProductService.findOne( { _id: productMapping.toObject().productId } );
1258
+
1259
+ await planoComplianceService.updateOne( { ...mappingQuery, planoMappingId: productMapping.toObject()._id, date: currentDate }, complianceData );
1102
1260
 
1103
- return res.sendSuccess( { data: productMapping.toObject(), status: true } );
1104
- } else if ( planogram.productResolutionLevel === 'L4' || planogram.productResolutionLevel === 'L5' ) {
1261
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1262
+ } else if ( fixture.productResolutionLevel === 'L4' ) {
1105
1263
  if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1106
1264
 
1107
1265
  if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
@@ -1128,43 +1286,25 @@ export async function scanv1( req, res ) {
1128
1286
 
1129
1287
  const productMapping = await planoMappingService.findOne( mappingQuery );
1130
1288
 
1131
- if ( !productMapping ) return res.sendError( 'No product mapped for the spot', 400 );
1289
+ if ( !productMapping ) {
1290
+ shelf = await fixtureShelfService.findOne( misplacedQuery );
1291
+ if ( !shelf ) {
1292
+ return res.sendSuccess( { data: 'missing', status: false } );
1293
+ }
1294
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1295
+ }
1132
1296
 
1133
1297
  const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1134
1298
 
1135
1299
  if ( productMapping.toObject().rfId !== req.body.rfId ) {
1136
- if ( planogram.productResolutionLevel === 'L4' ) {
1137
- const complianceData = { ...productMapping.toObject(), compliance: 'misplaced' };
1138
- delete complianceData._id;
1139
-
1140
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1141
- return res.sendSuccess( false );
1142
- } else if ( planogram.productResolutionLevel === 'L5' ) {
1143
- const misplacedQuery = {
1144
- planoId: req.body.planoId,
1145
- floorId: req.body.floorId,
1146
- fixtureId: req.body.fixtureId,
1147
- rfId: req.body.rfId,
1148
- };
1149
- const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1150
-
1151
- if ( productMapping.toObject()?.category === misplacedProductMapping.toObject()?.category ) {
1152
- const complianceData = { ...productMapping.toObject(), compliance: 'proper' };
1153
- delete complianceData._id;
1300
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'misplaced' };
1301
+ delete complianceData._id;
1154
1302
 
1155
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1156
- return res.sendSuccess( true );
1157
- } else {
1158
- const complianceData = { ...productMapping.toObject(), compliance: 'misplaced' };
1159
- delete complianceData._id;
1160
-
1161
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1162
- return res.sendSuccess( false );
1163
- }
1164
- }
1303
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1304
+ return res.sendSuccess( false );
1165
1305
  }
1166
1306
 
1167
- const complianceData = { ...productMapping.toObject(), compliance: 'proper' };
1307
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1168
1308
  delete complianceData._id;
1169
1309
 
1170
1310
  await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
@@ -1178,3 +1318,78 @@ export async function scanv1( req, res ) {
1178
1318
  return res.sendError( e, 500 );
1179
1319
  }
1180
1320
  }
1321
+
1322
+ export async function updateMissing( req, res ) {
1323
+ try {
1324
+ const { planoId, fixtureId } = req.body;
1325
+
1326
+ const [ planogram, fixture ] = await Promise.all( [
1327
+ planoService.findOne(
1328
+ { _id: new mongoose.Types.ObjectId( planoId ) },
1329
+ { storeId: 1, storeName: 1, planoId: '$_id', productResolutionLevel: 1 },
1330
+ ),
1331
+ storeFixtureService.findOne( {
1332
+ _id: new mongoose.Types.ObjectId( fixtureId ),
1333
+ } ),
1334
+ ] );
1335
+
1336
+ if ( !planogram ) return res.sendError( 'Planogram not found', 204 );
1337
+ if ( !fixture ) return res.sendError( 'Fixture not found', 204 );
1338
+
1339
+ const fixtureShelves = await fixtureShelfService.find( {
1340
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
1341
+ } );
1342
+
1343
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
1344
+
1345
+ await Promise.all(
1346
+ fixtureShelves.map( async ( shelf ) => {
1347
+ const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
1348
+
1349
+ if ( !productMappings.length ) {
1350
+ return { ...shelf.toObject(), products: [] };
1351
+ }
1352
+
1353
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
1354
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
1355
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
1356
+
1357
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1358
+
1359
+ await Promise.all(
1360
+ productMappings.map( async ( mapping ) => {
1361
+ const productData = productMap.get( mapping.productId.toString() );
1362
+ if ( !productData ) {
1363
+ return { ...mapping.toObject(), status: '' };
1364
+ }
1365
+
1366
+ const mappingCompliance = await planoComplianceService.findOne( {
1367
+ planoMappingId: mapping._id,
1368
+ date: currentDate,
1369
+ } );
1370
+
1371
+ if ( !mappingCompliance ) {
1372
+ delete mapping.toObject()._id;
1373
+ planoComplianceService.create( { ...mapping.toObject(), planoMappingId: mapping._id, compliance: 'missing', date: currentDate } );
1374
+ }
1375
+
1376
+ return {
1377
+ ...mapping.toObject(),
1378
+ ...productData,
1379
+ };
1380
+ } ),
1381
+ );
1382
+
1383
+
1384
+ return {
1385
+ ...shelf.toObject(),
1386
+ };
1387
+ } ),
1388
+ );
1389
+
1390
+ return res.sendSuccess( 'Updated successfully' );
1391
+ } catch ( e ) {
1392
+ logger.error( { functionName: 'fixtureShelfProductv1', error: e, message: req.body } );
1393
+ return res.sendError( e, 500 );
1394
+ }
1395
+ }
@@ -23,6 +23,7 @@ storeBuilderRouter
23
23
  .post( '/storeLayout', validate( validateDtos.storeList ), storeBuilderController.storeLayout )
24
24
  .post( '/storeFixtures', validate( validateDtos.storeList ), storeBuilderController.storeFixturesv1 )
25
25
  .post( '/FixtureShelfDetails', validate( validateDtos.fixtureShelfProduct ), storeBuilderController.fixtureShelfProductv1 )
26
- .post( '/scan', storeBuilderController.scanv1 );
26
+ .post( '/scan', storeBuilderController.scanv1 )
27
+ .post( '/updateMissing', storeBuilderController.updateMissing );
27
28
 
28
29