implement update recipe - does not create new ingredient groups, incredients or instruction steps yet
This commit is contained in:
parent
21742e3b24
commit
e33dfdb845
3 changed files with 152 additions and 1 deletions
117
bruno/recipe-backend/updateRecipe.bru
Normal file
117
bruno/recipe-backend/updateRecipe.bru
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
meta {
|
||||
name: updateRecipe
|
||||
type: http
|
||||
seq: 7
|
||||
}
|
||||
|
||||
put {
|
||||
url: http://localhost:4000/recipe/44a8f38c-9387-439e-aed6-c3369b776b1c
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImE0NDdlNDM0LTQyMWYtNDJiYS04MGRlLTM0ZDE1YzJmNWE2YyIsImlhdCI6MTc1OTA3NjA2NCwiZXhwIjoxNzU5MTYyNDY0fQ.exf_3fCrarW0LhUqPuadvp89BOUazEXtdSTkGDIAU_Q
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"id": "44a8f38c-9387-439e-aed6-c3369b776b1c",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"title": "Apfelkuchen Edeltrud",
|
||||
"amount": 1,
|
||||
"amountDescription": "Kuchen (26cm Durchmesser)",
|
||||
"instructions": [
|
||||
{
|
||||
"id": "9042d658-0102-4e63-8637-a82c5653aa9d",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"text": "Mürbteig von 400 g Mehl herstellen",
|
||||
"sortOrder": 1
|
||||
},
|
||||
{
|
||||
"id": "42f834f1-54d1-4149-ad2e-e6565add719b",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"text": "Äpfel schälen und kleinschneiden.",
|
||||
"sortOrder": 2
|
||||
},
|
||||
{
|
||||
"id": "a45ad765-f775-4969-ad36-ca2d5645a2fc",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"text": "Restlichen Teig ausrollen, Kuchen damit abdecken und mit Milch bepinseln.",
|
||||
"sortOrder": 4
|
||||
},
|
||||
{
|
||||
"id": "a45ad765-f775-4969-ad36-ca2d5645a2fc",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"text": "Springform fetten, zwei Drittel des Teigs hineindrücken, Äpfel mit Rosinen vermischen und einfüllen.",
|
||||
"sortOrder": 3
|
||||
},
|
||||
{
|
||||
"id": "e0435853-b1b9-46cb-b53f-f5345ffca729",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"text": "Backen",
|
||||
"sortOrder": 5
|
||||
}
|
||||
],
|
||||
"ingredientGroups": [
|
||||
{
|
||||
"id": "680b885a-6670-4982-b257-336a0b4c09ee",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"title": "Für den Teig",
|
||||
"sortOrder": 1,
|
||||
"ingredients": [
|
||||
{
|
||||
"id": "d216f7f5-3e16-46f2-914f-af012ded9623",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"amount": 400,
|
||||
"name": "Mehl",
|
||||
"unit": "g",
|
||||
"sortOrder": 1,
|
||||
"subtext": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ae6d32f4-a383-436b-8b9e-f693d74c955e",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"title": "Für die Füllung",
|
||||
"sortOrder": 2,
|
||||
"ingredients": [
|
||||
{
|
||||
"id": "9221faa8-a923-4c97-bb92-6d2dd7e94afc",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"amount": 5,
|
||||
"name": "große Äpfel",
|
||||
"unit": null,
|
||||
"sortOrder": 1,
|
||||
"subtext": null
|
||||
},
|
||||
{
|
||||
"id": "7f3264d3-a002-40a7-92e2-4b3d02ea8bfd",
|
||||
"createdAt": "2025-09-28T10:24:05.429Z",
|
||||
"updatedAt": "2025-09-28T10:24:05.429Z",
|
||||
"amount": 100,
|
||||
"name": "Rosinen",
|
||||
"unit": "g",
|
||||
"sortOrder": 2,
|
||||
"subtext": null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import { NotFoundError, ValidationError } from "../errors/httpErrors.js";
|
|||
import { RecipeInstructionStepDto } from "../dtos/RecipeInstructionStepDto.js";
|
||||
import { RecipeIngredientGroupDto } from "../dtos/RecipeIngredientGroupDto.js";
|
||||
import { RecipeIngredientDto } from "../dtos/RecipeIngredientDto.js";
|
||||
import { Entity } from "typeorm";
|
||||
|
||||
/**
|
||||
* Controls all recipe specific actions
|
||||
|
|
@ -15,6 +16,11 @@ export class RecipeController {
|
|||
private mapper: RecipeDtoEntityMapper
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Load a specific recipe
|
||||
* @param id recipe id
|
||||
* @returns RecipeDto for requested recipe
|
||||
*/
|
||||
async getRecipeById(id: string){
|
||||
const recipeEntity = await this.recipeRepository.findById(id);
|
||||
if(recipeEntity === null){
|
||||
|
|
@ -23,6 +29,20 @@ export class RecipeController {
|
|||
const recipeDto = this.mapper.toDto(recipeEntity);
|
||||
return recipeDto;
|
||||
}
|
||||
/**
|
||||
* Update recipe data
|
||||
* @param RecipeDto containing the entire updated recipe
|
||||
* @returns Up-to-date RecipeDto as saved in the database
|
||||
*/
|
||||
async updateRecipe(dto: RecipeDto){
|
||||
if (!this.isRecipeDtoValid(dto)) {
|
||||
throw new ValidationError("recipe data is not valid!")
|
||||
}
|
||||
const recipeEntity = this.mapper.toEntity(dto);
|
||||
// @todo doesn't create new ingredient groups, ingredients or instruction steps yet
|
||||
const savedEntity = await this.recipeRepository.save(recipeEntity);
|
||||
return this.mapper.toDto(savedEntity);
|
||||
}
|
||||
/**
|
||||
* Create a new recipe
|
||||
* @param dto RecipeDto containing the new recipe
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { RecipeDto } from "../dtos/RecipeDto.js";
|
|||
import { RecipeIngredientDtoEntityMapper } from "../mappers/RecipeIngredientDtoEntityMapper.js";
|
||||
import { RecipeIngredientGroupDtoEntityMapper } from "../mappers/RecipeIngredientGroupDtoEntityMapper.js";
|
||||
import { RecipeInstructionStepDtoEntityMapper } from "../mappers/RecipeInstructionStepDtoEntityMapper.js";
|
||||
import { ValidationError } from "../errors/httpErrors.js";
|
||||
|
||||
/**
|
||||
* Handles all recipe related routes
|
||||
|
|
@ -40,6 +41,19 @@ router.get(
|
|||
const responseDto = await recipeController.getRecipeById(id);
|
||||
res.status(201).json(responseDto);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
router.put(
|
||||
"/:id",
|
||||
asyncHandler(async(req, res) =>{
|
||||
const id = req.params.id;
|
||||
const recipeDto : RecipeDto = req.body;
|
||||
if(id != recipeDto.id){
|
||||
throw new ValidationError("Cannot save recipe! ID in request body " + recipeDto.id + " doesn't match ID in path " + id +"!")
|
||||
}
|
||||
const responseDto = await recipeController.updateRecipe(recipeDto);
|
||||
res.status(201).json(responseDto);
|
||||
})
|
||||
);
|
||||
|
||||
export default router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue