Files
CES_SERVE_WEB/src/services/product.service.ts
Welton Moura 402ac776ac feat: sistema GastroBar PDV completo
- Backend: Fastify + Prisma/SQLite com autenticacao JWT
- CRUD completo: usuarios, categorias, produtos, comandas
- Sistema de comandas com itens, status, pagamento
- Controle de estoque (entrada/saida automatica)
- Relatorios e dashboard com KPIs
- Notificacoes sonoras na cozinha
- Frontend: SPA vanilla TS com tema dark glassmorphism
- Mobile-first com bottom-sheet e cards compactos
- Busca de comandas por periodo
- Modal de detalhes com secao editavel colapsavel
2026-07-21 12:47:15 -03:00

89 lines
2.2 KiB
TypeScript

import { prisma } from '../lib/prisma';
import { ProductInput } from '../schemas/product.schema';
export async function getTopProducts(limit = 10) {
// Agrega a soma de quantidades vendidas para cada produto
const topItems = await prisma.itemPedido.groupBy({
by: ['produtoId'],
_sum: { quantidade: true },
orderBy: { _sum: { quantidade: 'desc' } },
take: limit,
});
if (!topItems.length) {
// Fallback: retorna os últimos produtos cadastrados
return prisma.produto.findMany({
where: { ativo: true },
include: { categoria: true },
orderBy: { nome: 'asc' },
take: limit,
});
}
const ids = topItems.map(t => t.produtoId);
const produtos = await prisma.produto.findMany({
where: { id: { in: ids }, ativo: true },
include: { categoria: true },
});
// Mantém a ordem de vendas + injeta totalVendido
return ids.map(id => {
const prod = produtos.find(p => p.id === id)!;
const vendas = topItems.find(t => t.produtoId === id)?._sum.quantidade ?? 0;
return { ...prod, totalVendido: vendas };
}).filter(Boolean);
}
export async function searchProducts(query: string) {
return prisma.produto.findMany({
where: {
ativo: true,
nome: { contains: query },
},
include: { categoria: true },
orderBy: { nome: 'asc' },
take: 20,
});
}
export async function createProduct(data: ProductInput) {
return prisma.produto.create({
data,
});
}
export async function listProducts() {
return prisma.produto.findMany({
include: { categoria: true },
});
}
export async function getProductById(id: string) {
return prisma.produto.findUnique({
where: { id },
include: { categoria: true },
});
}
export async function updateProduct(id: string, data: Partial<ProductInput>) {
return prisma.produto.update({
where: { id },
data,
});
}
export async function deleteProduct(id: string) {
return prisma.produto.delete({
where: { id },
});
}
export async function getLowStockProducts() {
const products = await prisma.produto.findMany({
where: { ativo: true },
include: { categoria: true },
orderBy: { estoqueAtual: 'asc' },
});
return products.filter(p => p.estoqueAtual <= p.estoqueMinimo);
}