const pool = require('../../../database/mysql'); const CAMPOS_CENTRO_CUSTO_SELECT = ` idcentrodecustos, descricao, limite, simular, investimento, habilitado, insert_date, update_date `; function normalizarTextoOuNull(valor) { if (valor === undefined || valor === null || valor === '') { return null; } return String(valor).trim(); } 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; } const numero = Number(valor); return numero === 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 = { idcentrodecustos: 'idcentrodecustos', descricao: 'descricao', limite: 'limite', simular: 'simular', investimento: 'investimento', habilitado: 'habilitado', insert_date: 'insert_date', update_date: 'update_date', }; return camposPermitidos[orderBy] || 'descricao'; } function resolverDirecao(orderDirection) { return String(orderDirection || '').toUpperCase() === 'DESC' ? 'DESC' : 'ASC'; } function montarWhereCentrosCusto(filtros = {}) { const where = []; const params = []; if (filtros.simular !== undefined && filtros.simular !== null && filtros.simular !== '') { where.push('simular = ?'); params.push(Number(filtros.simular)); } if (filtros.investimento !== undefined && filtros.investimento !== null && filtros.investimento !== '') { where.push('investimento = ?'); params.push(Number(filtros.investimento)); } if (filtros.habilitado !== undefined && filtros.habilitado !== null && filtros.habilitado !== '') { where.push('habilitado = ?'); params.push(Number(filtros.habilitado)); } if (filtros.busca) { where.push(` ( descricao LIKE ? ) `); const termo = `%${String(filtros.busca).trim()}%`; params.push(termo); } const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''; return { whereSql, params, }; } async function listarCentrosCusto(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 } = montarWhereCentrosCusto(filtros); const [rows] = await pool.query( ` SELECT ${CAMPOS_CENTRO_CUSTO_SELECT} FROM centrodecustos ${whereSql} ORDER BY ${orderBy} ${orderDirection}, idcentrodecustos ASC LIMIT ? OFFSET ? `, [...params, limite, offset] ); const [countRows] = await pool.query( ` SELECT COUNT(*) AS total FROM centrodecustos ${whereSql} `, params ); const [summaryRows] = await pool.query( ` SELECT COUNT(*) AS quantidade, COALESCE(SUM(limite), 0) AS limiteTotal, COALESCE(SUM(CASE WHEN habilitado = 1 THEN 1 ELSE 0 END), 0) AS habilitados, COALESCE(SUM(CASE WHEN habilitado = 0 THEN 1 ELSE 0 END), 0) AS desabilitados, COALESCE(SUM(CASE WHEN investimento = 1 THEN 1 ELSE 0 END), 0) AS investimentos, COALESCE(SUM(CASE WHEN simular = 1 THEN 1 ELSE 0 END), 0) AS simulaveis FROM centrodecustos ${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), limiteTotal: Number(summaryRows[0]?.limiteTotal || 0), habilitados: Number(summaryRows[0]?.habilitados || 0), desabilitados: Number(summaryRows[0]?.desabilitados || 0), investimentos: Number(summaryRows[0]?.investimentos || 0), simulaveis: Number(summaryRows[0]?.simulaveis || 0), }, }; } async function buscarCentroCustoPorId(id) { const [rows] = await pool.query( ` SELECT ${CAMPOS_CENTRO_CUSTO_SELECT} FROM centrodecustos WHERE idcentrodecustos = ? LIMIT 1 `, [id] ); return rows[0] || null; } async function criarCentroCusto(dados) { const { descricao, limite, simular, investimento, habilitado, } = dados; const [result] = await pool.query( ` INSERT INTO centrodecustos ( descricao, limite, simular, investimento, habilitado, insert_date, update_date ) VALUES (?, ?, ?, ?, ?, NOW(), NOW()) `, [ normalizarTextoOuNull(descricao), normalizarNumero(limite, 0), normalizarFlag(simular, 0), normalizarFlag(investimento, 0), normalizarFlag(habilitado, 1), ] ); return buscarCentroCustoPorId(result.insertId); } async function atualizarCentroCusto(id, dados) { const centroAtual = await buscarCentroCustoPorId(id); if (!centroAtual) { return null; } const { descricao, limite, simular, investimento, habilitado, } = dados; await pool.query( ` UPDATE centrodecustos SET descricao = ?, limite = ?, simular = ?, investimento = ?, habilitado = ?, update_date = NOW() WHERE idcentrodecustos = ? `, [ normalizarTextoOuNull(descricao), normalizarNumero(limite, 0), normalizarFlag(simular, 0), normalizarFlag(investimento, 0), normalizarFlag(habilitado, 1), id, ] ); return buscarCentroCustoPorId(id); } async function alterarHabilitadoCentroCusto(id, habilitado) { const centroAtual = await buscarCentroCustoPorId(id); if (!centroAtual) { return null; } await pool.query( ` UPDATE centrodecustos SET habilitado = ?, update_date = NOW() WHERE idcentrodecustos = ? `, [ normalizarFlag(habilitado, 1), id, ] ); return buscarCentroCustoPorId(id); } async function deletarCentroCusto(id) { const centroAtual = await buscarCentroCustoPorId(id); if (!centroAtual) { return false; } await pool.query( ` DELETE FROM centrodecustos WHERE idcentrodecustos = ? `, [id] ); return true; } module.exports = { listarCentrosCusto, buscarCentroCustoPorId, criarCentroCusto, atualizarCentroCusto, alterarHabilitadoCentroCusto, deletarCentroCusto, };