refactor(categories): move mutations into use cases

This commit is contained in:
2026-06-04 22:12:06 +02:00
parent 0af25417ab
commit f48ccb8c50
7 changed files with 183 additions and 80 deletions
+120
View File
@@ -0,0 +1,120 @@
import { Prisma } from "@/generated/prisma/client"
import prisma from "@/lib/prisma"
import type {
CreateCategoryFormType,
UpdateCategoryFormType,
} from "@/schemas/category.schema"
import { CategoryService } from "@/services/category.service"
type FieldErrors = Record<string, string[]>
type CategoryUseCaseResult =
| {
success: true
}
| {
success: false
errors: FieldErrors
}
function categoryError(errors: FieldErrors): CategoryUseCaseResult {
return {
success: false,
errors,
}
}
function isUniqueConstraintError(error: unknown) {
return (
error instanceof Prisma.PrismaClientKnownRequestError &&
error.code === "P2002"
)
}
export async function createCategoryUseCase(
input: CreateCategoryFormType,
): Promise<CategoryUseCaseResult> {
try {
return await prisma.$transaction(async (tx) => {
const existingCategory = await CategoryService.findByName(input.name, tx)
if (existingCategory) {
return categoryError({ name: ["Category already exists"] })
}
await CategoryService.create(input, tx)
return {
success: true,
}
})
} catch (error) {
if (isUniqueConstraintError(error)) {
return categoryError({ name: ["Category already exists"] })
}
throw error
}
}
export async function updateCategoryUseCase(
input: UpdateCategoryFormType,
): Promise<CategoryUseCaseResult> {
const { id, name } = input
try {
return await prisma.$transaction(async (tx) => {
const existingCategory = await CategoryService.findById(id, tx)
if (!existingCategory) {
return categoryError({ id: ["Category not found"] })
}
if (existingCategory.name === name) {
return categoryError({
name: ["Category name is the same as the old one"],
})
}
const categoryWithName = await CategoryService.findByName(name, tx)
if (categoryWithName) {
return categoryError({ name: ["Category already exists"] })
}
await CategoryService.update(id, { name }, tx)
return {
success: true,
}
})
} catch (error) {
if (isUniqueConstraintError(error)) {
return categoryError({ name: ["Category already exists"] })
}
throw error
}
}
export async function deleteCategoryUseCase(
id: string,
): Promise<CategoryUseCaseResult> {
return prisma.$transaction(async (tx) => {
const category = await CategoryService.findByIdWithItemsCount(id, tx)
if (!category) {
return categoryError({ id: ["Category not found"] })
}
if (category._count.items && category._count.items > 0) {
return categoryError({ id: ["Category has items"] })
}
await CategoryService.delete(id, tx)
return {
success: true,
}
})
}