diff --git a/Webshop.Api/Controllers/Admin/AdminPaymentMethodsController.cs b/Webshop.Api/Controllers/Admin/AdminPaymentMethodsController.cs index 8c90c44..7ec0a21 100644 --- a/Webshop.Api/Controllers/Admin/AdminPaymentMethodsController.cs +++ b/Webshop.Api/Controllers/Admin/AdminPaymentMethodsController.cs @@ -1,17 +1,19 @@ // src/Webshop.Api/Controllers/Admin/AdminPaymentMethodsController.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.DTOs.Payments; // AdminPaymentMethodDto -using Webshop.Application.Services.Admin; // IAdminPaymentMethodService +using Webshop.Application; +using Webshop.Application.DTOs.Payments; +using Webshop.Application.Services.Admin; namespace Webshop.Api.Controllers.Admin { [ApiController] - [Route("api/v1/admin/[controller]")] // Saubere Route - [Authorize(Roles = "Admin")] // Nur Admins + [Route("api/v1/admin/[controller]")] + [Authorize(Roles = "Admin")] public class AdminPaymentMethodsController : ControllerBase { private readonly IAdminPaymentMethodService _adminPaymentMethodService; @@ -22,45 +24,87 @@ namespace Webshop.Api.Controllers.Admin } [HttpGet] - public async Task>> GetAllPaymentMethods() + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + public async Task GetAllPaymentMethods() { - var paymentMethods = await _adminPaymentMethodService.GetAllAsync(); - return Ok(paymentMethods); + var result = await _adminPaymentMethodService.GetAllAsync(); + return Ok(result.Value); } [HttpGet("{id}")] - public async Task> GetPaymentMethodById(Guid id) + [ProducesResponseType(typeof(AdminPaymentMethodDto), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + public async Task GetPaymentMethodById(Guid id) { - var paymentMethod = await _adminPaymentMethodService.GetByIdAsync(id); - if (paymentMethod == null) return NotFound(); - return Ok(paymentMethod); + var result = await _adminPaymentMethodService.GetByIdAsync(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> CreatePaymentMethod([FromBody] AdminPaymentMethodDto paymentMethodDto) + [ProducesResponseType(typeof(AdminPaymentMethodDto), StatusCodes.Status201Created)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + public async Task CreatePaymentMethod([FromBody] AdminPaymentMethodDto paymentMethodDto) { - if (!ModelState.IsValid) return BadRequest(ModelState); - var createdPaymentMethod = await _adminPaymentMethodService.CreateAsync(paymentMethodDto); - return CreatedAtAction(nameof(GetPaymentMethodById), new { id = createdPaymentMethod.Id }, createdPaymentMethod); + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var result = await _adminPaymentMethodService.CreateAsync(paymentMethodDto); + + return result.Type switch + { + ServiceResultType.Success => CreatedAtAction(nameof(GetPaymentMethodById), new { id = result.Value!.Id }, result.Value), + ServiceResultType.InvalidInput => BadRequest(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } [HttpPut("{id}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] public async Task UpdatePaymentMethod(Guid id, [FromBody] AdminPaymentMethodDto paymentMethodDto) { - if (id != paymentMethodDto.Id) return BadRequest(); - if (!ModelState.IsValid) return BadRequest(ModelState); + if (id != paymentMethodDto.Id) + { + return BadRequest(new { Message = "ID in der URL und im Body stimmen nicht überein." }); + } + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } - var success = await _adminPaymentMethodService.UpdateAsync(paymentMethodDto); - if (!success) return NotFound(); - return NoContent(); // 204 No Content für erfolgreiches Update + var result = await _adminPaymentMethodService.UpdateAsync(paymentMethodDto); + + return result.Type switch + { + ServiceResultType.Success => NoContent(), + ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }), + ServiceResultType.InvalidInput => BadRequest(new { Message = result.ErrorMessage }), + _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." }) + }; } [HttpDelete("{id}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] public async Task DeletePaymentMethod(Guid id) { - var success = await _adminPaymentMethodService.DeleteAsync(id); - if (!success) return NotFound(); - return NoContent(); + var result = await _adminPaymentMethodService.DeleteAsync(id); + + 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/AdminPaymentMethodService.cs b/Webshop.Application/Services/Admin/AdminPaymentMethodService.cs index 6a7aff2..95bc70f 100644 --- a/Webshop.Application/Services/Admin/AdminPaymentMethodService.cs +++ b/Webshop.Application/Services/Admin/AdminPaymentMethodService.cs @@ -2,12 +2,13 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text.Json; // Wichtig für JsonSerializer +using System.Text.Json; using System.Threading.Tasks; -using Webshop.Application.DTOs.Payments; // AdminPaymentMethodDto und die neuen Configuration-DTOs -using Webshop.Domain.Entities; // PaymentMethod -using Webshop.Domain.Enums; // PaymentGatewayType -using Webshop.Domain.Interfaces; // IPaymentMethodRepository +using Webshop.Application; +using Webshop.Application.DTOs.Payments; +using Webshop.Domain.Entities; +using Webshop.Domain.Enums; +using Webshop.Domain.Interfaces; namespace Webshop.Application.Services.Admin { @@ -20,49 +21,51 @@ namespace Webshop.Application.Services.Admin _paymentMethodRepository = paymentMethodRepository; } - public async Task> GetAllAsync() + public async Task>> GetAllAsync() { var paymentMethods = await _paymentMethodRepository.GetAllAsync(); - - return paymentMethods.Select(pm => new AdminPaymentMethodDto + var dtos = paymentMethods.Select(pm => new AdminPaymentMethodDto { Id = pm.Id, Name = pm.Name, Description = pm.Description, IsActive = pm.IsActive, PaymentGatewayType = pm.PaymentGatewayType, - // Deserialisiere den JSON-String aus der DB in ein Objekt für die Admin-Ansicht Configuration = pm.Configuration != null ? JsonSerializer.Deserialize(pm.Configuration) : null, ProcessingFee = pm.ProcessingFee }).ToList(); + + return ServiceResult.Ok>(dtos); } - public async Task GetByIdAsync(Guid id) + public async Task> GetByIdAsync(Guid id) { var paymentMethod = await _paymentMethodRepository.GetByIdAsync(id); - if (paymentMethod == null) return null; + if (paymentMethod == null) + { + return ServiceResult.Fail(ServiceResultType.NotFound, $"Zahlungsmethode mit ID '{id}' nicht gefunden."); + } - return new AdminPaymentMethodDto + var dto = new AdminPaymentMethodDto { Id = paymentMethod.Id, Name = paymentMethod.Name, Description = paymentMethod.Description, IsActive = paymentMethod.IsActive, PaymentGatewayType = paymentMethod.PaymentGatewayType, - // Deserialisiere den JSON-String aus der DB in ein Objekt Configuration = paymentMethod.Configuration != null ? JsonSerializer.Deserialize(paymentMethod.Configuration) : null, ProcessingFee = paymentMethod.ProcessingFee }; + + return ServiceResult.Ok(dto); } - public async Task CreateAsync(AdminPaymentMethodDto paymentMethodDto) + public async Task> CreateAsync(AdminPaymentMethodDto paymentMethodDto) { var (isValid, configJson, errorMessage) = ValidateAndSerializeConfiguration(paymentMethodDto.PaymentGatewayType, paymentMethodDto.Configuration); if (!isValid) { - // In einer echten Anwendung würden Sie hier eine benutzerdefinierte Validierungs-Exception werfen, - // damit der Controller einen 400 Bad Request zurückgeben kann. - throw new ArgumentException(errorMessage); + return ServiceResult.Fail(ServiceResultType.InvalidInput, errorMessage!); } var newPaymentMethod = new PaymentMethod @@ -72,25 +75,28 @@ namespace Webshop.Application.Services.Admin Description = paymentMethodDto.Description, IsActive = paymentMethodDto.IsActive, PaymentGatewayType = paymentMethodDto.PaymentGatewayType, - Configuration = configJson, // Speichere den validierten JSON-String + Configuration = configJson, ProcessingFee = paymentMethodDto.ProcessingFee }; await _paymentMethodRepository.AddAsync(newPaymentMethod); paymentMethodDto.Id = newPaymentMethod.Id; - return paymentMethodDto; + return ServiceResult.Ok(paymentMethodDto); } - public async Task UpdateAsync(AdminPaymentMethodDto paymentMethodDto) + public async Task UpdateAsync(AdminPaymentMethodDto paymentMethodDto) { var existingPaymentMethod = await _paymentMethodRepository.GetByIdAsync(paymentMethodDto.Id); - if (existingPaymentMethod == null) return false; + if (existingPaymentMethod == null) + { + return ServiceResult.Fail(ServiceResultType.NotFound, $"Zahlungsmethode mit ID '{paymentMethodDto.Id}' nicht gefunden."); + } var (isValid, configJson, errorMessage) = ValidateAndSerializeConfiguration(paymentMethodDto.PaymentGatewayType, paymentMethodDto.Configuration); if (!isValid) { - throw new ArgumentException(errorMessage); + return ServiceResult.Fail(ServiceResultType.InvalidInput, errorMessage!); } existingPaymentMethod.Name = paymentMethodDto.Name; @@ -101,16 +107,19 @@ namespace Webshop.Application.Services.Admin existingPaymentMethod.ProcessingFee = paymentMethodDto.ProcessingFee; await _paymentMethodRepository.UpdateAsync(existingPaymentMethod); - return true; + return ServiceResult.Ok(); } - public async Task DeleteAsync(Guid id) + public async Task DeleteAsync(Guid id) { var paymentMethod = await _paymentMethodRepository.GetByIdAsync(id); - if (paymentMethod == null) return false; + if (paymentMethod == null) + { + return ServiceResult.Fail(ServiceResultType.NotFound, $"Zahlungsmethode mit ID '{id}' nicht gefunden."); + } await _paymentMethodRepository.DeleteAsync(id); - return true; + return ServiceResult.Ok(); } private (bool IsValid, string? ConfigJson, string? ErrorMessage) ValidateAndSerializeConfiguration(PaymentGatewayType type, object? configObject) @@ -148,8 +157,6 @@ namespace Webshop.Application.Services.Admin return (true, JsonSerializer.Serialize(payPalConfig), null); default: - // Für Typen wie Invoice oder CashOnDelivery, die keine spezielle Konfiguration brauchen, - // ist ein leeres JSON-Objekt '{}' ein gültiger Wert. return (true, JsonSerializer.Serialize(new object()), null); } } diff --git a/Webshop.Application/Services/Admin/Interfaces/IAdminPaymentMethodService.cs b/Webshop.Application/Services/Admin/Interfaces/IAdminPaymentMethodService.cs index 7b225af..25b60ae 100644 --- a/Webshop.Application/Services/Admin/Interfaces/IAdminPaymentMethodService.cs +++ b/Webshop.Application/Services/Admin/Interfaces/IAdminPaymentMethodService.cs @@ -2,35 +2,17 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Webshop.Application.DTOs.Payments; // Für AdminPaymentMethodDto +using Webshop.Application; +using Webshop.Application.DTOs.Payments; namespace Webshop.Application.Services.Admin { public interface IAdminPaymentMethodService { - /// - /// Ruft alle Zahlungsmethoden ab (sowohl aktive als auch inaktive). - /// - Task> GetAllAsync(); - - /// - /// Ruft eine einzelne Zahlungsmethode anhand ihrer ID ab. - /// - Task GetByIdAsync(Guid id); - - /// - /// Erstellt eine neue Zahlungsmethode. - /// - Task CreateAsync(AdminPaymentMethodDto paymentMethodDto); - - /// - /// Aktualisiert eine bestehende Zahlungsmethode. - /// - Task UpdateAsync(AdminPaymentMethodDto paymentMethodDto); - - /// - /// Löscht eine Zahlungsmethode anhand ihrer ID. - /// - Task DeleteAsync(Guid id); + Task>> GetAllAsync(); + Task> GetByIdAsync(Guid id); + Task> CreateAsync(AdminPaymentMethodDto paymentMethodDto); + Task UpdateAsync(AdminPaymentMethodDto paymentMethodDto); + Task DeleteAsync(Guid id); } } \ No newline at end of file