375 lines
11 KiB
C#
375 lines
11 KiB
C#
// Nya versionen av MenuService med Entity Framework
|
||
using Aberwyn.Models;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using SixLabors.ImageSharp;
|
||
using SixLabors.ImageSharp.Formats.Webp;
|
||
using SixLabors.ImageSharp.Processing;
|
||
using System.Globalization;
|
||
using static Aberwyn.Data.SetupService;
|
||
|
||
namespace Aberwyn.Data
|
||
{
|
||
public class MenuService
|
||
{
|
||
private readonly ApplicationDbContext _context;
|
||
|
||
// Detta är DI-konstruktorn – används som vanligt i controllers
|
||
public MenuService(ApplicationDbContext context)
|
||
{
|
||
_context = context;
|
||
}
|
||
|
||
public static MenuService CreateWithSetup(IHostEnvironment env)
|
||
{
|
||
var setup = SetupLoader.Load(env);
|
||
var connStr = SetupLoader.GetConnectionString(setup);
|
||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||
builder.UseMySql(connStr, ServerVersion.AutoDetect(connStr));
|
||
var context = new ApplicationDbContext(builder.Options);
|
||
return new MenuService(context);
|
||
}
|
||
|
||
public List<WeeklyMenuDto> GetWeeklyMenuDto(int weekNumber, int year)
|
||
{
|
||
var query = from wm in _context.WeeklyMenus
|
||
where wm.WeekNumber == weekNumber && wm.Year == year
|
||
join mDinner in _context.Meals on wm.DinnerMealId equals mDinner.Id into dinnerJoin
|
||
from mDinner in dinnerJoin.DefaultIfEmpty()
|
||
join mLunch in _context.Meals on wm.LunchMealId equals mLunch.Id into lunchJoin
|
||
from mLunch in lunchJoin.DefaultIfEmpty()
|
||
join mBreakfast in _context.Meals on wm.BreakfastMealId equals mBreakfast.Id into breakfastJoin
|
||
from mBreakfast in breakfastJoin.DefaultIfEmpty()
|
||
select new WeeklyMenuDto
|
||
{
|
||
Id = wm.Id,
|
||
DayOfWeek = wm.DayOfWeek,
|
||
WeekNumber = wm.WeekNumber,
|
||
Year = wm.Year,
|
||
BreakfastMealId = wm.BreakfastMealId,
|
||
LunchMealId = wm.LunchMealId,
|
||
DinnerMealId = wm.DinnerMealId,
|
||
BreakfastMealName = mBreakfast.Name,
|
||
LunchMealName = mLunch.Name,
|
||
DinnerMealName = mDinner.Name,
|
||
DinnerMealThumbnail = mDinner.ThumbnailData
|
||
};
|
||
|
||
return query.ToList();
|
||
}
|
||
|
||
|
||
|
||
|
||
public void UpdateWeeklyMenu(MenuViewModel model)
|
||
{
|
||
var existing = _context.WeeklyMenus
|
||
.Where(w => w.WeekNumber == model.WeekNumber && w.Year == model.Year)
|
||
.ToList();
|
||
|
||
_context.WeeklyMenus.RemoveRange(existing);
|
||
_context.WeeklyMenus.AddRange(model.WeeklyMenus);
|
||
_context.SaveChanges();
|
||
}
|
||
public int AddMeal(Meal meal)
|
||
{
|
||
SaveMeal(meal);
|
||
return meal.Id;
|
||
}
|
||
|
||
|
||
public void SaveMeal2(Meal meal)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(meal?.Name)) return;
|
||
|
||
meal.Name = meal.Name.Trim();
|
||
meal.CreatedAt = meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt;
|
||
|
||
var existing = _context.Meals
|
||
.AsNoTracking()
|
||
.FirstOrDefault(m => m.Id == meal.Id);
|
||
|
||
if (existing == null)
|
||
{
|
||
// Nytt objekt – försök behålla ID:t från prod
|
||
_context.Entry(meal).State = EntityState.Added;
|
||
}
|
||
else
|
||
{
|
||
// Befintlig – uppdatera
|
||
_context.Meals.Update(meal);
|
||
}
|
||
|
||
_context.SaveChanges();
|
||
}
|
||
|
||
public void SaveMeal(Meal meal)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(meal?.Name)) return;
|
||
|
||
meal.Name = meal.Name.Trim();
|
||
meal.CreatedAt = meal.CreatedAt == default ? DateTime.Now : meal.CreatedAt;
|
||
|
||
if (meal.Id == 0)
|
||
{
|
||
// Ny måltid
|
||
_context.Meals.Add(meal);
|
||
}
|
||
else
|
||
{
|
||
// Uppdatera existerande utan tracking-krockar
|
||
var existing = _context.Meals
|
||
.Include(m => m.Ingredients)
|
||
.FirstOrDefault(m => m.Id == meal.Id);
|
||
|
||
if (existing != null)
|
||
{
|
||
_context.Entry(existing).CurrentValues.SetValues(meal);
|
||
|
||
// OBS: Ingredienser hanteras separat
|
||
}
|
||
}
|
||
|
||
_context.SaveChanges();
|
||
}
|
||
|
||
|
||
public int GenerateMissingThumbnails()
|
||
{
|
||
var updatedCount = 0;
|
||
var meals = _context.Meals
|
||
.Where(m => m.ImageData != null && m.ThumbnailData == null)
|
||
.ToList();
|
||
|
||
foreach (var meal in meals)
|
||
{
|
||
using var ms = new MemoryStream(meal.ImageData);
|
||
using var image = Image.Load(ms);
|
||
|
||
image.Mutate(x => x.Resize(new ResizeOptions
|
||
{
|
||
Mode = ResizeMode.Max,
|
||
Size = new Size(300, 300)
|
||
}));
|
||
|
||
using var outStream = new MemoryStream();
|
||
var encoder = new WebpEncoder
|
||
{
|
||
Quality = 75
|
||
};
|
||
image.Save(outStream, encoder);
|
||
|
||
meal.ThumbnailData = outStream.ToArray();
|
||
updatedCount++;
|
||
}
|
||
|
||
_context.SaveChanges();
|
||
return updatedCount;
|
||
}
|
||
public List<Meal> GetMealsSlim(bool includeThumbnail = false)
|
||
{
|
||
if (includeThumbnail)
|
||
{
|
||
return _context.Meals
|
||
.Select(m => new Meal
|
||
{
|
||
Id = m.Id,
|
||
Name = m.Name,
|
||
Description = m.Description,
|
||
ThumbnailData = m.ThumbnailData
|
||
})
|
||
.ToList();
|
||
}
|
||
else
|
||
{
|
||
return _context.Meals
|
||
.Select(m => new Meal
|
||
{
|
||
Id = m.Id,
|
||
Name = m.Name,
|
||
Description = m.Description
|
||
})
|
||
.ToList();
|
||
}
|
||
}
|
||
|
||
public List<WeeklyMenu> GetAllWeeklyMenus()
|
||
{
|
||
var menus = _context.WeeklyMenus.ToList();
|
||
|
||
var allMeals = _context.Meals.ToDictionary(m => m.Id, m => m.Name);
|
||
|
||
foreach (var wm in menus)
|
||
{
|
||
wm.BreakfastMealName = wm.BreakfastMealId.HasValue && allMeals.TryGetValue(wm.BreakfastMealId.Value, out var breakfast)
|
||
? breakfast
|
||
: null;
|
||
|
||
wm.LunchMealName = wm.LunchMealId.HasValue && allMeals.TryGetValue(wm.LunchMealId.Value, out var lunch)
|
||
? lunch
|
||
: null;
|
||
|
||
wm.DinnerMealName = wm.DinnerMealId.HasValue && allMeals.TryGetValue(wm.DinnerMealId.Value, out var dinner)
|
||
? dinner
|
||
: null;
|
||
}
|
||
|
||
return menus;
|
||
}
|
||
|
||
|
||
public List<Ingredient> GetIngredientsForMeal(int mealId)
|
||
{
|
||
return _context.Ingredients
|
||
.Where(i => i.MealId == mealId)
|
||
.ToList();
|
||
}
|
||
|
||
public void SaveIngredients(int mealId, List<Ingredient> ingredients)
|
||
{
|
||
var existing = _context.Ingredients.Where(i => i.MealId == mealId);
|
||
_context.Ingredients.RemoveRange(existing);
|
||
|
||
foreach (var ing in ingredients)
|
||
{
|
||
ing.MealId = mealId;
|
||
}
|
||
|
||
_context.Ingredients.AddRange(ingredients);
|
||
_context.SaveChanges();
|
||
}
|
||
|
||
|
||
public List<Meal> GetMeals()
|
||
{
|
||
return _context.Meals.ToList();
|
||
}
|
||
|
||
public List<Meal> GetMealsDetailed()
|
||
{
|
||
return _context.Meals
|
||
.Include(m => m.Ingredients) // 🧠 detta behövs!
|
||
.OrderByDescending(m => m.CreatedAt)
|
||
.ToList();
|
||
}
|
||
|
||
|
||
public Meal GetMealById(int id)
|
||
{
|
||
var meal = _context.Meals
|
||
.Include(m => m.Ingredients)
|
||
.FirstOrDefault(m => m.Id == id);
|
||
return meal;
|
||
}
|
||
|
||
public void DeleteMeal(int id)
|
||
{
|
||
var meal = _context.Meals.Find(id);
|
||
if (meal != null)
|
||
{
|
||
_context.Meals.Remove(meal);
|
||
_context.SaveChanges();
|
||
}
|
||
}
|
||
|
||
public void SaveOrUpdateMeal(Meal meal)
|
||
{
|
||
SaveMeal(meal);
|
||
}
|
||
|
||
public void SaveOrUpdateMealWithIngredients(Meal meal)
|
||
{
|
||
var isNew = meal.Id == 0;
|
||
|
||
SaveMeal(meal);
|
||
|
||
if (meal.Ingredients != null && meal.Ingredients.Count > 0)
|
||
{
|
||
SaveIngredients(meal.Id, meal.Ingredients);
|
||
}
|
||
}
|
||
|
||
|
||
public List<Meal> GetMealsByCategory(string category)
|
||
{
|
||
return _context.Meals
|
||
.Where(m => m.Category == category)
|
||
.Include(m => m.Ingredients)
|
||
.OrderBy(m => m.Name)
|
||
.ToList();
|
||
}
|
||
public List<WeeklyMenu> GetWeeklyMenu(int weekNumber, int year)
|
||
{
|
||
var menus = _context.WeeklyMenus
|
||
.Where(m => m.WeekNumber == weekNumber && m.Year == year)
|
||
.ToList();
|
||
|
||
var mealIds = menus
|
||
.SelectMany(w => new int?[] { w.BreakfastMealId, w.LunchMealId, w.DinnerMealId })
|
||
.Where(id => id.HasValue)
|
||
.Select(id => id.Value)
|
||
.Distinct()
|
||
.ToList();
|
||
|
||
var allMeals = _context.Meals
|
||
.Where(m => mealIds.Contains(m.Id))
|
||
.Select(m => new {
|
||
m.Id,
|
||
m.Name,
|
||
m.ThumbnailData // Vi tar med detta även om det bara används för middag
|
||
})
|
||
.ToList()
|
||
.ToDictionary(m => m.Id, m => m);
|
||
|
||
|
||
foreach (var wm in menus)
|
||
{
|
||
if (wm.BreakfastMealId.HasValue && allMeals.TryGetValue(wm.BreakfastMealId.Value, out var breakfast))
|
||
wm.BreakfastMealName = breakfast.Name;
|
||
|
||
if (wm.LunchMealId.HasValue && allMeals.TryGetValue(wm.LunchMealId.Value, out var lunch))
|
||
wm.LunchMealName = lunch.Name;
|
||
|
||
if (wm.DinnerMealId.HasValue && allMeals.TryGetValue(wm.DinnerMealId.Value, out var dinner))
|
||
{
|
||
wm.DinnerMealName = dinner.Name;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
return menus;
|
||
}
|
||
|
||
public List<WeeklyMenu> GetMenuEntriesByDateRange(DateTime startDate, DateTime endDate)
|
||
{
|
||
var results = new List<WeeklyMenu>();
|
||
int startWeek = ISOWeek.GetWeekOfYear(startDate);
|
||
int endWeek = ISOWeek.GetWeekOfYear(endDate);
|
||
int startYear = startDate.Year;
|
||
int endYear = endDate.Year;
|
||
|
||
for (int y = startYear; y <= endYear; y++)
|
||
{
|
||
int fromWeek = y == startYear ? startWeek : 1;
|
||
int toWeek = y == endYear ? endWeek : ISOWeek.GetWeeksInYear(y);
|
||
|
||
for (int w = fromWeek; w <= toWeek; w++)
|
||
{
|
||
var menus = GetWeeklyMenu(w, y);
|
||
foreach (var menu in menus)
|
||
{
|
||
var dow = (DayOfWeek)(menu.DayOfWeek % 7);
|
||
var date = ISOWeek.ToDateTime(menu.Year, menu.WeekNumber, dow);
|
||
if (date.Date >= startDate.Date && date.Date <= endDate.Date)
|
||
{
|
||
menu.CreatedAt = date;
|
||
results.Add(menu);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return results;
|
||
}
|
||
}
|
||
}
|