diff --git a/Webshop.Api/Controllers/Admin/HomeController.cs b/Webshop.Api/Controllers/Admin/HomeController.cs new file mode 100644 index 0000000..d080c2c --- /dev/null +++ b/Webshop.Api/Controllers/Admin/HomeController.cs @@ -0,0 +1,44 @@ +// src/Webshop.Api/Controllers/Admin/AdminSuppliersController.cs +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Webshop.Application.DTOs; // SupplierDto +using Webshop.Application.Services.Admin; + +namespace Webshop.Api.Controllers.Admin +{ + [ApiController] + [Route("api/v1/admin/[controller]")] // z.B. /api/v1/admin/suppliers + [Authorize(Roles = "Admin")] // Nur Admins + public class AdminSuppliersController : ControllerBase + { + private readonly AdminSupplierService _adminSupplierService; + + public AdminSuppliersController(AdminSupplierService adminSupplierService) + { + _adminSupplierService = adminSupplierService; + } + + [HttpGet] + public async Task>> GetAllSuppliers() + { + var suppliers = await _adminSupplierService.GetAllSuppliersAsync(); + return Ok(suppliers); + } + + [HttpPost] + public async Task> CreateSupplier([FromBody] SupplierDto supplierDto) + { + if (!ModelState.IsValid) return BadRequest(ModelState); + var createdSupplier = await _adminSupplierService.CreateSupplierAsync(supplierDto); + return CreatedAtAction(nameof(GetSupplierById), new { id = createdSupplier.Id }, createdSupplier); + } + + [HttpGet("{id}")] + public async Task> GetSupplierById(Guid id) + { + var supplier = await _adminSupplierService.GetSupplierByIdAsync(id); + if (supplier == null) return NotFound(); + return Ok(supplier); + } + } +} \ No newline at end of file diff --git a/Webshop.Api/Program.cs b/Webshop.Api/Program.cs index 40c1466..b3f5c2a 100644 --- a/Webshop.Api/Program.cs +++ b/Webshop.Api/Program.cs @@ -66,6 +66,7 @@ builder.Services.AddAuthorization(); // Aktiviert die Autorisierung // 4. Unsere eigenen Interfaces und Klassen registrieren (Dependency Injection) builder.Services.AddScoped(); +builder.Services.AddScoped(); // NEU // AUTH Services builder.Services.AddScoped(); @@ -76,6 +77,7 @@ builder.Services.AddScoped(); // Ihr ProductService ist hier reg // ADMIN Services builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); // NEU // CUSTOMER Services (später Implementierungen hinzufügen) // builder.Services.AddScoped(); diff --git a/Webshop.Application/DTOs/SupplierDto.cs b/Webshop.Application/DTOs/SupplierDto.cs new file mode 100644 index 0000000..eab65c0 --- /dev/null +++ b/Webshop.Application/DTOs/SupplierDto.cs @@ -0,0 +1,14 @@ +// src/Webshop.Application/DTOs/SupplierDto.cs +namespace Webshop.Application.DTOs +{ + public class SupplierDto + { + public Guid Id { get; set; } = Guid.NewGuid(); // Für PUT/GET, bei POST optional + public string Name { get; set; } = string.Empty; + public string? ContactPerson { get; set; } + public string? Email { get; set; } + public string? PhoneNumber { get; set; } + public Guid? AddressId { get; set; } // Wenn Sie Adressen haben, sonst null + public string? Notes { get; set; } + } +} \ No newline at end of file diff --git a/Webshop.Application/Services/Admin/AdminSupplierService.cs b/Webshop.Application/Services/Admin/AdminSupplierService.cs new file mode 100644 index 0000000..5c9755c --- /dev/null +++ b/Webshop.Application/Services/Admin/AdminSupplierService.cs @@ -0,0 +1,68 @@ +// src/Webshop.Application/Services/Admin/AdminSupplierService.cs +using Webshop.Application.DTOs; // SupplierDto +using Webshop.Domain.Entities; +using Webshop.Domain.Interfaces; +using System.Collections.Generic; // Für IEnumerable + +namespace Webshop.Application.Services.Admin +{ + public class AdminSupplierService + { + private readonly ISupplierRepository _supplierRepository; + + public AdminSupplierService(ISupplierRepository supplierRepository) + { + _supplierRepository = supplierRepository; + } + + public async Task> GetAllSuppliersAsync() + { + var suppliers = await _supplierRepository.GetAllSuppliersAsync(); + 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 + }).ToList(); + } + + public async Task GetSupplierByIdAsync(Guid id) + { + var supplier = await _supplierRepository.GetSupplierByIdAsync(id); + if (supplier == null) return null; + return new SupplierDto + { + Id = supplier.Id, + Name = supplier.Name, + ContactPerson = supplier.ContactPerson, + Email = supplier.Email, + PhoneNumber = supplier.PhoneNumber, + AddressId = supplier.AddressId, + Notes = supplier.Notes + }; + } + + public async Task CreateSupplierAsync(SupplierDto supplierDto) + { + var newSupplier = new Supplier + { + Id = Guid.NewGuid(), // API generiert die ID + Name = supplierDto.Name, + ContactPerson = supplierDto.ContactPerson, + Email = supplierDto.Email, + PhoneNumber = supplierDto.PhoneNumber, + AddressId = supplierDto.AddressId, + Notes = supplierDto.Notes + }; + await _supplierRepository.AddSupplierAsync(newSupplier); + supplierDto.Id = newSupplier.Id; // ID zurückschreiben + return supplierDto; + } + + // TODO: UpdateSupplierAsync, DeleteSupplierAsync + } +} \ No newline at end of file diff --git a/Webshop.Domain/Interfaces/ISupplierRepository.cs b/Webshop.Domain/Interfaces/ISupplierRepository.cs new file mode 100644 index 0000000..8143532 --- /dev/null +++ b/Webshop.Domain/Interfaces/ISupplierRepository.cs @@ -0,0 +1,14 @@ +// src/Webshop.Domain/Interfaces/ISupplierRepository.cs +using Webshop.Domain.Entities; + +namespace Webshop.Domain.Interfaces +{ + public interface ISupplierRepository + { + Task> GetAllSuppliersAsync(); + Task GetSupplierByIdAsync(Guid id); + Task AddSupplierAsync(Supplier supplier); + Task UpdateSupplierAsync(Supplier supplier); + Task DeleteSupplierAsync(Guid id); + } +} \ No newline at end of file diff --git a/Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.Designer.cs b/Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.Designer.cs similarity index 99% rename from Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.Designer.cs rename to Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.Designer.cs index e98fc1d..65dee36 100644 --- a/Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.Designer.cs +++ b/Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.Designer.cs @@ -12,8 +12,8 @@ using Webshop.Infrastructure.Data; namespace Webshop.Infrastructure.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20250723094917_InitialCreate")] - partial class InitialCreate + [Migration("20250723102855_AddSuppliersAndOtherEntities")] + partial class AddSuppliersAndOtherEntities { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.cs b/Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.cs similarity index 99% rename from Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.cs rename to Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.cs index d58ae5b..690c06e 100644 --- a/Webshop.Infrastructure/Migrations/20250723094917_InitialCreate.cs +++ b/Webshop.Infrastructure/Migrations/20250723102855_AddSuppliersAndOtherEntities.cs @@ -7,7 +7,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Webshop.Infrastructure.Migrations { /// - public partial class InitialCreate : Migration + public partial class AddSuppliersAndOtherEntities : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) diff --git a/Webshop.Infrastructure/Repositories/SupplierRepository.cs b/Webshop.Infrastructure/Repositories/SupplierRepository.cs new file mode 100644 index 0000000..19c4e59 --- /dev/null +++ b/Webshop.Infrastructure/Repositories/SupplierRepository.cs @@ -0,0 +1,50 @@ +// src/Webshop.Infrastructure/Repositories/SupplierRepository.cs +using Microsoft.EntityFrameworkCore; // Für ToListAsync +using Webshop.Domain.Entities; +using Webshop.Domain.Interfaces; +using Webshop.Infrastructure.Data; + +namespace Webshop.Infrastructure.Repositories +{ + public class SupplierRepository : ISupplierRepository + { + private readonly ApplicationDbContext _context; + + public SupplierRepository(ApplicationDbContext context) + { + _context = context; + } + + public async Task> GetAllSuppliersAsync() + { + return await _context.Suppliers.ToListAsync(); + } + + public async Task GetSupplierByIdAsync(Guid id) + { + return await _context.Suppliers.FindAsync(id); + } + + public async Task AddSupplierAsync(Supplier supplier) + { + _context.Suppliers.Add(supplier); + await _context.SaveChangesAsync(); + } + + public async Task UpdateSupplierAsync(Supplier supplier) + { + _context.Suppliers.Update(supplier); + await _context.SaveChangesAsync(); + } + + public async Task DeleteSupplierAsync(Guid id) + { + var supplier = await _context.Suppliers.FindAsync(id); + if (supplier != null) + { + _context.Suppliers.Remove(supplier); + await _context.SaveChangesAsync(); + } + } + } +} \ No newline at end of file