update review entity
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-07-15 12:07:58 +03:30
parent a05643daf5
commit 204b4f2007
7 changed files with 266 additions and 296 deletions
@@ -9,11 +9,6 @@ export class CreateReviewDto {
@ApiProperty({ description: 'Food ID' })
foodId: string;
@IsNotEmpty()
@IsString()
@ApiProperty({ description: 'Order ID' })
orderId: string;
@IsNotEmpty()
@IsNumber()
@Min(1)
+3 -4
View File
@@ -7,13 +7,12 @@ import { PositivePoint, NegativePoint } from '../enums/review-point.enum';
import { ReviewStatus } from '../enums/review-status.enum';
@Entity({ tableName: 'reviews' })
@Unique({ properties: ['order', 'food', 'user'] })
@Unique({ properties: ['food', 'user'] })
@Index({ properties: ['food', 'status'] })
@Index({ properties: ['user'] })
@Index({ properties: ['order'] })
export class Review extends BaseEntity {
@ManyToOne(() => Order)
order: Order;
@Property({ type: 'boolean' })
isBuyer: boolean = false
@ManyToOne(() => Food)
food: Food;
@@ -5,8 +5,6 @@ export class ReviewCreatedEvent {
public readonly userId: string,
public readonly foodId: string,
public readonly foodName: string,
public readonly orderId: string,
public readonly orderNumber: string | number,
public readonly rating: number,
) {}
}
@@ -46,13 +46,12 @@ export class ReviewListeners {
restaurantId: event.restaurantId,
message: {
title: NotifTitleEnum.REVIEW_CREATED,
content: `نظر جدید برای غذا "${event.foodName}" با امتیاز ${event.rating} از 5 برای سفارش شماره ${event.orderNumber} ثبت شد`,
content: `نظر جدید برای غذا "${event.foodName}" با امتیاز ${event.rating} از 5 برای سفارش شماره ثبت شد`,
sms: {
templateId: this.reviewCreatedSmsTemplateId,
parameters: {
foodName: event.foodName,
rating: event.rating.toString(),
orderNumber: String(event.orderNumber),
},
},
pushNotif: {
+16 -38
View File
@@ -10,12 +10,12 @@ import { RequiredEntityData } from '@mikro-orm/core';
import { Review } from '../entities/review.entity';
import { FoodMessage, UserMessage, ReviewMessage } from 'src/common/enums/message.enum';
import { Order } from '../../orders/entities/order.entity';
import { OrderItem } from '../../orders/entities/order-item.entity';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { ReviewStatus } from '../enums/review-status.enum';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { ReviewCreatedEvent } from '../events/review.events';
import { sanitizeText } from '../../utils/sanitize.util';
import { OrderStatus } from 'src/modules/orders/interface/order.interface';
@Injectable()
export class ReviewService {
@@ -28,9 +28,9 @@ export class ReviewService {
) { }
async create(userId: string, createReviewDto: CreateReviewDto): Promise<Review> {
const { foodId, orderId, rating, comment, positivePoints, negativePoints } = createReviewDto;
const { foodId, rating, comment, positivePoints, negativePoints } = createReviewDto;
const food = await this.foodRepository.findOne({ id: foodId });
const food = await this.foodRepository.findOne({ id: foodId }, { populate: ['restaurant'] });
if (!food) {
throw new NotFoundException(FoodMessage.NOT_FOUND);
}
@@ -40,34 +40,14 @@ export class ReviewService {
throw new NotFoundException(UserMessage.USER_NOT_FOUND);
}
// Find order and verify it belongs to the user, populate restaurant to get restaurantId
const order = await this.em.findOne(Order, { id: orderId, user: { id: userId } }, { populate: ['restaurant'] });
if (!order) {
throw new NotFoundException('Order not found or does not belong to the current user');
}
// Verify the food is in the order
const orderItem = await this.em.findOne(OrderItem, {
order: { id: orderId },
food: { id: foodId },
});
if (!orderItem) {
throw new BadRequestException('Food is not in the specified order');
}
// Check if user already commented on this food for this order
const existingReview = await this.reviewRepository.findOne({
order: { id: orderId },
food: { id: foodId },
user: { id: userId },
});
if (existingReview) {
throw new BadRequestException(ReviewMessage.ALREADY_COMMENTED);
}
const isBuyer = await this.em.count(Order, {
status: OrderStatus.COMPLETED,
items: { food: { id: foodId } },
user: { id: userId }
}) > 0;
const data: RequiredEntityData<Review> = {
order,
isBuyer: true,
food,
user,
rating,
@@ -92,12 +72,10 @@ export class ReviewService {
ReviewCreatedEvent.name,
new ReviewCreatedEvent(
review.id,
order.restaurant.id,
food.restaurant.id,
userId,
foodId,
food.title || 'Unknown Food',
orderId,
order.orderNumber || '',
food.title || '',
rating,
),
);
@@ -120,8 +98,8 @@ export class ReviewService {
async findById(id: string, restaurantId: string): Promise<Review> {
const review = await this.reviewRepository.findOne(
{ id, order: { restaurant: { id: restaurantId } } },
{ populate: ['food', 'user', 'order'] },
{ id, food: { restaurant: { id: restaurantId } } },
{ populate: ['food', 'user'] },
);
if (!review) {
throw new NotFoundException(ReviewMessage.NOT_FOUND);
@@ -130,7 +108,7 @@ export class ReviewService {
}
async update(id: string, userId: string, dto: UpdateReviewDto, isAdmin: boolean = false): Promise<Review> {
const review = await this.reviewRepository.findOne({ id }, { populate: ['food', 'user', 'order'] });
const review = await this.reviewRepository.findOne({ id }, { populate: ['food', 'user',] });
if (!review) {
throw new NotFoundException(ReviewMessage.NOT_FOUND);
}
@@ -165,7 +143,7 @@ export class ReviewService {
}
async changeStatus(reviewId: string, status: ReviewStatus, restaurantId: string): Promise<Review> {
const review = await this.reviewRepository.findOne({ id: reviewId, order: { restaurant: { id: restaurantId } } });
const review = await this.reviewRepository.findOne({ id: reviewId, food: { restaurant: { id: restaurantId } } });
if (!review) {
throw new NotFoundException(ReviewMessage.NOT_FOUND);
}
@@ -175,7 +153,7 @@ export class ReviewService {
}
async remove(id: string, userId: string, isAdmin: boolean = false) {
const review = await this.reviewRepository.findOne({ id }, { populate: ['food', 'user', 'order'] });
const review = await this.reviewRepository.findOne({ id }, { populate: ['food', 'user'] });
if (!review) {
throw new NotFoundException(ReviewMessage.NOT_FOUND);
}