feat(meal-plan): add servings field to MealPlanEntry and update related functionality
feat(products): implement bulk update for product categories feat(recipes): add servings input to WriteRecipePage and update MealPlanClient for servings management refactor(types): enhance Product and Category types with additional properties
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { IsDateString, IsInt, IsPositive } from 'class-validator';
|
||||
import { IsDateString, IsInt, IsOptional, IsPositive, Min } from 'class-validator';
|
||||
|
||||
export class CreateMealPlanEntryDto {
|
||||
@IsDateString()
|
||||
@@ -7,4 +7,9 @@ export class CreateMealPlanEntryDto {
|
||||
@IsInt()
|
||||
@IsPositive()
|
||||
recipeId: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
servings?: number;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ const recipeSelect = {
|
||||
id: true,
|
||||
name: true,
|
||||
imageUrl: true,
|
||||
servings: true,
|
||||
ingredients: {
|
||||
select: {
|
||||
quantity: true,
|
||||
@@ -36,8 +37,8 @@ export class MealPlanService {
|
||||
const date = new Date(dto.date);
|
||||
return this.prisma.mealPlanEntry.upsert({
|
||||
where: { date },
|
||||
create: { date, recipeId: dto.recipeId },
|
||||
update: { recipeId: dto.recipeId },
|
||||
create: { date, recipeId: dto.recipeId, servings: dto.servings ?? null },
|
||||
update: { recipeId: dto.recipeId, servings: dto.servings ?? null },
|
||||
include: { recipe: { select: recipeSelect } },
|
||||
});
|
||||
}
|
||||
@@ -55,13 +56,16 @@ export class MealPlanService {
|
||||
async shoppingList(from: string, to: string) {
|
||||
const entries = await this.findByRange(from, to);
|
||||
|
||||
// Summera ingredienser per produkt+enhet
|
||||
// Summera ingredienser per produkt+enhet (skalat per portionsantal)
|
||||
const map = new Map<string, { productId: number; name: string; quantity: number; unit: string }>();
|
||||
for (const entry of entries) {
|
||||
const recipeServings = (entry.recipe as any).servings as number | null;
|
||||
const entryServings = (entry as any).servings as number | null;
|
||||
const scale = recipeServings && entryServings ? entryServings / recipeServings : 1;
|
||||
for (const ing of entry.recipe.ingredients) {
|
||||
const key = `${ing.product.id}-${ing.unit}`;
|
||||
const existing = map.get(key);
|
||||
const qty = Number(ing.quantity);
|
||||
const qty = Number(ing.quantity) * scale;
|
||||
if (existing) {
|
||||
existing.quantity += qty;
|
||||
} else {
|
||||
@@ -82,12 +86,15 @@ export class MealPlanService {
|
||||
async inventoryCompare(from: string, to: string) {
|
||||
const entries = await this.findByRange(from, to);
|
||||
|
||||
// Aggregera ingredienser per produkt+enhet
|
||||
// Aggregera ingredienser per produkt+enhet (skalat per portionsantal)
|
||||
const map = new Map<string, { productId: number; name: string; required: number; unit: string }>();
|
||||
for (const entry of entries) {
|
||||
const recipeServings = (entry.recipe as any).servings as number | null;
|
||||
const entryServings = (entry as any).servings as number | null;
|
||||
const scale = recipeServings && entryServings ? entryServings / recipeServings : 1;
|
||||
for (const ing of entry.recipe.ingredients) {
|
||||
const key = `${ing.product.id}-${ing.unit}`;
|
||||
const qty = Number(ing.quantity);
|
||||
const qty = Number(ing.quantity) * scale;
|
||||
const existing = map.get(key);
|
||||
if (existing) {
|
||||
existing.required += qty;
|
||||
|
||||
Reference in New Issue
Block a user