diff --git a/Webshop.Application/Services/Customers/CheckoutService.cs b/Webshop.Application/Services/Customers/CheckoutService.cs index d662778..760d496 100644 --- a/Webshop.Application/Services/Customers/CheckoutService.cs +++ b/Webshop.Application/Services/Customers/CheckoutService.cs @@ -1,4 +1,5 @@ -// src/Webshop.Application/Services/Customers/CheckoutService.cs +// /src/Webshop.Application/Services/Customers/CheckoutService.cs + using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; @@ -42,7 +43,7 @@ namespace Webshop.Application.Services.Customers await using var transaction = await _context.Database.BeginTransactionAsync(); try { - // 1. Validierung von Kunde, Adressen und Methoden + // --- 1. Validierung von Kunde, Adressen und Methoden --- var customer = await _customerRepository.GetByUserIdAsync(userId!); if (customer == null) return ServiceResult.Fail(ServiceResultType.Unauthorized, "Kundenprofil nicht gefunden."); @@ -61,7 +62,7 @@ namespace Webshop.Application.Services.Customers if (paymentMethod == null || !paymentMethod.IsActive) return ServiceResult.Fail(ServiceResultType.InvalidInput, "Ungültige oder inaktive Zahlungsmethode."); - // 2. Artikel verarbeiten und Lagerbestand prüfen + // --- 2. Artikel verarbeiten und Lagerbestand prüfen --- var orderItems = new List(); var productIds = orderDto.Items.Select(i => i.ProductId).ToList(); var products = await _context.Products.Where(p => productIds.Contains(p.Id)).ToListAsync(); @@ -97,18 +98,43 @@ namespace Webshop.Application.Services.Customers itemsTotal += orderItem.TotalPrice; } - // 3. Preise, Rabatte, Steuern und Gesamtbetrag berechnen - var discountResult = await _discountService.CalculateDiscountAsync(orderItems, orderDto.CouponCode); - decimal discountAmount = discountResult.TotalDiscountAmount; + // --- 3. Preise, Rabatte, Steuern und Gesamtbetrag berechnen --- + decimal discountAmount = 0; + var discountResult = new DiscountCalculationResult(); + + if (!string.IsNullOrWhiteSpace(orderDto.CouponCode)) + { + discountResult = await _discountService.CalculateDiscountAsync(orderItems, orderDto.CouponCode); + discountAmount = discountResult.TotalDiscountAmount; + + if (discountAmount <= 0) + { + await transaction.RollbackAsync(); + return ServiceResult.Fail(ServiceResultType.InvalidInput, "Der angegebene Gutscheincode ist ungültig, abgelaufen oder nicht auf die Produkte im Warenkorb anwendbar."); + } + + if (discountResult.AppliedDiscountIds.Count > 1) + { + await transaction.RollbackAsync(); + return ServiceResult.Fail(ServiceResultType.Failure, "Es können nicht mehrere Rabatte gleichzeitig angewendet werden."); + } + } + decimal shippingCost = shippingMethod.BaseCost; - decimal subTotal = itemsTotal + shippingCost - discountAmount; - if (subTotal < 0) subTotal = 0; + decimal subTotalBeforeDiscount = itemsTotal + shippingCost; + + if (discountAmount > subTotalBeforeDiscount) + { + discountAmount = subTotalBeforeDiscount; + } + + decimal subTotalAfterDiscount = subTotalBeforeDiscount - discountAmount; decimal taxRate = await _settingService.GetSettingValueAsync("GlobalTaxRate", 0.19m); - decimal taxAmount = subTotal * taxRate; - decimal orderTotal = subTotal + taxAmount; + decimal taxAmount = subTotalAfterDiscount * taxRate; + decimal orderTotal = subTotalAfterDiscount + taxAmount; - // 4. Bestellung erstellen + // --- 4. Bestellung erstellen --- var newOrder = new Order { CustomerId = customer.Id, @@ -129,7 +155,7 @@ namespace Webshop.Application.Services.Customers }; await _orderRepository.AddAsync(newOrder); - // 5. Rabattnutzung erhöhen + // --- 5. Rabattnutzung erhöhen --- if (discountResult.AppliedDiscountIds.Any()) { var appliedDiscounts = await _context.Discounts.Where(d => discountResult.AppliedDiscountIds.Contains(d.Id)).ToListAsync(); @@ -139,14 +165,16 @@ namespace Webshop.Application.Services.Customers await _context.SaveChangesAsync(); await transaction.CommitAsync(); - // 6. Erfolgreiche Antwort erstellen + // --- 6. Erfolgreiche Antwort erstellen --- var createdOrder = await _orderRepository.GetByIdAsync(newOrder.Id); return ServiceResult.Ok(MapToOrderDetailDto(createdOrder!)); } catch (Exception ex) { await transaction.RollbackAsync(); - return ServiceResult.Fail(ServiceResultType.Failure, $"Ein unerwarteter Fehler ist aufgetreten: {ex.Message}"); + // Log the full exception for debugging purposes + // _logger.LogError(ex, "An unexpected error occurred in CreateOrderAsync."); + return ServiceResult.Fail(ServiceResultType.Failure, "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut."); } } @@ -158,7 +186,7 @@ namespace Webshop.Application.Services.Customers OrderNumber = order.OrderNumber, OrderDate = order.OrderDate, CustomerId = order.CustomerId, - Status = Enum.Parse(order.OrderStatus), + Status = Enum.TryParse(order.OrderStatus, true, out var os) ? os : OrderStatus.Pending, TotalAmount = order.OrderTotal, ShippingAddress = new AddressDto { @@ -184,8 +212,8 @@ namespace Webshop.Application.Services.Customers Country = order.BillingAddress.Country, Type = order.BillingAddress.Type }, - PaymentMethod = order.PaymentMethod, - PaymentStatus = Enum.Parse(order.PaymentStatus), + PaymentMethod = order.PaymentMethodInfo?.Name, + PaymentStatus = Enum.TryParse(order.PaymentStatus, true, out var ps) ? ps : PaymentStatus.Pending, ShippingTrackingNumber = order.ShippingTrackingNumber, ShippedDate = order.ShippedDate, DeliveredDate = order.DeliveredDate,