From 3d206eda4e5b187e5061fbd192e6565d0006c12d Mon Sep 17 00:00:00 2001 From: "Tizian.Breuch" Date: Tue, 12 Aug 2025 13:20:47 +0200 Subject: [PATCH] address update --- .../Customers/AddressesController.cs | 48 ++++++++++++ .../DTOs/Customers/UpdateAddressDto.cs | 36 +++++++++ .../Services/Customers/AddressService.cs | 76 +++++++++++++++++-- .../Customers/Interfaces/IAddressService.cs | 4 +- 4 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 Webshop.Application/DTOs/Customers/UpdateAddressDto.cs diff --git a/Webshop.Api/Controllers/Customers/AddressesController.cs b/Webshop.Api/Controllers/Customers/AddressesController.cs index 1b61530..9bf4f8c 100644 --- a/Webshop.Api/Controllers/Customers/AddressesController.cs +++ b/Webshop.Api/Controllers/Customers/AddressesController.cs @@ -7,6 +7,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Webshop.Application.DTOs.Customers; using Webshop.Application.Services.Customers; +using Webshop.Application.Services.Customers.Interfaces; namespace Webshop.Api.Controllers.Customer { @@ -40,5 +41,52 @@ namespace Webshop.Api.Controllers.Customer return CreatedAtAction(nameof(GetMyAddresses), new { id = createdAddress.Id }, createdAddress); } + + [HttpPut("{id}")] + public async Task UpdateAddress(Guid id, [FromBody] UpdateAddressDto addressDto) + { + if (id != addressDto.Id) return BadRequest("ID in URL und Body stimmen nicht überein."); + if (!ModelState.IsValid) return BadRequest(ModelState); + + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var (success, errorMessage) = await _addressService.UpdateAddressAsync(addressDto, userId); + + if (!success) return BadRequest(new { Message = errorMessage }); + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task DeleteAddress(Guid id) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var (success, errorMessage) = await _addressService.DeleteAddressAsync(id, userId); + + if (!success) return BadRequest(new { Message = errorMessage }); + + return NoContent(); + } + + [HttpPost("default-shipping/{id}")] + public async Task SetDefaultShippingAddress(Guid id) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var (success, errorMessage) = await _addressService.SetDefaultShippingAddressAsync(id, userId); + + if (!success) return BadRequest(new { Message = errorMessage }); + + return Ok(); + } + + [HttpPost("default-billing/{id}")] + public async Task SetDefaultBillingAddress(Guid id) + { + var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); + var (success, errorMessage) = await _addressService.SetDefaultBillingAddressAsync(id, userId); + + if (!success) return BadRequest(new { Message = errorMessage }); + + return Ok(); + } } } \ No newline at end of file diff --git a/Webshop.Application/DTOs/Customers/UpdateAddressDto.cs b/Webshop.Application/DTOs/Customers/UpdateAddressDto.cs new file mode 100644 index 0000000..fa97a2d --- /dev/null +++ b/Webshop.Application/DTOs/Customers/UpdateAddressDto.cs @@ -0,0 +1,36 @@ +// src/Webshop.Application/DTOs/Customers/UpdateAddressDto.cs +using System; +using System.ComponentModel.DataAnnotations; +using Webshop.Domain.Enums; + +namespace Webshop.Application.DTOs.Customers +{ + public class UpdateAddressDto + { + [Required] + public Guid Id { get; set; } + + [Required] + public string Street { get; set; } = string.Empty; + + [Required] + public string HouseNumber { get; set; } = string.Empty; + + [Required] + public string City { get; set; } = string.Empty; + + [Required] + public string PostalCode { get; set; } = string.Empty; + + [Required] + public string Country { get; set; } = string.Empty; + + public AddressType Type { get; set; } + + // Fügen Sie auch FirstName und LastName hinzu, falls diese änderbar sein sollen + [Required] + public string FirstName { get; set; } = string.Empty; + [Required] + public string LastName { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Webshop.Application/Services/Customers/AddressService.cs b/Webshop.Application/Services/Customers/AddressService.cs index 3137bf2..9954341 100644 --- a/Webshop.Application/Services/Customers/AddressService.cs +++ b/Webshop.Application/Services/Customers/AddressService.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Webshop.Application.DTOs.Customers; using Webshop.Domain.Entities; using Webshop.Domain.Interfaces; +using Webshop.Infrastructure.Data; // Für direkten Zugriff auf den DbContext (optional) namespace Webshop.Application.Services.Customers { @@ -13,11 +14,13 @@ namespace Webshop.Application.Services.Customers { private readonly IAddressRepository _addressRepository; private readonly ICustomerRepository _customerRepository; + private readonly ApplicationDbContext _context; // Für komplexe Abfragen - public AddressService(IAddressRepository addressRepository, ICustomerRepository customerRepository) + public AddressService(IAddressRepository addressRepository, ICustomerRepository customerRepository, ApplicationDbContext context) { _addressRepository = addressRepository; _customerRepository = customerRepository; + _context = context; } public async Task> GetMyAddressesAsync(string userId) @@ -29,6 +32,8 @@ namespace Webshop.Application.Services.Customers return addresses.Select(a => new AddressDto { Id = a.Id, + FirstName = a.FirstName, + LastName = a.LastName, Street = a.Street, HouseNumber = a.HouseNumber, City = a.City, @@ -56,8 +61,9 @@ namespace Webshop.Application.Services.Customers var newAddress = new Address { - Id = Guid.NewGuid(), CustomerId = customer.Id, + FirstName = customer.FirstName, // Vorerst vom Kundenprofil übernehmen + LastName = customer.LastName, Street = addressDto.Street, HouseNumber = addressDto.HouseNumber, City = addressDto.City, @@ -72,16 +78,74 @@ namespace Webshop.Application.Services.Customers return (createdDto, null); } - // Update- und Delete-Logik (vereinfacht) - public async Task<(bool Success, string? ErrorMessage)> UpdateAddressAsync(Guid addressId, CreateAddressDto addressDto, string userId) + public async Task<(bool Success, string? ErrorMessage)> UpdateAddressAsync(UpdateAddressDto addressDto, string userId) { - // Implementierung ähnlich wie GetMyAddressByIdAsync + Speichern + var customer = await _customerRepository.GetByUserIdAsync(userId); + if (customer == null) return (false, "Kunde nicht gefunden."); + + var address = await _addressRepository.GetByIdAsync(addressDto.Id); + if (address == null || address.CustomerId != customer.Id) + { + return (false, "Adresse nicht gefunden oder gehört nicht zum aktuellen Benutzer."); + } + + address.FirstName = addressDto.FirstName; + address.LastName = addressDto.LastName; + address.Street = addressDto.Street; + address.HouseNumber = addressDto.HouseNumber; + address.City = addressDto.City; + address.PostalCode = addressDto.PostalCode; + address.Country = addressDto.Country; + address.Type = addressDto.Type; + + await _addressRepository.UpdateAsync(address); return (true, null); } public async Task<(bool Success, string? ErrorMessage)> DeleteAddressAsync(Guid addressId, string userId) { - // Implementierung ähnlich wie GetMyAddressByIdAsync + Löschen + var customer = await _customerRepository.GetByUserIdAsync(userId); + if (customer == null) return (false, "Kunde nicht gefunden."); + + var address = await _addressRepository.GetByIdAsync(addressId); + if (address == null || address.CustomerId != customer.Id) + { + return (false, "Adresse nicht gefunden oder gehört nicht zum aktuellen Benutzer."); + } + + await _addressRepository.DeleteAsync(addressId); + return (true, null); + } + + public async Task<(bool Success, string? ErrorMessage)> SetDefaultShippingAddressAsync(Guid addressId, string userId) + { + var customer = await _customerRepository.GetByUserIdAsync(userId); + if (customer == null) return (false, "Kunde nicht gefunden."); + + var address = await _addressRepository.GetByIdAsync(addressId); + if (address == null || address.CustomerId != customer.Id) + { + return (false, "Adresse nicht gefunden oder gehört nicht zum aktuellen Benutzer."); + } + + customer.DefaultShippingAddressId = addressId; + await _customerRepository.UpdateAsync(customer); + return (true, null); + } + + public async Task<(bool Success, string? ErrorMessage)> SetDefaultBillingAddressAsync(Guid addressId, string userId) + { + var customer = await _customerRepository.GetByUserIdAsync(userId); + if (customer == null) return (false, "Kunde nicht gefunden."); + + var address = await _addressRepository.GetByIdAsync(addressId); + if (address == null || address.CustomerId != customer.Id) + { + return (false, "Adresse nicht gefunden oder gehört nicht zum aktuellen Benutzer."); + } + + customer.DefaultBillingAddressId = addressId; + await _customerRepository.UpdateAsync(customer); return (true, null); } } diff --git a/Webshop.Application/Services/Customers/Interfaces/IAddressService.cs b/Webshop.Application/Services/Customers/Interfaces/IAddressService.cs index 009a91b..1a95921 100644 --- a/Webshop.Application/Services/Customers/Interfaces/IAddressService.cs +++ b/Webshop.Application/Services/Customers/Interfaces/IAddressService.cs @@ -11,7 +11,9 @@ namespace Webshop.Application.Services.Customers Task> GetMyAddressesAsync(string userId); Task GetMyAddressByIdAsync(Guid addressId, string userId); Task<(AddressDto? CreatedAddress, string? ErrorMessage)> CreateAddressAsync(CreateAddressDto addressDto, string userId); - Task<(bool Success, string? ErrorMessage)> UpdateAddressAsync(Guid addressId, CreateAddressDto addressDto, string userId); + Task<(bool Success, string? ErrorMessage)> UpdateAddressAsync(UpdateAddressDto addressDto, string userId); Task<(bool Success, string? ErrorMessage)> DeleteAddressAsync(Guid addressId, string userId); + Task<(bool Success, string? ErrorMessage)> SetDefaultShippingAddressAsync(Guid addressId, string userId); + Task<(bool Success, string? ErrorMessage)> SetDefaultBillingAddressAsync(Guid addressId, string userId); } } \ No newline at end of file