tango-app-api-store-builder 1.0.0-beta-12 → 1.0.0-beta-14

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-12",
3
+ "version": "1.0.0-beta-14",
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,7 @@ 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',
576
580
  };
577
581
  } ),
578
582
  );
@@ -601,7 +605,7 @@ export async function storeFixturesv1( req, res ) {
601
605
 
602
606
  return {
603
607
  ...fixture.toObject(),
604
- status: productCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
608
+ status: complianceCount === 0 ? '' : complianceCount === productCount ? 'complete' : 'incomplete',
605
609
  };
606
610
  } ),
607
611
  );
@@ -774,57 +778,144 @@ export async function fixtureShelfProductv1( req, res ) {
774
778
  if ( !planogram ) return res.sendError( 'Planogram not found', 204 );
775
779
  if ( !fixture ) return res.sendError( 'Fixture not found', 204 );
776
780
 
777
- const fixtureShelves = await fixtureShelfService.find( {
778
- fixtureId: new mongoose.Types.ObjectId( fixtureId ),
779
- } );
781
+ if ( fixture.toObject().productResolutionLevel === 'L1' ) {
782
+ const productMappings = await planoMappingService.find( { fixtureId: new mongoose.Types.ObjectId( fixtureId ) } );
783
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
784
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
785
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
780
786
 
781
- if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
787
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
782
788
 
783
- const shelfProducts = await Promise.all(
784
- fixtureShelves.map( async ( shelf ) => {
785
- const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
789
+ const productDetails = await Promise.all(
790
+ productMappings.map( async ( mapping ) => {
791
+ const productData = productMap.get( mapping.productId.toString() ) || {};
792
+ const mappingCompliance = await planoComplianceService.findOne( {
793
+ planoMappingId: mapping._id,
794
+ date: currentDate,
795
+ } );
786
796
 
787
- if ( !productMappings.length ) {
788
- return { ...shelf.toObject(), products: [] };
789
- }
797
+ const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
790
798
 
791
- const productIds = productMappings.map( ( mapping ) => mapping.productId );
792
- const products = await planoProductService.find( { _id: { $in: productIds } } );
793
- const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
799
+ return { ...mapping.toObject(), ...productData, status };
800
+ } ),
801
+ );
794
802
 
795
- const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
803
+ return res.sendSuccess( { ...fixture.toObject(), products: productDetails } );
804
+ }
805
+ if ( fixture.toObject().productResolutionLevel === 'L2' || fixture.toObject().productResolutionLevel === 'L4' ) {
806
+ const fixtureShelves = await fixtureShelfService.find( {
807
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
808
+ } );
796
809
 
797
- const productDetails = await Promise.all(
798
- productMappings.map( async ( mapping ) => {
799
- const productData = productMap.get( mapping.productId.toString() );
800
- if ( !productData ) {
801
- return { ...mapping.toObject(), status: '' };
802
- }
810
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
803
811
 
804
- const mappingCompliance = await planoComplianceService.findOne( {
805
- shelfId: mapping.shelfId,
806
- shelfPosition: mapping.shelfPosition,
807
- date: currentDate,
808
- } );
812
+ const shelfProducts = await Promise.all(
813
+ fixtureShelves.map( async ( shelf ) => {
814
+ const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
809
815
 
810
- const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
816
+ if ( !productMappings.length ) {
817
+ return { ...shelf.toObject(), products: [] };
818
+ }
811
819
 
812
- return {
813
- ...mapping.toObject(),
814
- ...productData,
815
- status,
816
- };
817
- } ),
818
- );
820
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
821
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
822
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
823
+
824
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
825
+
826
+ const productDetails = await Promise.all(
827
+ productMappings.map( async ( mapping ) => {
828
+ const productData = productMap.get( mapping.productId.toString() );
829
+ if ( !productData ) {
830
+ return { ...mapping.toObject(), status: '' };
831
+ }
832
+
833
+ const mappingCompliance = await planoComplianceService.findOne( {
834
+ planoMappingId: mapping._id,
835
+ date: currentDate,
836
+ } );
837
+
838
+ const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
839
+
840
+ return {
841
+ ...mapping.toObject(),
842
+ ...productData,
843
+ status,
844
+ };
845
+ } ),
846
+ );
847
+
848
+ return {
849
+ ...shelf.toObject(),
850
+ products: productDetails,
851
+ };
852
+ } ),
853
+ );
854
+
855
+ return res.sendSuccess( { ...fixture.toObject(), shelves: shelfProducts } );
856
+ } else if ( fixture.toObject().productResolutionLevel === 'L3' ) {
857
+ const fixtureShelves = await fixtureShelfService.find( {
858
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
859
+ } );
819
860
 
820
- return {
821
- ...shelf.toObject(),
822
- products: productDetails,
823
- };
824
- } ),
825
- );
861
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
862
+ const groupedShelves = await ( async () => {
863
+ const shelfProducts = await Promise.all(
864
+ fixtureShelves.map( async ( shelf ) => {
865
+ const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
866
+
867
+ if ( !productMappings.length ) {
868
+ return { ...shelf.toObject(), products: [] };
869
+ }
870
+
871
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
872
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
873
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
874
+
875
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
876
+
877
+ const productDetails = await Promise.all(
878
+ productMappings.map( async ( mapping ) => {
879
+ const productData = productMap.get( mapping.productId.toString() );
880
+ if ( !productData ) {
881
+ return { ...mapping.toObject(), status: '' };
882
+ }
883
+
884
+ const mappingCompliance = await planoComplianceService.findOne( {
885
+ planoMappingId: mapping._id,
886
+ date: currentDate,
887
+ } );
888
+
889
+ const status = mappingCompliance ? mappingCompliance.compliance : 'missing';
890
+
891
+ return {
892
+ ...mapping.toObject(),
893
+ ...productData,
894
+ status,
895
+ };
896
+ } ),
897
+ );
898
+
899
+ return {
900
+ ...shelf.toObject(),
901
+ products: productDetails,
902
+ };
903
+ } ),
904
+ );
826
905
 
827
- return res.sendSuccess( { ...fixture.toObject(), shelves: shelfProducts } );
906
+ return shelfProducts.reduce( ( acc, shelf ) => {
907
+ const sectionName = shelf.sectionName || 'Unknown';
908
+ if ( !acc[sectionName] ) {
909
+ acc[sectionName] = [];
910
+ }
911
+ acc[sectionName].push( shelf );
912
+ return acc;
913
+ }, {} );
914
+ } )();
915
+ return res.sendSuccess( { ...fixture.toObject(), categories: groupedShelves } );
916
+ } else {
917
+ return res.sendError( 'Incorrect resolution level', 400 );
918
+ }
828
919
  } catch ( e ) {
829
920
  logger.error( { functionName: 'fixtureShelfProductv1', error: e, message: req.body } );
830
921
  return res.sendError( e, 500 );
@@ -866,7 +957,7 @@ export async function scan( req, res ) {
866
957
  shelfId = req.body.shelfId;
867
958
  req.body.shelfId = shelfDetails.map( ( ele ) => ele._id );
868
959
  }
869
- let productCheck= await planoMappingService.findOne( { rfId: req.body.rfId } );
960
+ let productCheck = await planoMappingService.findOne( { rfId: req.body.rfId } );
870
961
  if ( !productCheck ) {
871
962
  return res.sendError( 'Product not found', 400 );
872
963
  }
@@ -968,79 +1059,243 @@ export async function scan( req, res ) {
968
1059
 
969
1060
  export async function scanv1( req, res ) {
970
1061
  try {
971
- const planogram = await planoService.findOne(
972
- { _id: new mongoose.Types.ObjectId( req.body.planoId ) },
1062
+ const fixture = await storeFixtureService.findOne(
1063
+ { _id: new mongoose.Types.ObjectId( req.body.fixtureId ) },
973
1064
  { storeId: 1, storeName: 1, planoId: '$_id', productResolutionLevel: 1 },
974
1065
  );
975
1066
 
976
- if ( !planogram ) return res.sendError( 'No data found', 204 );
1067
+ if ( !fixture ) return res.sendError( 'No data found', 204 );
977
1068
 
978
- if ( planogram.productResolutionLevel === 'L4' || planogram.productResolutionLevel === 'L5' ) {
1069
+ if ( fixture.productResolutionLevel === 'L1' ) {
979
1070
  if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
980
1071
 
1072
+ if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1073
+
981
1074
  if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
982
1075
 
1076
+ const mappingQuery = {
1077
+ planoId: req.body.planoId,
1078
+ floorId: req.body.floorId,
1079
+ fixtureId: req.body.fixtureId,
1080
+ rfId: req.body.rfId,
1081
+ };
1082
+
1083
+ const productMapping = await planoMappingService.findOne( mappingQuery );
1084
+
1085
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1086
+
1087
+ if ( !productMapping ) {
1088
+ const misplacedQuery = {
1089
+ planoId: req.body.planoId,
1090
+ floorId: req.body.floorId,
1091
+ rfId: req.body.rfId,
1092
+ };
1093
+ const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1094
+
1095
+ if ( !misplacedProductMapping ) {
1096
+ return res.sendSuccess( { data: 'missing', status: false } );
1097
+ }
1098
+
1099
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1100
+ delete complianceData._id;
1101
+
1102
+ let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1103
+
1104
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1105
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1106
+ }
1107
+
1108
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1109
+ delete complianceData._id;
1110
+
1111
+ let productDetails = await planoProductService.findOne( { _id: mappingQuery.productId } );
1112
+
1113
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1114
+
1115
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1116
+ } else if ( fixture.productResolutionLevel === 'L2' ) {
1117
+ if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1118
+
983
1119
  if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
984
1120
 
1121
+ if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1122
+
985
1123
  if ( !req.body.shelfId && req.body.rfId ) {
986
1124
  const shelf = await fixtureShelfService.findOne( { planoId: req.body.planoId, floorId: req.body.floorId, fixtureId: req.body.fixtureId, rfId: req.body.rfId } );
987
1125
  if ( !shelf ) return res.sendError( 'No matching shelf for the rfId', 400 );
988
- return res.sendSuccess( shelf.toObject()._id );
1126
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
989
1127
  }
990
1128
 
991
1129
  if ( !req.body.shelfId ) return res.sendError( 'Shelf id is required', 400 );
992
1130
 
993
- if ( !req.body.shelfPosition ) return res.sendError( 'Shelf position is required', 400 );
994
-
995
1131
  const mappingQuery = {
996
1132
  planoId: req.body.planoId,
997
1133
  floorId: req.body.floorId,
998
1134
  fixtureId: req.body.fixtureId,
999
1135
  shelfId: req.body.shelfId,
1000
- shelfPosition: req.body.shelfPosition,
1136
+ rfId: req.body.rfId,
1001
1137
  };
1002
1138
 
1003
1139
  const productMapping = await planoMappingService.findOne( mappingQuery );
1004
1140
 
1005
- if ( !productMapping ) return res.sendError( 'No product mapped for the spot', 400 );
1006
-
1007
1141
  const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1008
1142
 
1009
- if ( productMapping.toObject().rfId !== req.body.rfId ) {
1010
- if ( planogram.productResolutionLevel === 'L4' ) {
1011
- const complianceData = { ...productMapping.toObject(), compliance: 'misplaced' };
1012
- delete complianceData._id;
1143
+ if ( !productMapping ) {
1144
+ const misplacedQuery = {
1145
+ planoId: req.body.planoId,
1146
+ floorId: req.body.floorId,
1147
+ rfId: req.body.rfId,
1148
+ };
1149
+ const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1150
+
1151
+ if ( !misplacedProductMapping ) {
1152
+ const shelf = await fixtureShelfService.findOne( misplacedQuery );
1153
+ if ( !shelf ) {
1154
+ return res.sendSuccess( { data: 'missing', status: false } );
1155
+ }
1156
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1157
+ }
1013
1158
 
1014
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1015
- return res.sendSuccess( false );
1016
- } else if ( planogram.productResolutionLevel === 'L5' ) {
1017
- const misplacedQuery = {
1018
- planoId: req.body.planoId,
1019
- floorId: req.body.floorId,
1020
- fixtureId: req.body.fixtureId,
1021
- rfId: req.body.rfId,
1022
- };
1023
- const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1159
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1160
+ delete complianceData._id;
1161
+
1162
+ let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1163
+
1164
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1165
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1166
+ }
1024
1167
 
1025
- if ( productMapping.toObject()?.category === misplacedProductMapping.toObject()?.category ) {
1026
- const complianceData = { ...productMapping.toObject(), compliance: 'proper' };
1027
- delete complianceData._id;
1168
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1169
+ delete complianceData._id;
1170
+
1171
+ let productDetails = await planoProductService.findOne( { _id: productMapping.toObject().productId } );
1172
+
1173
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1028
1174
 
1029
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1030
- return res.sendSuccess( true );
1031
- } else {
1032
- const complianceData = { ...productMapping.toObject(), compliance: 'misplaced' };
1033
- delete complianceData._id;
1175
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1176
+ } else if ( fixture.productResolutionLevel === 'L3' ) {
1177
+ if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1178
+
1179
+ if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1034
1180
 
1035
- await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1036
- return res.sendSuccess( false );
1181
+ if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1182
+
1183
+ if ( !req.body.shelfId && req.body.rfId ) {
1184
+ const shelf = await fixtureShelfService.findOne( { planoId: req.body.planoId, floorId: req.body.floorId, fixtureId: req.body.fixtureId, rfId: req.body.rfId } );
1185
+ if ( !shelf ) return res.sendError( 'No matching shelf for the rfId', 400 );
1186
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1187
+ }
1188
+
1189
+ if ( !req.body.shelfId ) return res.sendError( 'Shelf id is required', 400 );
1190
+
1191
+ const mappingQuery = {
1192
+ planoId: req.body.planoId,
1193
+ floorId: req.body.floorId,
1194
+ fixtureId: req.body.fixtureId,
1195
+ shelfId: req.body.shelfId,
1196
+ rfId: req.body.rfId,
1197
+ };
1198
+
1199
+ const productMapping = await planoMappingService.findOne( mappingQuery );
1200
+
1201
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1202
+
1203
+ if ( !productMapping ) {
1204
+ const shelf = await fixtureShelfService.findOne( { _id: new mongoose.Types.ObjectId( req.body.shelfId ) } );
1205
+
1206
+ if ( !shelf ) {
1207
+ return res.sendError( 'Invalid shelf Id', 400 );
1208
+ }
1209
+ const misplacedQuery = {
1210
+ planoId: req.body.planoId,
1211
+ floorId: req.body.floorId,
1212
+ rfId: req.body.rfId,
1213
+ };
1214
+ const misplacedProductMapping = await planoMappingService.findOne( misplacedQuery );
1215
+
1216
+ if ( !misplacedProductMapping ) {
1217
+ const shelf = await fixtureShelfService.findOne( misplacedQuery );
1218
+ if ( !shelf ) {
1219
+ return res.sendSuccess( { data: 'missing', status: false } );
1037
1220
  }
1221
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1222
+ }
1223
+
1224
+ const misplacedProductShelf = await fixtureShelfService.findOne( { _id: misplacedProductMapping.toObject().shelfId } );
1225
+
1226
+ let misplacedProductDetails = await planoProductService.findOne( { _id: misplacedProductMapping.toObject().productId } );
1227
+
1228
+ if ( shelf.toObject().sectionName === misplacedProductShelf.toObject().sectionName ) {
1229
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'proper' };
1230
+ delete complianceData._id;
1231
+
1232
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1233
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: true } );
1234
+ } else {
1235
+ const complianceData = { ...misplacedProductMapping.toObject(), planoMappingId: misplacedProductMapping.toObject()._id, compliance: 'misplaced' };
1236
+ delete complianceData._id;
1237
+
1238
+ await planoComplianceService.updateOne( { ...misplacedQuery, date: currentDate }, complianceData );
1239
+ return res.sendSuccess( { data: { ...misplacedProductMapping.toObject(), ...( misplacedProductDetails ? misplacedProductDetails?.toObject() : {} ) }, status: false } );
1038
1240
  }
1039
1241
  }
1040
1242
 
1041
1243
  const complianceData = { ...productMapping.toObject(), compliance: 'proper' };
1042
1244
  delete complianceData._id;
1043
1245
 
1246
+ let productDetails = await planoProductService.findOne( { _id: productMapping.toObject().productId } );
1247
+
1248
+ await planoComplianceService.updateOne( { ...mappingQuery, planoMappingId: productMapping.toObject()._id, date: currentDate }, complianceData );
1249
+
1250
+ return res.sendSuccess( { data: { ...productMapping.toObject(), ...( productDetails ? productDetails?.toObject() : {} ) }, status: true } );
1251
+ } else if ( fixture.productResolutionLevel === 'L4' ) {
1252
+ if ( !req.body.floorId ) return res.sendError( 'Floor id is required', 400 );
1253
+
1254
+ if ( !req.body.rfId ) return res.sendError( 'RFID is required', 400 );
1255
+
1256
+ if ( !req.body.fixtureId ) return res.sendError( 'Fixture id is required', 400 );
1257
+
1258
+ if ( !req.body.shelfId && req.body.rfId ) {
1259
+ const shelf = await fixtureShelfService.findOne( { planoId: req.body.planoId, floorId: req.body.floorId, fixtureId: req.body.fixtureId, rfId: req.body.rfId } );
1260
+ if ( !shelf ) return res.sendError( 'No matching shelf for the rfId', 400 );
1261
+ return res.sendSuccess( shelf.toObject()._id );
1262
+ }
1263
+
1264
+ if ( !req.body.shelfId ) return res.sendError( 'Shelf id is required', 400 );
1265
+
1266
+ if ( !req.body.shelfPosition ) return res.sendError( 'Shelf position is required', 400 );
1267
+
1268
+ const mappingQuery = {
1269
+ planoId: req.body.planoId,
1270
+ floorId: req.body.floorId,
1271
+ fixtureId: req.body.fixtureId,
1272
+ shelfId: req.body.shelfId,
1273
+ shelfPosition: req.body.shelfPosition,
1274
+ };
1275
+
1276
+ const productMapping = await planoMappingService.findOne( mappingQuery );
1277
+
1278
+ if ( !productMapping ) {
1279
+ shelf = await fixtureShelfService.findOne( misplacedQuery );
1280
+ if ( !shelf ) {
1281
+ return res.sendSuccess( { data: 'missing', status: false } );
1282
+ }
1283
+ return res.sendSuccess( { shelfId: shelf.toObject()._id } );
1284
+ }
1285
+
1286
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1287
+
1288
+ if ( productMapping.toObject().rfId !== req.body.rfId ) {
1289
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'misplaced' };
1290
+ delete complianceData._id;
1291
+
1292
+ await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1293
+ return res.sendSuccess( false );
1294
+ }
1295
+
1296
+ const complianceData = { ...productMapping.toObject(), planoMappingId: productMapping.toObject()._id, compliance: 'proper' };
1297
+ delete complianceData._id;
1298
+
1044
1299
  await planoComplianceService.updateOne( { ...mappingQuery, date: currentDate }, complianceData );
1045
1300
 
1046
1301
  return res.sendSuccess( true );
@@ -1052,3 +1307,79 @@ export async function scanv1( req, res ) {
1052
1307
  return res.sendError( e, 500 );
1053
1308
  }
1054
1309
  }
1310
+
1311
+ export async function updateMissing( req, res ) {
1312
+ try {
1313
+ const { planoId, fixtureId } = req.body;
1314
+
1315
+ const [ planogram, fixture ] = await Promise.all( [
1316
+ planoService.findOne(
1317
+ { _id: new mongoose.Types.ObjectId( planoId ) },
1318
+ { storeId: 1, storeName: 1, planoId: '$_id', productResolutionLevel: 1 },
1319
+ ),
1320
+ storeFixtureService.findOne( {
1321
+ _id: new mongoose.Types.ObjectId( fixtureId ),
1322
+ } ),
1323
+ ] );
1324
+
1325
+ if ( !planogram ) return res.sendError( 'Planogram not found', 204 );
1326
+ if ( !fixture ) return res.sendError( 'Fixture not found', 204 );
1327
+
1328
+ const fixtureShelves = await fixtureShelfService.find( {
1329
+ fixtureId: new mongoose.Types.ObjectId( fixtureId ),
1330
+ } );
1331
+
1332
+ if ( !fixtureShelves.length ) return res.sendError( 'No shelves found for the fixture', 204 );
1333
+
1334
+ await Promise.all(
1335
+ fixtureShelves.map( async ( shelf ) => {
1336
+ const productMappings = await planoMappingService.find( { shelfId: shelf._id } );
1337
+
1338
+ if ( !productMappings.length ) {
1339
+ return { ...shelf.toObject(), products: [] };
1340
+ }
1341
+
1342
+ const productIds = productMappings.map( ( mapping ) => mapping.productId );
1343
+ const products = await planoProductService.find( { _id: { $in: productIds } } );
1344
+ const productMap = new Map( products.map( ( product ) => [ product._id.toString(), product.toObject() ] ) );
1345
+
1346
+ const currentDate = new Date( dayjs().format( 'YYYY-MM-DD' ) );
1347
+
1348
+ await Promise.all(
1349
+ productMappings.map( async ( mapping ) => {
1350
+ const productData = productMap.get( mapping.productId.toString() );
1351
+ if ( !productData ) {
1352
+ return { ...mapping.toObject(), status: '' };
1353
+ }
1354
+
1355
+ const mappingCompliance = await planoComplianceService.findOne( {
1356
+ shelfId: mapping.shelfId,
1357
+ shelfPosition: mapping.shelfPosition,
1358
+ date: currentDate,
1359
+ } );
1360
+
1361
+ if ( !mappingCompliance ) {
1362
+ delete mapping.toObject()._id;
1363
+ planoComplianceService.create( { ...mapping.toObject(), compliance: 'missing', date: currentDate } );
1364
+ }
1365
+
1366
+ return {
1367
+ ...mapping.toObject(),
1368
+ ...productData,
1369
+ };
1370
+ } ),
1371
+ );
1372
+
1373
+
1374
+ return {
1375
+ ...shelf.toObject(),
1376
+ };
1377
+ } ),
1378
+ );
1379
+
1380
+ return res.sendSuccess( 'Updated successfully' );
1381
+ } catch ( e ) {
1382
+ logger.error( { functionName: 'fixtureShelfProductv1', error: e, message: req.body } );
1383
+ return res.sendError( e, 500 );
1384
+ }
1385
+ }
@@ -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