feat(items): emit ISSUE/ADJUSTMENT movement on stock decrease
This commit is contained in:
@@ -179,6 +179,112 @@ describe("item use-cases", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("writes an ISSUE movement when a QUANTITY item stock decreases to zero", async () => {
|
||||
const actor = await createTestUser(prisma)
|
||||
const category = await createTestCategory(prisma)
|
||||
|
||||
const created = await createItemUseCase({
|
||||
actorId: actor.id,
|
||||
name: "Cable",
|
||||
categoryId: category.id,
|
||||
stock: 1,
|
||||
})
|
||||
|
||||
expect(created).toEqual({ success: true })
|
||||
|
||||
const item = await prisma.item.findUniqueOrThrow({
|
||||
where: { sku: "CABLE" },
|
||||
})
|
||||
|
||||
const updated = await updateItemUseCase({
|
||||
actorId: actor.id,
|
||||
id: item.id,
|
||||
name: "Cable",
|
||||
categoryId: category.id,
|
||||
stock: 0,
|
||||
})
|
||||
|
||||
expect(updated).toEqual({ success: true })
|
||||
|
||||
const refreshedItem = await prisma.item.findUniqueOrThrow({
|
||||
where: { id: item.id },
|
||||
})
|
||||
|
||||
expect(refreshedItem.stock).toBe(0)
|
||||
|
||||
const movements = await prisma.inventoryMovement.findMany({
|
||||
where: { stockLines: { some: { itemId: item.id } } },
|
||||
include: { stockLines: true },
|
||||
orderBy: [{ createdAt: "asc" }, { id: "asc" }],
|
||||
})
|
||||
|
||||
expect(movements).toHaveLength(2)
|
||||
expect(movements[1]).toMatchObject({
|
||||
type: "ISSUE",
|
||||
performedById: actor.id,
|
||||
})
|
||||
expect(movements[1].stockLines[0]).toMatchObject({
|
||||
itemId: item.id,
|
||||
stockDelta: -1,
|
||||
previousStock: 1,
|
||||
newStock: 0,
|
||||
})
|
||||
})
|
||||
|
||||
it("writes an ADJUSTMENT movement with INVENTORY_CORRECTION reason when QUANTITY item decreases with reason", async () => {
|
||||
const actor = await createTestUser(prisma)
|
||||
const category = await createTestCategory(prisma)
|
||||
|
||||
const created = await createItemUseCase({
|
||||
actorId: actor.id,
|
||||
name: "Mouse",
|
||||
categoryId: category.id,
|
||||
stock: 5,
|
||||
})
|
||||
|
||||
expect(created).toEqual({ success: true })
|
||||
|
||||
const item = await prisma.item.findUniqueOrThrow({
|
||||
where: { sku: "MOUSE" },
|
||||
})
|
||||
|
||||
const updated = await updateItemUseCase({
|
||||
actorId: actor.id,
|
||||
id: item.id,
|
||||
name: "Mouse",
|
||||
categoryId: category.id,
|
||||
stock: 4,
|
||||
reason: "INVENTORY_CORRECTION",
|
||||
})
|
||||
|
||||
expect(updated).toEqual({ success: true })
|
||||
|
||||
const refreshedItem = await prisma.item.findUniqueOrThrow({
|
||||
where: { id: item.id },
|
||||
})
|
||||
|
||||
expect(refreshedItem.stock).toBe(4)
|
||||
|
||||
const movements = await prisma.inventoryMovement.findMany({
|
||||
where: { stockLines: { some: { itemId: item.id } } },
|
||||
include: { stockLines: true },
|
||||
orderBy: [{ createdAt: "asc" }, { id: "asc" }],
|
||||
})
|
||||
|
||||
expect(movements).toHaveLength(2)
|
||||
expect(movements[1]).toMatchObject({
|
||||
type: "ADJUSTMENT",
|
||||
reason: "INVENTORY_CORRECTION",
|
||||
performedById: actor.id,
|
||||
})
|
||||
expect(movements[1].stockLines[0]).toMatchObject({
|
||||
itemId: item.id,
|
||||
stockDelta: -1,
|
||||
previousStock: 5,
|
||||
newStock: 4,
|
||||
})
|
||||
})
|
||||
|
||||
it("blocks deleting items with stock and soft deletes empty items", async () => {
|
||||
const actor = await createTestUser(prisma)
|
||||
const category = await createTestCategory(prisma)
|
||||
|
||||
Reference in New Issue
Block a user