@@ -57,24 +57,48 @@ const findOneProduct = async ({ productId, dbconnection }) => {
5757}
5858
5959// find all products from the database
60- const findAllProducts = async ( { dbconnection, logEvents } ) => {
60+ const findAllProducts = async ( { dbconnection, logEvents, ...filterOptions } ) => {
61+ const { category, minPrice, maxPrice, page, perPage, searchTerm } = filterOptions ;
6162
62- const db = await dbconnection ( ) ;
63- try {
64- const allProducts = await db . collection ( 'products' ) . find ( { } , {
65- projection : {
66- _id : 1 , title : 1 , description : 1 , price : 1 , category : 1 , brand : 1 , inventory : 1 , creationDate : 1 , expirationDate : 1 , origin : 1 , variations : 1 , salePrice : 1 , slug : 1 , totalRatings : 1 , totalReviews : 1 , totalSales : 1 , rateAverage : 1 ,
67- lastModified : 1 ,
68- instock : 1
69- }
70- } ) . toArray ( )
63+ //TODO: id necessary add limiting fields. this affect the projection props
7164
72- return allProducts . map ( ( product ) => {
73- const id = product . _id . toString ( ) ;
74- delete product . _id ;
75- return { ... product , id } ;
76- } ) ;
65+ const filter = { } ;
66+ if ( category ) filter . category = category ;
67+ if ( minPrice ) filter . price = { $gte : parseFloat ( minPrice ) } ;
68+ if ( maxPrice ) filter . price = { $lte : parseFloat ( maxPrice ) } ;
69+ if ( searchTerm ) filter . $text = { $search : searchTerm } ;
7770
71+ const projection = {
72+ _id : 0 , title : 1 , description : 1 , price : 1 , category : 1 , brand : 1 , creationDate : 1 , expirationDate : 1 , origin : 1 , variations : 1 , salePrice : 1 , slug : 1 ,
73+ lastModified : 1 ,
74+ instock : 1
75+ } ;
76+
77+ const offset = ( page - 1 ) * perPage ;
78+ const db = await dbconnection ( ) ;
79+
80+ try {
81+ const allProducts = await db
82+ . collection ( 'products' )
83+ . find ( filter )
84+ . project ( projection )
85+ . skip ( offset )
86+ . limit ( Number ( perPage ) )
87+ . toArray ( ) ;
88+
89+
90+ const totalProducts = await db
91+ . collection ( 'products' ) . countDocuments ( filter ) ;
92+ const totalPages = Math . ceil ( totalProducts / perPage ) ;
93+ const products = allProducts . map ( product => ( { ...product , id : product . _id . toString ( ) } ) ) ;
94+
95+ return {
96+ data : products ,
97+ totalProducts,
98+ totalPages,
99+ page,
100+ perPage
101+ } ;
78102 } catch ( error ) {
79103 console . log ( "Error from product DB handler: " , error ) ;
80104 logEvents (
@@ -83,7 +107,7 @@ const findAllProducts = async ({ dbconnection, logEvents }) => {
83107 ) ;
84108 return [ ] ;
85109 }
86- }
110+ } ;
87111
88112// update existing product
89113const updateProduct = async ( { productId, productData, dbconnection, logEvents } ) => {
@@ -169,8 +193,10 @@ const rateProduct = async ({ logEvents, ...ratingModel }) => {
169193 const productCollection = client . db ( "digital-market-place-updates" ) . collection ( "products" ) ;
170194 const ratingCollection = client . db ( "digital-market-place-updates" ) . collection ( "ratings" ) ;
171195
196+ // check if the product has been rated before.
172197 const existingProduct = await productCollection . findOne ( { _id : new ObjectId ( ratingModel . productId ) } , { session } ) ;
173- if ( ! existingProduct ) {
198+ if ( ! existingProduct ) { // cannot rate ghost product.
199+ session . abortTransaction ( ) ;
174200 return {
175201 error : {
176202 code : 404 ,
@@ -182,6 +208,7 @@ const rateProduct = async ({ logEvents, ...ratingModel }) => {
182208 /* find first if this user has already rate this existing product*/
183209 const existingRating = await ratingCollection . findOne ( { userId : ratingModel . userId , productId : ratingModel . productId } , { session } ) ;
184210 if ( existingRating ) {
211+ session . abortTransaction ( ) ;
185212 return {
186213 error : {
187214 code : 409 ,
@@ -190,17 +217,15 @@ const rateProduct = async ({ logEvents, ...ratingModel }) => {
190217 } ;
191218 }
192219
193- console . log ( "before insertion" )
194220 /* create a new rating document */
195221 const newRating = await ratingCollection . insertOne ( ratingModel , { session } ) ;
196- console . log ( "after insertion" )
197222 const { totalRatings } = existingProduct ;
198223 const totalReviews = totalRatings ?. reduce ( ( sum , rating ) => sum + rating , 0 ) || 0 ;
199- const newAverage = totalRatings ?. reduce ( ( sum , rating , index ) => sum + rating * ( index + 1 ) , 0 ) / ( totalReviews || 1 ) ;
224+ const newAverage = totalReviews ? totalRatings ?. reduce ( ( sum , rating , index ) => sum + rating * ( index + 1 ) , 0 ) / totalReviews : existingProduct . rateAverage ;
200225
201226 /* increase the new rating value in the totalRatings array */
202227 for ( let index = 0 ; index < 5 ; index ++ ) {
203- if ( ( ratingModel . ratingValue === ( index + 1 ) ) ) {
228+ if ( ratingModel . ratingValue === ( index + 1 ) ) {
204229 totalRatings [ index ] = totalRatings [ index ] + 1 ;
205230 }
206231 }
@@ -224,11 +249,8 @@ const rateProduct = async ({ logEvents, ...ratingModel }) => {
224249 } ,
225250 { session }
226251 ) ;
227-
228- await session . commitTransaction ( ) ;
229- console . log ( "Product rated successfully!" , updatedProduct ) ;
252+ // await session.commitTransaction();
230253 return { updatedProduct, newRating } ;
231-
232254 } , transactionOptions ) ;
233255
234256 } catch ( error ) {
@@ -244,7 +266,6 @@ const rateProduct = async ({ logEvents, ...ratingModel }) => {
244266 await client . close ( ) ;
245267 }
246268}
247-
248269// find one rating for a product based on product id and user id
249270const findOneRating = async ( { productId, userId } ) => {
250271
@@ -267,7 +288,7 @@ module.exports = ({ dbconnection, logEvents }) => {
267288 return Object . freeze ( {
268289 createProductDbHandler : async ( productData ) => createProduct ( productData , dbconnection , logEvents ) ,
269290 findOneProductDbHandler : async ( { productId } ) => findOneProduct ( { productId, dbconnection, logEvents } ) ,
270- findAllProductsDbHandler : async ( ) => findAllProducts ( { dbconnection, logEvents } ) ,
291+ findAllProductsDbHandler : async ( filterOptions ) => findAllProducts ( { dbconnection, logEvents, ... filterOptions } ) ,
271292 updateProductDbHandler : async ( { productId, productData } ) => updateProduct ( { productId, productData, dbconnection, logEvents } ) ,
272293 deleteProductDbHandler : async ( { productId } ) => deleteProduct ( { productId, dbconnection, logEvents } ) ,
273294 updateProductDbHandler : async ( { productId, ...productData } ) => updatedProduct ( { productId, dbconnection, logEvents, ...productData } ) ,
0 commit comments