Files
UniVerse/backend/UniVerse.Infrastructure/Services/ReviewService.cs
T

99 lines
4.3 KiB
C#

using Microsoft.EntityFrameworkCore;
using UniVerse.Application.DTOs.Common;
using UniVerse.Application.DTOs.Reviews;
using UniVerse.Application.Interfaces;
using UniVerse.Application.Mappings;
using UniVerse.Domain.Entities;
using UniVerse.Domain.Enums;
using UniVerse.Domain.Exceptions;
using UniVerse.Infrastructure.Data;
namespace UniVerse.Infrastructure.Services;
public class ReviewService : IReviewService
{
private readonly AppDbContext _db;
public ReviewService(AppDbContext db) => _db = db;
private IQueryable<Review> BaseQuery() => _db.Reviews
.Include(r => r.Lecture).Include(r => r.User);
public async Task<ReviewDto> CreateAsync(int userId, CreateReviewRequest req)
{
_ = await _db.Lectures.FindAsync(req.LectureId) ?? throw new NotFoundException("Lecture", req.LectureId);
if (await _db.Reviews.AnyAsync(r => r.LectureId == req.LectureId && r.UserId == userId))
throw new ConflictException("You already reviewed this lecture.");
var review = new Review
{
LectureId = req.LectureId, UserId = userId,
Rating = req.Rating, Text = req.Text,
LlmStatus = ReviewLlmStatus.Pending
};
_db.Reviews.Add(review);
await _db.SaveChangesAsync();
var full = await BaseQuery().FirstAsync(r => r.Id == review.Id);
return full.ToDto();
}
public async Task<ReviewDto> GetByIdAsync(int id)
{
var review = await BaseQuery().FirstOrDefaultAsync(r => r.Id == id)
?? throw new NotFoundException("Review", id);
return review.ToDto();
}
public async Task<ReviewDto> UpdateAsync(int id, int userId, UpdateReviewRequest req)
{
var review = await _db.Reviews.FindAsync(id) ?? throw new NotFoundException("Review", id);
if (review.UserId != userId) throw new ForbiddenException();
review.Rating = req.Rating; review.Text = req.Text;
review.LlmStatus = ReviewLlmStatus.Pending;
review.UpdatedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
return await GetByIdAsync(id);
}
public async Task DeleteAsync(int id, int userId, bool isAdmin = false)
{
var review = await _db.Reviews.FindAsync(id) ?? throw new NotFoundException("Review", id);
if (review.UserId != userId && !isAdmin) throw new ForbiddenException();
_db.Reviews.Remove(review);
await _db.SaveChangesAsync();
}
public async Task<PagedResult<ReviewDto>> GetByLectureAsync(int lectureId, PaginationRequest pagination)
{
var query = BaseQuery().Where(r => r.LectureId == lectureId);
var total = await query.CountAsync();
var items = await query.OrderByDescending(r => r.CreatedAt)
.Skip((pagination.Page - 1) * pagination.PageSize).Take(pagination.PageSize).ToListAsync();
return PagedResult<ReviewDto>.Create(items.Select(r => r.ToDto()).ToList(), total, pagination.Page, pagination.PageSize);
}
public async Task<PagedResult<ReviewDto>> GetByUserAsync(int userId, PaginationRequest pagination)
{
var query = BaseQuery().Where(r => r.UserId == userId);
var total = await query.CountAsync();
var items = await query.OrderByDescending(r => r.CreatedAt)
.Skip((pagination.Page - 1) * pagination.PageSize).Take(pagination.PageSize).ToListAsync();
return PagedResult<ReviewDto>.Create(items.Select(r => r.ToDto()).ToList(), total, pagination.Page, pagination.PageSize);
}
public async Task<PagedResult<ReviewDto>> GetPendingAsync(PaginationRequest pagination)
{
var query = BaseQuery().Where(r => r.LlmStatus == ReviewLlmStatus.Pending);
var total = await query.CountAsync();
var items = await query.OrderBy(r => r.CreatedAt)
.Skip((pagination.Page - 1) * pagination.PageSize).Take(pagination.PageSize).ToListAsync();
return PagedResult<ReviewDto>.Create(items.Select(r => r.ToDto()).ToList(), total, pagination.Page, pagination.PageSize);
}
public async Task ReanalyzeAsync(int id)
{
var review = await _db.Reviews.FindAsync(id) ?? throw new NotFoundException("Review", id);
review.LlmStatus = ReviewLlmStatus.Pending;
review.UpdatedAt = DateTime.UtcNow;
await _db.SaveChangesAsync();
}
}