ajustado movimentos fixos sangria
This commit is contained in:
parent
12dcc8506f
commit
36aba1c646
|
|
@ -69,6 +69,18 @@ function validarDadosMovimentoFixo(dados) {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
dados.idbancos_p !== undefined &&
|
||||
dados.idbancos_p !== null &&
|
||||
dados.idbancos_p !== ''
|
||||
) {
|
||||
const idbancosP = Number(dados.idbancos_p);
|
||||
|
||||
if (!Number.isInteger(idbancosP) || idbancosP <= 0) {
|
||||
return 'Banco de destino inválido.';
|
||||
}
|
||||
}
|
||||
|
||||
if (dados.habilitado !== undefined && dados.habilitado !== null && dados.habilitado !== '') {
|
||||
const habilitado = Number(dados.habilitado);
|
||||
|
||||
|
|
@ -77,6 +89,41 @@ function validarDadosMovimentoFixo(dados) {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
dados.gerar_automatico !== undefined &&
|
||||
dados.gerar_automatico !== null &&
|
||||
dados.gerar_automatico !== ''
|
||||
) {
|
||||
const gerarAutomatico =
|
||||
Number(dados.gerar_automatico);
|
||||
|
||||
if (![0, 1].includes(gerarAutomatico)) {
|
||||
return 'Configuração de geração automática inválida.';
|
||||
}
|
||||
}
|
||||
|
||||
if (dados.movimento === 'Sangria') {
|
||||
const idBancoOrigem = Number(dados.idbancos);
|
||||
const idBancoDestino = Number(dados.idbancos_p);
|
||||
|
||||
if (!idBancoDestino) {
|
||||
return 'Banco de destino é obrigatório para sangria.';
|
||||
}
|
||||
|
||||
if (idBancoOrigem === idBancoDestino) {
|
||||
return 'Banco de origem e banco de destino não podem ser iguais.';
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
dados.movimento !== 'Sangria' &&
|
||||
dados.idbancos_p !== undefined &&
|
||||
dados.idbancos_p !== null &&
|
||||
dados.idbancos_p !== ''
|
||||
) {
|
||||
return 'Banco de destino somente pode ser informado em uma sangria.';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -84,22 +131,24 @@ async function listar(req, res) {
|
|||
try {
|
||||
const idUsuario = extrairIdUsuarioLogado(req);
|
||||
|
||||
const resultado = await movimentosFixosService.listarMovimentosFixos({
|
||||
limite: req.query.limite,
|
||||
offset: req.query.offset,
|
||||
page: req.query.page,
|
||||
busca: req.query.busca,
|
||||
movimento: req.query.movimento,
|
||||
idbancos: req.query.idbancos,
|
||||
idcentrodecustos: req.query.idcentrodecustos,
|
||||
idclientes: req.query.idclientes,
|
||||
habilitado: req.query.habilitado,
|
||||
diaInicio: req.query.diaInicio,
|
||||
diaFim: req.query.diaFim,
|
||||
orderBy: req.query.orderBy,
|
||||
orderDirection: req.query.orderDirection,
|
||||
idUsuario,
|
||||
});
|
||||
const resultado =
|
||||
await movimentosFixosService.listarMovimentosFixos({
|
||||
limite: req.query.limite,
|
||||
offset: req.query.offset,
|
||||
page: req.query.page,
|
||||
busca: req.query.busca,
|
||||
movimento: req.query.movimento,
|
||||
idbancos: req.query.idbancos,
|
||||
idcentrodecustos: req.query.idcentrodecustos,
|
||||
idclientes: req.query.idclientes,
|
||||
habilitado: req.query.habilitado,
|
||||
gerar_automatico: req.query.gerar_automatico,
|
||||
diaInicio: req.query.diaInicio,
|
||||
diaFim: req.query.diaFim,
|
||||
orderBy: req.query.orderBy,
|
||||
orderDirection: req.query.orderDirection,
|
||||
idUsuario,
|
||||
});
|
||||
|
||||
return res.json({
|
||||
ok: true,
|
||||
|
|
@ -176,9 +225,12 @@ async function criar(req, res) {
|
|||
} catch (error) {
|
||||
console.error('Erro ao criar movimento fixo:', error);
|
||||
|
||||
return res.status(500).json({
|
||||
return res.status(error.statusCode || 500).json({
|
||||
ok: false,
|
||||
message: 'Erro ao criar movimento fixo.',
|
||||
message:
|
||||
error.statusCode
|
||||
? error.message
|
||||
: 'Erro ao criar movimento fixo.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -222,9 +274,12 @@ async function atualizar(req, res) {
|
|||
} catch (error) {
|
||||
console.error('Erro ao atualizar movimento fixo:', error);
|
||||
|
||||
return res.status(500).json({
|
||||
return res.status(error.statusCode || 500).json({
|
||||
ok: false,
|
||||
message: 'Erro ao atualizar movimento fixo.',
|
||||
message:
|
||||
error.statusCode
|
||||
? error.message
|
||||
: 'Erro ao atualizar movimento fixo.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,19 +9,31 @@ const CAMPOS_MOVIMENTO_FIXO_SELECT = `
|
|||
mf.idcentrodecustos,
|
||||
mf.idclientes,
|
||||
mf.habilitado,
|
||||
mf.gerar_automatico,
|
||||
mf.ultimo_mes_gerado,
|
||||
mf.idbancos,
|
||||
mf.idbancos_p,
|
||||
mf.insert_date,
|
||||
mf.update_date,
|
||||
b.descricao AS banco_descricao,
|
||||
bp.descricao AS banco_destino_descricao,
|
||||
cc.descricao AS centro_custo_descricao,
|
||||
c.nome AS cliente_nome
|
||||
`;
|
||||
|
||||
const FROM_MOVIMENTO_FIXO_JOIN = `
|
||||
FROM movimentosfixos mf
|
||||
INNER JOIN bancos b ON b.idbancos = mf.idbancos
|
||||
LEFT JOIN centrodecustos cc ON cc.idcentrodecustos = mf.idcentrodecustos
|
||||
LEFT JOIN clientes c ON c.idclientes = mf.idclientes
|
||||
INNER JOIN bancos b
|
||||
ON b.idbancos = mf.idbancos
|
||||
|
||||
LEFT JOIN bancos bp
|
||||
ON bp.idbancos = mf.idbancos_p
|
||||
|
||||
LEFT JOIN centrodecustos cc
|
||||
ON cc.idcentrodecustos = mf.idcentrodecustos
|
||||
|
||||
LEFT JOIN clientes c
|
||||
ON c.idclientes = mf.idclientes
|
||||
`;
|
||||
|
||||
function normalizarTextoOuNull(valor) {
|
||||
|
|
@ -96,10 +108,14 @@ function resolverOrdenacao(orderBy) {
|
|||
idcentrodecustos: 'mf.idcentrodecustos',
|
||||
idclientes: 'mf.idclientes',
|
||||
idbancos: 'mf.idbancos',
|
||||
idbancos_p: 'mf.idbancos_p',
|
||||
habilitado: 'mf.habilitado',
|
||||
gerar_automatico: 'mf.gerar_automatico',
|
||||
ultimo_mes_gerado: 'mf.ultimo_mes_gerado',
|
||||
insert_date: 'mf.insert_date',
|
||||
update_date: 'mf.update_date',
|
||||
banco_descricao: 'b.descricao',
|
||||
banco_destino_descricao: 'bp.descricao',
|
||||
centro_custo_descricao: 'cc.descricao',
|
||||
cliente_nome: 'c.nome',
|
||||
};
|
||||
|
|
@ -145,6 +161,15 @@ function montarWhereMovimentosFixos(filtros = {}) {
|
|||
params.push(Number(filtros.habilitado));
|
||||
}
|
||||
|
||||
if (
|
||||
filtros.gerar_automatico !== undefined &&
|
||||
filtros.gerar_automatico !== null &&
|
||||
filtros.gerar_automatico !== ''
|
||||
) {
|
||||
where.push('mf.gerar_automatico = ?');
|
||||
params.push(Number(filtros.gerar_automatico));
|
||||
}
|
||||
|
||||
if (filtros.diaInicio) {
|
||||
where.push('mf.dia_vencimento >= ?');
|
||||
params.push(Number(filtros.diaInicio));
|
||||
|
|
@ -161,6 +186,7 @@ function montarWhereMovimentosFixos(filtros = {}) {
|
|||
mf.descricao LIKE ?
|
||||
OR mf.movimento LIKE ?
|
||||
OR b.descricao LIKE ?
|
||||
OR bp.descricao LIKE ?
|
||||
OR cc.descricao LIKE ?
|
||||
OR c.nome LIKE ?
|
||||
)
|
||||
|
|
@ -173,6 +199,7 @@ function montarWhereMovimentosFixos(filtros = {}) {
|
|||
termo,
|
||||
termo,
|
||||
termo,
|
||||
termo,
|
||||
termo
|
||||
);
|
||||
}
|
||||
|
|
@ -203,6 +230,110 @@ async function bancoPertenceAoUsuario(idbancos, idUsuario) {
|
|||
return rows.length > 0;
|
||||
}
|
||||
|
||||
async function bancoExiste(idbancos) {
|
||||
if (!idbancos) return false;
|
||||
|
||||
const [rows] = await pool.query(
|
||||
`
|
||||
SELECT idbancos
|
||||
FROM bancos
|
||||
WHERE idbancos = ?
|
||||
AND habilitado = 1
|
||||
LIMIT 1
|
||||
`,
|
||||
[Number(idbancos)]
|
||||
);
|
||||
|
||||
return rows.length > 0;
|
||||
}
|
||||
|
||||
async function normalizarReferenciasMovimentoFixo(
|
||||
dados,
|
||||
idUsuario
|
||||
) {
|
||||
const movimento =
|
||||
normalizarTextoOuNull(dados.movimento);
|
||||
|
||||
const idBanco =
|
||||
normalizarNumeroOuNull(dados.idbancos);
|
||||
|
||||
const idBancoDestinoRecebido =
|
||||
normalizarNumeroOuNull(dados.idbancos_p);
|
||||
|
||||
const idClienteRecebido =
|
||||
normalizarNumeroOuNull(dados.idclientes);
|
||||
|
||||
const isSangria = movimento === 'Sangria';
|
||||
|
||||
if (!idBanco) {
|
||||
const error = new Error(
|
||||
'Banco/carteira é obrigatório para movimento fixo.'
|
||||
);
|
||||
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const bancoPrincipalValido =
|
||||
await bancoPertenceAoUsuario(
|
||||
idBanco,
|
||||
idUsuario
|
||||
);
|
||||
|
||||
if (!bancoPrincipalValido) {
|
||||
const error = new Error(
|
||||
'Banco/carteira não pertence ao usuário logado.'
|
||||
);
|
||||
|
||||
error.statusCode = 403;
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (isSangria) {
|
||||
if (!idBancoDestinoRecebido) {
|
||||
const error = new Error(
|
||||
'Banco de destino é obrigatório para sangria.'
|
||||
);
|
||||
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (idBanco === idBancoDestinoRecebido) {
|
||||
const error = new Error(
|
||||
'Banco de origem e banco de destino não podem ser iguais.'
|
||||
);
|
||||
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const bancoDestinoValido =
|
||||
await bancoExiste(idBancoDestinoRecebido);
|
||||
|
||||
if (!bancoDestinoValido) {
|
||||
const error = new Error(
|
||||
'Banco de destino inválido ou desabilitado.'
|
||||
);
|
||||
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
idbancos: idBanco,
|
||||
idclientes: null,
|
||||
idbancos_p: idBancoDestinoRecebido,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
idbancos: idBanco,
|
||||
idclientes: idClienteRecebido,
|
||||
idbancos_p: null,
|
||||
};
|
||||
}
|
||||
|
||||
async function listarMovimentosFixos(filtros = {}) {
|
||||
const limite = limitarNumero(filtros.limite, 20, 1, 100);
|
||||
const page = limitarNumero(filtros.page, 1, 1, 999999);
|
||||
|
|
@ -241,10 +372,10 @@ async function listarMovimentosFixos(filtros = {}) {
|
|||
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.movimento = 'Entrada' and mf.habilitado = 1 THEN mf.valor ELSE 0 END), 0) AS totalEntradas,
|
||||
COALESCE(SUM(CASE WHEN mf.movimento = 'Saida' and mf.habilitado = 1 THEN mf.valor ELSE 0 END), 0) AS totalSaidas,
|
||||
COALESCE(SUM(CASE WHEN mf.movimento = 'Sangria' and mf.habilitado = 1 THEN mf.valor ELSE 0 END), 0) AS totalSangrias,
|
||||
COALESCE(SUM(CASE WHEN mf.movimento = 'Estorno' and mf.habilitado = 1 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}
|
||||
|
|
@ -309,26 +440,34 @@ async function criarMovimentoFixo(dados, idUsuario) {
|
|||
valor,
|
||||
dia_vencimento,
|
||||
idcentrodecustos,
|
||||
idclientes,
|
||||
habilitado,
|
||||
idbancos,
|
||||
gerar_automatico,
|
||||
} = dados;
|
||||
|
||||
const idBancoNormalizado = normalizarNumeroOuNull(idbancos);
|
||||
const movimentoNormalizado =
|
||||
normalizarTextoOuNull(movimento);
|
||||
|
||||
const movimentosPermitidos = [
|
||||
'Entrada',
|
||||
'Saida',
|
||||
'Sangria',
|
||||
'Estorno',
|
||||
];
|
||||
|
||||
if (!movimentosPermitidos.includes(movimentoNormalizado)) {
|
||||
const error = new Error(
|
||||
'Tipo de movimento fixo inválido.'
|
||||
);
|
||||
|
||||
if (!idBancoNormalizado) {
|
||||
const error = new Error('Banco/carteira é obrigatório para movimento fixo.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const bancoValido = await bancoPertenceAoUsuario(idBancoNormalizado, idUsuario);
|
||||
|
||||
if (!bancoValido) {
|
||||
const error = new Error('Banco/carteira não pertence ao usuário logado.');
|
||||
error.statusCode = 403;
|
||||
throw error;
|
||||
}
|
||||
const referencias =
|
||||
await normalizarReferenciasMovimentoFixo(
|
||||
dados,
|
||||
idUsuario
|
||||
);
|
||||
|
||||
const [result] = await pool.query(
|
||||
`
|
||||
|
|
@ -340,28 +479,46 @@ async function criarMovimentoFixo(dados, idUsuario) {
|
|||
idcentrodecustos,
|
||||
idclientes,
|
||||
habilitado,
|
||||
gerar_automatico,
|
||||
ultimo_mes_gerado,
|
||||
idbancos,
|
||||
idbancos_p,
|
||||
insert_date,
|
||||
update_date
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, NOW(), NOW()
|
||||
)
|
||||
`,
|
||||
[
|
||||
normalizarTextoOuNull(movimento),
|
||||
movimentoNormalizado,
|
||||
normalizarTextoOuNull(descricao),
|
||||
normalizarNumero(valor, 0),
|
||||
normalizarNumero(dia_vencimento, 1),
|
||||
normalizarNumeroOuNull(idcentrodecustos),
|
||||
normalizarNumeroOuNull(idclientes),
|
||||
referencias.idclientes,
|
||||
normalizarFlag(habilitado, 1),
|
||||
idBancoNormalizado,
|
||||
normalizarFlag(gerar_automatico, 1),
|
||||
referencias.idbancos,
|
||||
referencias.idbancos_p,
|
||||
]
|
||||
);
|
||||
|
||||
return buscarMovimentoFixoPorId(result.insertId, idUsuario);
|
||||
return buscarMovimentoFixoPorId(
|
||||
result.insertId,
|
||||
idUsuario
|
||||
);
|
||||
}
|
||||
|
||||
async function atualizarMovimentoFixo(id, dados, idUsuario) {
|
||||
const movimentoAtual = await buscarMovimentoFixoPorId(id, idUsuario);
|
||||
async function atualizarMovimentoFixo(
|
||||
id,
|
||||
dados,
|
||||
idUsuario
|
||||
) {
|
||||
const movimentoAtual =
|
||||
await buscarMovimentoFixoPorId(
|
||||
id,
|
||||
idUsuario
|
||||
);
|
||||
|
||||
if (!movimentoAtual) {
|
||||
return null;
|
||||
|
|
@ -373,26 +530,46 @@ async function atualizarMovimentoFixo(id, dados, idUsuario) {
|
|||
valor,
|
||||
dia_vencimento,
|
||||
idcentrodecustos,
|
||||
idclientes,
|
||||
habilitado,
|
||||
idbancos,
|
||||
gerar_automatico,
|
||||
} = dados;
|
||||
|
||||
const idBancoNormalizado = normalizarNumeroOuNull(idbancos);
|
||||
const movimentoNormalizado =
|
||||
normalizarTextoOuNull(movimento);
|
||||
|
||||
const movimentosPermitidos = [
|
||||
'Entrada',
|
||||
'Saida',
|
||||
'Sangria',
|
||||
'Estorno',
|
||||
];
|
||||
|
||||
if (!movimentosPermitidos.includes(movimentoNormalizado)) {
|
||||
const error = new Error(
|
||||
'Tipo de movimento fixo inválido.'
|
||||
);
|
||||
|
||||
if (!idBancoNormalizado) {
|
||||
const error = new Error('Banco/carteira é obrigatório para movimento fixo.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const bancoValido = await bancoPertenceAoUsuario(idBancoNormalizado, idUsuario);
|
||||
const referencias =
|
||||
await normalizarReferenciasMovimentoFixo(
|
||||
dados,
|
||||
idUsuario
|
||||
);
|
||||
|
||||
if (!bancoValido) {
|
||||
const error = new Error('Banco/carteira não pertence ao usuário logado.');
|
||||
error.statusCode = 403;
|
||||
throw error;
|
||||
}
|
||||
const gerarAutomaticoNormalizado =
|
||||
gerar_automatico === undefined ||
|
||||
gerar_automatico === null ||
|
||||
gerar_automatico === ''
|
||||
? Number(
|
||||
movimentoAtual.gerar_automatico ?? 1
|
||||
)
|
||||
: normalizarFlag(
|
||||
gerar_automatico,
|
||||
1
|
||||
);
|
||||
|
||||
await pool.query(
|
||||
`
|
||||
|
|
@ -405,24 +582,31 @@ async function atualizarMovimentoFixo(id, dados, idUsuario) {
|
|||
idcentrodecustos = ?,
|
||||
idclientes = ?,
|
||||
habilitado = ?,
|
||||
gerar_automatico = ?,
|
||||
idbancos = ?,
|
||||
idbancos_p = ?,
|
||||
update_date = NOW()
|
||||
WHERE idmovimentosfixos = ?
|
||||
`,
|
||||
[
|
||||
normalizarTextoOuNull(movimento),
|
||||
movimentoNormalizado,
|
||||
normalizarTextoOuNull(descricao),
|
||||
normalizarNumero(valor, 0),
|
||||
normalizarNumero(dia_vencimento, 1),
|
||||
normalizarNumeroOuNull(idcentrodecustos),
|
||||
normalizarNumeroOuNull(idclientes),
|
||||
referencias.idclientes,
|
||||
normalizarFlag(habilitado, 1),
|
||||
idBancoNormalizado,
|
||||
gerarAutomaticoNormalizado,
|
||||
referencias.idbancos,
|
||||
referencias.idbancos_p,
|
||||
id,
|
||||
]
|
||||
);
|
||||
|
||||
return buscarMovimentoFixoPorId(id, idUsuario);
|
||||
return buscarMovimentoFixoPorId(
|
||||
id,
|
||||
idUsuario
|
||||
);
|
||||
}
|
||||
|
||||
async function alterarHabilitadoMovimentoFixo(id, habilitado, idUsuario) {
|
||||
|
|
|
|||
|
|
@ -85,26 +85,21 @@ function statusInicialPorMovimento(movimento) {
|
|||
return 'A receber';
|
||||
}
|
||||
|
||||
if (movimento === 'Saida') {
|
||||
if (movimento === 'Saida' || movimento === 'Sangria') {
|
||||
return 'A pagar';
|
||||
}
|
||||
|
||||
if (movimento === 'Sangria') {
|
||||
return 'Pago';
|
||||
}
|
||||
|
||||
return 'A pagar';
|
||||
}
|
||||
|
||||
function dataBaixaInicialPorMovimento(movimento, dataVencimento) {
|
||||
if (movimento === 'Sangria') {
|
||||
return dataVencimento;
|
||||
}
|
||||
|
||||
function dataBaixaInicialPorMovimento() {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function buscarFixosDoUsuario(connection, idUsuario) {
|
||||
async function buscarFixosDoUsuario(
|
||||
connection,
|
||||
idUsuario
|
||||
) {
|
||||
const [rows] = await connection.query(
|
||||
`
|
||||
SELECT
|
||||
|
|
@ -115,11 +110,19 @@ async function buscarFixosDoUsuario(connection, idUsuario) {
|
|||
mf.dia_vencimento,
|
||||
mf.idcentrodecustos,
|
||||
mf.idclientes,
|
||||
mf.idbancos
|
||||
mf.idbancos,
|
||||
mf.idbancos_p
|
||||
FROM movimentosfixos mf
|
||||
INNER JOIN bancos b ON b.idbancos = mf.idbancos
|
||||
INNER JOIN bancos b
|
||||
ON b.idbancos = mf.idbancos
|
||||
WHERE mf.habilitado = 1
|
||||
AND mf.gerar_automatico = 1
|
||||
AND mf.movimento IN (
|
||||
'Entrada',
|
||||
'Saida',
|
||||
'Sangria',
|
||||
'Estorno'
|
||||
)
|
||||
AND b.idusuarios = ?
|
||||
ORDER BY mf.idmovimentosfixos ASC
|
||||
`,
|
||||
|
|
@ -183,35 +186,53 @@ async function jaExisteMovimentoFixo(connection, fixo, competencia) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const [rowsMovimentoLegado] = await connection.query(
|
||||
`
|
||||
SELECT idcontasapagar
|
||||
FROM contasapagar
|
||||
WHERE deleted_at IS NULL
|
||||
AND idmovimentosfixos IS NULL
|
||||
AND competencia IS NULL
|
||||
AND movimento = ?
|
||||
AND descricao = ?
|
||||
AND idbancos = ?
|
||||
AND (
|
||||
(? IS NULL AND idcentrodecustos IS NULL)
|
||||
OR idcentrodecustos = ?
|
||||
)
|
||||
AND DATE(datavencimento) BETWEEN ? AND ?
|
||||
ORDER BY idcontasapagar DESC
|
||||
LIMIT 1
|
||||
FOR UPDATE
|
||||
`,
|
||||
[
|
||||
fixo.movimento,
|
||||
fixo.descricao,
|
||||
fixo.idbancos,
|
||||
fixo.idcentrodecustos || null,
|
||||
fixo.idcentrodecustos || null,
|
||||
`${competencia}-01`,
|
||||
`${competencia}-31`,
|
||||
]
|
||||
);
|
||||
const [rowsMovimentoLegado] =
|
||||
await connection.query(
|
||||
`
|
||||
SELECT idcontasapagar
|
||||
FROM contasapagar
|
||||
WHERE deleted_at IS NULL
|
||||
AND idmovimentosfixos IS NULL
|
||||
AND competencia IS NULL
|
||||
AND movimento = ?
|
||||
AND descricao = ?
|
||||
AND idbancos = ?
|
||||
AND (
|
||||
(? IS NULL AND idcentrodecustos IS NULL)
|
||||
OR idcentrodecustos = ?
|
||||
)
|
||||
AND (
|
||||
(? IS NULL AND idclientes IS NULL)
|
||||
OR idclientes = ?
|
||||
)
|
||||
AND (
|
||||
(? IS NULL AND idbancos_p IS NULL)
|
||||
OR idbancos_p = ?
|
||||
)
|
||||
AND DATE(datavencimento)
|
||||
BETWEEN ? AND ?
|
||||
ORDER BY idcontasapagar DESC
|
||||
LIMIT 1
|
||||
FOR UPDATE
|
||||
`,
|
||||
[
|
||||
fixo.movimento,
|
||||
fixo.descricao,
|
||||
fixo.idbancos,
|
||||
|
||||
fixo.idcentrodecustos || null,
|
||||
fixo.idcentrodecustos || null,
|
||||
|
||||
fixo.idclientes || null,
|
||||
fixo.idclientes || null,
|
||||
|
||||
fixo.idbancos_p || null,
|
||||
fixo.idbancos_p || null,
|
||||
|
||||
`${competencia}-01`,
|
||||
`${competencia}-31`,
|
||||
]
|
||||
);
|
||||
|
||||
if (rowsMovimentoLegado.length > 0) {
|
||||
const idContasPagar = rowsMovimentoLegado[0].idcontasapagar;
|
||||
|
|
@ -289,7 +310,20 @@ async function inserirMovimentoFixoGerado(connection, fixo, competencia, idUsuar
|
|||
insert_date,
|
||||
update_date,
|
||||
deleted_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, NULL, 'movimento_fixo', 0, NULL, NOW(), NOW(), NULL)
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?,
|
||||
1, 1,
|
||||
?, ?, ?, ?, ?, ?,
|
||||
NULL,
|
||||
?, ?, ?,
|
||||
NULL,
|
||||
'movimento_fixo',
|
||||
0,
|
||||
NULL,
|
||||
NOW(),
|
||||
NOW(),
|
||||
NULL
|
||||
)
|
||||
`,
|
||||
[
|
||||
fixo.movimento,
|
||||
|
|
@ -303,7 +337,15 @@ async function inserirMovimentoFixoGerado(connection, fixo, competencia, idUsuar
|
|||
fixo.idbancos || null,
|
||||
idUsuario,
|
||||
dataBaixa ? idUsuario : null,
|
||||
fixo.idclientes || null,
|
||||
|
||||
fixo.movimento === 'Sangria'
|
||||
? null
|
||||
: fixo.idclientes || null,
|
||||
|
||||
fixo.movimento === 'Sangria'
|
||||
? fixo.idbancos_p || null
|
||||
: null,
|
||||
|
||||
fixo.idmovimentosfixos,
|
||||
competencia,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ function pad2(valor) {
|
|||
return String(valor).padStart(2, '0');
|
||||
}
|
||||
|
||||
function resolverInvestimentoMovimento(movimento) {
|
||||
const centroEhInvestimento =
|
||||
Number(movimento.centro_custo_investimento) === 1;
|
||||
|
||||
const destinoEhInvestimento =
|
||||
movimento.movimento === 'Sangria' &&
|
||||
Number(movimento.banco_referencia_investimento) === 1;
|
||||
|
||||
return centroEhInvestimento || destinoEhInvestimento
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
function ultimoDiaDoMes(ano, mes) {
|
||||
return new Date(Number(ano), Number(mes), 0).getDate();
|
||||
}
|
||||
|
|
@ -218,7 +231,8 @@ async function buscarMovimentosDoMes(connection, { idUsuario, dataInicio, dataFi
|
|||
cc.descricao AS centro_custo_descricao,
|
||||
cc.investimento AS centro_custo_investimento,
|
||||
c.nome AS cliente_nome,
|
||||
bp.descricao AS banco_referencia_descricao
|
||||
bp.descricao AS banco_referencia_descricao,
|
||||
bp.investimento AS banco_referencia_investimento
|
||||
FROM contasapagar cp
|
||||
INNER JOIN bancos b
|
||||
ON b.idbancos = cp.idbancos
|
||||
|
|
@ -287,14 +301,23 @@ async function buscarFixosUsuario(connection, idUsuario) {
|
|||
mf.idcentrodecustos,
|
||||
mf.idclientes,
|
||||
mf.idbancos,
|
||||
mf.idbancos_p,
|
||||
|
||||
b.descricao AS banco_descricao,
|
||||
b.debito AS banco_debito,
|
||||
|
||||
bp.descricao AS banco_referencia_descricao,
|
||||
bp.investimento AS banco_referencia_investimento,
|
||||
|
||||
cc.descricao AS centro_custo_descricao,
|
||||
cc.investimento AS centro_custo_investimento,
|
||||
|
||||
c.nome AS cliente_nome
|
||||
FROM movimentosfixos mf
|
||||
INNER JOIN bancos b
|
||||
ON b.idbancos = mf.idbancos
|
||||
LEFT JOIN bancos bp
|
||||
ON bp.idbancos = mf.idbancos_p
|
||||
LEFT JOIN centrodecustos cc
|
||||
ON cc.idcentrodecustos = mf.idcentrodecustos
|
||||
LEFT JOIN clientes c
|
||||
|
|
@ -302,7 +325,9 @@ async function buscarFixosUsuario(connection, idUsuario) {
|
|||
WHERE mf.habilitado = 1
|
||||
AND b.idusuarios = ?
|
||||
AND COALESCE(mf.gerar_automatico, 1) = 1
|
||||
ORDER BY mf.dia_vencimento ASC, mf.descricao ASC
|
||||
ORDER BY
|
||||
mf.dia_vencimento ASC,
|
||||
mf.descricao ASC
|
||||
`,
|
||||
[idUsuario]
|
||||
);
|
||||
|
|
@ -363,8 +388,14 @@ function montarItensMovimentosExistentes(movimentosDoMes, incluirQuitadas) {
|
|||
const saidas = [];
|
||||
|
||||
for (const movimento of movimentosDoMes) {
|
||||
const bancoDebito = Number(movimento.banco_debito) === 1;
|
||||
const bancoCredito = Number(movimento.banco_debito) === 0;
|
||||
const bancoDebito =
|
||||
Number(movimento.banco_debito) === 1;
|
||||
|
||||
const bancoCredito =
|
||||
Number(movimento.banco_debito) === 0;
|
||||
|
||||
const investimento =
|
||||
resolverInvestimentoMovimento(movimento);
|
||||
|
||||
if (bancoDebito) {
|
||||
if (!incluirQuitadas && !statusEmAberto(movimento.status)) {
|
||||
|
|
@ -387,7 +418,7 @@ function montarItensMovimentosExistentes(movimentosDoMes, incluirQuitadas) {
|
|||
banco_debito: movimento.banco_debito,
|
||||
idcentrodecustos: movimento.idcentrodecustos,
|
||||
centro_custo_descricao: movimento.centro_custo_descricao,
|
||||
investimento: movimento.centro_custo_investimento,
|
||||
investimento: investimento,
|
||||
idclientes: movimento.idclientes,
|
||||
cliente_nome: movimento.cliente_nome,
|
||||
detalhes: {
|
||||
|
|
@ -415,7 +446,7 @@ function montarItensMovimentosExistentes(movimentosDoMes, incluirQuitadas) {
|
|||
banco_debito: movimento.banco_debito,
|
||||
idcentrodecustos: movimento.idcentrodecustos,
|
||||
centro_custo_descricao: movimento.centro_custo_descricao,
|
||||
investimento: movimento.centro_custo_investimento,
|
||||
investimento: investimento,
|
||||
idclientes: movimento.idclientes,
|
||||
cliente_nome: movimento.cliente_nome,
|
||||
detalhes: {
|
||||
|
|
@ -443,7 +474,7 @@ function montarItensMovimentosExistentes(movimentosDoMes, incluirQuitadas) {
|
|||
banco_debito: movimento.banco_debito,
|
||||
idcentrodecustos: movimento.idcentrodecustos,
|
||||
centro_custo_descricao: movimento.centro_custo_descricao,
|
||||
investimento: movimento.centro_custo_investimento,
|
||||
investimento: investimento,
|
||||
idclientes: movimento.idclientes,
|
||||
cliente_nome: movimento.cliente_nome,
|
||||
})
|
||||
|
|
@ -553,6 +584,7 @@ function montarItensFixosPrevistos({
|
|||
}
|
||||
|
||||
const dataVencimento = montarDataVencimento(ano, mes, fixo.dia_vencimento);
|
||||
const investimento = resolverInvestimentoMovimento(fixo);
|
||||
|
||||
if (movimentoEhEntrada(fixo.movimento)) {
|
||||
entradas.push(
|
||||
|
|
@ -570,7 +602,7 @@ function montarItensFixosPrevistos({
|
|||
banco_debito: fixo.banco_debito,
|
||||
idcentrodecustos: fixo.idcentrodecustos,
|
||||
centro_custo_descricao: fixo.centro_custo_descricao,
|
||||
investimento: fixo.centro_custo_investimento,
|
||||
investimento: investimento,
|
||||
idclientes: fixo.idclientes,
|
||||
cliente_nome: fixo.cliente_nome,
|
||||
})
|
||||
|
|
@ -585,15 +617,16 @@ function montarItensFixosPrevistos({
|
|||
descricao: fixo.descricao,
|
||||
valor: fixo.valor,
|
||||
movimento: fixo.movimento,
|
||||
status: fixo.movimento === 'Sangria' ? 'Pago' : 'A pagar',
|
||||
status: 'A pagar',
|
||||
data: dataVencimento,
|
||||
idmovimentosfixos: fixo.idmovimentosfixos,
|
||||
idbancos: fixo.idbancos,
|
||||
banco_descricao: fixo.banco_descricao,
|
||||
banco_debito: fixo.banco_debito,
|
||||
idcentrodecustos: fixo.idcentrodecustos,
|
||||
centro_custo_descricao: fixo.centro_custo_descricao,
|
||||
investimento: fixo.centro_custo_investimento,
|
||||
centro_custo_descricao:
|
||||
fixo.centro_custo_descricao,
|
||||
investimento,
|
||||
idclientes: fixo.idclientes,
|
||||
cliente_nome: fixo.cliente_nome,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -283,9 +283,13 @@ export function MovimentoForm({ mode, initialData }: MovimentoFormProps) {
|
|||
}, [meusBancos, idBanco]);
|
||||
|
||||
const statusDisponiveis = useMemo<MovimentoStatus[]>(() => {
|
||||
if (movimento === 'Entrada') return ['Recebido', 'A receber'];
|
||||
if (movimento === 'Saida') return ['Pago', 'A pagar'];
|
||||
if (movimento === 'Sangria') return ['Pago'];
|
||||
if (movimento === 'Entrada') {
|
||||
return ['Recebido', 'A receber'];
|
||||
}
|
||||
|
||||
if (movimento === 'Saida' || movimento === 'Sangria') {
|
||||
return ['Pago', 'A pagar'];
|
||||
}
|
||||
|
||||
return ['Pago', 'Recebido'];
|
||||
}, [movimento]);
|
||||
|
|
@ -324,8 +328,6 @@ export function MovimentoForm({ mode, initialData }: MovimentoFormProps) {
|
|||
|
||||
if (movimento === 'Sangria') {
|
||||
setReferenciaTipo('banco');
|
||||
setStatus('Pago');
|
||||
setDataBaixa((dataAtual) => dataAtual || hojeISO());
|
||||
setParcelas('1');
|
||||
setParcela('1');
|
||||
setGerarParcelas(false);
|
||||
|
|
@ -415,6 +417,17 @@ export function MovimentoForm({ mode, initialData }: MovimentoFormProps) {
|
|||
status,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'A pagar' || status === 'A receber') {
|
||||
setDataBaixa('');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dataBaixa) {
|
||||
setDataBaixa(hojeISO());
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
function limparFormulario() {
|
||||
setDescricao('');
|
||||
setValor('');
|
||||
|
|
@ -567,8 +580,10 @@ export function MovimentoForm({ mode, initialData }: MovimentoFormProps) {
|
|||
function montarPayload(confirmarDuplicado = false): CriarMovimentoRequest {
|
||||
const isSangria = movimento === 'Sangria';
|
||||
|
||||
const statusFinal = isSangria ? 'Pago' : status;
|
||||
const referenciaTipoFinal = isSangria ? 'banco' : referenciaTipo;
|
||||
const statusFinal = status;
|
||||
const referenciaTipoFinal = isSangria
|
||||
? 'banco'
|
||||
: referenciaTipo;
|
||||
const parcelaFinal = isSangria ? 1 : Number(parcela || 1);
|
||||
const parcelasFinal = isSangria ? 1 : Number(parcelas || 1);
|
||||
const dataBaixaFinal =
|
||||
|
|
@ -731,7 +746,6 @@ export function MovimentoForm({ mode, initialData }: MovimentoFormProps) {
|
|||
label="Situação"
|
||||
value={status}
|
||||
onChange={(event) => setStatus(event.target.value as MovimentoStatus)}
|
||||
disabled={movimento === 'Sangria'}
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import EventRepeatIcon from '@mui/icons-material/EventRepeat';
|
|||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
listarBancos,
|
||||
listarMeusBancos,
|
||||
listarCentrosCusto,
|
||||
listarClientes,
|
||||
|
|
@ -123,9 +124,8 @@ function movimentoLabel(movimento: MovimentoFixoTipo) {
|
|||
export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const isEdit = mode === 'edit';
|
||||
|
||||
const [bancos, setBancos] = useState<Banco[]>([]);
|
||||
const [meusBancos, setMeusBancos] = useState<Banco[]>([]);
|
||||
const [todosBancos, setTodosBancos] = useState<Banco[]>([]);
|
||||
const [centrosCusto, setCentrosCusto] = useState<CentroCusto[]>([]);
|
||||
const [clientes, setClientes] = useState<Cliente[]>([]);
|
||||
|
||||
|
|
@ -141,7 +141,16 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
const [idCentroCusto, setIdCentroCusto] = useState('');
|
||||
const [idCliente, setIdCliente] = useState('');
|
||||
const [idBanco, setIdBanco] = useState('');
|
||||
const [idBancoReferencia, setIdBancoReferencia] = useState('');
|
||||
const [habilitado, setHabilitado] = useState('1');
|
||||
const [gerarAutomatico, setGerarAutomatico] = useState('1');
|
||||
|
||||
const isEdit = mode === 'edit';
|
||||
const isSangria = movimento === 'Sangria';
|
||||
const usaCliente =
|
||||
movimento === 'Entrada' ||
|
||||
movimento === 'Saida' ||
|
||||
movimento === 'Estorno';
|
||||
|
||||
const titulo = isEdit ? 'Editar movimento fixo' : 'Novo movimento fixo';
|
||||
const subtitulo = isEdit
|
||||
|
|
@ -149,10 +158,19 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
: 'Cadastre lançamentos recorrentes para automatizar o financeiro depois.';
|
||||
|
||||
const movimentoDescricao = useMemo(() => {
|
||||
if (movimento === 'Entrada') return 'Entrada recorrente';
|
||||
if (movimento === 'Saida') return 'Saída recorrente';
|
||||
if (movimento === 'Sangria') return 'Sangria recorrente';
|
||||
return 'Estorno recorrente';
|
||||
if (movimento === 'Entrada') {
|
||||
return 'Receita recorrente a receber';
|
||||
}
|
||||
|
||||
if (movimento === 'Saida') {
|
||||
return 'Despesa recorrente a pagar';
|
||||
}
|
||||
|
||||
if (movimento === 'Sangria') {
|
||||
return 'Retirada recorrente a efetivar';
|
||||
}
|
||||
|
||||
return 'Estorno recorrente a receber';
|
||||
}, [movimento]);
|
||||
|
||||
const clienteSelecionado = useMemo(() => {
|
||||
|
|
@ -161,6 +179,28 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
return clientes.find((cliente) => String(cliente.id) === String(idCliente)) || null;
|
||||
}, [clientes, idCliente]);
|
||||
|
||||
const bancoOrigemSelecionado = useMemo(() => {
|
||||
if (!idBanco) return null;
|
||||
|
||||
return (
|
||||
meusBancos.find(
|
||||
(banco) =>
|
||||
String(banco.id) === String(idBanco)
|
||||
) || null
|
||||
);
|
||||
}, [meusBancos, idBanco]);
|
||||
|
||||
const bancoDestinoSelecionado = useMemo(() => {
|
||||
if (!idBancoReferencia) return null;
|
||||
|
||||
return (
|
||||
todosBancos.find(
|
||||
(banco) =>
|
||||
String(banco.id) === String(idBancoReferencia)
|
||||
) || null
|
||||
);
|
||||
}, [todosBancos, idBancoReferencia]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialData) return;
|
||||
|
||||
|
|
@ -168,10 +208,38 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
setDescricao(initialData.descricao || '');
|
||||
setValor(String(initialData.valor || ''));
|
||||
setDiaVencimento(String(initialData.dia_vencimento || 1));
|
||||
setIdCentroCusto(initialData.idcentrodecustos ? String(initialData.idcentrodecustos) : '');
|
||||
setIdCliente(initialData.idclientes ? String(initialData.idclientes) : '');
|
||||
setIdBanco(initialData.idbancos ? String(initialData.idbancos) : '');
|
||||
setHabilitado(String(initialData.habilitado ?? 1));
|
||||
|
||||
setIdCentroCusto(
|
||||
initialData.idcentrodecustos
|
||||
? String(initialData.idcentrodecustos)
|
||||
: ''
|
||||
);
|
||||
|
||||
setIdCliente(
|
||||
initialData.idclientes
|
||||
? String(initialData.idclientes)
|
||||
: ''
|
||||
);
|
||||
|
||||
setIdBanco(
|
||||
initialData.idbancos
|
||||
? String(initialData.idbancos)
|
||||
: ''
|
||||
);
|
||||
|
||||
setIdBancoReferencia(
|
||||
initialData.idbancos_p
|
||||
? String(initialData.idbancos_p)
|
||||
: ''
|
||||
);
|
||||
|
||||
setHabilitado(
|
||||
String(initialData.habilitado ?? 1)
|
||||
);
|
||||
|
||||
setGerarAutomatico(
|
||||
String(initialData.gerar_automatico ?? 1)
|
||||
);
|
||||
}, [initialData]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -180,13 +248,20 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
setLoadingRefs(true);
|
||||
setErro('');
|
||||
|
||||
const [bancosData, centrosData, clientesData] = await Promise.all([
|
||||
const [
|
||||
meusBancosData,
|
||||
todosBancosData,
|
||||
centrosData,
|
||||
clientesData,
|
||||
] = await Promise.all([
|
||||
listarMeusBancos(),
|
||||
listarBancos(),
|
||||
listarCentrosCusto(),
|
||||
listarClientes(),
|
||||
]);
|
||||
|
||||
setBancos(bancosData);
|
||||
setMeusBancos(meusBancosData);
|
||||
setTodosBancos(todosBancosData);
|
||||
setCentrosCusto(centrosData);
|
||||
setClientes(clientesData);
|
||||
} catch (error: any) {
|
||||
|
|
@ -203,6 +278,17 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
carregarReferencias();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (movimento === 'Sangria') {
|
||||
// Sangria usa banco de destino e nunca cliente.
|
||||
setIdCliente('');
|
||||
return;
|
||||
}
|
||||
|
||||
// Outros movimentos usam cliente e nunca banco de destino.
|
||||
setIdBancoReferencia('');
|
||||
}, [movimento]);
|
||||
|
||||
function limparFormulario() {
|
||||
setMovimento('Saida');
|
||||
setDescricao('');
|
||||
|
|
@ -211,7 +297,9 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
setIdCentroCusto('');
|
||||
setIdCliente('');
|
||||
setIdBanco('');
|
||||
setIdBancoReferencia('');
|
||||
setHabilitado('1');
|
||||
setGerarAutomatico('1');
|
||||
}
|
||||
|
||||
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
|
|
@ -234,6 +322,28 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!idBanco) {
|
||||
setErro('Selecione o banco ou carteira do movimento fixo.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (usaCliente && !idCliente) {
|
||||
setErro('Selecione o cliente de referência.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSangria) {
|
||||
if (!idBancoReferencia) {
|
||||
setErro('Selecione o banco de destino da sangria.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (String(idBanco) === String(idBancoReferencia)) {
|
||||
setErro('Banco de origem e banco de destino não podem ser iguais.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
setSaving(true);
|
||||
setErro('');
|
||||
|
|
@ -244,10 +354,23 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
descricao: descricao.trim(),
|
||||
valor: Number(valor),
|
||||
dia_vencimento: dia,
|
||||
|
||||
idcentrodecustos: toNumberOrNull(idCentroCusto),
|
||||
idclientes: toNumberOrNull(idCliente),
|
||||
habilitado: Number(habilitado || 1),
|
||||
idbancos: toNumberOrNull(idBanco),
|
||||
|
||||
idclientes:
|
||||
usaCliente
|
||||
? toNumberOrNull(idCliente)
|
||||
: null,
|
||||
|
||||
idbancos: Number(idBanco),
|
||||
|
||||
idbancos_p:
|
||||
isSangria
|
||||
? toNumberOrNull(idBancoReferencia)
|
||||
: null,
|
||||
|
||||
habilitado: Number(habilitado),
|
||||
gerar_automatico: Number(gerarAutomatico),
|
||||
};
|
||||
|
||||
if (isEdit) {
|
||||
|
|
@ -377,6 +500,30 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
<MenuItem value="0">Desabilitado</MenuItem>
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
select
|
||||
label="Geração automática"
|
||||
value={gerarAutomatico}
|
||||
onChange={(event) =>
|
||||
setGerarAutomatico(event.target.value)
|
||||
}
|
||||
helperText={
|
||||
Number(gerarAutomatico) === 1
|
||||
? 'O movimento será gerado automaticamente em cada competência.'
|
||||
: 'O cadastro ficará salvo, mas não será gerado automaticamente.'
|
||||
}
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="1">
|
||||
Gerar automaticamente
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem value="0">
|
||||
Não gerar automaticamente
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
label="Descrição"
|
||||
value={descricao}
|
||||
|
|
@ -415,19 +562,31 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
|
||||
<FormSection
|
||||
title="Classificação"
|
||||
description="Associe banco/carteira, centro de custo e cliente ao movimento fixo."
|
||||
description={
|
||||
isSangria
|
||||
? 'Associe o banco de origem, o banco de destino e o centro de custo.'
|
||||
: 'Associe banco/carteira, centro de custo e cliente ao movimento fixo.'
|
||||
}
|
||||
>
|
||||
<TextField
|
||||
select
|
||||
label="Banco/Carteira"
|
||||
required
|
||||
label={isSangria ? 'Banco de origem' : 'Banco/Carteira'}
|
||||
value={idBanco}
|
||||
onChange={(event) => setIdBanco(event.target.value)}
|
||||
helperText={
|
||||
isSangria
|
||||
? 'Conta da qual o valor será retirado.'
|
||||
: 'Conta ou carteira associada ao movimento.'
|
||||
}
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="">Nenhum</MenuItem>
|
||||
{bancos.map((banco) => (
|
||||
<MenuItem key={banco.id} value={String(banco.id)}>
|
||||
{meusBancos.map((banco) => (
|
||||
<MenuItem
|
||||
key={banco.id}
|
||||
value={String(banco.id)}
|
||||
>
|
||||
{banco.descricao}
|
||||
</MenuItem>
|
||||
))}
|
||||
|
|
@ -437,33 +596,80 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
select
|
||||
label="Centro de custo"
|
||||
value={idCentroCusto}
|
||||
onChange={(event) => setIdCentroCusto(event.target.value)}
|
||||
onChange={(event) =>
|
||||
setIdCentroCusto(event.target.value)
|
||||
}
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="">Nenhum</MenuItem>
|
||||
|
||||
{centrosCusto.map((centro) => (
|
||||
<MenuItem key={centro.id} value={String(centro.id)}>
|
||||
<MenuItem
|
||||
key={centro.id}
|
||||
value={String(centro.id)}
|
||||
>
|
||||
{centro.descricao}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
select
|
||||
label="Cliente"
|
||||
value={idCliente}
|
||||
onChange={(event) => setIdCliente(event.target.value)}
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="">Nenhum</MenuItem>
|
||||
{clientes.map((cliente) => (
|
||||
<MenuItem key={cliente.id} value={String(cliente.id)}>
|
||||
{cliente.nome}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
{usaCliente && (
|
||||
<TextField
|
||||
select
|
||||
required
|
||||
label="Cliente"
|
||||
value={idCliente}
|
||||
onChange={(event) =>
|
||||
setIdCliente(event.target.value)
|
||||
}
|
||||
helperText="Cliente relacionado ao movimento recorrente."
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="">Selecione</MenuItem>
|
||||
|
||||
{clientes.map((cliente) => (
|
||||
<MenuItem
|
||||
key={cliente.id}
|
||||
value={String(cliente.id)}
|
||||
>
|
||||
{cliente.nome}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
)}
|
||||
|
||||
{isSangria && (
|
||||
<TextField
|
||||
select
|
||||
required
|
||||
label="Banco de destino"
|
||||
value={idBancoReferencia}
|
||||
onChange={(event) =>
|
||||
setIdBancoReferencia(event.target.value)
|
||||
}
|
||||
helperText="Conta que receberá o valor da sangria."
|
||||
fullWidth
|
||||
sx={fieldSx}
|
||||
>
|
||||
<MenuItem value="">Selecione</MenuItem>
|
||||
|
||||
{todosBancos
|
||||
.filter(
|
||||
(banco) =>
|
||||
String(banco.id) !== String(idBanco)
|
||||
)
|
||||
.map((banco) => (
|
||||
<MenuItem
|
||||
key={banco.id}
|
||||
value={String(banco.id)}
|
||||
>
|
||||
{banco.descricao}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
)}
|
||||
</FormSection>
|
||||
|
||||
<Stack
|
||||
|
|
@ -592,13 +798,60 @@ export function MovimentoFixoForm({ mode, initialData }: MovimentoFixoFormProps)
|
|||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Cliente
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
>
|
||||
Geração
|
||||
</Typography>
|
||||
<Typography fontWeight={800}>
|
||||
{clienteSelecionado?.nome || 'Nenhum'}
|
||||
|
||||
<Typography
|
||||
fontWeight={800}
|
||||
color={
|
||||
Number(gerarAutomatico) === 1
|
||||
? 'primary.main'
|
||||
: 'text.secondary'
|
||||
}
|
||||
>
|
||||
{Number(gerarAutomatico) === 1
|
||||
? 'Automática'
|
||||
: 'Manual'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{isSangria ? 'Banco de origem' : 'Banco/Carteira'}
|
||||
</Typography>
|
||||
|
||||
<Typography fontWeight={800}>
|
||||
{bancoOrigemSelecionado?.descricao || 'Não selecionado'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{usaCliente && (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Cliente
|
||||
</Typography>
|
||||
|
||||
<Typography fontWeight={800}>
|
||||
{clienteSelecionado?.nome || 'Não selecionado'}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{isSangria && (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Banco de destino
|
||||
</Typography>
|
||||
|
||||
<Typography fontWeight={800}>
|
||||
{bancoDestinoSelecionado?.descricao || 'Não selecionado'}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
export type MovimentoFixoTipo = 'Entrada' | 'Saida' | 'Sangria' | 'Estorno';
|
||||
export type MovimentoFixoTipo =
|
||||
| 'Entrada'
|
||||
| 'Saida'
|
||||
| 'Sangria'
|
||||
| 'Estorno';
|
||||
|
||||
export type MovimentoFixo = {
|
||||
idmovimentosfixos: number;
|
||||
|
|
@ -6,14 +10,25 @@ export type MovimentoFixo = {
|
|||
descricao: string;
|
||||
valor: number;
|
||||
dia_vencimento: number;
|
||||
|
||||
idcentrodecustos: number | null;
|
||||
idclientes?: number | null;
|
||||
idclientes: number | null;
|
||||
|
||||
// Banco principal/origem do movimento.
|
||||
idbancos: number;
|
||||
|
||||
// Banco de destino utilizado apenas em Sangria.
|
||||
idbancos_p: number | null;
|
||||
|
||||
habilitado: number;
|
||||
idbancos: number | null;
|
||||
gerar_automatico: number;
|
||||
ultimo_mes_gerado: string | null;
|
||||
|
||||
insert_date: string | null;
|
||||
update_date: string | null;
|
||||
|
||||
banco_descricao?: string | null;
|
||||
banco_destino_descricao?: string | null;
|
||||
centro_custo_descricao?: string | null;
|
||||
cliente_nome?: string | null;
|
||||
};
|
||||
|
|
@ -23,42 +38,16 @@ export type CriarMovimentoFixoRequest = {
|
|||
descricao: string;
|
||||
valor: number;
|
||||
dia_vencimento: number;
|
||||
|
||||
idcentrodecustos: number | null;
|
||||
idclientes?: number | null;
|
||||
idclientes: number | null;
|
||||
|
||||
idbancos: number;
|
||||
idbancos_p: number | null;
|
||||
|
||||
habilitado: number;
|
||||
idbancos: number | null;
|
||||
gerar_automatico: number;
|
||||
};
|
||||
|
||||
export type AtualizarMovimentoFixoRequest = CriarMovimentoFixoRequest;
|
||||
|
||||
export type MovimentosFixosPagination = {
|
||||
total: number;
|
||||
limite: number;
|
||||
offset: number;
|
||||
page: number;
|
||||
totalPages: number;
|
||||
};
|
||||
|
||||
export type MovimentosFixosSummary = {
|
||||
quantidade: number;
|
||||
valorTotal: number;
|
||||
totalEntradas: number;
|
||||
totalSaidas: number;
|
||||
totalSangrias: number;
|
||||
totalEstornos: number;
|
||||
habilitados: number;
|
||||
desabilitados: number;
|
||||
};
|
||||
|
||||
export type ApiResponse<T> = {
|
||||
ok: boolean;
|
||||
message?: string;
|
||||
data: T;
|
||||
};
|
||||
|
||||
export type MovimentosFixosListResponse = {
|
||||
ok: boolean;
|
||||
data: MovimentoFixo[];
|
||||
pagination: MovimentosFixosPagination;
|
||||
summary: MovimentosFixosSummary;
|
||||
};
|
||||
export type AtualizarMovimentoFixoRequest =
|
||||
CriarMovimentoFixoRequest;
|
||||
|
|
@ -144,19 +144,33 @@ function origemColor(origem: string) {
|
|||
return 'default';
|
||||
}
|
||||
|
||||
function criarItemManual(tipo: SimulacaoMensalTipoItem): SimulacaoMensalItem {
|
||||
const id = `manual:${tipo}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
|
||||
function criarItemManual(
|
||||
tipo: SimulacaoMensalTipoItem
|
||||
): SimulacaoMensalItem {
|
||||
const id =
|
||||
`manual:${tipo}:${Date.now()}:${Math.random()
|
||||
.toString(16)
|
||||
.slice(2)}`;
|
||||
|
||||
return {
|
||||
id,
|
||||
tipo,
|
||||
origem: 'manual',
|
||||
descricao: tipo === 'entrada' ? 'Nova entrada' : 'Nova saída',
|
||||
descricao:
|
||||
tipo === 'entrada'
|
||||
? 'Nova entrada'
|
||||
: 'Nova saída',
|
||||
valor: 0,
|
||||
valor_original: 0,
|
||||
movimento: tipo === 'entrada' ? 'Entrada' : 'Saida',
|
||||
movimento:
|
||||
tipo === 'entrada'
|
||||
? 'Entrada'
|
||||
: 'Saida',
|
||||
status: 'Simulado',
|
||||
data: null,
|
||||
|
||||
investimento: 0,
|
||||
|
||||
editavel: true,
|
||||
editado: true,
|
||||
};
|
||||
|
|
@ -303,6 +317,30 @@ function SimulacaoLista({
|
|||
}
|
||||
/>
|
||||
|
||||
{!isEntrada && (
|
||||
<TextField
|
||||
select
|
||||
label="Investimento"
|
||||
value={Number(item.investimento || 0)}
|
||||
size="small"
|
||||
sx={{
|
||||
width: {
|
||||
xs: '100%',
|
||||
md: 165,
|
||||
},
|
||||
}}
|
||||
onChange={(event) =>
|
||||
onAlterarItem(tipo, item.id, {
|
||||
investimento: Number(event.target.value),
|
||||
editado: true,
|
||||
})
|
||||
}
|
||||
>
|
||||
<MenuItem value={0}>Não</MenuItem>
|
||||
<MenuItem value={1}>Sim</MenuItem>
|
||||
</TextField>
|
||||
)}
|
||||
|
||||
<Tooltip title="Remover da simulação">
|
||||
<IconButton
|
||||
color="error"
|
||||
|
|
@ -396,6 +434,16 @@ function SimulacaoLista({
|
|||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
|
||||
{!isEntrada && Number(item.investimento) === 1 && (
|
||||
<Chip
|
||||
size="small"
|
||||
label="Investimento"
|
||||
color="info"
|
||||
icon={<AccountBalanceIcon />}
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
|
|
|||
Loading…
Reference in New Issue