395 lines
8.9 KiB
JavaScript
395 lines
8.9 KiB
JavaScript
|
|
const pool = require('../../../database/mysql');
|
||
|
|
|
||
|
|
const CAMPOS_MOVIMENTO_FIXO_SELECT = `
|
||
|
|
mf.idmovimentosfixos,
|
||
|
|
mf.movimento,
|
||
|
|
mf.descricao,
|
||
|
|
mf.valor,
|
||
|
|
mf.dia_vencimento,
|
||
|
|
mf.idcentrodecustos,
|
||
|
|
mf.habilitado,
|
||
|
|
mf.idbancos,
|
||
|
|
mf.insert_date,
|
||
|
|
mf.update_date,
|
||
|
|
b.descricao AS banco_descricao,
|
||
|
|
cc.descricao AS centro_custo_descricao
|
||
|
|
`;
|
||
|
|
|
||
|
|
const FROM_MOVIMENTO_FIXO_JOIN = `
|
||
|
|
FROM movimentosfixos mf
|
||
|
|
LEFT JOIN bancos b ON b.idbancos = mf.idbancos
|
||
|
|
LEFT JOIN centrodecustos cc ON cc.idcentrodecustos = mf.idcentrodecustos
|
||
|
|
`;
|
||
|
|
|
||
|
|
function normalizarTextoOuNull(valor) {
|
||
|
|
if (valor === undefined || valor === null || valor === '') {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return String(valor).trim();
|
||
|
|
}
|
||
|
|
|
||
|
|
function normalizarNumeroOuNull(valor) {
|
||
|
|
if (valor === undefined || valor === null || valor === '') {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const numero = Number(valor);
|
||
|
|
|
||
|
|
if (!Number.isFinite(numero)) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return numero;
|
||
|
|
}
|
||
|
|
|
||
|
|
function normalizarNumero(valor, padrao = 0) {
|
||
|
|
if (valor === undefined || valor === null || valor === '') {
|
||
|
|
return padrao;
|
||
|
|
}
|
||
|
|
|
||
|
|
const numero = Number(valor);
|
||
|
|
|
||
|
|
if (!Number.isFinite(numero)) {
|
||
|
|
return padrao;
|
||
|
|
}
|
||
|
|
|
||
|
|
return numero;
|
||
|
|
}
|
||
|
|
|
||
|
|
function normalizarFlag(valor, padrao = 0) {
|
||
|
|
if (valor === undefined || valor === null || valor === '') {
|
||
|
|
return padrao;
|
||
|
|
}
|
||
|
|
|
||
|
|
return Number(valor) === 1 ? 1 : 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
function limitarNumero(valor, padrao, minimo, maximo) {
|
||
|
|
const numero = Number(valor);
|
||
|
|
|
||
|
|
if (!Number.isFinite(numero)) {
|
||
|
|
return padrao;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (numero < minimo) {
|
||
|
|
return minimo;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (numero > maximo) {
|
||
|
|
return maximo;
|
||
|
|
}
|
||
|
|
|
||
|
|
return numero;
|
||
|
|
}
|
||
|
|
|
||
|
|
function resolverOrdenacao(orderBy) {
|
||
|
|
const camposPermitidos = {
|
||
|
|
idmovimentosfixos: 'mf.idmovimentosfixos',
|
||
|
|
movimento: 'mf.movimento',
|
||
|
|
descricao: 'mf.descricao',
|
||
|
|
valor: 'mf.valor',
|
||
|
|
dia_vencimento: 'mf.dia_vencimento',
|
||
|
|
idcentrodecustos: 'mf.idcentrodecustos',
|
||
|
|
idbancos: 'mf.idbancos',
|
||
|
|
habilitado: 'mf.habilitado',
|
||
|
|
insert_date: 'mf.insert_date',
|
||
|
|
update_date: 'mf.update_date',
|
||
|
|
banco_descricao: 'b.descricao',
|
||
|
|
centro_custo_descricao: 'cc.descricao',
|
||
|
|
};
|
||
|
|
|
||
|
|
return camposPermitidos[orderBy] || 'mf.dia_vencimento';
|
||
|
|
}
|
||
|
|
|
||
|
|
function resolverDirecao(orderDirection) {
|
||
|
|
return String(orderDirection || '').toUpperCase() === 'DESC' ? 'DESC' : 'ASC';
|
||
|
|
}
|
||
|
|
|
||
|
|
function montarWhereMovimentosFixos(filtros = {}) {
|
||
|
|
const where = [];
|
||
|
|
const params = [];
|
||
|
|
|
||
|
|
if (filtros.movimento) {
|
||
|
|
where.push('mf.movimento = ?');
|
||
|
|
params.push(filtros.movimento);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.idbancos) {
|
||
|
|
where.push('mf.idbancos = ?');
|
||
|
|
params.push(Number(filtros.idbancos));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.idcentrodecustos) {
|
||
|
|
where.push('mf.idcentrodecustos = ?');
|
||
|
|
params.push(Number(filtros.idcentrodecustos));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.habilitado !== undefined && filtros.habilitado !== null && filtros.habilitado !== '') {
|
||
|
|
where.push('mf.habilitado = ?');
|
||
|
|
params.push(Number(filtros.habilitado));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.diaInicio) {
|
||
|
|
where.push('mf.dia_vencimento >= ?');
|
||
|
|
params.push(Number(filtros.diaInicio));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.diaFim) {
|
||
|
|
where.push('mf.dia_vencimento <= ?');
|
||
|
|
params.push(Number(filtros.diaFim));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (filtros.busca) {
|
||
|
|
where.push(`
|
||
|
|
(
|
||
|
|
mf.descricao LIKE ?
|
||
|
|
OR mf.movimento LIKE ?
|
||
|
|
OR b.descricao LIKE ?
|
||
|
|
OR cc.descricao LIKE ?
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
const termo = `%${String(filtros.busca).trim()}%`;
|
||
|
|
|
||
|
|
params.push(
|
||
|
|
termo,
|
||
|
|
termo,
|
||
|
|
termo,
|
||
|
|
termo
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
||
|
|
|
||
|
|
return {
|
||
|
|
whereSql,
|
||
|
|
params,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async function listarMovimentosFixos(filtros = {}) {
|
||
|
|
const limite = limitarNumero(filtros.limite, 20, 1, 100);
|
||
|
|
const page = limitarNumero(filtros.page, 1, 1, 999999);
|
||
|
|
const offset = filtros.offset !== undefined
|
||
|
|
? limitarNumero(filtros.offset, 0, 0, 999999999)
|
||
|
|
: (page - 1) * limite;
|
||
|
|
|
||
|
|
const orderBy = resolverOrdenacao(filtros.orderBy);
|
||
|
|
const orderDirection = resolverDirecao(filtros.orderDirection);
|
||
|
|
|
||
|
|
const { whereSql, params } = montarWhereMovimentosFixos(filtros);
|
||
|
|
|
||
|
|
const [rows] = await pool.query(
|
||
|
|
`
|
||
|
|
SELECT
|
||
|
|
${CAMPOS_MOVIMENTO_FIXO_SELECT}
|
||
|
|
${FROM_MOVIMENTO_FIXO_JOIN}
|
||
|
|
${whereSql}
|
||
|
|
ORDER BY ${orderBy} ${orderDirection}, mf.idmovimentosfixos ASC
|
||
|
|
LIMIT ? OFFSET ?
|
||
|
|
`,
|
||
|
|
[...params, limite, offset]
|
||
|
|
);
|
||
|
|
|
||
|
|
const [countRows] = await pool.query(
|
||
|
|
`
|
||
|
|
SELECT COUNT(*) AS total
|
||
|
|
${FROM_MOVIMENTO_FIXO_JOIN}
|
||
|
|
${whereSql}
|
||
|
|
`,
|
||
|
|
params
|
||
|
|
);
|
||
|
|
|
||
|
|
const [summaryRows] = await pool.query(
|
||
|
|
`
|
||
|
|
SELECT
|
||
|
|
COUNT(*) AS quantidade,
|
||
|
|
COALESCE(SUM(mf.valor), 0) AS valorTotal,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.movimento = 'Entrada' THEN mf.valor ELSE 0 END), 0) AS totalEntradas,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.movimento = 'Saida' THEN mf.valor ELSE 0 END), 0) AS totalSaidas,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.movimento = 'Sangria' THEN mf.valor ELSE 0 END), 0) AS totalSangrias,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.movimento = 'Estorno' THEN mf.valor ELSE 0 END), 0) AS totalEstornos,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.habilitado = 1 THEN 1 ELSE 0 END), 0) AS habilitados,
|
||
|
|
COALESCE(SUM(CASE WHEN mf.habilitado = 0 THEN 1 ELSE 0 END), 0) AS desabilitados
|
||
|
|
${FROM_MOVIMENTO_FIXO_JOIN}
|
||
|
|
${whereSql}
|
||
|
|
`,
|
||
|
|
params
|
||
|
|
);
|
||
|
|
|
||
|
|
const total = Number(countRows[0]?.total || 0);
|
||
|
|
const totalPages = Math.max(1, Math.ceil(total / limite));
|
||
|
|
|
||
|
|
return {
|
||
|
|
data: rows,
|
||
|
|
pagination: {
|
||
|
|
total,
|
||
|
|
limite,
|
||
|
|
offset,
|
||
|
|
page: Math.floor(offset / limite) + 1,
|
||
|
|
totalPages,
|
||
|
|
},
|
||
|
|
summary: {
|
||
|
|
quantidade: Number(summaryRows[0]?.quantidade || 0),
|
||
|
|
valorTotal: Number(summaryRows[0]?.valorTotal || 0),
|
||
|
|
totalEntradas: Number(summaryRows[0]?.totalEntradas || 0),
|
||
|
|
totalSaidas: Number(summaryRows[0]?.totalSaidas || 0),
|
||
|
|
totalSangrias: Number(summaryRows[0]?.totalSangrias || 0),
|
||
|
|
totalEstornos: Number(summaryRows[0]?.totalEstornos || 0),
|
||
|
|
habilitados: Number(summaryRows[0]?.habilitados || 0),
|
||
|
|
desabilitados: Number(summaryRows[0]?.desabilitados || 0),
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async function buscarMovimentoFixoPorId(id) {
|
||
|
|
const [rows] = await pool.query(
|
||
|
|
`
|
||
|
|
SELECT
|
||
|
|
${CAMPOS_MOVIMENTO_FIXO_SELECT}
|
||
|
|
${FROM_MOVIMENTO_FIXO_JOIN}
|
||
|
|
WHERE mf.idmovimentosfixos = ?
|
||
|
|
LIMIT 1
|
||
|
|
`,
|
||
|
|
[id]
|
||
|
|
);
|
||
|
|
|
||
|
|
return rows[0] || null;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function criarMovimentoFixo(dados) {
|
||
|
|
const {
|
||
|
|
movimento,
|
||
|
|
descricao,
|
||
|
|
valor,
|
||
|
|
dia_vencimento,
|
||
|
|
idcentrodecustos,
|
||
|
|
habilitado,
|
||
|
|
idbancos,
|
||
|
|
} = dados;
|
||
|
|
|
||
|
|
const [result] = await pool.query(
|
||
|
|
`
|
||
|
|
INSERT INTO movimentosfixos (
|
||
|
|
movimento,
|
||
|
|
descricao,
|
||
|
|
valor,
|
||
|
|
dia_vencimento,
|
||
|
|
idcentrodecustos,
|
||
|
|
habilitado,
|
||
|
|
idbancos,
|
||
|
|
insert_date,
|
||
|
|
update_date
|
||
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
|
||
|
|
`,
|
||
|
|
[
|
||
|
|
normalizarTextoOuNull(movimento),
|
||
|
|
normalizarTextoOuNull(descricao),
|
||
|
|
normalizarNumero(valor, 0),
|
||
|
|
normalizarNumero(dia_vencimento, 1),
|
||
|
|
normalizarNumeroOuNull(idcentrodecustos),
|
||
|
|
normalizarFlag(habilitado, 1),
|
||
|
|
normalizarNumeroOuNull(idbancos),
|
||
|
|
]
|
||
|
|
);
|
||
|
|
|
||
|
|
return buscarMovimentoFixoPorId(result.insertId);
|
||
|
|
}
|
||
|
|
|
||
|
|
async function atualizarMovimentoFixo(id, dados) {
|
||
|
|
const movimentoAtual = await buscarMovimentoFixoPorId(id);
|
||
|
|
|
||
|
|
if (!movimentoAtual) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const {
|
||
|
|
movimento,
|
||
|
|
descricao,
|
||
|
|
valor,
|
||
|
|
dia_vencimento,
|
||
|
|
idcentrodecustos,
|
||
|
|
habilitado,
|
||
|
|
idbancos,
|
||
|
|
} = dados;
|
||
|
|
|
||
|
|
await pool.query(
|
||
|
|
`
|
||
|
|
UPDATE movimentosfixos
|
||
|
|
SET
|
||
|
|
movimento = ?,
|
||
|
|
descricao = ?,
|
||
|
|
valor = ?,
|
||
|
|
dia_vencimento = ?,
|
||
|
|
idcentrodecustos = ?,
|
||
|
|
habilitado = ?,
|
||
|
|
idbancos = ?,
|
||
|
|
update_date = NOW()
|
||
|
|
WHERE idmovimentosfixos = ?
|
||
|
|
`,
|
||
|
|
[
|
||
|
|
normalizarTextoOuNull(movimento),
|
||
|
|
normalizarTextoOuNull(descricao),
|
||
|
|
normalizarNumero(valor, 0),
|
||
|
|
normalizarNumero(dia_vencimento, 1),
|
||
|
|
normalizarNumeroOuNull(idcentrodecustos),
|
||
|
|
normalizarFlag(habilitado, 1),
|
||
|
|
normalizarNumeroOuNull(idbancos),
|
||
|
|
id,
|
||
|
|
]
|
||
|
|
);
|
||
|
|
|
||
|
|
return buscarMovimentoFixoPorId(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
async function alterarHabilitadoMovimentoFixo(id, habilitado) {
|
||
|
|
const movimentoAtual = await buscarMovimentoFixoPorId(id);
|
||
|
|
|
||
|
|
if (!movimentoAtual) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
await pool.query(
|
||
|
|
`
|
||
|
|
UPDATE movimentosfixos
|
||
|
|
SET
|
||
|
|
habilitado = ?,
|
||
|
|
update_date = NOW()
|
||
|
|
WHERE idmovimentosfixos = ?
|
||
|
|
`,
|
||
|
|
[
|
||
|
|
normalizarFlag(habilitado, 1),
|
||
|
|
id,
|
||
|
|
]
|
||
|
|
);
|
||
|
|
|
||
|
|
return buscarMovimentoFixoPorId(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
async function deletarMovimentoFixo(id) {
|
||
|
|
const movimentoAtual = await buscarMovimentoFixoPorId(id);
|
||
|
|
|
||
|
|
if (!movimentoAtual) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
await pool.query(
|
||
|
|
`
|
||
|
|
DELETE FROM movimentosfixos
|
||
|
|
WHERE idmovimentosfixos = ?
|
||
|
|
`,
|
||
|
|
[id]
|
||
|
|
);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
listarMovimentosFixos,
|
||
|
|
buscarMovimentoFixoPorId,
|
||
|
|
criarMovimentoFixo,
|
||
|
|
atualizarMovimentoFixo,
|
||
|
|
alterarHabilitadoMovimentoFixo,
|
||
|
|
deletarMovimentoFixo,
|
||
|
|
};
|