235 lines
5.6 KiB
TypeScript
235 lines
5.6 KiB
TypeScript
import type { Prisma } from "@/generated/prisma/client"
|
|
import { paginate } from "@/lib/paginate"
|
|
import prisma from "@/lib/prisma"
|
|
import type {
|
|
Item,
|
|
ItemSummary,
|
|
ItemWithAssetAndMovementCount,
|
|
ItemWithAssetCount,
|
|
} from "@/types"
|
|
|
|
export const ItemService = {
|
|
findAllItemsCount: async (): Promise<number> => {
|
|
return prisma.item.count({ where: { deletedAt: { equals: null } } })
|
|
},
|
|
|
|
findAllWithAssetCount: async ({
|
|
page,
|
|
pageSize,
|
|
search,
|
|
}: {
|
|
page?: number
|
|
pageSize?: number
|
|
search?: string
|
|
}) => {
|
|
return paginate<ItemWithAssetCount>({
|
|
model: prisma.item,
|
|
page,
|
|
pageSize,
|
|
where: {
|
|
deletedAt: null,
|
|
...(search
|
|
? {
|
|
name: { contains: search, mode: "insensitive" },
|
|
}
|
|
: {}),
|
|
},
|
|
orderBy: { name: "asc" },
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
stock: true,
|
|
category: { select: { id: true, name: true } },
|
|
_count: { select: { assets: true } },
|
|
},
|
|
})
|
|
},
|
|
|
|
findAll: async (opts?: {
|
|
includeCategory?: boolean
|
|
includeAssets?: boolean
|
|
includeMovements?: boolean
|
|
}): Promise<Item[]> => {
|
|
return prisma.item.findMany({
|
|
include: {
|
|
category: !!opts?.includeCategory,
|
|
assets: opts?.includeAssets
|
|
? { select: { id: true, serialNumber: true, status: true } }
|
|
: false,
|
|
stockMovementLines: opts?.includeMovements
|
|
? {
|
|
select: {
|
|
id: true,
|
|
stockDelta: true,
|
|
movement: { select: { type: true } },
|
|
},
|
|
}
|
|
: false,
|
|
},
|
|
})
|
|
},
|
|
|
|
findAllAssignable: async (): Promise<Item[]> => {
|
|
return prisma.item.findMany({
|
|
where: {
|
|
deletedAt: null,
|
|
OR: [
|
|
{
|
|
stock: { gt: 0 },
|
|
assets: { some: {} },
|
|
},
|
|
{
|
|
stock: 0,
|
|
assets: { some: {} },
|
|
},
|
|
{
|
|
stock: 0,
|
|
assets: { none: {} },
|
|
},
|
|
],
|
|
},
|
|
orderBy: { name: "asc" },
|
|
}) as Promise<Item[]>
|
|
},
|
|
|
|
findByIdWithCategory: async (
|
|
id: string,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<ItemSummary | null> => {
|
|
return db.item.findUnique({
|
|
where: { id },
|
|
include: {
|
|
category: { select: { id: true, name: true } },
|
|
},
|
|
})
|
|
},
|
|
|
|
findByIdWithAssetCount: async (
|
|
id: string,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<ItemWithAssetCount | null> => {
|
|
return db.item.findUnique({
|
|
where: { id },
|
|
include: {
|
|
category: { select: { id: true, name: true } },
|
|
_count: { select: { assets: true } },
|
|
},
|
|
})
|
|
},
|
|
|
|
findByIdWithAssetAndMovementCount: async (
|
|
id: string,
|
|
): Promise<ItemWithAssetAndMovementCount | null> => {
|
|
const item = await prisma.item.findUnique({
|
|
where: { id },
|
|
include: {
|
|
category: { select: { id: true, name: true } },
|
|
_count: { select: { assets: true, stockMovementLines: true } },
|
|
},
|
|
})
|
|
|
|
return item
|
|
? {
|
|
...item,
|
|
_count: {
|
|
assets: item._count.assets,
|
|
movements: item._count.stockMovementLines,
|
|
},
|
|
}
|
|
: null
|
|
},
|
|
|
|
findByName: async (
|
|
name: string,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item | null> => {
|
|
return db.item.findFirst({
|
|
where: { name },
|
|
include: { category: true, assets: true, stockMovementLines: true },
|
|
}) as Promise<Item | null>
|
|
},
|
|
|
|
findById: async (
|
|
id: string,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item | null> => {
|
|
return db.item.findUnique({
|
|
where: { id },
|
|
include: { category: true, assets: true, stockMovementLines: true },
|
|
}) as Promise<Item | null>
|
|
},
|
|
|
|
findAllWithStock: async (): Promise<Item[]> => {
|
|
return prisma.item.findMany({
|
|
orderBy: { name: "asc" },
|
|
where: {
|
|
stock: { gt: 0 },
|
|
deletedAt: { equals: null },
|
|
},
|
|
include: {
|
|
category: true,
|
|
assets: { select: { id: true, serialNumber: true, status: true } },
|
|
stockMovementLines: {
|
|
select: {
|
|
id: true,
|
|
stockDelta: true,
|
|
movement: { select: { type: true } },
|
|
},
|
|
},
|
|
},
|
|
}) as Promise<Item[]>
|
|
},
|
|
|
|
create: async (
|
|
data: Prisma.ItemCreateInput,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item> => {
|
|
return db.item.create({ data })
|
|
},
|
|
|
|
update: async (
|
|
id: string,
|
|
data: Prisma.ItemUpdateInput,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item> => {
|
|
return db.item.update({ where: { id }, data })
|
|
},
|
|
|
|
updateStock: async (
|
|
id: string,
|
|
quantity: number,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item> => {
|
|
return db.item.update({
|
|
where: { id },
|
|
data: { stock: { increment: quantity } },
|
|
})
|
|
},
|
|
|
|
decrementStockIfAvailable: async (
|
|
id: string,
|
|
quantity: number,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<boolean> => {
|
|
const result = await db.item.updateMany({
|
|
where: {
|
|
id,
|
|
stock: { gte: quantity },
|
|
},
|
|
data: { stock: { decrement: quantity } },
|
|
})
|
|
|
|
return result.count === 1
|
|
},
|
|
|
|
delete: async (
|
|
id: string,
|
|
db: Prisma.TransactionClient | typeof prisma = prisma,
|
|
): Promise<Item> => {
|
|
return db.item.update({
|
|
where: { id },
|
|
data: { deletedAt: new Date() },
|
|
})
|
|
},
|
|
}
|