Compare commits

..

3 Commits

Author SHA1 Message Date
Tizian.Breuch 9ab23ef29a Merge branch 'develop' of https://gitea.tzbre.dev/admin/ShopSolution-backend into develop
Branch - test - Build and Push Backend API Docker Image / build-and-push (push) Successful in 26s
2025-11-07 11:03:15 +01:00
Tizian.Breuch 6353591638 test bilder 2025-11-07 11:03:05 +01:00
admin c2e8761690 .gitea/workflows/pipeline.yml aktualisiert
Branch - test - Build and Push Backend API Docker Image / build-and-push (push) Successful in 25s
2025-11-07 09:54:31 +00:00
2 changed files with 54 additions and 4 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ name: Branch - test - Build and Push Backend API Docker Image
on:
push:
branches:
- test # Wird ausgelöst bei jedem Push auf den Master-Branch
- develop # Wird ausgelöst bei jedem Push auf den Master-Branch
# Definition der Jobs, die in diesem Workflow ausgeführt werden
jobs:
@@ -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 öffentlichen Shop-Bereich zuständig ist.
/// Alle hier zurü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ü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ö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<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ü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<ProductDto>(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));
}
/// <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ö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<IEnumerable<ProductDto>>(dtos);
}
// Private Hilfsmethode, um Codeduplizierung zu vermeiden
/// <summary>
/// Private Hilfsmethode, um eine Product-Entität in ein ProductDto zu konvertieren.
/// Dies vermeidet Codeduplizierung und stellt eine konsistente Datenstruktur sicher.
/// </summary>
/// <param name="product">Die Product-Entität aus der Datenbank.</param>
/// <param name="useShortDescription">Gibt an, ob die Kurz- oder Langbeschreibung verwendet werden soll.</param>
/// <returns>Ein befü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ü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,