// src/Webshop.Application/Services/Public/DiscountService.cs using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Webshop.Application.Services.Public.Interfaces; using Webshop.Domain.Entities; using Webshop.Domain.Interfaces; using Webshop.Infrastructure.Data; namespace Webshop.Application.Services.Public { public class DiscountService : IDiscountService { private readonly ApplicationDbContext _context; // Direkter Zugriff auf DbSets private readonly IDiscountRepository _discountRepository; private readonly IProductRepository _productRepository; public DiscountService( ApplicationDbContext context, IDiscountRepository discountRepository, IProductRepository productRepository) { _context = context; _discountRepository = discountRepository; _productRepository = productRepository; } public async Task CalculateDiscountAsync(List orderItems, string? couponCode) { decimal totalDiscount = 0; // 1. Hole alle relevanten Rabatte var discounts = await _context.Discounts .Include(d => d.ProductDiscounts) .Include(d => d.categorieDiscounts) .Where(d => d.IsActive && d.StartDate <= DateTimeOffset.UtcNow && (!d.EndDate.HasValue || d.EndDate >= DateTimeOffset.UtcNow)) .ToListAsync(); // Filtern nach Gutscheincode if (!string.IsNullOrEmpty(couponCode)) { discounts = discounts.Where(d => d.CouponCode == couponCode && d.RequiresCouponCode).ToList(); } else { // Rabatte ohne Gutscheincode, falls zutreffend discounts = discounts.Where(d => !d.RequiresCouponCode).ToList(); } // 2. Wende Rabatte auf Artikel an foreach (var item in orderItems) { decimal itemDiscount = 0; // Wir nehmen an, dass ein Artikel nur den besten Rabatt erhalten kann var applicableDiscount = discounts.FirstOrDefault(d => d.ProductDiscounts.Any(pd => pd.ProductId == item.ProductId) || // Rabatt auf Produkt d.categorieDiscounts.Any(cd => _context.Productcategories.Any(pc => pc.ProductId == item.ProductId && pc.categorieId == cd.categorieId)) // Rabatt auf Kategorie ); if (applicableDiscount != null) { itemDiscount = item.UnitPrice * item.Quantity * (applicableDiscount.DiscountValue / 100); // Hier müsste die Logik für FixedAmount-Rabatte hin } totalDiscount += itemDiscount; } // 3. Wende Warenkorb-Rabatte an (falls keine spezifischen Produkte/Kategorien zugewiesen sind) var cartDiscounts = discounts.Where(d => !d.ProductDiscounts.Any() && !d.categorieDiscounts.Any()).ToList(); decimal cartTotal = orderItems.Sum(i => i.TotalPrice); foreach (var discount in cartDiscounts) { if (discount.MinimumOrderAmount.HasValue && cartTotal < discount.MinimumOrderAmount.Value) continue; // Beispiel: Prozentualer Rabatt auf den Warenkorb if (discount.DiscountType == DiscountType.Percentage.ToString()) { totalDiscount += cartTotal * (discount.DiscountValue / 100); } } return totalDiscount; } } }