customerreviwew

This commit is contained in:
Tizian.Breuch
2025-09-25 16:25:36 +02:00
parent 1f28c189ce
commit 32d6f4508f
3 changed files with 55 additions and 13 deletions

View File

@@ -1,8 +1,10 @@
// src/Webshop.Api/Controllers/Customer/ReviewsController.cs // src/Webshop.Api/Controllers/Customer/ReviewsController.cs
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Webshop.Application;
using Webshop.Application.DTOs.Reviews; using Webshop.Application.DTOs.Reviews;
using Webshop.Application.Services.Customers; using Webshop.Application.Services.Customers;
@@ -21,16 +23,34 @@ namespace Webshop.Api.Controllers.Customer
} }
[HttpPost] [HttpPost]
[ProducesResponseType(typeof(ReviewDto), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]
public async Task<IActionResult> CreateReview([FromBody] CreateReviewDto reviewDto) public async Task<IActionResult> CreateReview([FromBody] CreateReviewDto reviewDto)
{ {
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new { Message = "Benutzer konnte nicht identifiziert werden." });
}
var result = await _customerReviewService.CreateReviewAsync(reviewDto, userId); var result = await _customerReviewService.CreateReviewAsync(reviewDto, userId);
if (result.Type == Application.ServiceResultType.Success) return result.Type switch
{ {
return Ok(result.Value); ServiceResultType.Success => CreatedAtAction(null, new { id = result.Value!.Id }, result.Value), // 201 Created
} ServiceResultType.Unauthorized => Unauthorized(new { Message = result.ErrorMessage }),
return BadRequest(new { Message = result.ErrorMessage }); ServiceResultType.Forbidden => Forbid(), // 403 Forbidden
ServiceResultType.Conflict => Conflict(new { Message = result.ErrorMessage }), // 409 Conflict
_ => BadRequest(new { Message = result.ErrorMessage }) // 400 for InvalidInput or other failures
};
} }
} }
} }

View File

@@ -1,4 +1,4 @@
// src/Webshop.Application/Services/Customers/Interfaces/IReviewService.cs // src/Webshop.Application/Services/Customers/Interfaces/ICustomerReviewService.cs
using System.Threading.Tasks; using System.Threading.Tasks;
using Webshop.Application; using Webshop.Application;
using Webshop.Application.DTOs.Reviews; using Webshop.Application.DTOs.Reviews;

View File

@@ -1,7 +1,9 @@
// src/Webshop.Application/Services/Customers/ReviewService.cs // src/Webshop.Application/Services/Customers/CustomerReviewService.cs
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Webshop.Application;
using Webshop.Application.DTOs.Reviews; using Webshop.Application.DTOs.Reviews;
using Webshop.Domain.Entities; using Webshop.Domain.Entities;
using Webshop.Domain.Interfaces; using Webshop.Domain.Interfaces;
@@ -25,12 +27,20 @@ namespace Webshop.Application.Services.Customers
public async Task<ServiceResult<ReviewDto>> CreateReviewAsync(CreateReviewDto reviewDto, string userId) public async Task<ServiceResult<ReviewDto>> CreateReviewAsync(CreateReviewDto reviewDto, string userId)
{ {
var customer = await _customerRepository.GetByUserIdAsync(userId); var customer = await _customerRepository.GetByUserIdAsync(userId);
if (customer == null) return ServiceResult.Fail<ReviewDto>(ServiceResultType.Unauthorized, "Kunde nicht gefunden."); if (customer == null)
return ServiceResult.Fail<ReviewDto>(ServiceResultType.Unauthorized, "Kundenprofil nicht gefunden.");
// Business-Regel: Hat der Kunde dieses Produkt gekauft? // Business-Regel 1: Hat der Kunde dieses Produkt bereits bewertet?
// bool hasPurchased = await _context.OrderItems bool hasAlreadyReviewed = await _context.Reviews
// .AnyAsync(oi => oi.ProductId == reviewDto.ProductId && oi.Order.CustomerId == customer.Id); .AnyAsync(r => r.ProductId == reviewDto.ProductId && r.CustomerId == customer.Id);
// if (!hasPurchased) return ServiceResult.Fail<ReviewDto>(ServiceResultType.Forbidden, "Sie können nur Produkte bewerten, die Sie gekauft haben."); if (hasAlreadyReviewed)
return ServiceResult.Fail<ReviewDto>(ServiceResultType.Conflict, "Sie haben dieses Produkt bereits bewertet.");
// Business-Regel 2: Hat der Kunde dieses Produkt überhaupt gekauft?
bool hasPurchased = await _context.OrderItems
.AnyAsync(oi => oi.ProductId == reviewDto.ProductId && oi.Order.CustomerId == customer.Id);
if (!hasPurchased)
return ServiceResult.Fail<ReviewDto>(ServiceResultType.Forbidden, "Sie können nur Produkte bewerten, die Sie auch gekauft haben.");
var newReview = new Review var newReview = new Review
{ {
@@ -40,12 +50,24 @@ namespace Webshop.Application.Services.Customers
Title = reviewDto.Title, Title = reviewDto.Title,
Comment = reviewDto.Comment, Comment = reviewDto.Comment,
ReviewDate = DateTimeOffset.UtcNow, ReviewDate = DateTimeOffset.UtcNow,
IsApproved = false // Bewertungen müssen vom Admin freigegeben werden IsApproved = false // Bewertungen müssen standardmäßig vom Admin freigegeben werden
}; };
await _reviewRepository.AddAsync(newReview); await _reviewRepository.AddAsync(newReview);
var resultDto = new ReviewDto { /* Mapping */ }; // Mapping vervollständigen, um das erstellte Objekt zurückzugeben
var resultDto = new ReviewDto
{
Id = newReview.Id,
ProductId = newReview.ProductId,
CustomerName = $"{customer.FirstName} {customer.LastName}".Trim(),
Rating = newReview.Rating,
Title = newReview.Title,
Comment = newReview.Comment,
ReviewDate = newReview.ReviewDate,
IsApproved = newReview.IsApproved
};
return ServiceResult.Ok(resultDto); return ServiceResult.Ok(resultDto);
} }
} }