diff --git a/Webshop.Api/Controllers/Admin/AdminAnalyticsController.cs b/Webshop.Api/Controllers/Admin/AdminAnalyticsController.cs
new file mode 100644
index 0000000..777c5a1
--- /dev/null
+++ b/Webshop.Api/Controllers/Admin/AdminAnalyticsController.cs
@@ -0,0 +1,36 @@
+// src/Webshop.Api/Controllers/Admin/AdminAnalyticsController.cs
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using Webshop.Application.DTOs.Admin;
+using Webshop.Application.Services.Admin.Interfaces;
+
+namespace Webshop.Api.Controllers.Admin
+{
+ ///
+ /// Stellt aggregierte Analysedaten für das Admin-Dashboard bereit.
+ ///
+ [ApiController]
+ [Route("api/v1/admin/[controller]")]
+ [Authorize(Roles = "Admin")]
+ public class AdminAnalyticsController : ControllerBase
+ {
+ private readonly IAdminAnalyticsService _analyticsService;
+
+ public AdminAnalyticsController(IAdminAnalyticsService analyticsService)
+ {
+ _analyticsService = analyticsService;
+ }
+
+ ///
+ /// Ruft die aggregierten Analysedaten und KPIs für den Admin-Bereich ab.
+ ///
+ /// Der Zeitraum für die Statistiken (Last7Days, Last30Days, AllTime). Standard ist Last30Days.
+ [HttpGet]
+ public async Task> GetAnalytics([FromQuery] AnalyticsPeriod period = AnalyticsPeriod.Last30Days)
+ {
+ var stats = await _analyticsService.GetAnalyticsAsync(period);
+ return Ok(stats);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Webshop.Api/Program.cs b/Webshop.Api/Program.cs
index 7eb282f..c277e72 100644
--- a/Webshop.Api/Program.cs
+++ b/Webshop.Api/Program.cs
@@ -149,6 +149,7 @@ builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
+builder.Services.AddScoped();
// Controller und API-Infrastruktur
builder.Services.AddControllers()
diff --git a/Webshop.Application/DTOs/Admin/AnalyticsDto.cs b/Webshop.Application/DTOs/Admin/AnalyticsDto.cs
new file mode 100644
index 0000000..80c047e
--- /dev/null
+++ b/Webshop.Application/DTOs/Admin/AnalyticsDto.cs
@@ -0,0 +1,114 @@
+// src/Webshop.Application/DTOs/Admin/AnalyticsDto.cs
+using System.Collections.Generic;
+
+namespace Webshop.Application.DTOs.Admin
+{
+ ///
+ /// Fasst alle relevanten Analysedaten und KPIs für den Admin-Bereich zusammen.
+ ///
+ public class AnalyticsDto
+ {
+ ///
+ /// Die wichtigsten Kennzahlen (Key Performance Indicators).
+ ///
+ public KpiSummaryDto KpiSummary { get; set; } = new KpiSummaryDto();
+
+ ///
+ /// Eine Liste von Datenpunkten für Umsatz-Charts (z.B. Umsatz pro Tag).
+ ///
+ public List SalesOverTime { get; set; } = new List();
+
+ ///
+ /// Die Top 10 der meistverkauften Produkte im ausgewählten Zeitraum.
+ ///
+ public List TopPerformingProducts { get; set; } = new List();
+
+ ///
+ /// Informationen zum aktuellen Lagerbestand.
+ ///
+ public InventoryStatusDto InventoryStatus { get; set; } = new InventoryStatusDto();
+ }
+
+ ///
+ /// Die wichtigsten Kennzahlen (Key Performance Indicators).
+ ///
+ public class KpiSummaryDto
+ {
+ ///
+ /// Der Gesamtumsatz (netto) im ausgewählten Zeitraum.
+ ///
+ public decimal TotalRevenue { get; set; }
+
+ ///
+ /// Die Gesamtzahl der Bestellungen im ausgewählten Zeitraum.
+ ///
+ public int TotalOrders { get; set; }
+
+ ///
+ /// Die Gesamtzahl aller registrierten Kunden.
+ ///
+ public int TotalCustomers { get; set; }
+
+ ///
+ /// Die Anzahl der Neukunden, die sich im ausgewählten Zeitraum registriert haben.
+ ///
+ public int NewCustomersThisPeriod { get; set; }
+
+ ///
+ /// Der durchschnittliche Wert einer Bestellung im ausgewählten Zeitraum.
+ ///
+ public decimal AverageOrderValue { get; set; }
+ }
+
+ ///
+ /// Ein Datenpunkt für Umsatz-Charts (z.B. Umsatz pro Tag).
+ ///
+ public class SalesDataPointDto
+ {
+ ///
+ /// Das Datum des Datenpunkts im Format 'yyyy-MM-dd'.
+ ///
+ public string Date { get; set; } = string.Empty;
+
+ ///
+ /// Der an diesem Tag generierte Umsatz.
+ ///
+ public decimal Revenue { get; set; }
+ }
+
+ ///
+ /// Repräsentiert ein gut verkauftes Produkt.
+ ///
+ public class TopProductDto
+ {
+ public Guid ProductId { get; set; }
+ public string Name { get; set; } = string.Empty;
+ public string Sku { get; set; } = string.Empty;
+
+ ///
+ /// Die Gesamtzahl der verkauften Einheiten im ausgewählten Zeitraum.
+ ///
+ public int UnitsSold { get; set; }
+
+ ///
+ /// Der Gesamtumsatz, der mit diesem Produkt im ausgewählten Zeitraum erzielt wurde.
+ ///
+ public decimal TotalRevenue { get; set; }
+ }
+
+ ///
+ /// Informationen zum Lagerbestand.
+ ///
+ public class InventoryStatusDto
+ {
+ ///
+ /// Die Anzahl der Produkte, deren Lagerbestand unter dem in den Einstellungen definierten Schwellenwert liegt.
+ ///
+ public int ProductsWithLowStock { get; set; }
+
+ ///
+ /// Der prozentuale Anteil der Produkte, die auf Lager sind (Menge > 0).
+ ///
+ public double OverallStockAvailabilityPercentage { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Webshop.Application/Services/Admin/AdminAnalyticsService.cs b/Webshop.Application/Services/Admin/AdminAnalyticsService.cs
new file mode 100644
index 0000000..bd2b051
--- /dev/null
+++ b/Webshop.Application/Services/Admin/AdminAnalyticsService.cs
@@ -0,0 +1,116 @@
+// src/Webshop.Application/Services/Admin/AdminAnalyticsService.cs
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Webshop.Application.DTOs.Admin;
+using Webshop.Application.Services.Admin.Interfaces;
+using Webshop.Domain.Enums;
+using Webshop.Domain.Interfaces;
+using Webshop.Infrastructure.Data;
+
+namespace Webshop.Application.Services.Admin
+{
+ public class AdminAnalyticsService : IAdminAnalyticsService
+ {
+ private readonly ApplicationDbContext _context;
+ private readonly ISettingService _settingService;
+
+ public AdminAnalyticsService(ApplicationDbContext context, ISettingService settingService)
+ {
+ _context = context;
+ _settingService = settingService;
+ }
+
+ public async Task GetAnalyticsAsync(AnalyticsPeriod period)
+ {
+ var startDate = GetStartDateFromPeriod(period);
+
+ var filteredOrders = await _context.Orders
+ .Where(o => o.OrderDate >= startDate && o.OrderStatus != OrderStatus.Cancelled.ToString())
+ .ToListAsync();
+
+ var analyticsDto = new AnalyticsDto
+ {
+ KpiSummary = await GetKpiSummaryAsync(startDate, filteredOrders),
+ SalesOverTime = GetSalesOverTime(filteredOrders),
+ TopPerformingProducts = await GetTopPerformingProductsAsync(startDate),
+ InventoryStatus = await GetInventoryStatusAsync()
+ };
+
+ return analyticsDto;
+ }
+
+ private async Task GetKpiSummaryAsync(DateTimeOffset startDate, List filteredOrders)
+ {
+ var totalRevenue = filteredOrders.Sum(o => o.OrderTotal);
+ var totalOrders = filteredOrders.Count;
+
+ return new KpiSummaryDto
+ {
+ TotalRevenue = totalRevenue,
+ TotalOrders = totalOrders,
+ TotalCustomers = await _context.Customers.CountAsync(),
+ NewCustomersThisPeriod = await _context.Users.CountAsync(u => u.CreatedDate >= startDate),
+ AverageOrderValue = totalOrders > 0 ? totalRevenue / totalOrders : 0
+ };
+ }
+
+ private List GetSalesOverTime(List orders)
+ {
+ return orders
+ .GroupBy(o => o.OrderDate.Date)
+ .Select(g => new SalesDataPointDto
+ {
+ Date = g.Key.ToString("yyyy-MM-dd"),
+ Revenue = g.Sum(o => o.OrderTotal)
+ })
+ .OrderBy(dp => dp.Date)
+ .ToList();
+ }
+
+ private async Task> GetTopPerformingProductsAsync(DateTimeOffset startDate)
+ {
+ return await _context.OrderItems
+ .Where(oi => oi.Order.OrderDate >= startDate && oi.ProductId.HasValue)
+ .GroupBy(oi => new { oi.ProductId, oi.ProductName, oi.ProductSKU })
+ .Select(g => new TopProductDto
+ {
+ ProductId = g.Key.ProductId!.Value,
+ Name = g.Key.ProductName,
+ Sku = g.Key.ProductSKU,
+ UnitsSold = g.Sum(oi => oi.Quantity),
+ TotalRevenue = g.Sum(oi => oi.TotalPrice)
+ })
+ .OrderByDescending(p => p.UnitsSold)
+ .Take(10)
+ .ToListAsync();
+ }
+
+ private async Task GetInventoryStatusAsync()
+ {
+ var lowStockThreshold = await _settingService.GetSettingValueAsync("LowStockThreshold", 10);
+
+ var totalProducts = await _context.Products.CountAsync(p => p.IsActive);
+ var productsInStock = await _context.Products.CountAsync(p => p.IsActive && p.StockQuantity > 0);
+ var productsWithLowStock = await _context.Products.CountAsync(p => p.IsActive && p.StockQuantity > 0 && p.StockQuantity <= lowStockThreshold);
+
+ return new InventoryStatusDto
+ {
+ ProductsWithLowStock = productsWithLowStock,
+ OverallStockAvailabilityPercentage = totalProducts > 0 ? Math.Round((double)productsInStock / totalProducts * 100, 2) : 0
+ };
+ }
+
+ private DateTimeOffset GetStartDateFromPeriod(AnalyticsPeriod period)
+ {
+ return period switch
+ {
+ AnalyticsPeriod.Last7Days => DateTimeOffset.UtcNow.AddDays(-7),
+ AnalyticsPeriod.Last30Days => DateTimeOffset.UtcNow.AddDays(-30),
+ _ => DateTimeOffset.MinValue
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/Webshop.Application/Services/Admin/Interfaces/IAdminAnalyticsService.cs b/Webshop.Application/Services/Admin/Interfaces/IAdminAnalyticsService.cs
new file mode 100644
index 0000000..c44fa64
--- /dev/null
+++ b/Webshop.Application/Services/Admin/Interfaces/IAdminAnalyticsService.cs
@@ -0,0 +1,13 @@
+// src/Webshop.Application/Services/Admin/Interfaces/IAdminAnalyticsService.cs
+using System.Threading.Tasks;
+using Webshop.Application.DTOs.Admin;
+
+namespace Webshop.Application.Services.Admin.Interfaces
+{
+ public enum AnalyticsPeriod { Last7Days, Last30Days, AllTime }
+
+ public interface IAdminAnalyticsService
+ {
+ Task GetAnalyticsAsync(AnalyticsPeriod period);
+ }
+}
\ No newline at end of file