diff --git a/src/services/reviewFeedback.service.ts b/src/services/reviewFeedback.service.ts index 73b9a98..e469c9d 100644 --- a/src/services/reviewFeedback.service.ts +++ b/src/services/reviewFeedback.service.ts @@ -3,7 +3,13 @@ import { getUser } from "./user.service"; import ReviewFeedback from "../models/ReviewFeedback"; import User from "../models/User"; import UserSettings from "../models/UserSettings"; -import { IReviewFeedback, IUser, IReviewFeedbackOutput, CompleteFeedback } from "../types"; +import { + IReviewFeedback, + IUser, + IReviewFeedbackOutput, + CompleteFeedback, +} from "../types"; +import { addNotification } from "./notification.service"; import logger from "../config/loggingConfig"; @@ -19,15 +25,23 @@ import logger from "../config/loggingConfig"; const computeRatings = async (user_settings_id: string) => { try { // Fetch all reviews for the user - const reviewFeedbackCount = await ReviewFeedback.countDocuments({ review_receiver_id: user_settings_id }).exec(); + const reviewFeedbackCount = await ReviewFeedback.countDocuments({ + review_receiver_id: user_settings_id, + }).exec(); if (reviewFeedbackCount === 0) { // Default value when there are no reviews - await UserSettings.findOneAndUpdate({ user_settings_id }, { trust_meter_rating: 100 }).exec(); + await UserSettings.findOneAndUpdate( + { user_settings_id }, + { trust_meter_rating: 100 } + ).exec(); return 100; } // Calculate the total number of reviews and the number of zero ratings - const totalReviews = reviewFeedbackCount - const zeroRatingsCount = await ReviewFeedback.countDocuments({ review_receiver_id: user_settings_id, rating: 0 }).exec(); + const totalReviews = reviewFeedbackCount; + const zeroRatingsCount = await ReviewFeedback.countDocuments({ + review_receiver_id: user_settings_id, + rating: 0, + }).exec(); // Calculate the percentage of zero ratings const zeroRatingsPercentage = (zeroRatingsCount / totalReviews) * 100; @@ -35,13 +49,13 @@ const computeRatings = async (user_settings_id: string) => { // Determine the value based on the percentage of zero ratings let value; switch (true) { - case (zeroRatingsPercentage <= 5): + case zeroRatingsPercentage <= 5: value = 100; break; - case (zeroRatingsPercentage > 5 && zeroRatingsPercentage <= 10): + case zeroRatingsPercentage > 5 && zeroRatingsPercentage <= 10: value = 80; break; - case (zeroRatingsPercentage > 10 && zeroRatingsPercentage <= 20): + case zeroRatingsPercentage > 10 && zeroRatingsPercentage <= 20: value = 50; break; default: @@ -49,23 +63,28 @@ const computeRatings = async (user_settings_id: string) => { } // Update the user's rating value in the database - await UserSettings.findOneAndUpdate({ user_settings_id }, { trust_meter_rating: value }); + await UserSettings.findOneAndUpdate( + { user_settings_id }, + { trust_meter_rating: value } + ); return value; } catch (error: any) { - logger.error(`Failed to compute ratings for userSettingsID ${ user_settings_id }: ${ error }`); + logger.error( + `Failed to compute ratings for userSettingsID ${user_settings_id}: ${error}` + ); throw error; } }; export const getReviewFeedback = async ( - review_receiver_id: string, - searchQuery?: string + review_receiver_id: string, + searchQuery?: string ): Promise => { try { //condition to search by username if (searchQuery && searchQuery.trim()) { const user = await User.findOne({ - pi_username: searchQuery + pi_username: searchQuery, }); if (!user) { return null; @@ -74,12 +93,16 @@ export const getReviewFeedback = async ( } const receivedFeedbackList = await ReviewFeedback.find({ - review_receiver_id: review_receiver_id - }).sort({ review_date: -1 }).exec(); + review_receiver_id: review_receiver_id, + }) + .sort({ review_date: -1 }) + .exec(); const givenFeedbackList = await ReviewFeedback.find({ - review_giver_id: review_receiver_id - }).sort({ review_date: -1 }).exec(); + review_giver_id: review_receiver_id, + }) + .sort({ review_date: -1 }) + .exec(); const updatedReceivedFeedbackList = await Promise.all( receivedFeedbackList.map(async (reviewFeedback) => { @@ -87,11 +110,15 @@ export const getReviewFeedback = async ( const reviewer = await getUser(reviewFeedback.review_giver_id); const receiver = await getUser(reviewFeedback.review_receiver_id); - const giverName = reviewer ? reviewer.user_name : ''; - const receiverName = receiver ? receiver.user_name : ''; + const giverName = reviewer ? reviewer.user_name : ""; + const receiverName = receiver ? receiver.user_name : ""; // Return the updated review feedback object - return { ...reviewFeedback.toObject(), giver: giverName, receiver: receiverName }; + return { + ...reviewFeedback.toObject(), + giver: giverName, + receiver: receiverName, + }; }) ); @@ -101,25 +128,32 @@ export const getReviewFeedback = async ( const reviewer = await getUser(reviewFeedback.review_giver_id); const receiver = await getUser(reviewFeedback.review_receiver_id); - const giverName = reviewer ? reviewer.user_name : ''; - const receiverName = receiver ? receiver.user_name : ''; + const giverName = reviewer ? reviewer.user_name : ""; + const receiverName = receiver ? receiver.user_name : ""; // Return the updated review feedback object - return { ...reviewFeedback.toObject(), giver: giverName, receiver: receiverName }; + return { + ...reviewFeedback.toObject(), + giver: giverName, + receiver: receiverName, + }; }) ); return { givenReviews: updatedGivenFeedbackList, - receivedReviews: updatedReceivedFeedbackList + receivedReviews: updatedReceivedFeedbackList, } as unknown as CompleteFeedback; - } catch (error: any) { - logger.error(`Failed to retrieve reviews for reviewReceiverID ${ review_receiver_id }: ${ error }`); + logger.error( + `Failed to retrieve reviews for reviewReceiverID ${review_receiver_id}: ${error}` + ); throw error; } }; -export const getReviewFeedbackById = async (review_id: string): Promise<{ +export const getReviewFeedbackById = async ( + review_id: string +): Promise<{ review: IReviewFeedbackOutput | null; replies: IReviewFeedbackOutput[]; } | null> => { @@ -133,7 +167,9 @@ export const getReviewFeedbackById = async (review_id: string): Promise<{ } // Fetch replies to the main review - const replies = await ReviewFeedback.find({ reply_to_review_id: review_id }).exec(); + const replies = await ReviewFeedback.find({ + reply_to_review_id: review_id, + }).exec(); // Fetch giver and receiver names for each reply asynchronously const updatedReplyList = await Promise.all( @@ -143,11 +179,15 @@ export const getReviewFeedbackById = async (review_id: string): Promise<{ getUser(reply.review_receiver_id), ]); - const giverName = reviewer?.user_name || 'Unknown'; - const receiverName = receiver?.user_name || 'Unknown'; + const giverName = reviewer?.user_name || "Unknown"; + const receiverName = receiver?.user_name || "Unknown"; // Return updated reply object - return { ...reply.toObject(), giver: giverName, receiver: receiverName }; + return { + ...reply.toObject(), + giver: giverName, + receiver: receiverName, + }; }) ); @@ -157,42 +197,54 @@ export const getReviewFeedbackById = async (review_id: string): Promise<{ getUser(reviewFeedback.review_receiver_id), ]); - const giverName = reviewer?.user_name || 'Unknown'; - const receiverName = receiver?.user_name || 'Unknown'; + const giverName = reviewer?.user_name || "Unknown"; + const receiverName = receiver?.user_name || "Unknown"; // Create the main review object with giver and receiver names - const mainReview = { ...reviewFeedback.toObject(), giver: giverName, receiver: receiverName }; + const mainReview = { + ...reviewFeedback.toObject(), + giver: giverName, + receiver: receiverName, + }; return { review: mainReview as unknown as IReviewFeedbackOutput, replies: updatedReplyList as unknown as IReviewFeedbackOutput[], }; } catch (error: any) { - logger.error(`Failed to retrieve review for reviewID ${ review_id }: ${ error }`); + logger.error( + `Failed to retrieve review for reviewID ${review_id}: ${error}` + ); throw error; } }; -export const addReviewFeedback = async (authUser: IUser, formData: any, image: string): Promise => { +export const addReviewFeedback = async ( + authUser: IUser, + formData: any, + image: string +): Promise => { try { const reviewFeedbackData: Partial = { - review_receiver_id: formData.review_receiver_id || '', + review_receiver_id: formData.review_receiver_id || "", review_giver_id: authUser.pi_uid, reply_to_review_id: formData.reply_to_review_id || null, - rating: formData.rating || '', - comment: formData.comment || '', - image: image || '', - review_date: new Date() + rating: formData.rating || "", + comment: formData.comment || "", + image: image || "", + review_date: new Date(), }; const newReviewFeedback = new ReviewFeedback(reviewFeedbackData); const savedReviewFeedback = await newReviewFeedback.save(); - const computedValue = await computeRatings(savedReviewFeedback.review_receiver_id); + const computedValue = await computeRatings( + savedReviewFeedback.review_receiver_id + ); logger.info(`Computed review rating: ${computedValue}`); return savedReviewFeedback as IReviewFeedback; } catch (error: any) { - logger.error(`Failed to add review: ${ error }`); + logger.error(`Failed to add review: ${error}`); throw error; } }; @@ -206,15 +258,19 @@ export const updateReviewFeedback = async ( const review = await ReviewFeedback.findById(reviewId).exec(); if (!review) { - logger.error(`Review with ID ${ reviewId } not found`); + logger.error(`Review with ID ${reviewId} not found`); const error = new Error(`Review with ID ${reviewId} not found`); error.name = "NotFoundError"; throw error; } if (review.review_giver_id !== authUser.pi_uid) { - logger.error(`User with ID: ${ review.review_giver_id } does not have permission to update this review`); - const error = new Error(`User with ID: ${ review.review_giver_id } does not have permission to update this review`); + logger.error( + `User with ID: ${review.review_giver_id} does not have permission to update this review` + ); + const error = new Error( + `User with ID: ${review.review_giver_id} does not have permission to update this review` + ); error.name = "ForbiddenError"; throw error; } @@ -231,7 +287,22 @@ export const updateReviewFeedback = async ( await review.save(); await computeRatings(review.review_receiver_id); - - logger.info(`Review ${reviewId} updated successfully by user ${authUser.pi_uid}`); + // Send notification to review receiver + try { + const message = `${ + authUser.user_name || authUser.pi_uid + } has updated a review they gave you on ${new Date().toLocaleString()}`; + await addNotification(review.review_receiver_id, message); + logger.info( + `Notification sent to ${review.review_receiver_id}: "${message}"` + ); + } catch (notifyErr: any) { + logger.error( + `Failed to send notification for review update: ${notifyErr.message}` + ); + } + logger.info( + `Review ${reviewId} updated successfully by user ${authUser.pi_uid}` + ); return review as IReviewFeedback; -}; \ No newline at end of file +};