feat(items): adapt item flows to inventory schema defaults and SKU generation

This commit is contained in:
2026-06-19 17:14:22 +02:00
parent 7b8a415c6a
commit 965a04a468
7 changed files with 306 additions and 19 deletions
@@ -10,6 +10,7 @@ import {
let prisma: PrismaClient
let createItemUseCase: typeof import("@/use-cases/item.use-cases").createItemUseCase
let deleteItemUseCase: typeof import("@/use-cases/item.use-cases").deleteItemUseCase
let updateItemUseCase: typeof import("@/use-cases/item.use-cases").updateItemUseCase
beforeAll(async () => {
await startIntegrationTestDatabase()
@@ -20,6 +21,7 @@ beforeAll(async () => {
prisma = prismaModule.prisma
createItemUseCase = itemUseCases.createItemUseCase
deleteItemUseCase = itemUseCases.deleteItemUseCase
updateItemUseCase = itemUseCases.updateItemUseCase
})
beforeEach(async () => {
@@ -32,7 +34,7 @@ afterAll(async () => {
})
describe("item use-cases", () => {
it("creates an item with initial stock and records an IN movement", async () => {
it("creates an item with operational fields and records an IN movement", async () => {
const actor = await createTestUser(prisma)
const category = await createTestCategory(prisma)
@@ -41,6 +43,10 @@ describe("item use-cases", () => {
name: "Laptop",
categoryId: category.id,
stock: 3,
trackingType: "QUANTITY",
status: "ACTIVE",
minStock: 1,
targetStock: 6,
})
expect(result).toEqual({ success: true })
@@ -54,6 +60,10 @@ describe("item use-cases", () => {
name: "Laptop",
categoryId: category.id,
stock: 3,
trackingType: "QUANTITY",
status: "ACTIVE",
minStock: 1,
targetStock: 6,
deletedAt: null,
})
expect(item?.stockMovementLines).toHaveLength(1)
@@ -66,6 +76,83 @@ describe("item use-cases", () => {
})
})
it("generates unique skus for different names with the same normalized base", async () => {
const actor = await createTestUser(prisma)
const category = await createTestCategory(prisma)
await createItemUseCase({
actorId: actor.id,
name: "Item A!",
categoryId: category.id,
stock: 0,
})
const secondCreate = await createItemUseCase({
actorId: actor.id,
name: "Item A?",
categoryId: category.id,
stock: 0,
})
expect(secondCreate).toEqual({ success: true })
const items = await prisma.item.findMany({
where: { categoryId: category.id },
orderBy: { sku: "asc" },
select: { sku: true, name: true },
})
expect(items).toEqual([
{ sku: "ITEM-A", name: "Item A!" },
{ sku: "ITEM-A-2", name: "Item A?" },
])
})
it("updates operational item fields without changing the sku", async () => {
const actor = await createTestUser(prisma)
const category = await createTestCategory(prisma)
const createResult = await createItemUseCase({
actorId: actor.id,
name: "Monitor",
categoryId: category.id,
stock: 1,
})
expect(createResult).toEqual({ success: true })
const item = await prisma.item.findUniqueOrThrow({
where: { sku: "MONITOR" },
})
const updateResult = await updateItemUseCase({
actorId: actor.id,
id: item.id,
name: "Monitor",
categoryId: category.id,
stock: 0,
trackingType: "SERIALIZED",
status: "DISCONTINUED",
minStock: 2,
targetStock: 8,
})
expect(updateResult).toEqual({ success: true })
const updatedItem = await prisma.item.findUniqueOrThrow({
where: { id: item.id },
})
expect(updatedItem).toMatchObject({
sku: "MONITOR",
stock: 0,
trackingType: "SERIALIZED",
status: "DISCONTINUED",
minStock: 2,
targetStock: 8,
})
})
it("rejects duplicate item names", async () => {
const actor = await createTestUser(prisma)
const category = await createTestCategory(prisma)