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
This commit is contained in:
88
src/services/product.service.ts
Normal file
88
src/services/product.service.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user