Primeiro commit
This commit is contained in:
635
server.js
Normal file
635
server.js
Normal file
@@ -0,0 +1,635 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const multer = require('multer');
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
require('dotenv').config();
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
// Middleware
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use('/uploads', express.static('uploads'));
|
||||
app.use(express.static(path.join(__dirname, 'client/build')));
|
||||
|
||||
// Configuração do multer para upload de imagens
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, 'uploads/');
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const uniqueName = `${Date.now()}-${uuidv4()}${path.extname(file.originalname)}`;
|
||||
cb(null, uniqueName);
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage: storage,
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (file.mimetype.startsWith('image/')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Apenas imagens são permitidas!'), false);
|
||||
}
|
||||
},
|
||||
limits: { fileSize: 5 * 1024 * 1024 } // 5MB
|
||||
});
|
||||
|
||||
// Inicializar banco de dados
|
||||
const db = new sqlite3.Database('./liberi_kids.db', (err) => {
|
||||
if (err) {
|
||||
console.error('Erro ao conectar com o banco de dados:', err.message);
|
||||
} else {
|
||||
console.log('Conectado ao banco de dados SQLite.');
|
||||
initializeDatabase();
|
||||
}
|
||||
});
|
||||
|
||||
// Função para inicializar as tabelas
|
||||
function initializeDatabase() {
|
||||
// Tabela de produtos
|
||||
db.run(`CREATE TABLE IF NOT EXISTS produtos (
|
||||
id TEXT PRIMARY KEY,
|
||||
id_produto TEXT,
|
||||
marca TEXT NOT NULL,
|
||||
nome TEXT NOT NULL,
|
||||
estacao TEXT NOT NULL,
|
||||
genero TEXT DEFAULT 'Unissex',
|
||||
fornecedor_id TEXT,
|
||||
valor_compra REAL NOT NULL,
|
||||
valor_revenda REAL NOT NULL,
|
||||
foto_principal_url TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (fornecedor_id) REFERENCES fornecedores (id)
|
||||
)`);
|
||||
|
||||
// Tabela de variações de produtos (tamanho, cor, quantidade)
|
||||
db.run(`CREATE TABLE IF NOT EXISTS produto_variacoes (
|
||||
id TEXT PRIMARY KEY,
|
||||
produto_id TEXT NOT NULL,
|
||||
tamanho TEXT NOT NULL,
|
||||
cor TEXT NOT NULL,
|
||||
quantidade INTEGER NOT NULL DEFAULT 0,
|
||||
foto_url TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (produto_id) REFERENCES produtos (id) ON DELETE CASCADE
|
||||
)`);
|
||||
|
||||
// Tabela de clientes
|
||||
db.run(`CREATE TABLE IF NOT EXISTS clientes (
|
||||
id TEXT PRIMARY KEY,
|
||||
nome_completo TEXT NOT NULL,
|
||||
email TEXT,
|
||||
telefone TEXT,
|
||||
endereco TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
|
||||
// Tabela de fornecedores
|
||||
db.run(`CREATE TABLE IF NOT EXISTS fornecedores (
|
||||
id TEXT PRIMARY KEY,
|
||||
razao_social TEXT NOT NULL,
|
||||
telefone TEXT,
|
||||
whatsapp TEXT,
|
||||
endereco TEXT,
|
||||
email TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
|
||||
// Tabela de tipos de despesas
|
||||
db.run(`CREATE TABLE IF NOT EXISTS tipos_despesas (
|
||||
id TEXT PRIMARY KEY,
|
||||
nome TEXT NOT NULL UNIQUE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
|
||||
// Tabela de despesas
|
||||
db.run(`CREATE TABLE IF NOT EXISTS despesas (
|
||||
id TEXT PRIMARY KEY,
|
||||
tipo_despesa_id TEXT NOT NULL,
|
||||
fornecedor_id TEXT,
|
||||
data DATE NOT NULL,
|
||||
valor REAL NOT NULL,
|
||||
descricao TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (tipo_despesa_id) REFERENCES tipos_despesas (id),
|
||||
FOREIGN KEY (fornecedor_id) REFERENCES fornecedores (id)
|
||||
)`);
|
||||
|
||||
// Tabela de vendas
|
||||
db.run(`CREATE TABLE IF NOT EXISTS vendas (
|
||||
id TEXT PRIMARY KEY,
|
||||
cliente_id TEXT,
|
||||
tipo_pagamento TEXT NOT NULL, -- 'vista' ou 'parcelado'
|
||||
valor_total REAL NOT NULL,
|
||||
desconto REAL DEFAULT 0,
|
||||
parcelas INTEGER DEFAULT 1,
|
||||
valor_parcela REAL,
|
||||
data_venda DATE NOT NULL,
|
||||
status TEXT DEFAULT 'concluida', -- 'concluida', 'cancelada'
|
||||
observacoes TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (cliente_id) REFERENCES clientes (id)
|
||||
)`);
|
||||
|
||||
// Tabela de itens da venda
|
||||
db.run(`CREATE TABLE IF NOT EXISTS venda_itens (
|
||||
id TEXT PRIMARY KEY,
|
||||
venda_id TEXT NOT NULL,
|
||||
produto_variacao_id TEXT NOT NULL,
|
||||
quantidade INTEGER NOT NULL,
|
||||
valor_unitario REAL NOT NULL,
|
||||
valor_total REAL NOT NULL,
|
||||
FOREIGN KEY (venda_id) REFERENCES vendas (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (produto_variacao_id) REFERENCES produto_variacoes (id)
|
||||
)`);
|
||||
|
||||
console.log('Tabelas do banco de dados inicializadas.');
|
||||
}
|
||||
|
||||
// Rotas da API
|
||||
|
||||
// === PRODUTOS ===
|
||||
app.get('/api/produtos', (req, res) => {
|
||||
const query = `
|
||||
SELECT p.*, f.razao_social as fornecedor_nome,
|
||||
COUNT(pv.id) as total_variacoes,
|
||||
SUM(pv.quantidade) as estoque_total
|
||||
FROM produtos p
|
||||
LEFT JOIN fornecedores f ON p.fornecedor_id = f.id
|
||||
LEFT JOIN produto_variacoes pv ON p.id = pv.produto_id
|
||||
GROUP BY p.id
|
||||
ORDER BY p.created_at DESC
|
||||
`;
|
||||
|
||||
db.all(query, [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/produtos', upload.any(), (req, res) => {
|
||||
console.log('Recebendo requisição para criar produto:', req.body);
|
||||
console.log('Arquivos recebidos:', req.files ? req.files.length : 0);
|
||||
|
||||
const { id_produto, marca, nome, estacao, genero, fornecedor_id, valor_compra, valor_revenda, variacoes_data } = req.body;
|
||||
const produtoId = uuidv4();
|
||||
|
||||
// Validações básicas
|
||||
if (!marca || !nome || !estacao || !valor_compra || !valor_revenda) {
|
||||
return res.status(400).json({ error: 'Campos obrigatórios não preenchidos' });
|
||||
}
|
||||
|
||||
// Parse das variações
|
||||
let variacoes = [];
|
||||
try {
|
||||
if (variacoes_data) {
|
||||
variacoes = JSON.parse(variacoes_data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao fazer parse das variações:', error);
|
||||
return res.status(400).json({ error: 'Dados de variações inválidos' });
|
||||
}
|
||||
|
||||
if (variacoes.length === 0) {
|
||||
return res.status(400).json({ error: 'Pelo menos uma variação é obrigatória' });
|
||||
}
|
||||
|
||||
// Iniciar transação
|
||||
db.serialize(() => {
|
||||
db.run('BEGIN TRANSACTION');
|
||||
|
||||
// Inserir produto
|
||||
const produtoQuery = `INSERT INTO produtos (id, id_produto, marca, nome, estacao, genero, fornecedor_id, valor_compra, valor_revenda)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
const fornecedorIdFinal = fornecedor_id && fornecedor_id !== '' ? fornecedor_id : null;
|
||||
|
||||
db.run(produtoQuery, [produtoId, id_produto, marca, nome, estacao, genero || 'Unissex', fornecedorIdFinal, valor_compra, valor_revenda], function(err) {
|
||||
if (err) {
|
||||
console.error('Erro ao inserir produto:', err);
|
||||
db.run('ROLLBACK');
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
|
||||
console.log('Produto inserido com sucesso, processando variações...');
|
||||
|
||||
// Processar variações e fotos
|
||||
let variacoesProcessadas = 0;
|
||||
const totalVariacoes = variacoes.length;
|
||||
|
||||
if (totalVariacoes === 0) {
|
||||
db.run('COMMIT');
|
||||
return res.json({ id: produtoId, message: 'Produto criado com sucesso!' });
|
||||
}
|
||||
|
||||
variacoes.forEach((variacao, varIndex) => {
|
||||
const variacaoId = uuidv4();
|
||||
|
||||
// Inserir variação
|
||||
const variacaoQuery = `INSERT INTO produto_variacoes (id, produto_id, tamanho, cor, quantidade)
|
||||
VALUES (?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(variacaoQuery, [variacaoId, produtoId, variacao.tamanho, variacao.cor, variacao.quantidade], function(err) {
|
||||
if (err) {
|
||||
console.error('Erro ao inserir variação:', err);
|
||||
db.run('ROLLBACK');
|
||||
return res.status(500).json({ error: err.message });
|
||||
}
|
||||
|
||||
// Processar fotos desta variação
|
||||
const fotosVariacao = req.files ? req.files.filter(file =>
|
||||
file.fieldname.startsWith(`variacao_${varIndex}_foto_`)
|
||||
) : [];
|
||||
|
||||
if (fotosVariacao.length > 0) {
|
||||
// Usar a primeira foto como foto_url da variação
|
||||
const primeiraFoto = fotosVariacao[0];
|
||||
const fotoUrl = `/uploads/${primeiraFoto.filename}`;
|
||||
|
||||
// Atualizar variação com a primeira foto
|
||||
db.run('UPDATE produto_variacoes SET foto_url = ? WHERE id = ?', [fotoUrl, variacaoId], function(err) {
|
||||
if (err) {
|
||||
console.error('Erro ao atualizar foto da variação:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
variacoesProcessadas++;
|
||||
console.log(`Variação processada: ${variacoesProcessadas}/${totalVariacoes}`);
|
||||
|
||||
if (variacoesProcessadas === totalVariacoes) {
|
||||
db.run('COMMIT');
|
||||
console.log('Produto criado com sucesso!');
|
||||
res.json({ id: produtoId, message: 'Produto criado com sucesso!' });
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/api/produtos/:id', upload.single('foto_principal'), (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { id_produto, marca, nome, estacao, genero, fornecedor_id, valor_compra, valor_revenda } = req.body;
|
||||
|
||||
let query, params;
|
||||
|
||||
if (req.file) {
|
||||
const foto_principal_url = `/uploads/${req.file.filename}`;
|
||||
query = `UPDATE produtos
|
||||
SET id_produto = ?, marca = ?, nome = ?, estacao = ?, genero = ?, fornecedor_id = ?, valor_compra = ?, valor_revenda = ?, foto_principal_url = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`;
|
||||
params = [id_produto, marca, nome, estacao, genero || 'Unissex', fornecedor_id, valor_compra, valor_revenda, foto_principal_url, id];
|
||||
} else {
|
||||
query = `UPDATE produtos
|
||||
SET id_produto = ?, marca = ?, nome = ?, estacao = ?, genero = ?, fornecedor_id = ?, valor_compra = ?, valor_revenda = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`;
|
||||
params = [id_produto, marca, nome, estacao, genero || 'Unissex', fornecedor_id, valor_compra, valor_revenda, id];
|
||||
}
|
||||
|
||||
db.run(query, params, function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ message: 'Produto atualizado com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === VARIAÇÕES DE PRODUTOS ===
|
||||
app.get('/api/produtos/:id/variacoes', (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
db.all('SELECT * FROM produto_variacoes WHERE produto_id = ? ORDER BY tamanho, cor', [id], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/produtos/:id/variacoes', upload.single('foto'), (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { tamanho, cor, quantidade } = req.body;
|
||||
const foto_url = req.file ? `/uploads/${req.file.filename}` : null;
|
||||
const variacao_id = uuidv4();
|
||||
|
||||
const query = `INSERT INTO produto_variacoes (id, produto_id, tamanho, cor, quantidade, foto_url)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(query, [variacao_id, id, tamanho, cor, quantidade, foto_url], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ id: variacao_id, message: 'Variação adicionada com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === CLIENTES ===
|
||||
app.get('/api/clientes', (req, res) => {
|
||||
db.all('SELECT * FROM clientes ORDER BY nome_completo', [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/clientes', (req, res) => {
|
||||
const { nome_completo, email, telefone, endereco } = req.body;
|
||||
const id = uuidv4();
|
||||
|
||||
const query = `INSERT INTO clientes (id, nome_completo, email, telefone, endereco)
|
||||
VALUES (?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(query, [id, nome_completo, email, telefone, endereco], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ id, message: 'Cliente cadastrado com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === FORNECEDORES ===
|
||||
app.get('/api/fornecedores', (req, res) => {
|
||||
db.all('SELECT * FROM fornecedores ORDER BY razao_social', [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/fornecedores', (req, res) => {
|
||||
const { razao_social, telefone, whatsapp, endereco, email } = req.body;
|
||||
const id = uuidv4();
|
||||
|
||||
const query = `INSERT INTO fornecedores (id, razao_social, telefone, whatsapp, endereco, email)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(query, [id, razao_social, telefone, whatsapp, endereco, email], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ id, message: 'Fornecedor cadastrado com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === TIPOS DE DESPESAS ===
|
||||
app.get('/api/tipos-despesas', (req, res) => {
|
||||
db.all('SELECT * FROM tipos_despesas ORDER BY nome', [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/tipos-despesas', (req, res) => {
|
||||
const { nome } = req.body;
|
||||
const id = uuidv4();
|
||||
|
||||
const query = `INSERT INTO tipos_despesas (id, nome) VALUES (?, ?)`;
|
||||
|
||||
db.run(query, [id, nome], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ id, message: 'Tipo de despesa criado com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === DESPESAS ===
|
||||
app.get('/api/despesas', (req, res) => {
|
||||
const query = `
|
||||
SELECT d.*, td.nome as tipo_nome, f.razao_social as fornecedor_nome
|
||||
FROM despesas d
|
||||
LEFT JOIN tipos_despesas td ON d.tipo_despesa_id = td.id
|
||||
LEFT JOIN fornecedores f ON d.fornecedor_id = f.id
|
||||
ORDER BY d.data DESC
|
||||
`;
|
||||
|
||||
db.all(query, [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/despesas', (req, res) => {
|
||||
const { tipo_despesa_id, fornecedor_id, data, valor, descricao } = req.body;
|
||||
const id = uuidv4();
|
||||
|
||||
const query = `INSERT INTO despesas (id, tipo_despesa_id, fornecedor_id, data, valor, descricao)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(query, [id, tipo_despesa_id, fornecedor_id || null, data, valor, descricao], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ id, message: 'Despesa cadastrada com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
app.put('/api/despesas/:id', (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { tipo_despesa_id, fornecedor_id, data, valor, descricao } = req.body;
|
||||
|
||||
const query = `UPDATE despesas
|
||||
SET tipo_despesa_id = ?, fornecedor_id = ?, data = ?, valor = ?, descricao = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`;
|
||||
|
||||
db.run(query, [tipo_despesa_id, fornecedor_id || null, data, valor, descricao, id], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ message: 'Despesa atualizada com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/api/despesas/:id', (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
db.run('DELETE FROM despesas WHERE id = ?', [id], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ message: 'Despesa excluída com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === VENDAS ===
|
||||
app.get('/api/vendas', (req, res) => {
|
||||
const query = `
|
||||
SELECT v.*, c.nome_completo as cliente_nome
|
||||
FROM vendas v
|
||||
LEFT JOIN clientes c ON v.cliente_id = c.id
|
||||
ORDER BY v.data_venda DESC
|
||||
`;
|
||||
|
||||
db.all(query, [], (err, rows) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/api/vendas', (req, res) => {
|
||||
const { cliente_id, tipo_pagamento, valor_total, desconto, parcelas, data_venda, observacoes, itens } = req.body;
|
||||
const vendaId = uuidv4();
|
||||
const valor_parcela = tipo_pagamento === 'parcelado' ? (valor_total - desconto) / parcelas : 0;
|
||||
|
||||
// Iniciar transação
|
||||
db.serialize(() => {
|
||||
db.run('BEGIN TRANSACTION');
|
||||
|
||||
// Inserir venda
|
||||
const vendaQuery = `INSERT INTO vendas (id, cliente_id, tipo_pagamento, valor_total, desconto, parcelas, valor_parcela, data_venda, observacoes)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(vendaQuery, [vendaId, cliente_id || null, tipo_pagamento, valor_total, desconto, parcelas, valor_parcela, data_venda, observacoes], function(err) {
|
||||
if (err) {
|
||||
db.run('ROLLBACK');
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
// Inserir itens da venda
|
||||
let itemsProcessed = 0;
|
||||
const totalItems = itens.length;
|
||||
|
||||
if (totalItems === 0) {
|
||||
db.run('COMMIT');
|
||||
res.json({ id: vendaId, message: 'Venda registrada com sucesso!' });
|
||||
return;
|
||||
}
|
||||
|
||||
itens.forEach((item) => {
|
||||
const itemId = uuidv4();
|
||||
const itemQuery = `INSERT INTO venda_itens (id, venda_id, produto_variacao_id, quantidade, valor_unitario, valor_total)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
db.run(itemQuery, [itemId, vendaId, item.produto_variacao_id, item.quantidade, item.valor_unitario, item.valor_total], function(err) {
|
||||
if (err) {
|
||||
db.run('ROLLBACK');
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
// Atualizar estoque
|
||||
const updateEstoque = `UPDATE produto_variacoes
|
||||
SET quantidade = quantidade - ?
|
||||
WHERE id = ?`;
|
||||
|
||||
db.run(updateEstoque, [item.quantidade, item.produto_variacao_id], function(err) {
|
||||
if (err) {
|
||||
db.run('ROLLBACK');
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
itemsProcessed++;
|
||||
if (itemsProcessed === totalItems) {
|
||||
db.run('COMMIT');
|
||||
res.json({ id: vendaId, message: 'Venda registrada com sucesso!' });
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.delete('/api/vendas/:id', (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
db.run('DELETE FROM vendas WHERE id = ?', [id], function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
res.json({ message: 'Venda excluída com sucesso!' });
|
||||
});
|
||||
});
|
||||
|
||||
// === TESTE ===
|
||||
app.get('/api/test', (req, res) => {
|
||||
res.json({ message: 'API funcionando corretamente!', timestamp: new Date() });
|
||||
});
|
||||
|
||||
// === DASHBOARD ===
|
||||
app.get('/api/dashboard', (req, res) => {
|
||||
const queries = {
|
||||
totalProdutos: 'SELECT COUNT(*) as count FROM produtos',
|
||||
totalClientes: 'SELECT COUNT(*) as count FROM clientes',
|
||||
totalFornecedores: 'SELECT COUNT(*) as count FROM fornecedores',
|
||||
vendasMes: `SELECT COUNT(*) as count, SUM(valor_total) as total
|
||||
FROM vendas
|
||||
WHERE strftime('%Y-%m', data_venda) = strftime('%Y-%m', 'now')`,
|
||||
estoqueTotal: 'SELECT SUM(quantidade) as total FROM produto_variacoes',
|
||||
despesasMes: `SELECT SUM(valor) as total
|
||||
FROM despesas
|
||||
WHERE strftime('%Y-%m', data) = strftime('%Y-%m', 'now')`
|
||||
};
|
||||
|
||||
const results = {};
|
||||
let completed = 0;
|
||||
const total = Object.keys(queries).length;
|
||||
|
||||
Object.entries(queries).forEach(([key, query]) => {
|
||||
db.get(query, [], (err, row) => {
|
||||
if (err) {
|
||||
results[key] = { error: err.message };
|
||||
} else {
|
||||
results[key] = row;
|
||||
}
|
||||
|
||||
completed++;
|
||||
if (completed === total) {
|
||||
res.json(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Servir arquivos estáticos do React
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
|
||||
});
|
||||
|
||||
// Criar diretório de uploads se não existir
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync('uploads')) {
|
||||
fs.mkdirSync('uploads');
|
||||
}
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Servidor rodando na porta ${PORT}`);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
Reference in New Issue
Block a user