- 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
89 lines
2.2 KiB
TypeScript
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);
|
|
}
|