try
This commit is contained in:
@@ -1,15 +1,19 @@
|
|||||||
|
// src/Webshop.Api/Controllers/Customer/ProfileController.cs
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using Webshop.Application.DTOs; // CustomerDto
|
||||||
|
using Webshop.Application.DTOs.Auth; // ChangePasswordRequestDto
|
||||||
|
using Webshop.Application.DTOs.Customers; // UpdateCustomerProfileDto
|
||||||
|
using Webshop.Application.Services;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application.DTOs.Customers;
|
using Webshop.Application.Services.Customers;
|
||||||
using Webshop.Application.Services.Customers.Interfaces;
|
|
||||||
|
|
||||||
namespace Webshop.Api.Controllers.Customers
|
namespace Webshop.Api.Controllers.Customer
|
||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/v1/customer/profile")] // Eindeutige Route f<>r das Profil
|
[Route("api/v1/customer/[controller]")] // z.B. /api/v1/customer/profile
|
||||||
[Authorize(Roles = "Customer")] // Nur f<>r eingeloggte Kunden!
|
[Authorize(Roles = "Customer")]
|
||||||
public class ProfileController : ControllerBase
|
public class ProfileController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ICustomerService _customerService;
|
private readonly ICustomerService _customerService;
|
||||||
@@ -19,33 +23,49 @@ namespace Webshop.Api.Controllers.Customers
|
|||||||
_customerService = customerService;
|
_customerService = customerService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hilfsmethode, um die ID des eingeloggten Benutzers aus dem Token zu holen
|
[HttpGet("me")] // /api/v1/customer/profile/me
|
||||||
private string GetUserId() => User.FindFirstValue(ClaimTypes.NameIdentifier)!;
|
|
||||||
|
|
||||||
[HttpGet("me")] // GET /api/v1/customer/profile/me
|
|
||||||
public async Task<ActionResult<CustomerDto>> GetMyProfile()
|
public async Task<ActionResult<CustomerDto>> GetMyProfile()
|
||||||
{
|
{
|
||||||
var userId = GetUserId();
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
var profile = await _customerService.GetMyProfileAsync(userId);
|
if (string.IsNullOrEmpty(userId)) return Unauthorized(new { Message = "Benutzer-ID nicht im Token gefunden." });
|
||||||
|
|
||||||
if (profile == null)
|
var customerProfile = await _customerService.GetMyProfileAsync(userId);
|
||||||
{
|
if (customerProfile == null) return NotFound(new { Message = "Kundenprofil nicht gefunden. Bitte erstellen Sie es." });
|
||||||
return NotFound("Kundenprofil nicht gefunden.");
|
|
||||||
}
|
return Ok(customerProfile);
|
||||||
return Ok(profile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("me")] // PUT /api/v1/customer/profile/me
|
[HttpPost("change-password")] // /api/v1/customer/profile/change-password
|
||||||
public async Task<IActionResult> UpdateMyProfile([FromBody] UpdateCustomerProfileDto profileDto)
|
public async Task<IActionResult> ChangePassword([FromBody] ChangePasswordRequestDto request)
|
||||||
{
|
{
|
||||||
var userId = GetUserId();
|
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||||
var success = await _customerService.UpdateMyProfileAsync(userId, profileDto);
|
|
||||||
|
|
||||||
if (!success)
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
if (string.IsNullOrEmpty(userId)) return Unauthorized(new { Message = "Benutzer-ID nicht im Token gefunden." });
|
||||||
|
|
||||||
|
var (success, errorMessage) = await _customerService.ChangePasswordAsync(userId, request);
|
||||||
|
|
||||||
|
if (!success) return BadRequest(new { Message = errorMessage });
|
||||||
|
|
||||||
|
return Ok(new { Message = "Passwort erfolgreich ge<67>ndert. Bitte melden Sie sich mit dem neuen Passwort an." });
|
||||||
|
}
|
||||||
|
|
||||||
|
// << NEUER/AKTUALISIERTER ENDPUNKT F<>R PROFIL-AKTUALISIERUNG >>
|
||||||
|
[HttpPost("update-profile")] // /api/v1/customer/profile/update-profile
|
||||||
|
public async Task<IActionResult> UpdateProfile([FromBody] UpdateCustomerProfileDto request)
|
||||||
{
|
{
|
||||||
return NotFound("Kundenprofil nicht gefunden.");
|
if (!ModelState.IsValid) return BadRequest(ModelState);
|
||||||
}
|
|
||||||
return NoContent(); // Standardantwort f<>r ein erfolgreiches Update
|
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
|
if (string.IsNullOrEmpty(userId)) return Unauthorized(new { Message = "Benutzer-ID nicht im Token gefunden." });
|
||||||
|
|
||||||
|
var (success, errorMessage) = await _customerService.UpdateMyProfileAsync(userId, request);
|
||||||
|
|
||||||
|
if (!success) return BadRequest(new { Message = errorMessage });
|
||||||
|
|
||||||
|
return Ok(new { Message = "Profil erfolgreich aktualisiert." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// << ENTFERNT: UpdateContactInfo Endpoint >>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ using Webshop.Application.Services.Admin.Interfaces;
|
|||||||
using Webshop.Application.Services.Public.Interfaces;
|
using Webshop.Application.Services.Public.Interfaces;
|
||||||
using Webshop.Application.Services.Customers.Interfaces;
|
using Webshop.Application.Services.Customers.Interfaces;
|
||||||
using Webshop.Application.Services.Customers;
|
using Webshop.Application.Services.Customers;
|
||||||
|
using Webshop.Domain.Identity;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@@ -136,6 +137,7 @@ builder.Services.AddSwaggerGen(c =>
|
|||||||
|
|
||||||
var app = builder.Build(); // <-- Hier wird die App gebaut
|
var app = builder.Build(); // <-- Hier wird die App gebaut
|
||||||
|
|
||||||
|
// OPTIONALE BL<42>CKE F<>R MIGRATION UND BENUTZERINITIALISIERUNG - DIESER CODE WIRD VOR APP.RUN() AUSGEF<45>HRT
|
||||||
// OPTIONALE BL<42>CKE F<>R MIGRATION UND BENUTZERINITIALISIERUNG - DIESER CODE WIRD VOR APP.RUN() AUSGEF<45>HRT
|
// OPTIONALE BL<42>CKE F<>R MIGRATION UND BENUTZERINITIALISIERUNG - DIESER CODE WIRD VOR APP.RUN() AUSGEF<45>HRT
|
||||||
using (var scope = app.Services.CreateScope())
|
using (var scope = app.Services.CreateScope())
|
||||||
{
|
{
|
||||||
@@ -150,7 +152,7 @@ using (var scope = app.Services.CreateScope())
|
|||||||
// Dieser Block erstellt Rollen und initiale Benutzer, falls sie noch nicht existieren.
|
// Dieser Block erstellt Rollen und initiale Benutzer, falls sie noch nicht existieren.
|
||||||
// BITTE ENTFERNEN ODER KOMMENTIEREN SIE DIESEN BLOCK AUS, NACHDEM SIE IHRE ERSTEN BENUTZER ERSTELLT HABEN!
|
// BITTE ENTFERNEN ODER KOMMENTIEREN SIE DIESEN BLOCK AUS, NACHDEM SIE IHRE ERSTEN BENUTZER ERSTELLT HABEN!
|
||||||
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
|
var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
|
||||||
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
|
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>(); // << KORREKT: UserManager f<>r ApplicationUser >>
|
||||||
|
|
||||||
string[] roleNames = { "Admin", "Customer" };
|
string[] roleNames = { "Admin", "Customer" };
|
||||||
|
|
||||||
@@ -162,23 +164,39 @@ using (var scope = app.Services.CreateScope())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erstelle einen initialen Admin-Benutzer
|
// Erstelle einen initialen Admin-Benutzer und sein Customer-Profil
|
||||||
var adminUser = await userManager.FindByEmailAsync("admin@yourwebshop.com");
|
var adminUser = await userManager.FindByEmailAsync("admin@yourwebshop.com"); // << ANPASSEN >>
|
||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
// Erstellen Sie hier eine Instanz von ApplicationUser
|
adminUser = new ApplicationUser // << KORREKT: ERSTELLT ApplicationUser >>
|
||||||
adminUser = new ApplicationUser
|
|
||||||
{
|
{
|
||||||
UserName = "admin@yourwebshop.com",
|
UserName = "admin@yourwebshop.com", // << ANPASSEN >>
|
||||||
Email = "admin@yourwebshop.com",
|
Email = "admin@yourwebshop.com", // << ANPASSEN >>
|
||||||
EmailConfirmed = true,
|
EmailConfirmed = true,
|
||||||
CreatedDate = DateTimeOffset.UtcNow // Setzen Sie Ihr neues Feld!
|
CreatedDate = DateTimeOffset.UtcNow, // Custom Property auf ApplicationUser
|
||||||
|
LastActive = DateTimeOffset.UtcNow // Custom Property auf ApplicationUser
|
||||||
};
|
};
|
||||||
var createAdmin = await userManager.CreateAsync(adminUser, "SecureAdminPass123!");
|
var createAdmin = await userManager.CreateAsync(adminUser, "SecureAdminPass123!"); // << ANPASSEN >>
|
||||||
if (createAdmin.Succeeded)
|
if (createAdmin.Succeeded)
|
||||||
{
|
{
|
||||||
await userManager.AddToRoleAsync(adminUser, "Admin");
|
await userManager.AddToRoleAsync(adminUser, "Admin");
|
||||||
Console.WriteLine("Admin user created.");
|
Console.WriteLine("Admin user created.");
|
||||||
|
|
||||||
|
// Erstelle Customer-Profil f<>r Admin (falls Admins auch Kundenprofile haben sollen)
|
||||||
|
var adminCustomerProfile = await context.Customers.FirstOrDefaultAsync(c => c.AspNetUserId == adminUser.Id); // << KORREKT: SUCHT NACH AspNetUserId >>
|
||||||
|
if (adminCustomerProfile == null)
|
||||||
|
{
|
||||||
|
adminCustomerProfile = new Webshop.Domain.Entities.Customer
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
AspNetUserId = adminUser.Id, // << KORREKT: VERKN<4B>PFUNG <20>BER AspNetUserId >>
|
||||||
|
FirstName = "Admin",
|
||||||
|
LastName = "User"
|
||||||
|
};
|
||||||
|
context.Customers.Add(adminCustomerProfile);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine("Admin's Customer profile created.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -186,29 +204,46 @@ using (var scope = app.Services.CreateScope())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erstelle einen initialen Kunden-Benutzer
|
// Erstelle einen initialen Kunden-Benutzer und sein Customer-Profil (KOMBINIERT)
|
||||||
var customerUser = await userManager.FindByEmailAsync("customer@yourwebshop.com");
|
var customerUser = await userManager.FindByEmailAsync("customer@yourwebshop.com"); // << ANPASSEN >>
|
||||||
if (customerUser == null)
|
if (customerUser == null)
|
||||||
{
|
{
|
||||||
// Erstellen Sie auch hier eine Instanz von ApplicationUser
|
customerUser = new ApplicationUser // << KORREKT: ERSTELLT ApplicationUser >>
|
||||||
customerUser = new ApplicationUser
|
|
||||||
{
|
{
|
||||||
UserName = "customer@yourwebshop.com",
|
UserName = "customer@yourwebshop.com", // << ANPASSEN >>
|
||||||
Email = "customer@yourwebshop.com",
|
Email = "customer@yourwebshop.com", // << ANPASSEN >>
|
||||||
EmailConfirmed = true,
|
EmailConfirmed = true,
|
||||||
CreatedDate = DateTimeOffset.UtcNow // Setzen Sie Ihr neues Feld!
|
CreatedDate = DateTimeOffset.UtcNow, // Custom Property auf ApplicationUser
|
||||||
|
LastActive = DateTimeOffset.UtcNow // Custom Property auf ApplicationUser
|
||||||
};
|
};
|
||||||
var createCustomer = await userManager.CreateAsync(customerUser, "SecureCustomerPass123!");
|
var createCustomer = await userManager.CreateAsync(customerUser, "SecureCustomerPass123!"); // << ANPASSEN >>
|
||||||
if (createCustomer.Succeeded)
|
if (createCustomer.Succeeded)
|
||||||
{
|
{
|
||||||
await userManager.AddToRoleAsync(customerUser, "Customer");
|
await userManager.AddToRoleAsync(customerUser, "Customer");
|
||||||
Console.WriteLine("Customer user created.");
|
Console.WriteLine("Customer user created.");
|
||||||
|
|
||||||
|
// Kombinierter Teil: Customer-Profil erstellen, direkt nach IdentityUser-Erstellung
|
||||||
|
var customerProfile = await context.Customers.FirstOrDefaultAsync(c => c.AspNetUserId == customerUser.Id); // << KORREKT: SUCHT NACH AspNetUserId >>
|
||||||
|
if (customerProfile == null)
|
||||||
|
{
|
||||||
|
customerProfile = new Webshop.Domain.Entities.Customer
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
AspNetUserId = customerUser.Id,
|
||||||
|
FirstName = "Test",
|
||||||
|
LastName = "Kunde"
|
||||||
|
};
|
||||||
|
context.Customers.Add(customerProfile);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine("Customer profile created for new customer user.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error creating customer user: {string.Join(", ", createCustomer.Errors.Select(e => e.Description))}");
|
Console.WriteLine($"Error creating customer user: {string.Join(", ", createCustomer.Errors.Select(e => e.Description))}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// --- ENDE DES TEMPOR<4F>REN SETUP-BLOCKS ---
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ using Webshop.Application.DTOs.Products;
|
|||||||
using Webshop.Application.DTOs.Payments;
|
using Webshop.Application.DTOs.Payments;
|
||||||
using Webshop.Application.DTOs.Orders;
|
using Webshop.Application.DTOs.Orders;
|
||||||
using Webshop.Application.DTOs.Discounts;
|
using Webshop.Application.DTOs.Discounts;
|
||||||
using Webshop.Application.DTOs.Categorys; // Für Guid.NewGuid()
|
using Webshop.Application.DTOs.Categorys;
|
||||||
|
|
||||||
namespace Webshop.Api.SwaggerFilters
|
namespace Webshop.Api.SwaggerFilters
|
||||||
{
|
{
|
||||||
|
|||||||
19
Webshop.Application/DTOs/Auth/ChangePasswordRequestDto.cs
Normal file
19
Webshop.Application/DTOs/Auth/ChangePasswordRequestDto.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// src/Webshop.Application/DTOs/Auth/ChangePasswordRequestDto.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Webshop.Application.DTOs.Auth
|
||||||
|
{
|
||||||
|
public class ChangePasswordRequestDto
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "Altes Passwort ist erforderlich.")]
|
||||||
|
public string OldPassword { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Neues Passwort ist erforderlich.")]
|
||||||
|
[MinLength(6, ErrorMessage = "Passwort muss mindestens 6 Zeichen lang sein.")]
|
||||||
|
public string NewPassword { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Passwortbestätigung ist erforderlich.")]
|
||||||
|
[Compare("NewPassword", ErrorMessage = "Neues Passwort und Bestätigung stimmen nicht überein.")]
|
||||||
|
public string ConfirmNewPassword { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,26 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
// src/Webshop.Application/DTOs/Customers/UpdateCustomerProfileDto.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace Webshop.Application.DTOs.Customers
|
namespace Webshop.Application.DTOs.Customers
|
||||||
{
|
{
|
||||||
public class UpdateCustomerProfileDto
|
public class UpdateCustomerProfileDto
|
||||||
{
|
{
|
||||||
[Required(ErrorMessage = "Vorname ist erforderlich.")]
|
[Required(ErrorMessage = "Vorname ist erforderlich.")]
|
||||||
[MaxLength(100)]
|
[StringLength(100)]
|
||||||
public string FirstName { get; set; } = string.Empty;
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required(ErrorMessage = "Nachname ist erforderlich.")]
|
[Required(ErrorMessage = "Nachname ist erforderlich.")]
|
||||||
[MaxLength(100)]
|
[StringLength(100)]
|
||||||
public string LastName { get; set; } = string.Empty;
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Phone(ErrorMessage = "Ungültiges Telefonnummernformat.")]
|
||||||
|
public string? PhoneNumber { get; set; } // Telefonnummer des Benutzers
|
||||||
|
|
||||||
|
[EmailAddress(ErrorMessage = "Ungültiges E-Mail-Format.")]
|
||||||
|
public string? Email { get; set; } // E-Mail des Benutzers
|
||||||
|
|
||||||
|
// Optional, aber gute Sicherheitspraxis: Aktuelles Passwort zur Bestätigung sensibler Änderungen
|
||||||
|
[Required(ErrorMessage = "Aktuelles Passwort ist zur Bestätigung erforderlich.")]
|
||||||
|
public string CurrentPassword { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// src/Webshop.Application/DTOs/Users/AdminResetPasswordRequestDto.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Webshop.Application.DTOs.Users
|
||||||
|
{
|
||||||
|
public class AdminResetPasswordRequestDto
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "Benutzer-ID ist erforderlich.")]
|
||||||
|
public string UserId { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Neues Passwort ist erforderlich.")]
|
||||||
|
[MinLength(6, ErrorMessage = "Passwort muss mindestens 6 Zeichen lang sein.")]
|
||||||
|
public string NewPassword { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Passwortbestätigung ist erforderlich.")]
|
||||||
|
[Compare("NewPassword", ErrorMessage = "Neues Passwort und Bestätigung stimmen nicht überein.")]
|
||||||
|
public string ConfirmNewPassword { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,25 @@
|
|||||||
// src/Webshop.Application/DTOs/Users/UserDto.cs
|
// src/Webshop.Application/DTOs/Users/UserDto.cs
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Webshop.Application.DTOs.Users
|
namespace Webshop.Application.DTOs.Users
|
||||||
{
|
{
|
||||||
public class UserDto
|
public class UserDto
|
||||||
{
|
{
|
||||||
public string Id { get; set; } = string.Empty;
|
public string Id { get; set; } = string.Empty; // Vom ApplicationUser.Id
|
||||||
public string Email { get; set; } = string.Empty;
|
public string Email { get; set; } = string.Empty; // Vom ApplicationUser.Email
|
||||||
public string UserName { get; set; } = string.Empty;
|
public string UserName { get; set; } = string.Empty; // Vom ApplicationUser.UserName
|
||||||
public List<string> Roles { get; set; } = new List<string>();
|
public List<string> Roles { get; set; } = new List<string>(); // Aus Identity-System
|
||||||
public DateTimeOffset CreatedDate { get; set; }
|
public DateTimeOffset CreatedDate { get; set; } // Vom ApplicationUser.CreatedDate
|
||||||
public bool EmailConfirmed { get; set; }
|
public bool EmailConfirmed { get; set; } // Vom ApplicationUser.EmailConfirmed
|
||||||
|
|
||||||
// Hinzugef<65>gte Felder
|
public DateTimeOffset? LastActive { get; set; } // Vom ApplicationUser.LastActive
|
||||||
public DateTimeOffset? LastActive { get; set; }
|
public string? PhoneNumber { get; set; } // Vom ApplicationUser.PhoneNumber
|
||||||
public string FirstName { get; set; } = string.Empty;
|
|
||||||
public string LastName { get; set; } = string.Empty;
|
// << NEU: Customer-Felder, die NICHT in ApplicationUser sind >>
|
||||||
|
public string FirstName { get; set; } = string.Empty; // Vom Customer.FirstName
|
||||||
|
public string LastName { get; set; } = string.Empty; // Vom Customer.LastName
|
||||||
|
public Guid? DefaultShippingAddressId { get; set; } // Vom Customer
|
||||||
|
public Guid? DefaultBillingAddressId { get; set; } // Vom Customer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ using System.Linq;
|
|||||||
using Webshop.Application.DTOs.Products;
|
using Webshop.Application.DTOs.Products;
|
||||||
using Webshop.Application.Services.Admin.Interfaces; // F<>r Select
|
using Webshop.Application.Services.Admin.Interfaces; // F<>r Select
|
||||||
|
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Admin
|
namespace Webshop.Application.Services.Admin
|
||||||
{
|
{
|
||||||
public class AdminProductService : IAdminProductService // Sicherstellen, dass IAdminProductService implementiert wird
|
public class AdminProductService : IAdminProductService // Sicherstellen, dass IAdminProductService implementiert wird
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application.DTOs.Suppliers;
|
using Webshop.Application.DTOs.Suppliers;
|
||||||
using Webshop.Application.Services.Admin.Interfaces;
|
using Webshop.Application.Services.Admin.Interfaces;
|
||||||
|
using Webshop.Domain.Identity;
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Admin
|
namespace Webshop.Application.Services.Admin
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Webshop.Application.DTOs.Users;
|
|||||||
using Webshop.Application.Services.Admin.Interfaces;
|
using Webshop.Application.Services.Admin.Interfaces;
|
||||||
using Webshop.Domain.Entities;
|
using Webshop.Domain.Entities;
|
||||||
using Webshop.Infrastructure.Data; // WICHTIG: Stellt sicher, dass ApplicationDbContext gefunden wird.
|
using Webshop.Infrastructure.Data; // WICHTIG: Stellt sicher, dass ApplicationDbContext gefunden wird.
|
||||||
|
using Webshop.Domain.Identity;
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Admin
|
namespace Webshop.Application.Services.Admin
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
// src/Webshop.Application/Services/Admin/Interfaces/IAdminUserService.cs
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application.DTOs.Users;
|
using Webshop.Application.DTOs.Users;
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +1,122 @@
|
|||||||
|
// src/Webshop.Application/Services/Customers/CustomerService.cs
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application.DTOs.Customers;
|
using Webshop.Application.DTOs; // CustomerDto
|
||||||
using Webshop.Application.Services.Customers.Interfaces;
|
using Webshop.Application.DTOs.Auth; // ChangePasswordRequestDto
|
||||||
using Webshop.Domain.Interfaces; // Wichtig für ICustomerRepository
|
using Webshop.Application.DTOs.Customers; // UpdateCustomerProfileDto
|
||||||
|
using Webshop.Domain.Entities; // Customer Entity
|
||||||
|
using Webshop.Domain.Interfaces; // ICustomerRepository
|
||||||
|
using Webshop.Domain.Identity; // Für ApplicationUser
|
||||||
|
using System.Linq; // Für Select
|
||||||
|
using System.Collections.Generic; // Für IEnumerable
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Customers
|
namespace Webshop.Application.Services.Customers
|
||||||
{
|
{
|
||||||
public class CustomerService : ICustomerService
|
public class CustomerService : ICustomerService
|
||||||
{
|
{
|
||||||
private readonly ICustomerRepository _customerRepository;
|
private readonly ICustomerRepository _customerRepository;
|
||||||
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
public CustomerService(ICustomerRepository customerRepository)
|
public CustomerService(ICustomerRepository customerRepository, UserManager<ApplicationUser> userManager)
|
||||||
{
|
{
|
||||||
_customerRepository = customerRepository;
|
_customerRepository = customerRepository;
|
||||||
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CustomerDto?> GetMyProfileAsync(string userId)
|
public async Task<CustomerDto?> GetMyProfileAsync(string userId)
|
||||||
{
|
{
|
||||||
var customer = await _customerRepository.GetByUserIdAsync(userId);
|
var customer = await _customerRepository.GetByUserIdAsync(userId);
|
||||||
if (customer == null)
|
if (customer == null) return null;
|
||||||
{
|
|
||||||
return null;
|
var identityUser = await _userManager.FindByIdAsync(userId);
|
||||||
}
|
if (identityUser == null) return null;
|
||||||
|
|
||||||
// Mappe die Entity auf das CustomerDto
|
|
||||||
return new CustomerDto
|
return new CustomerDto
|
||||||
{
|
{
|
||||||
Id = customer.Id,
|
Id = customer.Id,
|
||||||
UserId = customer.AspNetUserId,
|
UserId = customer.AspNetUserId,
|
||||||
FirstName = customer.FirstName,
|
FirstName = customer.FirstName,
|
||||||
LastName = customer.LastName,
|
LastName = customer.LastName,
|
||||||
// Fügen Sie hier weitere Felder hinzu, die der Kunde sehen soll (Email, Phone etc.)
|
Email = identityUser.Email ?? string.Empty, // E-Mail vom ApplicationUser
|
||||||
|
PhoneNumber = identityUser.PhoneNumber, // Telefonnummer vom ApplicationUser
|
||||||
|
DefaultShippingAddressId = customer.DefaultShippingAddressId,
|
||||||
|
DefaultBillingAddressId = customer.DefaultBillingAddressId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> UpdateMyProfileAsync(string userId, UpdateCustomerProfileDto profileDto)
|
public async Task<(bool Success, string ErrorMessage)> ChangePasswordAsync(string userId, ChangePasswordRequestDto request)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByIdAsync(userId);
|
||||||
|
if (user == null) return (false, "Benutzer nicht gefunden.");
|
||||||
|
|
||||||
|
var result = await _userManager.ChangePasswordAsync(user, request.OldPassword, request.NewPassword);
|
||||||
|
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
var errors = string.Join(" ", result.Errors.Select(e => e.Description));
|
||||||
|
return (false, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, "Passwort erfolgreich geändert.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// << NEUE IMPLEMENTIERUNG: UpdateMyProfileAsync verarbeitet alle Felder >>
|
||||||
|
public async Task<(bool Success, string ErrorMessage)> UpdateMyProfileAsync(string userId, UpdateCustomerProfileDto profileDto)
|
||||||
{
|
{
|
||||||
var customer = await _customerRepository.GetByUserIdAsync(userId);
|
var customer = await _customerRepository.GetByUserIdAsync(userId);
|
||||||
if (customer == null)
|
if (customer == null) return (false, "Kundenprofil nicht gefunden.");
|
||||||
|
|
||||||
|
var identityUser = await _userManager.FindByIdAsync(userId);
|
||||||
|
if (identityUser == null) return (false, "Benutzerkonto nicht gefunden.");
|
||||||
|
|
||||||
|
// 1. Aktuelles Passwort prüfen (für alle sensiblen Änderungen)
|
||||||
|
if (!await _userManager.CheckPasswordAsync(identityUser, profileDto.CurrentPassword))
|
||||||
{
|
{
|
||||||
return false; // Kunde nicht gefunden
|
return (false, "Falsches aktuelles Passwort zur Bestätigung.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aktualisiere die Felder
|
// 2. Felder der Customer-Entität aktualisieren (FirstName, LastName)
|
||||||
customer.FirstName = profileDto.FirstName;
|
customer.FirstName = profileDto.FirstName;
|
||||||
customer.LastName = profileDto.LastName;
|
customer.LastName = profileDto.LastName;
|
||||||
|
// customer.PhoneNumber = profileDto.PhoneNumber; // Entfernt, da es jetzt in ApplicationUser zentralisiert ist
|
||||||
|
await _customerRepository.UpdateAsync(customer); // Speichert Änderungen im Customer-Profil
|
||||||
|
|
||||||
await _customerRepository.UpdateAsync(customer);
|
// 3. Felder des ApplicationUser (IdentityUser) aktualisieren (Email, PhoneNumber)
|
||||||
return true;
|
bool identityUserChanged = false;
|
||||||
|
|
||||||
|
// E-Mail aktualisieren (wenn anders und nicht leer)
|
||||||
|
if (!string.IsNullOrEmpty(profileDto.Email) && identityUser.Email != profileDto.Email)
|
||||||
|
{
|
||||||
|
identityUser.Email = profileDto.Email;
|
||||||
|
identityUser.NormalizedEmail = _userManager.NormalizeEmail(profileDto.Email);
|
||||||
|
identityUser.UserName = profileDto.Email; // Oft wird der UserName auch mit der E-Mail synchronisiert
|
||||||
|
identityUser.NormalizedUserName = _userManager.NormalizeName(profileDto.Email);
|
||||||
|
// Optional: user.EmailConfirmed = false; wenn Sie Bestätigungs-E-Mails senden
|
||||||
|
identityUserChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Telefonnummer aktualisieren (wenn anders und nicht leer)
|
||||||
|
if (!string.IsNullOrEmpty(profileDto.PhoneNumber) && identityUser.PhoneNumber != profileDto.PhoneNumber)
|
||||||
|
{
|
||||||
|
identityUser.PhoneNumber = profileDto.PhoneNumber;
|
||||||
|
// Optional: identityUser.PhoneNumberConfirmed = false;
|
||||||
|
identityUserChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identityUserChanged)
|
||||||
|
{
|
||||||
|
var updateResult = await _userManager.UpdateAsync(identityUser);
|
||||||
|
if (!updateResult.Succeeded)
|
||||||
|
{
|
||||||
|
var errors = string.Join(" ", updateResult.Errors.Select(e => e.Description));
|
||||||
|
return (false, $"Fehler beim Aktualisieren der Kontaktdaten: {errors}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true, "Profil und Kontaktdaten erfolgreich aktualisiert.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// << ENTFERNT: UpdateMyContactInfoAsync >>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
|
// src/Webshop.Application/Services/Customers/ICustomerService.cs
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Application.DTOs.Customers; // Korrektes Using für DTOs
|
using Webshop.Application.DTOs; // CustomerDto
|
||||||
|
using Webshop.Application.DTOs.Auth; // ChangePasswordRequestDto
|
||||||
|
using Webshop.Application.DTOs.Customers; // UpdateCustomerProfileDto
|
||||||
|
|
||||||
namespace Webshop.Application.Services.Customers.Interfaces
|
namespace Webshop.Application.Services.Customers
|
||||||
{
|
{
|
||||||
public interface ICustomerService
|
public interface ICustomerService
|
||||||
{
|
{
|
||||||
Task<CustomerDto?> GetMyProfileAsync(string userId);
|
Task<CustomerDto?> GetMyProfileAsync(string userId);
|
||||||
Task<bool> UpdateMyProfileAsync(string userId, UpdateCustomerProfileDto profileDto);
|
Task<(bool Success, string ErrorMessage)> ChangePasswordAsync(string userId, ChangePasswordRequestDto request);
|
||||||
|
Task<(bool Success, string ErrorMessage)> UpdateMyProfileAsync(string userId, UpdateCustomerProfileDto profileDto);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Webshop.Domain.Entities
|
|
||||||
{
|
|
||||||
public class ApplicationUser : IdentityUser
|
|
||||||
{
|
|
||||||
public DateTimeOffset CreatedDate { get; set; }
|
|
||||||
public DateTimeOffset? LastActive { get; set; }
|
|
||||||
public virtual Customer Customer { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,38 @@
|
|||||||
using System;
|
// src/Webshop.Domain/Entities/Customer.cs
|
||||||
|
using System;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Webshop.Domain.Identity; // Für ApplicationUser
|
||||||
|
|
||||||
namespace Webshop.Domain.Entities
|
namespace Webshop.Domain.Entities
|
||||||
{
|
{
|
||||||
public class Customer
|
public class Customer
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; } = Guid.NewGuid(); // Default-Wert setzen
|
||||||
[Required]
|
|
||||||
public string AspNetUserId { get; set; }
|
|
||||||
[Required]
|
|
||||||
[MaxLength(100)]
|
|
||||||
public string FirstName { get; set; }
|
|
||||||
[Required]
|
|
||||||
[MaxLength(100)]
|
|
||||||
public string LastName { get; set; }
|
|
||||||
|
|
||||||
public virtual ApplicationUser User { get; set; }
|
[Required]
|
||||||
|
public string AspNetUserId { get; set; } // Fremdschlüssel zu ApplicationUser.Id
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string FirstName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string LastName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
// << ENTFERNT: Email ist auf ApplicationUser >>
|
||||||
|
// << ENTFERNT: PhoneNumber ist auf ApplicationUser >>
|
||||||
|
// << ENTFERNT: CreatedDate ist auf ApplicationUser >>
|
||||||
|
|
||||||
|
public Guid? DefaultShippingAddressId { get; set; } // Fremdschlüssel zur Standardversandadresse
|
||||||
|
public Guid? DefaultBillingAddressId { get; set; } // Fremdschlüssel zur Standardrechnungsadresse
|
||||||
|
|
||||||
|
// Navigation Property zum ApplicationUser
|
||||||
|
public virtual ApplicationUser User { get; set; } = default!; // Muss auf ApplicationUser verweisen
|
||||||
|
|
||||||
|
// Navigation Properties zu Collections
|
||||||
public virtual ICollection<Address> Addresses { get; set; } = new List<Address>();
|
public virtual ICollection<Address> Addresses { get; set; } = new List<Address>();
|
||||||
public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
|
public virtual ICollection<Order> Orders { get; set; } = new List<Order>();
|
||||||
public virtual ICollection<Review> Reviews { get; set; } = new List<Review>();
|
public virtual ICollection<Review> Reviews { get; set; } = new List<Review>();
|
||||||
|
|||||||
16
Webshop.Domain/Identity/ApplicationUser.cs
Normal file
16
Webshop.Domain/Identity/ApplicationUser.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// src/Webshop.Domain/Identity/ApplicationUser.cs
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Webshop.Domain.Identity // KORREKTER NAMESPACE
|
||||||
|
{
|
||||||
|
public class ApplicationUser : IdentityUser
|
||||||
|
{
|
||||||
|
public DateTimeOffset CreatedDate { get; set; } = DateTimeOffset.UtcNow; // Setzt Standardwert
|
||||||
|
public DateTimeOffset? LastActive { get; set; }
|
||||||
|
|
||||||
|
// Navigation Property zur Customer-Entität (One-to-One)
|
||||||
|
// Customer ist nullable, falls nicht jeder ApplicationUser ein Customer-Profil hat
|
||||||
|
public virtual Entities.Customer? Customer { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
// src/Webshop.Domain/Interfaces/ICustomerRepository.cs
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Webshop.Domain.Entities;
|
using Webshop.Domain.Entities;
|
||||||
|
|
||||||
@@ -6,7 +7,12 @@ namespace Webshop.Domain.Interfaces
|
|||||||
{
|
{
|
||||||
public interface ICustomerRepository
|
public interface ICustomerRepository
|
||||||
{
|
{
|
||||||
Task<Customer?> GetByUserIdAsync(string userId);
|
Task<IEnumerable<Customer>> GetAllAsync(); // Standard CRUD
|
||||||
Task UpdateAsync(Customer customer);
|
Task<Customer?> GetByIdAsync(Guid id); // Standard CRUD
|
||||||
|
Task AddAsync(Customer entity); // Standard CRUD
|
||||||
|
Task UpdateAsync(Customer entity); // Standard CRUD
|
||||||
|
Task DeleteAsync(Guid id); // Standard CRUD
|
||||||
|
|
||||||
|
Task<Customer?> GetByUserIdAsync(string userId); // << DIESE METHODE IST NEU UND WICHTIG >>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
|
// src/Webshop.Infrastructure/Repositories/CustomerRepository.cs
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Webshop.Domain.Entities;
|
using Webshop.Domain.Entities;
|
||||||
using Webshop.Domain.Interfaces;
|
using Webshop.Domain.Interfaces;
|
||||||
using Webshop.Infrastructure.Data;
|
using Webshop.Infrastructure.Data;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Webshop.Infrastructure.Repositories
|
namespace Webshop.Infrastructure.Repositories
|
||||||
{
|
{
|
||||||
public class CustomerRepository : ICustomerRepository
|
public class CustomerRepository : ICustomerRepository // MUSS public sein
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
@@ -16,15 +18,17 @@ namespace Webshop.Infrastructure.Repositories
|
|||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Customer?> GetByUserIdAsync(string userId)
|
// Beispiel-Implementierungen (wenn nicht schon vorhanden):
|
||||||
{
|
public async Task<IEnumerable<Customer>> GetAllAsync() => await _context.Customers.ToListAsync();
|
||||||
return await _context.Customers.FirstOrDefaultAsync(c => c.AspNetUserId == userId);
|
public async Task<Customer?> GetByIdAsync(Guid id) => await _context.Customers.FindAsync(id);
|
||||||
}
|
public async Task AddAsync(Customer entity) { _context.Customers.Add(entity); await _context.SaveChangesAsync(); }
|
||||||
|
public async Task UpdateAsync(Customer entity) { _context.Customers.Update(entity); await _context.SaveChangesAsync(); }
|
||||||
|
public async Task DeleteAsync(Guid id) { var entity = await _context.Customers.FindAsync(id); if (entity != null) { _context.Customers.Remove(entity); await _context.SaveChangesAsync(); } }
|
||||||
|
|
||||||
public async Task UpdateAsync(Customer customer)
|
// KORREKTE IMPLEMENTIERUNG F<>R GetByUserIdAsync
|
||||||
|
public async Task<Customer?> GetByUserIdAsync(string aspNetUserId)
|
||||||
{
|
{
|
||||||
_context.Customers.Update(customer);
|
return await _context.Customers.FirstOrDefaultAsync(c => c.AspNetUserId == aspNetUserId);
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
// src/Webshop.Infrastructure/Repositories/SupplierRepository.cs
|
// src/Webshop.Infrastructure/Repositories/SupplierRepository.cs
|
||||||
// Auto-generiert von CreateWebshopFiles.ps1 (aktualisiert um Implementierungen)
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore; // Wichtig für ToListAsync, FindAsync etc.
|
|
||||||
using Webshop.Domain.Entities;
|
using Webshop.Domain.Entities;
|
||||||
using Webshop.Domain.Interfaces;
|
using Webshop.Domain.Interfaces;
|
||||||
using Webshop.Infrastructure.Data;
|
using Webshop.Infrastructure.Data;
|
||||||
using System; // Für Guid
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Webshop.Infrastructure.Repositories
|
namespace Webshop.Infrastructure.Repositories
|
||||||
{
|
{
|
||||||
public class SupplierRepository : ISupplierRepository // Hier muss das Interface stehen
|
public class SupplierRepository : ISupplierRepository // MUSS public sein
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
@@ -19,8 +18,6 @@ namespace Webshop.Infrastructure.Repositories
|
|||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- IMPLEMENTIERUNG DER ISupplierRepository METHODEN ---
|
|
||||||
|
|
||||||
public async Task<IEnumerable<Supplier>> GetAllSuppliersAsync()
|
public async Task<IEnumerable<Supplier>> GetAllSuppliersAsync()
|
||||||
{
|
{
|
||||||
return await _context.Suppliers.ToListAsync();
|
return await _context.Suppliers.ToListAsync();
|
||||||
@@ -34,7 +31,7 @@ namespace Webshop.Infrastructure.Repositories
|
|||||||
public async Task AddSupplierAsync(Supplier supplier)
|
public async Task AddSupplierAsync(Supplier supplier)
|
||||||
{
|
{
|
||||||
_context.Suppliers.Add(supplier);
|
_context.Suppliers.Add(supplier);
|
||||||
await _context.SaveChangesAsync(); // Änderungen in der DB speichern
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateSupplierAsync(Supplier supplier)
|
public async Task UpdateSupplierAsync(Supplier supplier)
|
||||||
@@ -45,11 +42,11 @@ namespace Webshop.Infrastructure.Repositories
|
|||||||
|
|
||||||
public async Task DeleteSupplierAsync(Guid id)
|
public async Task DeleteSupplierAsync(Guid id)
|
||||||
{
|
{
|
||||||
var supplier = await _context.Suppliers.FindAsync(id); // Lieferant zuerst finden
|
var supplier = await _context.Suppliers.FindAsync(id);
|
||||||
if (supplier != null)
|
if (supplier != null)
|
||||||
{
|
{
|
||||||
_context.Suppliers.Remove(supplier); // Lieferant entfernen
|
_context.Suppliers.Remove(supplier);
|
||||||
await _context.SaveChangesAsync(); // Änderungen speichern
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user