90 lines
3.6 KiB
C#
90 lines
3.6 KiB
C#
// 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<decimal> CalculateDiscountAsync(List<OrderItem> 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;
|
|
}
|
|
}
|
|
} |