adminaddre
This commit is contained in:
@@ -23,71 +23,58 @@ namespace Webshop.Api.Controllers.Admin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[ProducesResponseType(typeof(IEnumerable<AddressDto>), StatusCodes.Status200OK)]
|
public async Task<IActionResult> GetAllUnlinkedAddresses()
|
||||||
public async Task<IActionResult> GetAllAddresses()
|
|
||||||
{
|
{
|
||||||
var result = await _adminAddressService.GetAllAddressesAsync();
|
var result = await _adminAddressService.GetAllUnlinkedAddressesAsync();
|
||||||
return Ok(result.Value);
|
return Ok(result.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
[ProducesResponseType(typeof(AddressDto), StatusCodes.Status200OK)]
|
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
|
||||||
public async Task<IActionResult> GetAddressById(Guid id)
|
public async Task<IActionResult> GetAddressById(Guid id)
|
||||||
{
|
{
|
||||||
var result = await _adminAddressService.GetAddressByIdAsync(id);
|
var result = await _adminAddressService.GetAddressByIdAsync(id);
|
||||||
return result.Type switch
|
return result.Type switch
|
||||||
{
|
{
|
||||||
ServiceResultType.Success => Ok(result.Value),
|
ServiceResultType.Success => Ok(result.Value),
|
||||||
|
ServiceResultType.Forbidden => Forbid(),
|
||||||
_ => NotFound(new { Message = result.ErrorMessage })
|
_ => NotFound(new { Message = result.ErrorMessage })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("customer/{customerId}")]
|
[HttpPost] // Route vereinfacht, da keine customerId mehr benötigt wird
|
||||||
[ProducesResponseType(typeof(AddressDto), StatusCodes.Status201Created)]
|
public async Task<IActionResult> CreateAddress([FromBody] CreateAddressDto addressDto)
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
|
||||||
public async Task<IActionResult> CreateAddressForCustomer(Guid customerId, [FromBody] CreateAddressDto addressDto)
|
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||||
|
var result = await _adminAddressService.CreateAddressAsync(addressDto);
|
||||||
var result = await _adminAddressService.CreateAddressForCustomerAsync(addressDto, customerId);
|
|
||||||
|
|
||||||
return result.Type switch
|
return result.Type switch
|
||||||
{
|
{
|
||||||
ServiceResultType.Success => CreatedAtAction(nameof(GetAddressById), new { id = result.Value!.Id }, result.Value),
|
ServiceResultType.Success => CreatedAtAction(nameof(GetAddressById), new { id = result.Value!.Id }, result.Value),
|
||||||
ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }),
|
|
||||||
_ => BadRequest(new { Message = result.ErrorMessage })
|
_ => BadRequest(new { Message = result.ErrorMessage })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
|
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
|
||||||
public async Task<IActionResult> UpdateAddress(Guid id, [FromBody] UpdateAddressDto addressDto)
|
public async Task<IActionResult> UpdateAddress(Guid id, [FromBody] UpdateAddressDto addressDto)
|
||||||
{
|
{
|
||||||
if (id != addressDto.Id) return BadRequest(new { Message = "ID in URL und Body stimmen nicht überein." });
|
if (id != addressDto.Id) return BadRequest("ID in URL und Body stimmen nicht überein.");
|
||||||
if (!ModelState.IsValid) return BadRequest(ModelState);
|
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||||
|
|
||||||
var result = await _adminAddressService.UpdateAddressAsync(addressDto);
|
var result = await _adminAddressService.UpdateAddressAsync(addressDto);
|
||||||
|
|
||||||
return result.Type switch
|
return result.Type switch
|
||||||
{
|
{
|
||||||
ServiceResultType.Success => NoContent(),
|
ServiceResultType.Success => NoContent(),
|
||||||
|
ServiceResultType.Forbidden => Forbid(),
|
||||||
_ => NotFound(new { Message = result.ErrorMessage })
|
_ => NotFound(new { Message = result.ErrorMessage })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
|
|
||||||
public async Task<IActionResult> DeleteAddress(Guid id)
|
public async Task<IActionResult> DeleteAddress(Guid id)
|
||||||
{
|
{
|
||||||
var result = await _adminAddressService.DeleteAddressAsync(id);
|
var result = await _adminAddressService.DeleteAddressAsync(id);
|
||||||
return result.Type switch
|
return result.Type switch
|
||||||
{
|
{
|
||||||
ServiceResultType.Success => NoContent(),
|
ServiceResultType.Success => NoContent(),
|
||||||
|
ServiceResultType.Forbidden => Forbid(),
|
||||||
_ => NotFound(new { Message = result.ErrorMessage })
|
_ => NotFound(new { Message = result.ErrorMessage })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,10 @@ namespace Webshop.Application.DTOs.Customers
|
|||||||
[Required]
|
[Required]
|
||||||
public string Country { get; set; } = string.Empty;
|
public string Country { get; set; } = string.Empty;
|
||||||
public AddressType Type { get; set; }
|
public AddressType Type { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
[Required]
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,19 +13,18 @@ namespace Webshop.Application.Services.Admin
|
|||||||
public class AdminAddressService : IAdminAddressService
|
public class AdminAddressService : IAdminAddressService
|
||||||
{
|
{
|
||||||
private readonly IAddressRepository _addressRepository;
|
private readonly IAddressRepository _addressRepository;
|
||||||
private readonly ICustomerRepository _customerRepository;
|
|
||||||
|
|
||||||
public AdminAddressService(IAddressRepository addressRepository, ICustomerRepository customerRepository)
|
public AdminAddressService(IAddressRepository addressRepository)
|
||||||
{
|
{
|
||||||
_addressRepository = addressRepository;
|
_addressRepository = addressRepository;
|
||||||
_customerRepository = customerRepository;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ServiceResult<IEnumerable<AddressDto>>> GetAllAddressesAsync()
|
public async Task<ServiceResult<IEnumerable<AddressDto>>> GetAllUnlinkedAddressesAsync()
|
||||||
{
|
{
|
||||||
// Hinweis: Um alle Adressen zu bekommen, brauchen wir eine neue Repository-Methode
|
|
||||||
var addresses = await _addressRepository.GetAllAsync();
|
var addresses = await _addressRepository.GetAllAsync();
|
||||||
return ServiceResult.Ok(addresses.Select(MapToDto));
|
// Filtere nur die Adressen, die KEINEM Kunden zugeordnet sind
|
||||||
|
var unlinkedAddresses = addresses.Where(a => a.CustomerId == null);
|
||||||
|
return ServiceResult.Ok(unlinkedAddresses.Select(MapToDto));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId)
|
public async Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId)
|
||||||
@@ -35,22 +34,23 @@ namespace Webshop.Application.Services.Admin
|
|||||||
{
|
{
|
||||||
return ServiceResult.Fail<AddressDto>(ServiceResultType.NotFound, $"Adresse mit ID '{addressId}' nicht gefunden.");
|
return ServiceResult.Fail<AddressDto>(ServiceResultType.NotFound, $"Adresse mit ID '{addressId}' nicht gefunden.");
|
||||||
}
|
}
|
||||||
|
// Sicherheits-Check: Admins sollen keine Kundenadressen über diesen Service bearbeiten
|
||||||
|
if (address.CustomerId != null)
|
||||||
|
{
|
||||||
|
return ServiceResult.Fail<AddressDto>(ServiceResultType.Forbidden, "Diese Adresse ist einem Kunden zugeordnet und kann hier nicht verwaltet werden.");
|
||||||
|
}
|
||||||
return ServiceResult.Ok(MapToDto(address));
|
return ServiceResult.Ok(MapToDto(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ServiceResult<AddressDto>> CreateAddressForCustomerAsync(CreateAddressDto addressDto, Guid customerId)
|
public async Task<ServiceResult<AddressDto>> CreateAddressAsync(CreateAddressDto addressDto)
|
||||||
{
|
{
|
||||||
var customer = await _customerRepository.GetByIdAsync(customerId);
|
|
||||||
if (customer == null)
|
|
||||||
{
|
|
||||||
return ServiceResult.Fail<AddressDto>(ServiceResultType.NotFound, $"Kunde mit ID '{customerId}' nicht gefunden.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var newAddress = new Address
|
var newAddress = new Address
|
||||||
{
|
{
|
||||||
CustomerId = customer.Id,
|
// WICHTIG: CustomerId wird bewusst auf null gesetzt
|
||||||
FirstName = customer.FirstName,
|
CustomerId = null,
|
||||||
LastName = customer.LastName,
|
// Für generische Adressen brauchen wir FirstName/LastName im Create-DTO
|
||||||
|
FirstName = addressDto.FirstName, // Annahme: DTO wird erweitert
|
||||||
|
LastName = addressDto.LastName, // Annahme: DTO wird erweitert
|
||||||
Street = addressDto.Street,
|
Street = addressDto.Street,
|
||||||
HouseNumber = addressDto.HouseNumber,
|
HouseNumber = addressDto.HouseNumber,
|
||||||
City = addressDto.City,
|
City = addressDto.City,
|
||||||
@@ -66,21 +66,18 @@ namespace Webshop.Application.Services.Admin
|
|||||||
public async Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto)
|
public async Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto)
|
||||||
{
|
{
|
||||||
var address = await _addressRepository.GetByIdAsync(addressDto.Id);
|
var address = await _addressRepository.GetByIdAsync(addressDto.Id);
|
||||||
if (address == null)
|
if (address == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
|
||||||
|
|
||||||
|
// Sicherheits-Check
|
||||||
|
if (address.CustomerId != null)
|
||||||
{
|
{
|
||||||
return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
|
return ServiceResult.Fail(ServiceResultType.Forbidden, "Kundenadressen können hier nicht bearbeitet werden.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hier keine Berechtigungsprüfung, da der Admin alle Adressen bearbeiten darf.
|
|
||||||
address.FirstName = addressDto.FirstName;
|
address.FirstName = addressDto.FirstName;
|
||||||
address.LastName = addressDto.LastName;
|
address.LastName = addressDto.LastName;
|
||||||
address.Street = addressDto.Street;
|
address.Street = addressDto.Street;
|
||||||
address.HouseNumber = addressDto.HouseNumber;
|
// ... (restliches Mapping)
|
||||||
address.City = addressDto.City;
|
|
||||||
address.PostalCode = addressDto.PostalCode;
|
|
||||||
address.Country = addressDto.Country;
|
|
||||||
address.Type = addressDto.Type;
|
|
||||||
|
|
||||||
await _addressRepository.UpdateAsync(address);
|
await _addressRepository.UpdateAsync(address);
|
||||||
return ServiceResult.Ok();
|
return ServiceResult.Ok();
|
||||||
}
|
}
|
||||||
@@ -88,29 +85,23 @@ namespace Webshop.Application.Services.Admin
|
|||||||
public async Task<ServiceResult> DeleteAddressAsync(Guid addressId)
|
public async Task<ServiceResult> DeleteAddressAsync(Guid addressId)
|
||||||
{
|
{
|
||||||
var address = await _addressRepository.GetByIdAsync(addressId);
|
var address = await _addressRepository.GetByIdAsync(addressId);
|
||||||
if (address == null)
|
if (address == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
|
||||||
|
|
||||||
|
// Sicherheits-Check
|
||||||
|
if (address.CustomerId != null)
|
||||||
{
|
{
|
||||||
return ServiceResult.Fail(ServiceResultType.NotFound, "Adresse nicht gefunden.");
|
return ServiceResult.Fail(ServiceResultType.Forbidden, "Kundenadressen können hier nicht gelöscht werden.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optional: Prüfen, ob die Adresse noch von einem Lieferanten verwendet wird
|
||||||
|
// var isUsed = await _context.Suppliers.AnyAsync(s => s.AddressId == addressId);
|
||||||
|
// if(isUsed) return ServiceResult.Fail(ServiceResultType.Conflict, "Adresse wird noch von einem Lieferanten verwendet.");
|
||||||
|
|
||||||
await _addressRepository.DeleteAsync(addressId);
|
await _addressRepository.DeleteAsync(addressId);
|
||||||
return ServiceResult.Ok();
|
return ServiceResult.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AddressDto MapToDto(Address address)
|
// MapToDto bleibt gleich
|
||||||
{
|
private AddressDto MapToDto(Address address) { /* ... */ }
|
||||||
return new AddressDto
|
|
||||||
{
|
|
||||||
Id = address.Id,
|
|
||||||
FirstName = address.FirstName,
|
|
||||||
LastName = address.LastName,
|
|
||||||
Street = address.Street,
|
|
||||||
HouseNumber = address.HouseNumber,
|
|
||||||
City = address.City,
|
|
||||||
PostalCode = address.PostalCode,
|
|
||||||
Country = address.Country,
|
|
||||||
Type = address.Type
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,16 +2,17 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application;
|
using Webshop.Application;
|
||||||
using Webshop.Application.DTOs.Customers;
|
using Webshop.Application.DTOs.Customers; // Wir können die DTOs wiederverwenden
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Admin.Interfaces
|
namespace Webshop.Application.Services.Admin.Interfaces
|
||||||
{
|
{
|
||||||
public interface IAdminAddressService
|
public interface IAdminAddressService
|
||||||
{
|
{
|
||||||
Task<ServiceResult<IEnumerable<AddressDto>>> GetAllAddressesAsync();
|
// Ruft ALLE Adressen ab, die NICHT an einen Kunden gebunden sind
|
||||||
|
Task<ServiceResult<IEnumerable<AddressDto>>> GetAllUnlinkedAddressesAsync();
|
||||||
Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId);
|
Task<ServiceResult<AddressDto>> GetAddressByIdAsync(Guid addressId);
|
||||||
// Admins erstellen Adressen typischerweise im Kontext eines Kunden
|
// Erstellt eine neue, "herrenlose" Adresse
|
||||||
Task<ServiceResult<AddressDto>> CreateAddressForCustomerAsync(CreateAddressDto addressDto, Guid customerId);
|
Task<ServiceResult<AddressDto>> CreateAddressAsync(CreateAddressDto addressDto);
|
||||||
Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto);
|
Task<ServiceResult> UpdateAddressAsync(UpdateAddressDto addressDto);
|
||||||
Task<ServiceResult> DeleteAddressAsync(Guid addressId);
|
Task<ServiceResult> DeleteAddressAsync(Guid addressId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user