test bilder
Some checks failed
Branch - test - Build and Push Backend API Docker Image / build-and-push (push) Failing after 20s
Some checks failed
Branch - test - Build and Push Backend API Docker Image / build-and-push (push) Failing after 20s
This commit is contained in:
@@ -111,18 +111,131 @@ namespace Webshop.Application.Services.Admin
|
||||
#region Unchanged Methods
|
||||
public async Task<ServiceResult> UpdateAdminProductAsync(UpdateAdminProductDto productDto)
|
||||
{
|
||||
var existingProduct = await _context.Products.Include(p => p.Images).Include(p => p.Productcategories).FirstOrDefaultAsync(p => p.Id == productDto.Id);
|
||||
if (existingProduct == null) { return ServiceResult.Fail(ServiceResultType.NotFound, $"Produkt mit ID '{productDto.Id}' nicht gefunden."); }
|
||||
// 1. Produkt aus der DB laden (inklusive der zugeh<65>rigen Bilder und Kategorien)
|
||||
var existingProduct = await _context.Products
|
||||
.Include(p => p.Images)
|
||||
.Include(p => p.Productcategories)
|
||||
.FirstOrDefaultAsync(p => p.Id == productDto.Id);
|
||||
|
||||
if (existingProduct == null)
|
||||
{
|
||||
return ServiceResult.Fail(ServiceResultType.NotFound, $"Produkt mit ID '{productDto.Id}' nicht gefunden.");
|
||||
}
|
||||
|
||||
// 2. Validierung (SKU und Slug auf Einzigartigkeit pr<70>fen)
|
||||
var skuExists = await _context.Products.AnyAsync(p => p.SKU == productDto.SKU && p.Id != productDto.Id);
|
||||
if (skuExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit der SKU '{productDto.SKU}' existiert bereits."); }
|
||||
if (skuExists)
|
||||
{
|
||||
return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit der SKU '{productDto.SKU}' existiert bereits.");
|
||||
}
|
||||
var slugExists = await _context.Products.AnyAsync(p => p.Slug == productDto.Slug && p.Id != productDto.Id);
|
||||
if (slugExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit dem Slug '{productDto.Slug}' existiert bereits."); }
|
||||
if (productDto.ImagesToDelete != null && productDto.ImagesToDelete.Any()) { 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); 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 && productDto.AdditionalImageFiles.Any()) { int displayOrder = (existingProduct.Images.Any() ? existingProduct.Images.Max(i => i.DisplayOrder) : 0) + 1; foreach (var file in productDto.AdditionalImageFiles) { 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.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; existingProduct.IsFeatured = productDto.IsFeatured; existingProduct.FeaturedDisplayOrder = productDto.FeaturedDisplayOrder;
|
||||
existingProduct.Productcategories.Clear(); if (productDto.CategorieIds != null) { foreach (var categorieId in productDto.CategorieIds) { existingProduct.Productcategories.Add(new Productcategorie { categorieId = categorieId }); } }
|
||||
await _productRepository.UpdateProductAsync(existingProduct); return ServiceResult.Ok();
|
||||
if (slugExists)
|
||||
{
|
||||
return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit dem Slug '{productDto.Slug}' existiert bereits.");
|
||||
}
|
||||
|
||||
// 3. WICHTIG: Den Concurrency Token setzen!
|
||||
// Sagt Entity Framework, welche Version des Produkts der Benutzer urspr<70>nglich hatte.
|
||||
// "xmin" ist der Name der Concurrency-Spalte in PostgreSQL.
|
||||
_context.Entry(existingProduct).Property("xmin").OriginalValue = productDto.RowVersion;
|
||||
|
||||
// 4. Bilder-Logik (aufger<65>umt und klarer)
|
||||
await HandleImageUpdates(productDto, existingProduct);
|
||||
|
||||
// 5. Produkt-Eigenschaften mappen
|
||||
MapDtoToEntity(productDto, existingProduct);
|
||||
|
||||
// 6. Kategorie-Verkn<6B>pfungen aktualisieren
|
||||
UpdateProductCategories(productDto, existingProduct);
|
||||
|
||||
// 7. Speichern
|
||||
try
|
||||
{
|
||||
await _productRepository.UpdateProductAsync(existingProduct);
|
||||
return ServiceResult.Ok();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
// Dieser Fehler wird jetzt ausgel<65>st, wenn jemand anderes das Produkt in der Zwischenzeit ge<67>ndert hat.
|
||||
return ServiceResult.Fail(ServiceResultType.Conflict, "Die Produktdaten wurden von einem anderen Benutzer ge<67>ndert. Bitte laden Sie die Seite neu.");
|
||||
}
|
||||
}
|
||||
|
||||
private void MapDtoToEntity(UpdateAdminProductDto dto, Product entity)
|
||||
{
|
||||
entity.Name = dto.Name;
|
||||
entity.Description = dto.Description;
|
||||
entity.SKU = dto.SKU;
|
||||
entity.Price = dto.Price;
|
||||
entity.IsActive = dto.IsActive;
|
||||
entity.StockQuantity = dto.StockQuantity;
|
||||
entity.Slug = dto.Slug;
|
||||
entity.Weight = dto.Weight;
|
||||
entity.OldPrice = dto.OldPrice;
|
||||
entity.SupplierId = dto.SupplierId;
|
||||
entity.PurchasePrice = dto.PurchasePrice;
|
||||
entity.LastModifiedDate = DateTimeOffset.UtcNow;
|
||||
entity.IsFeatured = dto.IsFeatured;
|
||||
entity.FeaturedDisplayOrder = dto.FeaturedDisplayOrder;
|
||||
}
|
||||
|
||||
private async Task HandleImageUpdates(UpdateAdminProductDto dto, Product entity)
|
||||
{
|
||||
// Bilder zum L<>schen entfernen
|
||||
if (dto.ImagesToDelete != null && dto.ImagesToDelete.Any())
|
||||
{
|
||||
var imagesToRemove = entity.Images.Where(img => dto.ImagesToDelete.Contains(img.Id)).ToList();
|
||||
foreach (var image in imagesToRemove)
|
||||
{
|
||||
// Optional: Datei auch aus dem Storage l<>schen
|
||||
// await _fileStorageService.DeleteFileAsync(image.Url);
|
||||
}
|
||||
_context.ProductImages.RemoveRange(imagesToRemove);
|
||||
}
|
||||
|
||||
// Hauptbild aktualisieren/hinzuf<75>gen
|
||||
if (dto.MainImageFile != null)
|
||||
{
|
||||
// Altes Hauptbild als "nicht Hauptbild" markieren oder l<>schen
|
||||
var oldMainImage = entity.Images.FirstOrDefault(i => i.IsMainImage);
|
||||
if (oldMainImage != null) oldMainImage.IsMainImage = false;
|
||||
|
||||
await using var stream = dto.MainImageFile.OpenReadStream();
|
||||
var url = await _fileStorageService.SaveFileAsync(stream, dto.MainImageFile.FileName, dto.MainImageFile.ContentType);
|
||||
entity.Images.Add(new ProductImage { Url = url, IsMainImage = true });
|
||||
}
|
||||
else if (dto.MainImageId.HasValue) // Wenn ein existierendes Bild zum Hauptbild gemacht wird
|
||||
{
|
||||
entity.Images.ToList().ForEach(i => i.IsMainImage = (i.Id == dto.MainImageId.Value));
|
||||
}
|
||||
|
||||
// Zus<75>tzliche neue Bilder hinzuf<75>gen
|
||||
if (dto.AdditionalImageFiles != null && dto.AdditionalImageFiles.Any())
|
||||
{
|
||||
foreach (var file in dto.AdditionalImageFiles)
|
||||
{
|
||||
await using var stream = file.OpenReadStream();
|
||||
var url = await _fileStorageService.SaveFileAsync(stream, file.FileName, file.ContentType);
|
||||
entity.Images.Add(new ProductImage { Url = url, IsMainImage = false });
|
||||
}
|
||||
}
|
||||
|
||||
// DisplayOrder neu berechnen
|
||||
int displayOrder = 1;
|
||||
var orderedImages = entity.Images.OrderByDescending(i => i.IsMainImage).ThenBy(i => i.CreatedDate).ToList();
|
||||
orderedImages.ForEach(i => i.DisplayOrder = displayOrder++);
|
||||
}
|
||||
|
||||
private void UpdateProductCategories(UpdateAdminProductDto dto, Product entity)
|
||||
{
|
||||
entity.Productcategories.Clear();
|
||||
if (dto.CategorieIds != null)
|
||||
{
|
||||
foreach (var categoryId in dto.CategorieIds)
|
||||
{
|
||||
entity.Productcategories.Add(new Productcategorie { categorieId = categoryId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ServiceResult> DeleteAdminProductAsync(Guid id)
|
||||
|
||||
Reference in New Issue
Block a user