diff --git a/Webshop.Application/Services/Public/ProductService.cs b/Webshop.Application/Services/Public/ProductService.cs index a745af1..4eee385 100644 --- a/Webshop.Application/Services/Public/ProductService.cs +++ b/Webshop.Application/Services/Public/ProductService.cs @@ -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 { + /// + /// Service, der für die Abfrage von Produktinformationen für den öffentlichen Shop-Bereich zuständig ist. + /// Alle hier zurückgegebenen Daten sind für jeden Besucher sichtbar. + /// public class ProductService : IProductService { private readonly ApplicationDbContext _context; @@ -21,53 +26,96 @@ namespace Webshop.Application.Services.Public _context = context; } + /// + /// Ruft eine Liste aller aktiven Produkte für die allgemeine Produktübersicht ab. + /// + /// Eine Liste von ProductDto-Objekten. public async Task>> 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örigen 'Productcategories'-Verknüpfungen mit. + .Include(p => p.Productcategories) + // Lädt von dort aus die eigentliche 'categorie'-Entität. + .ThenInclude(pc => pc.categorie) + // Lädt auch die zugehö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ät in ein ProductDto um. + // 'useShortDescription: true' sorgt dafü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ück. return ServiceResult.Ok>(dtos); } + /// + /// Ruft ein einzelnes, aktives Produkt anhand seines eindeutigen Slugs ab (für die Produktdetailseite). + /// + /// Der URL-freundliche Slug des Produkts. + /// Ein einzelnes ProductDto oder ein NotFound-Ergebnis. public async Task> GetProductBySlugAsync(string slug) { + // Startet eine Abfrage auf die 'Products'-Tabelle. var product = await _context.Products + // Lädt alle notwendigen verknü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ückgegeben. if (product == null) { return ServiceResult.Fail(ServiceResultType.NotFound, $"Produkt mit dem Slug '{slug}' wurde nicht gefunden."); } + // Wandelt die gefundene Entität in ein DTO um. + // 'useShortDescription: false' sorgt dafür, dass die vollständige, lange Beschreibung verwendet wird. return ServiceResult.Ok(MapToDto(product, useShortDescription: false)); } + /// + /// Ruft eine Liste der als "hervorgehoben" markierten Produkte ab (z.B. für die Startseite). + /// + /// Eine Liste von ProductDto-Objekten, sortiert nach ihrer Anzeigereihenfolge. public async Task>> 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örigen Bilder und Kategorien. .Include(p => p.Images) .Include(p => p.Productcategories).ThenInclude(pc => pc.categorie) .ToListAsync(); + // Wandelt die Entitäten in DTOs um (mit kurzer Beschreibung). var dtos = products.Select(p => MapToDto(p, useShortDescription: true)).ToList(); + return ServiceResult.Ok>(dtos); } - // Private Hilfsmethode, um Codeduplizierung zu vermeiden + /// + /// Private Hilfsmethode, um eine Product-Entität in ein ProductDto zu konvertieren. + /// Dies vermeidet Codeduplizierung und stellt eine konsistente Datenstruktur sicher. + /// + /// Die Product-Entität aus der Datenbank. + /// Gibt an, ob die Kurz- oder Langbeschreibung verwendet werden soll. + /// Ein befülltes ProductDto-Objekt. 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ü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üpften Bilder, sortiert nach DisplayOrder, auf eine Liste von ProductImageDto. Images = product.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto { Id = img.Id,