feat: add product validation in recipe update and creation; throw BadRequestException for inactive products
Test Suite / test (24.15.0) (push) Has been cancelled
Test Suite / test (24.15.0) (push) Has been cancelled
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { ForbiddenException, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
import { BadRequestException, ForbiddenException, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import * as fs from 'node:fs/promises';
|
import * as fs from 'node:fs/promises';
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
@@ -21,6 +21,21 @@ export class RecipesService {
|
|||||||
throw new NotFoundException(`Recipe with id ${id} not found`);
|
throw new NotFoundException(`Recipe with id ${id} not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async assertProductsActive(productIds: number[]): Promise<void> {
|
||||||
|
if (productIds.length === 0) return;
|
||||||
|
const activeProducts = await this.prisma.product.findMany({
|
||||||
|
where: { id: { in: productIds }, isActive: true },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
if (activeProducts.length !== productIds.length) {
|
||||||
|
const foundIds = new Set(activeProducts.map((p) => p.id));
|
||||||
|
const missing = productIds.filter((id) => !foundIds.has(id));
|
||||||
|
throw new BadRequestException(
|
||||||
|
`En eller flera ingrediensprodukter är inaktiva eller finns inte: ${missing.join(', ')}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async findRecipeByIdOrThrow(id: number) {
|
private async findRecipeByIdOrThrow(id: number) {
|
||||||
const recipe = await this.prisma.recipe.findUnique({ where: { id } });
|
const recipe = await this.prisma.recipe.findUnique({ where: { id } });
|
||||||
if (!recipe) {
|
if (!recipe) {
|
||||||
@@ -232,6 +247,9 @@ export class RecipesService {
|
|||||||
const existingRecipe = await this.findRecipeByIdOrThrow(id);
|
const existingRecipe = await this.findRecipeByIdOrThrow(id);
|
||||||
this.assertRecipeEditableByUser(existingRecipe, userId, id);
|
this.assertRecipeEditableByUser(existingRecipe, userId, id);
|
||||||
|
|
||||||
|
// Validera att alla produkter är aktiva
|
||||||
|
await this.assertProductsActive(updateRecipeDto.ingredients.map((i) => i.productId));
|
||||||
|
|
||||||
// Ta bort gamla ingredienser
|
// Ta bort gamla ingredienser
|
||||||
await this.prisma.recipeIngredient.deleteMany({
|
await this.prisma.recipeIngredient.deleteMany({
|
||||||
where: { recipeId: id },
|
where: { recipeId: id },
|
||||||
@@ -379,6 +397,9 @@ export class RecipesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async create(createRecipeDto: CreateRecipeDto, userId: number) {
|
async create(createRecipeDto: CreateRecipeDto, userId: number) {
|
||||||
|
// Validera att alla produkter är aktiva
|
||||||
|
await this.assertProductsActive(createRecipeDto.ingredients.map((i) => i.productId));
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`[create] Incoming imageUrl from client: ${createRecipeDto.imageUrl ?? 'null'}`,
|
`[create] Incoming imageUrl from client: ${createRecipeDto.imageUrl ?? 'null'}`,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user