@@ -1,4 +1,5 @@
// src/Webshop.Application/Services/Public/ProductService.cs
// / src/Webshop.Application/Services/Public/ProductService.cs
using Microsoft.EntityFrameworkCore ;
using System.Collections.Generic ;
using System.Linq ;
@@ -12,6 +13,10 @@ using Webshop.Infrastructure.Data;
namespace Webshop.Application.Services.Public
{
/// <summary>
/// Service, der f<> r die Abfrage von Produktinformationen f<> r den <20> ffentlichen Shop-Bereich zust<73> ndig ist.
/// Alle hier zur<75> ckgegebenen Daten sind f<> r jeden Besucher sichtbar.
/// </summary>
public class ProductService : IProductService
{
private readonly ApplicationDbContext _context ;
@@ -21,53 +26,96 @@ namespace Webshop.Application.Services.Public
_context = context ;
}
/// <summary>
/// Ruft eine Liste aller aktiven Produkte f<> r die allgemeine Produkt<6B> bersicht ab.
/// </summary>
/// <returns>Eine Liste von ProductDto-Objekten.</returns>
public async Task < ServiceResult < IEnumerable < ProductDto > > > GetAllProductsAsync ( )
{
// Startet eine Abfrage auf die 'Products'-Tabelle in der Datenbank.
var products = await _context . Products
. Include ( p = > p . Productcategories ) . ThenInclude ( pc = > pc . categorie )
// L<> dt die zugeh<65> rigen 'Productcategories'-Verkn<6B> pfungen mit.
. Include ( p = > p . Productcategories )
// L<> dt von dort aus die eigentliche 'categorie'-Entit<69> t.
. ThenInclude ( pc = > pc . categorie )
// L<> dt auch die zugeh<65> rigen Produktbilder mit.
. Include ( p = > p . Images )
// Filtert die Ergebnisse: Nur Produkte, die als 'IsActive' markiert sind.
. Where ( p = > p . IsActive )
// F<> hrt die Abfrage auf der Datenbank aus und l<> dt die Ergebnisse in eine Liste.
. ToListAsync ( ) ;
// Wandelt jede Product-Entit<69> t in ein ProductDto um.
// 'useShortDescription: true' sorgt daf<61> r, dass die k<> rzere Beschreibung f<> r die Listenansicht verwendet wird.
var dtos = products . Select ( p = > MapToDto ( p , useShortDescription : true ) ) . ToList ( ) ;
// Gibt das erfolgreiche Ergebnis mit der DTO-Liste zur<75> ck.
return ServiceResult . Ok < IEnumerable < ProductDto > > ( dtos ) ;
}
/// <summary>
/// Ruft ein einzelnes, aktives Produkt anhand seines eindeutigen Slugs ab (f<> r die Produktdetailseite).
/// </summary>
/// <param name="slug">Der URL-freundliche Slug des Produkts.</param>
/// <returns>Ein einzelnes ProductDto oder ein NotFound-Ergebnis.</returns>
public async Task < ServiceResult < ProductDto > > GetProductBySlugAsync ( string slug )
{
// Startet eine Abfrage auf die 'Products'-Tabelle.
var product = await _context . Products
// L<> dt alle notwendigen verkn<6B> pften Daten f<> r die Detailansicht.
. Include ( p = > p . Productcategories ) . ThenInclude ( pc = > pc . categorie )
. Include ( p = > p . Images )
// Findet das erste Produkt, das dem Slug entspricht UND aktiv ist.
. FirstOrDefaultAsync ( p = > p . Slug = = slug & & p . IsActive ) ;
// Wenn kein Produkt gefunden wurde (oder es inaktiv ist), wird ein Fehler zur<75> ckgegeben.
if ( product = = null )
{
return ServiceResult . Fail < ProductDto > ( ServiceResultType . NotFound , $"Produkt mit dem Slug '{slug}' wurde nicht gefunden." ) ;
}
// Wandelt die gefundene Entit<69> t in ein DTO um.
// 'useShortDescription: false' sorgt daf<61> r, dass die vollst<73> ndige, lange Beschreibung verwendet wird.
return ServiceResult . Ok ( MapToDto ( product , useShortDescription : false ) ) ;
}
/// <summary>
/// Ruft eine Liste der als "hervorgehoben" markierten Produkte ab (z.B. f<> r die Startseite).
/// </summary>
/// <returns>Eine Liste von ProductDto-Objekten, sortiert nach ihrer Anzeigereihenfolge.</returns>
public async Task < ServiceResult < IEnumerable < ProductDto > > > GetFeaturedProductsAsync ( )
{
// Startet eine Abfrage auf die 'Products'-Tabelle.
var products = await _context . Products
// Filtert nur Produkte, die sowohl aktiv als auch als "featured" markiert sind.
. Where ( p = > p . IsActive & & p . IsFeatured )
// Sortiert die Ergebnisse nach der vom Admin festgelegten Reihenfolge.
. OrderBy ( p = > p . FeaturedDisplayOrder )
// L<> dt die zugeh<65> rigen Bilder und Kategorien.
. Include ( p = > p . Images )
. Include ( p = > p . Productcategories ) . ThenInclude ( pc = > pc . categorie )
. ToListAsync ( ) ;
// Wandelt die Entit<69> ten in DTOs um (mit kurzer Beschreibung).
var dtos = products . Select ( p = > MapToDto ( p , useShortDescription : true ) ) . ToList ( ) ;
return ServiceResult . Ok < IEnumerable < ProductDto > > ( dtos ) ;
}
// Private Hilfsmethode, um Codeduplizierung zu vermeiden
/ // <summary>
/// Private Hilfsmethode, um eine Product-Entit<69> t in ein ProductDto zu konvertieren.
/// Dies vermeidet Codeduplizierung und stellt eine konsistente Datenstruktur sicher.
/// </summary>
/// <param name="product">Die Product-Entit<69> t aus der Datenbank.</param>
/// <param name="useShortDescription">Gibt an, ob die Kurz- oder Langbeschreibung verwendet werden soll.</param>
/// <returns>Ein bef<65> lltes ProductDto-Objekt.</returns>
private ProductDto MapToDto ( Product product , bool useShortDescription )
{
return new ProductDto
{
Id = product . Id ,
Name = product . Name ,
// W<> hlt die passende Beschreibung basierend auf dem 'useShortDescription'-Flag.
Description = useShortDescription ? product . ShortDescription : product . Description ,
Price = product . Price ,
OldPrice = product . OldPrice ,
@@ -75,12 +123,14 @@ namespace Webshop.Application.Services.Public
IsInStock = product . IsInStock ,
StockQuantity = product . StockQuantity ,
Slug = product . Slug ,
// Mappt die verkn<6B> pften Kategorien auf eine Liste von CategorieDto.
categories = product . Productcategories . Select ( pc = > new CategorieDto
{
Id = pc . categorie . Id ,
Name = pc . categorie . Name ,
Slug = pc . categorie . Slug
} ) . ToList ( ) ,
// Mappt die verkn<6B> pften Bilder, sortiert nach DisplayOrder, auf eine Liste von ProductImageDto.
Images = product . Images . OrderBy ( i = > i . DisplayOrder ) . Select ( img = > new ProductImageDto
{
Id = img . Id ,