417 lines
14 KiB
JavaScript
417 lines
14 KiB
JavaScript
import api from './api';
|
|
import { handleRequest, simulateLatency } from './serviceUtils';
|
|
|
|
/**
|
|
* Service de Extrato para financeiro-v2
|
|
* Alimenta as telas de cruzamento (receitas e despesas) com /api/extrato/apresentar.
|
|
* tipoOperacao: "C" = receitas (entradas), "D" = despesas (saídas).
|
|
*/
|
|
export const extratoService = {
|
|
/**
|
|
* Busca extrato bancário
|
|
* Rota: GET /extrato/apresentar
|
|
* Retorna array bruto; o consumidor filtra por tipoOperacao (C/D).
|
|
* @param {Object} params - Opcional { mes, ano }
|
|
* @returns {Promise<Array<{idextrato, dataEntrada, descricao, valor, tipoOperacao, categoria, beneficiario_pagador, ...}>>}
|
|
*/
|
|
fetchExtrato: (params) => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/apresentar', { params });
|
|
const raw = response?.data ?? response;
|
|
|
|
// Lógica robusta de extração (igual ao workspaceConciliacaoService)
|
|
// Prioridade: dados -> Base_Dados_API -> raw (se array) -> Object.values(raw)
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
|
|
if (!Array.isArray(data)) {
|
|
// Se for objeto (ex: { '0': {...}, '1': {...} }), converte para array
|
|
data = Object.values(data || {});
|
|
}
|
|
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Categorias (opcional, para labels)
|
|
* Rota: GET /categorias/apresentar
|
|
*/
|
|
fetchCategorias: () => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/categorias/apresentar');
|
|
const raw = response?.data ?? response;
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
|
|
if (!Array.isArray(data)) {
|
|
data = Object.values(data || {});
|
|
}
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Caixinhas (opcional, para labels)
|
|
* Rota: GET /caixinhas/apresentar
|
|
*/
|
|
fetchCaixinhas: () => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/caixinhas/apresentar');
|
|
const raw = response?.data ?? response;
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
|
|
if (!Array.isArray(data)) {
|
|
data = Object.values(data || {});
|
|
}
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Saldo atual da conta
|
|
* Rota: GET /saldo
|
|
* Resposta: { bloqueado?, disponivel, total? }
|
|
* @returns {Promise<{ disponivel: number, bloqueado?: number, total?: number }>}
|
|
*/
|
|
fetchSaldo: () => handleRequest({
|
|
mockFn: () => simulateLatency({ disponivel: 0, bloqueado: null, total: null }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/saldo');
|
|
// Tenta extrair de varias formas, pois saldo costuma variar a estrutura
|
|
const raw = response?.data ?? response;
|
|
const data = raw?.dados ?? raw?.Base_Dados_API ?? raw ?? {};
|
|
|
|
const num = (v) => (v != null && v !== '' ? Number(v) : null);
|
|
|
|
// Procura propriedade disponivel/saldo/valor em data ou no raw
|
|
const disponivel = num(data.disponivel) ?? num(data.saldo) ?? num(data.valor) ??
|
|
num(raw.disponivel) ?? num(raw.saldo) ?? num(raw.valor) ??
|
|
(typeof data === 'number' ? data : 0);
|
|
|
|
return {
|
|
disponivel: Number(disponivel) || 0,
|
|
bloqueado: num(data.bloqueado ?? raw.bloqueado),
|
|
total: num(data.total ?? raw.total)
|
|
};
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Saldos armazenados (histórico)
|
|
* Rota: GET /saldo/armazenado/apresentar
|
|
* Pode retornar array ou objeto único { data_saldo, saldo_disponivel, ... }.
|
|
* Usado para obter último saldo do mês passado (cruzamento fluxo de caixa).
|
|
* @returns {Promise<Array<{ data?: string, data_saldo?: string, mes?: number, ano?: number, saldo?: number, saldo_disponivel?: string, ... }>>}
|
|
*/
|
|
fetchSaldoArmazenado: () => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/saldo/armazenado/apresentar');
|
|
const raw = response?.data ?? response;
|
|
let list = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
|
|
if (!Array.isArray(list)) {
|
|
if (list && typeof list === 'object' && list !== null) {
|
|
const keys = Object.keys(list);
|
|
const isSingleRecord = keys.some(k => k === 'data_saldo' || k === 'saldo_disponivel' || k === 'idsaldos_mensais');
|
|
if (isSingleRecord) {
|
|
list = [list];
|
|
} else {
|
|
// Tenta converter objeto indexado em array
|
|
list = Object.values(list).map(v => typeof v === 'object' ? v : { saldo: v });
|
|
}
|
|
} else {
|
|
list = [];
|
|
}
|
|
}
|
|
|
|
return list.map((item) => {
|
|
const data = item.data ?? item.dataSaldo ?? item.data_saldo ?? item.data_armazenado;
|
|
const d = data ? new Date(data) : null;
|
|
const valid = d && !Number.isNaN(d.getTime());
|
|
const saldoVal = item.saldo_disponivel ?? item.saldo ?? item.valor;
|
|
const saldo = typeof saldoVal === 'string' ? Number(saldoVal.replace(',', '.')) : Number(saldoVal ?? 0);
|
|
|
|
return {
|
|
...item,
|
|
data: data ?? null,
|
|
data_saldo: item.data_saldo ?? data,
|
|
mes: item.mes ?? (valid ? d.getMonth() + 1 : null),
|
|
ano: item.ano ?? (valid ? d.getFullYear() : null),
|
|
saldo: Number.isFinite(saldo) ? saldo : 0
|
|
};
|
|
});
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Fluxo de entrada e saída mensal
|
|
* Rota: GET /extrato/fluxo
|
|
* Retorna dados mensais de entrada e saída
|
|
* @param {Object} params - Opcional { mes, ano }
|
|
* @returns {Promise<{ mensal: Array<{ mes, ano, entrada, saida, ... }> }>}
|
|
*/
|
|
fetchFluxo: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({ mensal: [], anual: [], diario: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/fluxo', { params });
|
|
const raw = response?.data ?? response;
|
|
const data = raw?.dados ?? raw?.Base_Dados_API ?? raw ?? {};
|
|
|
|
const mensal = data.mensal ?? raw.mensal ?? [];
|
|
const anual = data.anual ?? raw.anual ?? [];
|
|
const diario = data.diario ?? raw.diario ?? [];
|
|
|
|
const toArray = (obj) => Array.isArray(obj) ? obj : (obj ? Object.values(obj) : []);
|
|
|
|
return {
|
|
mensal: toArray(mensal),
|
|
anual: toArray(anual),
|
|
diario: toArray(diario)
|
|
};
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca soma por categoria
|
|
* Rota: GET /extrato/soma_por_categoria
|
|
* @param {Object} params - { mes, ano, tipoOperacao }
|
|
*/
|
|
getSomaPorCategoria: (params) => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/soma_por_categoria', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Exporta extrato em PDF
|
|
* Rota: GET /extrato/pdf
|
|
*/
|
|
exportPDF: () => handleRequest({
|
|
mockFn: () => simulateLatency(new Blob(['PDF mock'], { type: 'application/pdf' })),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/pdf', {
|
|
responseType: 'blob'
|
|
});
|
|
return response.data;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca navegação hierárquica detalhada por caixinha
|
|
* Rota: GET /extrato/apresentar/caixinha/detalhado
|
|
* @param {Object} params - { caixinha, mes, ano }
|
|
*/
|
|
getCaixinhaDetalhada: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({}),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/apresentar/caixinha/detalhado', {
|
|
params
|
|
});
|
|
return response.data;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca saldo consolidado com entradas e saídas do mês vigente e saldo anterior
|
|
* Rota: GET /saldo/entradas_mes_mais_ultimo_saldo
|
|
* @param {Object} params - { mes, ano }
|
|
*/
|
|
fetchSaldoConsolidado: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({ entradas: 0, saidas: 0, saldo_anterior: 0, saldo_atual: 0, lista_entradas: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/saldo/entradas_mes_mais_ultimo_saldo', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca empresas/clientes financeiros
|
|
* Rota: GET /empresas_financeiro
|
|
* @returns {Promise<Array>}
|
|
*/
|
|
fetchEmpresas: () => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/empresas_financeiro');
|
|
const raw = response?.data ?? response;
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
|
|
if (!Array.isArray(data)) {
|
|
data = Object.values(data || {});
|
|
}
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca dados de recebimento de juros (mensal e anual)
|
|
* Rota: GET /extrato/mensal_anual
|
|
* @returns {Promise<{ mensal: Array, anual: Array }>}
|
|
*/
|
|
fetchJuros: () => handleRequest({
|
|
mockFn: () => simulateLatency({ mensal: [], anual: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/mensal_anual');
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca soma de recebimentos via PIX para o painel
|
|
* Rota: GET /extrato/pix
|
|
*/
|
|
fetchPixSoma: () => handleRequest({
|
|
mockFn: () => simulateLatency({ total: 0, quantidade: 0 }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/pix');
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca lista de itens recebidos via PIX para apresentar
|
|
* Rota: GET /extrato/pix/apresentar
|
|
*/
|
|
fetchPixApresentar: () => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/pix/apresentar');
|
|
const raw = response?.data ?? response;
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
if (!Array.isArray(data)) {
|
|
data = Object.values(data || {});
|
|
}
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca dados detalhados de PIX por empresa
|
|
* Rota: GET /extrato/pix/empresas
|
|
* @param {Object} params - { mes, ano } (opcional)
|
|
* @returns {Promise<Array>}
|
|
*/
|
|
fetchPixEmpresas: (params) => handleRequest({
|
|
mockFn: () => simulateLatency([]),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/pix/empresas', { params });
|
|
const raw = response?.data ?? response;
|
|
let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
if (!Array.isArray(data)) {
|
|
data = Object.values(data || {});
|
|
}
|
|
return Array.isArray(data) ? data : [];
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca totais de entradas planejadas para o painel de cruzamento
|
|
* Rota: GET /financeiro/resumo_mes
|
|
* @param {Object} params - { mes, ano }
|
|
*/
|
|
fetchEntradasPlanejadasTotal: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({
|
|
mes: Number(params.mes),
|
|
ano: Number(params.ano),
|
|
total_planejado: 0,
|
|
total_boletos_a_receber: 0,
|
|
total_planejado_geral: 0,
|
|
total_realizado: 0,
|
|
diferenca: 0
|
|
}),
|
|
apiFn: async () => {
|
|
const response = await api.get('/financeiro/resumo_mes', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca dados para o gráfico de planejado vs executado (Receitas)
|
|
* Rota: GET /extrato/planejado/grafico
|
|
* @param {Object} params - { dia, mes, ano }
|
|
*/
|
|
fetchPlanejadoGrafico: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({ filtro: params, grafico: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/planejado/grafico', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca totais de despesas planejadas para o painel de cruzamento
|
|
* Rota: GET /financeiro/despesas_mes
|
|
* @param {Object} params - { mes, ano }
|
|
*/
|
|
fetchDespesasResumo: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({
|
|
mes: Number(params.mes),
|
|
ano: Number(params.ano),
|
|
total_planejado: 0,
|
|
total_realizado: 0,
|
|
diferenca: 0
|
|
}),
|
|
apiFn: async () => {
|
|
const response = await api.get('/financeiro/despesas_mes', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca dados para o gráfico de planejado vs executado (Despesas)
|
|
* Rota: GET /extrato/despesas/grafico
|
|
* @param {Object} params - { dia, mes, ano }
|
|
*/
|
|
fetchDespesasGrafico: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({ filtro: params, grafico: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/despesas/grafico', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca detalhamento de juros adicionados
|
|
* Rota: GET /extrato/adicionado
|
|
* @param {Object} params - { mes, ano }
|
|
*/
|
|
fetchJurosAdicionados: (params) => handleRequest({
|
|
mockFn: () => simulateLatency({ adicionado: [], total_adicionado: 0, total_registros: 0 }),
|
|
apiFn: async () => {
|
|
const response = await api.get('/extrato/adicionado', { params });
|
|
return response?.data ?? response;
|
|
}
|
|
}),
|
|
|
|
/**
|
|
* Busca transações de um beneficiário específico
|
|
* Rota: POST /beneficiario_aplicado
|
|
* Resposta esperada: { "categoria": "NOME DO CLIENTE", "linha_tempo": [...] }
|
|
* Retorna: { categoria: string, linhaTemp: Array }
|
|
* @param {string} beneficiario_pagador
|
|
*/
|
|
fetchBeneficiarioAplicado: (beneficiario_pagador) => handleRequest({
|
|
mockFn: () => simulateLatency({ categoria: '', linha_tempo: [] }),
|
|
apiFn: async () => {
|
|
const response = await api.post('/beneficiario_aplicado', {
|
|
beneficiario_pagador: beneficiario_pagador
|
|
});
|
|
const raw = response?.data ?? response;
|
|
// A resposta é um objeto com "categoria" e "linha_tempo"
|
|
const root = raw?.dados ?? raw?.Base_Dados_API ?? raw;
|
|
const categoria = root?.categoria ?? '';
|
|
const linhaTemp = root?.linha_tempo ?? [];
|
|
return {
|
|
categoria,
|
|
linha_tempo: Array.isArray(linhaTemp) ? linhaTemp : []
|
|
};
|
|
}
|
|
})
|
|
};
|
|
|