feat: add functionality to manually add ingredients; implement CreateIngredientDto and update RecipesController and RecipesService
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-05 13:38:23 +02:00
parent dba3c63ec4
commit 3ea5a4778f
4 changed files with 246 additions and 0 deletions
@@ -0,0 +1,16 @@
import { IsString, IsNumber, IsOptional } from 'class-validator';
export class CreateIngredientDto {
@IsNumber()
productId: number;
@IsNumber()
quantity: number;
@IsString()
unit: string;
@IsOptional()
@IsString()
note?: string;
}
+10
View File
@@ -2,6 +2,7 @@ import { Body, Controller, Delete, Get, HttpCode, Param, ParseIntPipe, Post, Pat
import { IsString } from 'class-validator';
import { RecipesService } from './recipes.service';
import { CreateRecipeDto } from './dto/create-recipe.dto';
import { CreateIngredientDto } from './dto/create-ingredient.dto';
import { ParseMarkdownDto } from './dto/parse-markdown.dto';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import { ShareRecipeDto } from './dto/share-recipe.dto';
@@ -77,6 +78,15 @@ export class RecipesController {
return this.recipesService.updateImage(id, dto.sourceUrl, user.userId);
}
@Post(':id/ingredients')
async addIngredient(
@Param('id', ParseIntPipe) id: number,
@Body() ingredient: CreateIngredientDto,
@CurrentUser() user: { userId: number },
) {
return this.recipesService.addIngredient(id, ingredient, user.userId);
}
@Patch(':id/visibility')
async setVisibility(
@Param('id', ParseIntPipe) id: number,
+20
View File
@@ -4,6 +4,7 @@ import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import { PrismaService } from '../prisma/prisma.service';
import { CreateRecipeDto } from './dto/create-recipe.dto';
import { CreateIngredientDto } from './dto/create-ingredient.dto';
import { ParseMarkdownDto } from './dto/parse-markdown.dto';
import { downloadAndOptimizeImage } from '../common/utils/download-image';
import { parseRecipeMarkdown, ParsedRecipe, ParsedIngredient } from '../common/utils/recipe-parser';
@@ -475,6 +476,25 @@ export class RecipesService {
}
}
async addIngredient(id: number, ingredient: CreateIngredientDto, userId: number) {
const recipe = await this.findRecipeByIdOrThrow(id);
await this.assertRecipeOwnedByUser(recipe, userId, id);
await this.assertProductsActive([ingredient.productId]);
return this.prisma.recipeIngredient.create({
data: {
productId: ingredient.productId,
quantity: ingredient.quantity,
unit: ingredient.unit,
note: ingredient.note || null,
recipeId: id,
},
include: {
product: { include: { nutrition: true } },
},
});
}
async parseMarkdown(dto: ParseMarkdownDto) {
// Delegera markdown-parsning till microservice-importer
const importerUrl = process.env.IMPORTER_SERVICE_URL || 'http://importer-api:3001';