test bilder erneut

This commit is contained in:
Tizian.Breuch
2025-08-08 15:50:01 +02:00
parent 562d720c4a
commit c2af53c5ce
7 changed files with 65 additions and 69 deletions

View File

@@ -1,5 +1,4 @@
// src/Webshop.Application/DTOs/Products/CreateAdminProductDto.cs
using Microsoft.AspNetCore.Http; // Für IFormFile
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -21,13 +20,12 @@ namespace Webshop.Application.DTOs.Products
[Required]
public string Slug { get; set; }
// << NEU: Felder für den Bildupload >>
public IFormFile? MainImageFile { get; set; }
public List<IFormFile>? AdditionalImageFiles { get; set; }
// << KORREKTUR: Felder für Bild-URLs, keine IFormFile >>
public string? MainImageUrl { get; set; }
public List<string>? AdditionalImageUrls { get; set; }
public List<Guid> CategorieIds { get; set; } = new List<Guid>();
// ... weitere Felder, die beim Erstellen benötigt werden (z.B. SupplierId, PurchasePrice etc.) ...
public decimal? Weight { get; set; }
public decimal? OldPrice { get; set; }
public Guid? SupplierId { get; set; }

View File

@@ -10,4 +10,4 @@ namespace Webshop.Application.DTOs.Products
public bool IsMainImage { get; set; }
public int DisplayOrder { get; set; }
}
}
}

View File

@@ -1,5 +1,4 @@
// src/Webshop.Application/DTOs/Products/UpdateAdminProductDto.cs
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
@@ -23,14 +22,12 @@ namespace Webshop.Application.DTOs.Products
[Required]
public string Slug { get; set; }
// << NEU: Felder für den Bildupload und -verwaltung >>
public IFormFile? MainImageFile { get; set; } // Optional: Neues Hauptbild hochladen
public List<IFormFile>? AdditionalImageFiles { get; set; } // Optional: Weitere Bilder hochladen
public List<Guid>? ImagesToDelete { get; set; } // Liste der IDs von Bildern, die gelöscht werden sollen
// << KORREKTUR: Felder für Bild-URLs >>
public string? MainImageUrl { get; set; }
public List<string>? AdditionalImageUrls { get; set; }
public List<Guid> CategorieIds { get; set; } = new List<Guid>();
// ... weitere Felder, die beim Aktualisieren benötigt werden ...
public decimal? Weight { get; set; }
public decimal? OldPrice { get; set; }
public Guid? SupplierId { get; set; }

View File

@@ -15,16 +15,13 @@ namespace Webshop.Application.Services.Admin
public class AdminProductService : IAdminProductService
{
private readonly IProductRepository _productRepository;
private readonly IFileStorageService _fileStorageService;
private readonly ApplicationDbContext _context;
public AdminProductService(
IProductRepository productRepository,
IFileStorageService fileStorageService,
ApplicationDbContext context)
{
_productRepository = productRepository;
_fileStorageService = fileStorageService;
_context = context;
}
@@ -33,6 +30,7 @@ namespace Webshop.Application.Services.Admin
var products = await _context.Products
.Include(p => p.Productcategories)
.Include(p => p.Images)
.OrderBy(p => p.Name)
.ToListAsync();
return products.Select(p => new AdminProductDto
@@ -53,7 +51,7 @@ namespace Webshop.Application.Services.Admin
SupplierId = p.SupplierId,
PurchasePrice = p.PurchasePrice,
categorieIds = p.Productcategories.Select(pc => pc.categorieId).ToList(),
Images = p.Images.Select(img => new ProductImageDto
Images = p.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto
{
Id = img.Id,
Url = img.Url,
@@ -90,7 +88,7 @@ namespace Webshop.Application.Services.Admin
SupplierId = product.SupplierId,
PurchasePrice = product.PurchasePrice,
categorieIds = product.Productcategories.Select(pc => pc.categorieId).ToList(),
Images = product.Images.Select(img => new ProductImageDto
Images = product.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto
{
Id = img.Id,
Url = img.Url,
@@ -100,23 +98,19 @@ namespace Webshop.Application.Services.Admin
};
}
public async Task<AdminProductDto> CreateAdminProductAsync(CreateAdminProductDto productDto)
public async Task<AdminProductDto?> CreateAdminProductAsync(CreateAdminProductDto productDto)
{
var images = new List<ProductImage>();
if (productDto.MainImageFile != null)
if (!string.IsNullOrEmpty(productDto.MainImageUrl))
{
await using var stream = productDto.MainImageFile.OpenReadStream();
var url = await _fileStorageService.SaveFileAsync(stream, productDto.MainImageFile.FileName, productDto.MainImageFile.ContentType);
images.Add(new ProductImage { Url = url, IsMainImage = true, DisplayOrder = 1 });
images.Add(new ProductImage { Url = productDto.MainImageUrl, IsMainImage = true, DisplayOrder = 1 });
}
if (productDto.AdditionalImageFiles != null)
if (productDto.AdditionalImageUrls != null)
{
int order = 2;
foreach (var file in productDto.AdditionalImageFiles)
foreach (var url in productDto.AdditionalImageUrls)
{
await using var stream = file.OpenReadStream();
var url = await _fileStorageService.SaveFileAsync(stream, file.FileName, file.ContentType);
images.Add(new ProductImage { Url = url, IsMainImage = false, DisplayOrder = order++ });
}
}
@@ -130,13 +124,17 @@ namespace Webshop.Application.Services.Admin
IsActive = productDto.IsActive,
StockQuantity = productDto.StockQuantity,
Slug = productDto.Slug,
Weight = productDto.Weight,
OldPrice = productDto.OldPrice,
SupplierId = productDto.SupplierId,
PurchasePrice = productDto.PurchasePrice,
Images = images,
Productcategories = productDto.CategorieIds.Select(cId => new Productcategorie { categorieId = cId }).ToList()
};
await _productRepository.AddProductAsync(newProduct);
return (await GetAdminProductByIdAsync(newProduct.Id))!;
return await GetAdminProductByIdAsync(newProduct.Id);
}
public async Task<bool> UpdateAdminProductAsync(UpdateAdminProductDto productDto)
@@ -148,34 +146,44 @@ namespace Webshop.Application.Services.Admin
if (existingProduct == null) return false;
if (productDto.ImagesToDelete != null)
{
var imagesToRemove = existingProduct.Images.Where(img => productDto.ImagesToDelete.Contains(img.Id)).ToList();
_context.ProductImages.RemoveRange(imagesToRemove);
}
if (productDto.MainImageFile != null)
{
var existingMainImage = existingProduct.Images.FirstOrDefault(img => img.IsMainImage);
if (existingMainImage != null) _context.ProductImages.Remove(existingMainImage);
// Basisdaten aktualisieren
existingProduct.Name = productDto.Name;
existingProduct.Description = productDto.Description;
existingProduct.SKU = productDto.SKU;
existingProduct.Price = productDto.Price;
existingProduct.IsActive = productDto.IsActive;
existingProduct.StockQuantity = productDto.StockQuantity;
existingProduct.Slug = productDto.Slug;
existingProduct.Weight = productDto.Weight;
existingProduct.OldPrice = productDto.OldPrice;
existingProduct.SupplierId = productDto.SupplierId;
existingProduct.PurchasePrice = productDto.PurchasePrice;
existingProduct.LastModifiedDate = DateTimeOffset.UtcNow;
await using var stream = productDto.MainImageFile.OpenReadStream();
var url = await _fileStorageService.SaveFileAsync(stream, productDto.MainImageFile.FileName, productDto.MainImageFile.ContentType);
existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = true, DisplayOrder = 1 });
}
if (productDto.AdditionalImageFiles != null)
// Kategorien synchronisieren
existingProduct.Productcategories.Clear();
if (productDto.CategorieIds != null)
{
int displayOrder = (existingProduct.Images.Any() ? existingProduct.Images.Max(i => i.DisplayOrder) : 0) + 1;
foreach (var file in productDto.AdditionalImageFiles)
foreach (var categorieId in productDto.CategorieIds)
{
await using var stream = file.OpenReadStream();
var url = await _fileStorageService.SaveFileAsync(stream, file.FileName, file.ContentType);
existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = false, DisplayOrder = displayOrder++ });
existingProduct.Productcategories.Add(new Productcategorie { categorieId = categorieId });
}
}
existingProduct.Name = productDto.Name;
existingProduct.Description = productDto.Description;
// ... (restliche Felder aktualisieren) ...
// Bilder synchronisieren
existingProduct.Images.Clear();
if (!string.IsNullOrEmpty(productDto.MainImageUrl))
{
existingProduct.Images.Add(new ProductImage { Url = productDto.MainImageUrl, IsMainImage = true, DisplayOrder = 1 });
}
if (productDto.AdditionalImageUrls != null)
{
int order = 2;
foreach (var url in productDto.AdditionalImageUrls)
{
existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = false, DisplayOrder = order++ });
}
}
await _productRepository.UpdateProductAsync(existingProduct);
return true;

View File

@@ -1,4 +1,5 @@
// src/Webshop.Application/Services/Admin/Interfaces/IAdminProductService.cs
// src/Webshop.Application/Services/Admin/IAdminProductService.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Webshop.Application.DTOs.Products;
@@ -9,8 +10,8 @@ namespace Webshop.Application.Services.Admin.Interfaces
{
Task<IEnumerable<AdminProductDto>> GetAllAdminProductsAsync();
Task<AdminProductDto?> GetAdminProductByIdAsync(Guid id);
Task<AdminProductDto> CreateAdminProductAsync(CreateAdminProductDto productDto); // << NEUER TYP >>
Task<bool> UpdateAdminProductAsync(UpdateAdminProductDto productDto); // << NEUER TYP >>
Task<AdminProductDto?> CreateAdminProductAsync(CreateAdminProductDto productDto); // << DTO-TYP GEÄNDERT >>
Task<bool> UpdateAdminProductAsync(UpdateAdminProductDto productDto); // << DTO-TYP GEÄNDERT >>
Task<bool> DeleteAdminProductAsync(Guid id);
}
}