diff --git a/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs b/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs index c949d7a..61a295b 100644 --- a/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs +++ b/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs @@ -1,9 +1,11 @@ // src/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Threading.Tasks; +using Webshop.Application; using Webshop.Application.DTOs.Suppliers; using Webshop.Application.Services.Admin.Interfaces; @@ -14,7 +16,6 @@ namespace Webshop.Api.Controllers.Admin [Authorize(Roles = "Admin")] public class AdminSuppliersController : ControllerBase { - // Der Controller hängt vom Interface ab, nicht von der konkreten Klasse private readonly IAdminSupplierService _adminSupplierService; public AdminSuppliersController(IAdminSupplierService adminSupplierService) @@ -23,49 +24,89 @@ namespace Webshop.Api.Controllers.Admin } [HttpGet] - public async Task>> GetAllSuppliers() + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllSuppliers() { - var suppliers = await _adminSupplierService.GetAllSuppliersAsync(); - return Ok(suppliers); + var result = await _adminSupplierService.GetAllSuppliersAsync(); + return Ok(result.Value); } [HttpGet("{id:guid}")] - public async Task> GetSupplierById(Guid id) + [ProducesResponseType(typeof(SupplierDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + public async Task GetSupplierById(Guid id) { - var supplier = await _adminSupplierService.GetSupplierByIdAsync(id); - if (supplier == null) return NotFound(); - return Ok(supplier); + var result = await _adminSupplierService.GetSupplierByIdAsync(id); + + return result.Type switch + { + ServiceResultType.Success => Ok(result.Value), + ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } [HttpPost] - public async Task> CreateSupplier([FromBody] SupplierDto supplierDto) + [ProducesResponseType(typeof(SupplierDto), StatusCodes.Status201Created)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)] + public async Task CreateSupplier([FromBody] SupplierDto supplierDto) { - if (supplierDto == null) return BadRequest("Supplier data is required."); - if (!ModelState.IsValid) return BadRequest(ModelState); + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } - var createdSupplier = await _adminSupplierService.CreateSupplierAsync(supplierDto); - return CreatedAtAction(nameof(GetSupplierById), new { id = createdSupplier.Id }, createdSupplier); + var result = await _adminSupplierService.CreateSupplierAsync(supplierDto); + + return result.Type switch + { + ServiceResultType.Success => CreatedAtAction(nameof(GetSupplierById), new { id = result.Value!.Id }, result.Value), + ServiceResultType.Conflict => Conflict(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } [HttpPut("{id:guid}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)] public async Task UpdateSupplier(Guid id, [FromBody] SupplierDto supplierDto) { - if (id != supplierDto.Id) return BadRequest("Mismatched ID in route and body."); - if (!ModelState.IsValid) return BadRequest(ModelState); + if (id != supplierDto.Id) + { + return BadRequest(new { Message = "ID in der URL und im Body stimmen nicht überein." }); + } + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } - var success = await _adminSupplierService.UpdateSupplierAsync(id, supplierDto); - if (!success) return NotFound(); + var result = await _adminSupplierService.UpdateSupplierAsync(supplierDto); - return NoContent(); // Standardantwort für erfolgreiches Update + return result.Type switch + { + ServiceResultType.Success => NoContent(), + ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }), + ServiceResultType.Conflict => Conflict(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } [HttpDelete("{id:guid}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] public async Task DeleteSupplier(Guid id) { - var success = await _adminSupplierService.DeleteSupplierAsync(id); - if (!success) return NotFound(); + var result = await _adminSupplierService.DeleteSupplierAsync(id); - return NoContent(); // Standardantwort für erfolgreiches Löschen + return result.Type switch + { + ServiceResultType.Success => NoContent(), + ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } } } \ No newline at end of file diff --git a/Webshop.Application/Services/Admin/AdminSupplierService.cs b/Webshop.Application/Services/Admin/AdminSupplierService.cs index b11777d..69cae8e 100644 --- a/Webshop.Application/Services/Admin/AdminSupplierService.cs +++ b/Webshop.Application/Services/Admin/AdminSupplierService.cs @@ -1,64 +1,50 @@ // src/Webshop.Application/Services/Admin/AdminSupplierService.cs using Webshop.Domain.Entities; -using Webshop.Domain.Interfaces; // Wichtig für ISupplierRepository +using Webshop.Domain.Interfaces; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Webshop.Application; using Webshop.Application.DTOs.Suppliers; using Webshop.Application.Services.Admin.Interfaces; -using Webshop.Domain.Identity; namespace Webshop.Application.Services.Admin { - // Implementiert das Interface, das der Controller erwartet public class AdminSupplierService : IAdminSupplierService { private readonly ISupplierRepository _supplierRepository; - // Lässt sich das Repository per Dependency Injection geben public AdminSupplierService(ISupplierRepository supplierRepository) { _supplierRepository = supplierRepository; } - public async Task> GetAllSuppliersAsync() + public async Task>> GetAllSuppliersAsync() { var suppliers = await _supplierRepository.GetAllSuppliersAsync(); - // Mappt die Entity-Liste zu einer DTO-Liste für die API - return suppliers.Select(s => new SupplierDto - { - Id = s.Id, - Name = s.Name, - ContactPerson = s.ContactPerson, - Email = s.Email, - PhoneNumber = s.PhoneNumber, - AddressId = s.AddressId, - Notes = s.Notes - }); + var dtos = suppliers.Select(MapToDto); + return ServiceResult.Ok>(dtos); } - public async Task GetSupplierByIdAsync(Guid id) + public async Task> GetSupplierByIdAsync(Guid id) { var supplier = await _supplierRepository.GetSupplierByIdAsync(id); - if (supplier == null) return null; - - // Mappt die gefundene Entity zu einem DTO - return new SupplierDto + if (supplier == null) { - Id = supplier.Id, - Name = supplier.Name, - ContactPerson = supplier.ContactPerson, - Email = supplier.Email, - PhoneNumber = supplier.PhoneNumber, - AddressId = supplier.AddressId, - Notes = supplier.Notes - }; + return ServiceResult.Fail(ServiceResultType.NotFound, $"Lieferant mit ID '{id}' nicht gefunden."); + } + return ServiceResult.Ok(MapToDto(supplier)); } - public async Task CreateSupplierAsync(SupplierDto supplierDto) + public async Task> CreateSupplierAsync(SupplierDto supplierDto) { - // Wandelt das DTO von der API in eine Datenbank-Entity um + var allSuppliers = await _supplierRepository.GetAllSuppliersAsync(); + if (allSuppliers.Any(s => s.Name.Equals(supplierDto.Name, StringComparison.OrdinalIgnoreCase))) + { + return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein Lieferant mit dem Namen '{supplierDto.Name}' existiert bereits."); + } + var supplier = new Supplier { Name = supplierDto.Name, @@ -71,20 +57,24 @@ namespace Webshop.Application.Services.Admin await _supplierRepository.AddSupplierAsync(supplier); - // Gibt ein DTO mit der neu generierten ID zurück supplierDto.Id = supplier.Id; - return supplierDto; + return ServiceResult.Ok(supplierDto); } - public async Task UpdateSupplierAsync(Guid id, SupplierDto supplierDto) + public async Task UpdateSupplierAsync(SupplierDto supplierDto) { - var existingSupplier = await _supplierRepository.GetSupplierByIdAsync(id); + var existingSupplier = await _supplierRepository.GetSupplierByIdAsync(supplierDto.Id); if (existingSupplier == null) { - return false; // Konnte nicht gefunden werden + return ServiceResult.Fail(ServiceResultType.NotFound, $"Lieferant mit ID '{supplierDto.Id}' nicht gefunden."); + } + + var allSuppliers = await _supplierRepository.GetAllSuppliersAsync(); + if (allSuppliers.Any(s => s.Name.Equals(supplierDto.Name, StringComparison.OrdinalIgnoreCase) && s.Id != supplierDto.Id)) + { + return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderer Lieferant mit dem Namen '{supplierDto.Name}' existiert bereits."); } - // Aktualisiert die Daten der gefundenen Entity existingSupplier.Name = supplierDto.Name; existingSupplier.ContactPerson = supplierDto.ContactPerson; existingSupplier.Email = supplierDto.Email; @@ -93,19 +83,39 @@ namespace Webshop.Application.Services.Admin existingSupplier.Notes = supplierDto.Notes; await _supplierRepository.UpdateSupplierAsync(existingSupplier); - return true; + return ServiceResult.Ok(); } - public async Task DeleteSupplierAsync(Guid id) + public async Task DeleteSupplierAsync(Guid id) { var supplier = await _supplierRepository.GetSupplierByIdAsync(id); if (supplier == null) { - return false; // Konnte nicht gefunden werden + return ServiceResult.Fail(ServiceResultType.NotFound, $"Lieferant mit ID '{id}' nicht gefunden."); } + // Hier könnte man noch prüfen, ob der Lieferant Produkten zugeordnet ist (Conflict) + // if (await _productRepository.AnyAsync(p => p.SupplierId == id)) + // { + // return ServiceResult.Fail(ServiceResultType.Conflict, "Lieferant kann nicht gelöscht werden, da ihm Produkte zugeordnet sind."); + // } + await _supplierRepository.DeleteSupplierAsync(id); - return true; + return ServiceResult.Ok(); + } + + private SupplierDto MapToDto(Supplier s) + { + return new SupplierDto + { + Id = s.Id, + Name = s.Name, + ContactPerson = s.ContactPerson, + Email = s.Email, + PhoneNumber = s.PhoneNumber, + AddressId = s.AddressId, + Notes = s.Notes + }; } } } \ No newline at end of file diff --git a/Webshop.Application/Services/Admin/Interfaces/IAdminSupplierService.cs b/Webshop.Application/Services/Admin/Interfaces/IAdminSupplierService.cs index bf6d643..3844528 100644 --- a/Webshop.Application/Services/Admin/Interfaces/IAdminSupplierService.cs +++ b/Webshop.Application/Services/Admin/Interfaces/IAdminSupplierService.cs @@ -1,21 +1,18 @@ // src/Webshop.Application/Services/Admin/IAdminSupplierService.cs - -using System; // Für Guid +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Webshop.Application; using Webshop.Application.DTOs.Suppliers; namespace Webshop.Application.Services.Admin.Interfaces { public interface IAdminSupplierService { - // Diese Methoden waren bereits vorhanden - Task> GetAllSuppliersAsync(); - Task GetSupplierByIdAsync(Guid id); - Task CreateSupplierAsync(SupplierDto supplierDto); - - // --- HIER DIE FEHLENDEN METHODEN ERGÄNZEN --- - Task UpdateSupplierAsync(Guid id, SupplierDto supplierDto); - Task DeleteSupplierAsync(Guid id); + Task>> GetAllSuppliersAsync(); + Task> GetSupplierByIdAsync(Guid id); + Task> CreateSupplierAsync(SupplierDto supplierDto); + Task UpdateSupplierAsync(SupplierDto supplierDto); // Parameter vereinfacht + Task DeleteSupplierAsync(Guid id); } } \ No newline at end of file