change some logic to the repositories
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Category
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Category;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public class CategoryRepository : ICategoryRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
|
||||||
|
public CategoryRepository(FrancescosRecipesWorldDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Category> GetCategoryByIdAsync(Guid categoryId)
|
||||||
|
{
|
||||||
|
var category = await _context.Categories.FindAsync(categoryId);
|
||||||
|
return category ?? throw new InvalidDataException($"Category {categoryId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Category>> GetAllCategoriesAsync()
|
||||||
|
{
|
||||||
|
return await _context.Categories.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Recipe>> GetRecipesByCategoryAsync(Guid categoryId)
|
||||||
|
{
|
||||||
|
var category = await _context.Categories
|
||||||
|
.Include(c => c.Recipes)
|
||||||
|
.FirstOrDefaultAsync(c => c.Id == categoryId);
|
||||||
|
|
||||||
|
if (category == null)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException($"Category {categoryId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return category.Recipes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Category
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Category;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
|
||||||
|
public interface ICategoryRepository
|
||||||
|
{
|
||||||
|
Task<Category> GetCategoryByIdAsync(Guid categoryId);
|
||||||
|
|
||||||
|
Task<IEnumerable<Category>> GetAllCategoriesAsync();
|
||||||
|
|
||||||
|
Task<IEnumerable<Recipe>> GetRecipesByCategoryAsync(Guid categoryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Ingredient
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Ingredient;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.RecipeIngredient;
|
||||||
|
|
||||||
|
public interface IIngredientRepository
|
||||||
|
{
|
||||||
|
Task<Ingredient> CreateIngredientToRecipeAsync(Recipe recipe, string ingredientName);
|
||||||
|
|
||||||
|
Task UpdateIngredientAsync(Ingredient ingredient);
|
||||||
|
|
||||||
|
Task<List<RecipeIngredient>> GetIngredientsByRecipeIdAsync(Guid recipeId);
|
||||||
|
|
||||||
|
Task<List<Ingredient>> GetIngredientsByNameAsync(string name);
|
||||||
|
|
||||||
|
Task RemoveIngredientFromRecipeAsync(Recipe recipe, Guid ingredientId);
|
||||||
|
|
||||||
|
Task<Ingredient> GetIngredientByIdAsync(Guid ingredientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Ingredient
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Ingredient;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.RecipeIngredient;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public class IngredientRepository : IIngredientRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
|
||||||
|
public IngredientRepository(
|
||||||
|
FrancescosRecipesWorldDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Ingredient> CreateIngredientToRecipeAsync(Recipe recipe, string ingredientName)
|
||||||
|
{
|
||||||
|
if (recipe is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Recipe not found", nameof(recipe));
|
||||||
|
}
|
||||||
|
|
||||||
|
var newIngredient = new Ingredient
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Name = ingredientName,
|
||||||
|
};
|
||||||
|
|
||||||
|
var recipeIngredient = new RecipeIngredient
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Recipe = recipe,
|
||||||
|
Ingredient = newIngredient,
|
||||||
|
Quantity = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Ingredients.Add(newIngredient);
|
||||||
|
_context.RecipeIngredients.Add(recipeIngredient);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return newIngredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveIngredientFromRecipeAsync(Recipe recipe, Guid ingredientId)
|
||||||
|
{
|
||||||
|
if (recipe == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(recipe));
|
||||||
|
}
|
||||||
|
|
||||||
|
var ingredientToRemove = recipe.RecipeIngredients.FirstOrDefault(i => i.Id == ingredientId);
|
||||||
|
|
||||||
|
if (ingredientToRemove != null)
|
||||||
|
{
|
||||||
|
recipe.RecipeIngredients.Remove(ingredientToRemove);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Ingredient>> GetIngredientsByNameAsync(string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
return await _context.Ingredients.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _context.Ingredients
|
||||||
|
.Where(i => i.Name.ToLower().Contains(name.ToLower()))
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<RecipeIngredient>> GetIngredientsByRecipeIdAsync(Guid recipeId)
|
||||||
|
{
|
||||||
|
return await _context.RecipeIngredients
|
||||||
|
.Include(ri => ri.Ingredient)
|
||||||
|
.Include(ri => ri.Unit)
|
||||||
|
.Where(ri => ri.Recipe.Id == recipeId)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateIngredientAsync(Ingredient ingredient)
|
||||||
|
{
|
||||||
|
if (ingredient == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(ingredient));
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingIngredient = await _context.Ingredients.FindAsync(ingredient.Id);
|
||||||
|
if (existingIngredient == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Ingredient with ID {ingredient.Id} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
existingIngredient.Name = ingredient.Name;
|
||||||
|
|
||||||
|
_context.Ingredients.Update(existingIngredient);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Ingredient> GetIngredientByIdAsync(Guid ingredientId)
|
||||||
|
{
|
||||||
|
var ingredient = await _context.Ingredients.FindAsync(ingredientId);
|
||||||
|
return ingredient ?? throw new InvalidDataException($"Address {ingredientId} not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Instruction
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Instruction;
|
||||||
|
|
||||||
|
public interface IInstructionRepository
|
||||||
|
{
|
||||||
|
Task<Instruction> GetInstructionAsync(Guid instructionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Instruction
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Instruction;
|
||||||
|
|
||||||
|
public class InstructionRepository : IInstructionRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
|
||||||
|
public InstructionRepository(FrancescosRecipesWorldDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Instruction> GetInstructionAsync(Guid instructionId)
|
||||||
|
{
|
||||||
|
var instruction = await _context.Instructions.FindAsync(instructionId);
|
||||||
|
return instruction ?? throw new InvalidDataException($"Instruction {instructionId} not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.MediaFile
|
||||||
|
{
|
||||||
|
public interface IMediaFileRepository
|
||||||
|
{
|
||||||
|
Task ReplaceInstructionImageAsync(Guid instructionId, IFormFile? newPhoto);
|
||||||
|
|
||||||
|
Task UploadInstructionImageAsync(Guid instructionId, IFormFile? photo);
|
||||||
|
|
||||||
|
Task ReplaceRecipeImageAsync(Guid recipeId, IFormFile? newPhoto);
|
||||||
|
|
||||||
|
Task UploadRecipeImageAsync(Guid recipeId, IFormFile? photo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.MediaFile
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.MediaFile;
|
||||||
|
using Francesco.Recipes.World.Repositories.Instruction;
|
||||||
|
using Francesco.Recipes.World.Repositories.Recipe;
|
||||||
|
|
||||||
|
public class MediaFileRepository : IMediaFileRepository
|
||||||
|
{
|
||||||
|
private readonly IInstructionRepository _instructionRepository;
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
private readonly IRecipeRepository _recipeRepository;
|
||||||
|
|
||||||
|
public MediaFileRepository(IInstructionRepository instructionRepository, FrancescosRecipesWorldDbContext context, IRecipeRepository recipeRepository)
|
||||||
|
{
|
||||||
|
_instructionRepository = instructionRepository;
|
||||||
|
_context = context;
|
||||||
|
_recipeRepository = recipeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ReplaceInstructionImageAsync(Guid instructionId, IFormFile? newPhoto)
|
||||||
|
{
|
||||||
|
if (newPhoto is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(newPhoto));
|
||||||
|
}
|
||||||
|
|
||||||
|
var instruction = await _instructionRepository.GetInstructionAsync(instructionId);
|
||||||
|
_context.RemoveRange(instruction.MediaFiles);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
await UploadInstructionImageAsync(instructionId, newPhoto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ReplaceRecipeImageAsync(Guid recipeId, IFormFile? newPhoto)
|
||||||
|
{
|
||||||
|
if (newPhoto is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(newPhoto));
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipe = await _recipeRepository.GetRecipeAsync(recipeId);
|
||||||
|
_context.RemoveRange(recipe.MediaFiles);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
await UploadInstructionImageAsync(recipeId, newPhoto);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UploadInstructionImageAsync(Guid instructionId, IFormFile? photo)
|
||||||
|
{
|
||||||
|
if (photo is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(photo));
|
||||||
|
}
|
||||||
|
|
||||||
|
var instruction = await _instructionRepository.GetInstructionAsync(instructionId);
|
||||||
|
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
await photo.CopyToAsync(memoryStream);
|
||||||
|
|
||||||
|
var instructionImage = new MediaFile
|
||||||
|
{
|
||||||
|
FileName = photo.FileName,
|
||||||
|
MimeType = photo.ContentType,
|
||||||
|
Data = memoryStream.ToArray(),
|
||||||
|
Instruction = instruction,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Add(instructionImage);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UploadRecipeImageAsync(Guid recipeId, IFormFile? photo)
|
||||||
|
{
|
||||||
|
if (photo is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(photo));
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipe = await _recipeRepository.GetRecipeAsync(recipeId);
|
||||||
|
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
await photo.CopyToAsync(memoryStream);
|
||||||
|
|
||||||
|
var recipeImage = new MediaFile
|
||||||
|
{
|
||||||
|
FileName = photo.FileName,
|
||||||
|
MimeType = photo.ContentType,
|
||||||
|
Data = memoryStream.ToArray(),
|
||||||
|
Recipe = recipe,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Add(recipeImage);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Recipe
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Category;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Unit;
|
||||||
|
|
||||||
|
public interface IRecipeRepository
|
||||||
|
{
|
||||||
|
Task<Recipe> GetRecipeAsync(Guid recipeId);
|
||||||
|
|
||||||
|
Task AddOrCreateIngredientToRecipeAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId);
|
||||||
|
|
||||||
|
Task RemoveIngredientFromRecipeAsync(Guid recipeId, Guid ingredientId);
|
||||||
|
|
||||||
|
Task<IEnumerable<Recipe>> GetRecipesByNameOrIngredientAsync(string name, string ingredient);
|
||||||
|
|
||||||
|
Task<IEnumerable<Recipe>> GetRecipesByDifficultyAsync(Difficulty difficulty);
|
||||||
|
|
||||||
|
Task<Unit> AddUnitToRecipeAsync(string name, string symbol);
|
||||||
|
|
||||||
|
Task<Recipe> CreateRecipeForCategoryAsync(Category category, string name, string description, Difficulty difficulty, int servings, TimeSpan preparationTime, TimeSpan cookingTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Recipe
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Category;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Ingredient;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.RecipeIngredient;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Unit;
|
||||||
|
using Francesco.Recipes.World.Repositories.Ingredient;
|
||||||
|
using Francesco.Recipes.World.Repositories.Unit;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public class RecipeRepository : IRecipeRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
private readonly IIngredientRepository _ingredientRepository;
|
||||||
|
private readonly IUnitRepository _unitRepository;
|
||||||
|
|
||||||
|
public RecipeRepository(
|
||||||
|
FrancescosRecipesWorldDbContext context, IIngredientRepository ingredientRepository, IUnitRepository unitRepository)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_ingredientRepository = ingredientRepository;
|
||||||
|
_unitRepository = unitRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Recipe> GetRecipeAsync(Guid recipeId)
|
||||||
|
{
|
||||||
|
var recipe = await _context.Recipes.FindAsync(recipeId);
|
||||||
|
return recipe ?? throw new InvalidDataException($"Address {recipeId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddOrCreateIngredientToRecipeAsync(Guid recipeId, string ingredientName, int quantity, Guid unitId)
|
||||||
|
{
|
||||||
|
var recipe = await GetRecipeAsync(recipeId);
|
||||||
|
var unit = await _unitRepository.GetUnitByIdAsync(unitId);
|
||||||
|
|
||||||
|
if (quantity <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(quantity), "Die Menge muss größer als 0 sein.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var ingredients = await _ingredientRepository.GetIngredientsByNameAsync(ingredientName);
|
||||||
|
Ingredient ingredient;
|
||||||
|
|
||||||
|
if (ingredients == null || !ingredients.Any())
|
||||||
|
{
|
||||||
|
ingredient = new Ingredient
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Name = ingredientName,
|
||||||
|
};
|
||||||
|
_context.Ingredients.Add(ingredient);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ingredient = ingredients.First();
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingEntry = await _context.RecipeIngredients
|
||||||
|
.FirstOrDefaultAsync(ri => ri.Recipe.Id == recipeId && ri.Ingredient.Id == ingredient.Id);
|
||||||
|
if (existingEntry != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Das Rezept enthält diese Zutat bereits.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipeIngredient = new RecipeIngredient
|
||||||
|
{
|
||||||
|
Recipe = recipe,
|
||||||
|
Ingredient = ingredient,
|
||||||
|
Unit = unit,
|
||||||
|
Quantity = quantity,
|
||||||
|
};
|
||||||
|
_context.Add(recipeIngredient);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Recipe> CreateRecipeForCategoryAsync(
|
||||||
|
Category category,
|
||||||
|
string name,
|
||||||
|
string description,
|
||||||
|
Difficulty difficulty,
|
||||||
|
int servings,
|
||||||
|
TimeSpan preparationTime,
|
||||||
|
TimeSpan cookingTime)
|
||||||
|
{
|
||||||
|
if (category == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(category), "Category cannot be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name), "Name cannot be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servings <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(servings), "Servings must be greater than 0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipe = new Recipe
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Name = name,
|
||||||
|
Description = description,
|
||||||
|
Difficulty = difficulty,
|
||||||
|
Servings = servings,
|
||||||
|
PreparationTime = preparationTime,
|
||||||
|
CookingTime = cookingTime,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
Category = category,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Recipes.Add(recipe);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return recipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveIngredientFromRecipeAsync(Guid recipeId, Guid ingredientId)
|
||||||
|
{
|
||||||
|
var recipe = await GetRecipeAsync(recipeId);
|
||||||
|
var recipeIngredient = await _context.RecipeIngredients
|
||||||
|
.FirstOrDefaultAsync(ri => ri.Recipe.Id == recipeId && ri.Ingredient.Id == ingredientId);
|
||||||
|
|
||||||
|
if (recipeIngredient == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Diese Zutat ist nicht mit dem Rezept verknüpft.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.RecipeIngredients.Remove(recipeIngredient);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Recipe>> GetRecipesByNameOrIngredientAsync(string name, string ingredient)
|
||||||
|
{
|
||||||
|
var query = _context.Recipes
|
||||||
|
.Include(r => r.RecipeIngredients)
|
||||||
|
.ThenInclude(ri => ri.Ingredient)
|
||||||
|
.AsQueryable();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
query = query.Where(r => r.Name.Contains(name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(ingredient))
|
||||||
|
{
|
||||||
|
var ingredientMatches = await _ingredientRepository.GetIngredientsByNameAsync(ingredient);
|
||||||
|
var ingredientIds = ingredientMatches.Select(i => i.Id).ToList();
|
||||||
|
|
||||||
|
if (ingredientIds.Any())
|
||||||
|
{
|
||||||
|
query = query.Where(r => r.RecipeIngredients.Any(ri => ingredientIds.Contains(ri.Ingredient.Id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await query.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Recipe>> GetRecipesByDifficultyAsync(Difficulty difficulty)
|
||||||
|
{
|
||||||
|
return await _context.Recipes
|
||||||
|
.Where(r => r.Difficulty == difficulty)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> AddUnitToRecipeAsync(string name, string symbol)
|
||||||
|
{
|
||||||
|
return await _unitRepository.AddUnitAsync(name, symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
namespace Francesco.Recipes.World.Repositories.ShoppingList
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Shoppinglist;
|
||||||
|
|
||||||
|
public interface IShoppingListRepository
|
||||||
|
{
|
||||||
|
Task AddIngredientToShoppingListAsync(Guid recipeIngredientId, Guid shoppingListId);
|
||||||
|
|
||||||
|
Task RemoveRecipeIngredientFromShoppingListAsync(Guid recipeIngredientId);
|
||||||
|
|
||||||
|
Task RemoveRecipeFromShoppingListIfEmptyAsync(Guid recipeId, Guid shoppingListId);
|
||||||
|
|
||||||
|
Task<IEnumerable<ShoppingList>> GetShoppingListsByIngredientOfRecipeAsync(Guid ingredientId, Guid recipeId);
|
||||||
|
|
||||||
|
Task<Recipe?> GetRecipeByNameAndImageAsync(string recipeName, string imageFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.ShoppingList
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.IngredientShoppingList;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Recipe;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Shoppinglist;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public class ShoppingListRepository : IShoppingListRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
|
||||||
|
public ShoppingListRepository(FrancescosRecipesWorldDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddIngredientToShoppingListAsync(Guid recipeIngredientId, Guid shoppingListId)
|
||||||
|
{
|
||||||
|
var existingEntry = await _context.RecipeIngredientsShoppingLists
|
||||||
|
.FirstOrDefaultAsync(risl => risl.RecipeIngredient.Id == recipeIngredientId && risl.ShoppingList.Id == shoppingListId);
|
||||||
|
|
||||||
|
if (existingEntry != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipeIngredient = await _context.RecipeIngredients
|
||||||
|
.FirstOrDefaultAsync(ri => ri.Id == recipeIngredientId);
|
||||||
|
|
||||||
|
if (recipeIngredient == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Recipe ingredient with ID {recipeIngredientId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var shoppingList = await _context.ShoppingLists
|
||||||
|
.FirstOrDefaultAsync(sl => sl.Id == shoppingListId);
|
||||||
|
|
||||||
|
if (shoppingList == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Shopping list with ID {shoppingListId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var newEntry = new RecipeIngredientShoppingList
|
||||||
|
{
|
||||||
|
RecipeIngredient = recipeIngredient,
|
||||||
|
ShoppingList = shoppingList,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.RecipeIngredientsShoppingLists.Add(newEntry);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveRecipeIngredientFromShoppingListAsync(Guid recipeIngredientId)
|
||||||
|
{
|
||||||
|
var entry = await _context.RecipeIngredientsShoppingLists
|
||||||
|
.FirstOrDefaultAsync(risl => risl.RecipeIngredient.Id == recipeIngredientId);
|
||||||
|
|
||||||
|
if (entry != null)
|
||||||
|
{
|
||||||
|
_context.RecipeIngredientsShoppingLists.Remove(entry);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveRecipeFromShoppingListIfEmptyAsync(Guid recipeId, Guid shoppingListId)
|
||||||
|
{
|
||||||
|
var hasIngredients = await _context.RecipeIngredientsShoppingLists
|
||||||
|
.AnyAsync(risl => risl.RecipeIngredient.Recipe.Id == recipeId && risl.ShoppingList.Id == shoppingListId);
|
||||||
|
|
||||||
|
if (!hasIngredients)
|
||||||
|
{
|
||||||
|
var shoppingList = await _context.ShoppingLists
|
||||||
|
.Include(sl => sl.RecipeIngredientShoppingLists)
|
||||||
|
.FirstOrDefaultAsync(sl => sl.Id == shoppingListId);
|
||||||
|
|
||||||
|
if (shoppingList != null)
|
||||||
|
{
|
||||||
|
var recipeToRemove = shoppingList.RecipeIngredientShoppingLists
|
||||||
|
.FirstOrDefault(risl => risl.RecipeIngredient.Recipe.Id == recipeId);
|
||||||
|
|
||||||
|
if (recipeToRemove != null)
|
||||||
|
{
|
||||||
|
_context.RecipeIngredientsShoppingLists.Remove(recipeToRemove);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<ShoppingList>> GetShoppingListsByIngredientOfRecipeAsync(Guid ingredientId, Guid recipeId)
|
||||||
|
{
|
||||||
|
return await _context.ShoppingLists
|
||||||
|
.Where(sl => sl.RecipeIngredientShoppingLists.Any(risl => risl.RecipeIngredient.Ingredient.Id == ingredientId && risl.RecipeIngredient.Recipe.Id == recipeId))
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Recipe?> GetRecipeByNameAndImageAsync(string recipeName, string imageFileName)
|
||||||
|
{
|
||||||
|
return await _context.Recipes
|
||||||
|
.Where(r => r.Name == recipeName && r.MediaFiles.Any(mf => mf.FileName == imageFileName))
|
||||||
|
.Include(r => r.MediaFiles.Where(mf => mf.FileName == imageFileName))
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Unit
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Unit;
|
||||||
|
|
||||||
|
public interface IUnitRepository
|
||||||
|
{
|
||||||
|
Task<Unit> GetUnitByIdAsync(Guid unitId);
|
||||||
|
|
||||||
|
Task<Unit> AddUnitAsync(string name, string symbol);
|
||||||
|
|
||||||
|
Task<IEnumerable<Unit>> GetAllUnitsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
namespace Francesco.Recipes.World.Repositories.Unit
|
||||||
|
{
|
||||||
|
using Francesco.Recipes.World.Data;
|
||||||
|
using Francesco.Recipes.World.Models.BackendModels.Unit;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
public class UnitRepository : IUnitRepository
|
||||||
|
{
|
||||||
|
private readonly FrancescosRecipesWorldDbContext _context;
|
||||||
|
|
||||||
|
public UnitRepository(
|
||||||
|
FrancescosRecipesWorldDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> GetUnitByIdAsync(Guid unitId)
|
||||||
|
{
|
||||||
|
var unit = await _context.Units.FindAsync(unitId);
|
||||||
|
return unit ?? throw new InvalidDataException($"Address {unitId} not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Unit> AddUnitAsync(string name, string symbol)
|
||||||
|
{
|
||||||
|
var unit = new Unit
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Name = name,
|
||||||
|
Symbol = symbol,
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Units.Add(unit);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Unit>> GetAllUnitsAsync()
|
||||||
|
{
|
||||||
|
return await _context.Units.ToListAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user