bling-mcp
Version:
API MCP para integração com Bling
173 lines (164 loc) • 5.74 kB
text/typescript
import { blingClient, renovarToken } from '../blingClient.js';
import axios from 'axios';
/**
* Interface para Conta a Receber (baseada no schema da API)
*/
export interface ContaReceber {
id?: number;
situacao: number;
vencimento: string;
valor: number;
idTransacao?: string;
linkQRCodePix?: string;
linkBoleto?: string;
dataEmissao?: string;
contato?: any;
formaPagamento?: any;
contaContabil?: any;
origem?: any;
saldo?: number;
vencimentoOriginal?: string;
numeroDocumento?: string;
competencia?: string;
historico?: string;
numeroBanco?: string;
portador?: any;
categoria?: any;
vendedor?: any;
borderos?: number[];
ocorrencia?: any;
[key: string]: any;
}
export interface ListarContasReceberParams {
pagina?: number;
limite?: number;
situacoes?: number[];
tipoFiltroData?: string;
dataInicial?: string;
dataFinal?: string;
idsCategorias?: number[];
idPortador?: number;
idContato?: number;
idVendedor?: number;
idFormaPagamento?: number;
boletoGerado?: number;
}
/**
* Lista as contas a receber
*/
export async function listarContasReceber(params?: ListarContasReceberParams): Promise<{ data: ContaReceber[]; pagination: any }> {
try {
console.log('Listando contas a receber', params);
const response = await blingClient.get('/contas/receber', { params });
return {
data: response.data.data as ContaReceber[],
pagination: {
// Adapte conforme resposta real da API
page: response.data.page || 1,
totalPages: response.data.totalPages || 1,
totalItems: response.data.data?.length || 0,
limit: response.data.limit || response.data.data?.length || 0
}
};
} catch (error) {
return handleApiError(error, 'listarContasReceber', params);
}
}
/**
* Obtém uma conta a receber pelo ID
*/
export async function obterContaReceber(id: number | string): Promise<ContaReceber> {
try {
console.log('Obtendo conta a receber', id);
const response = await blingClient.get(`/contas/receber/${id}`);
if (response.data && response.data.data) {
return response.data.data as ContaReceber;
}
return response.data as ContaReceber;
} catch (error) {
return handleApiError(error, 'obterContaReceber', { id });
}
}
/**
* Cria uma nova conta a receber
*/
export async function criarContaReceber(conta: ContaReceber): Promise<ContaReceber> {
try {
console.log('Criando conta a receber', conta);
const response = await blingClient.post('/contas/receber', conta);
if (response.data && response.data.data) {
return response.data.data as ContaReceber;
}
return response.data as ContaReceber;
} catch (error) {
return handleApiError(error, 'criarContaReceber', conta);
}
}
/**
* Atualiza uma conta a receber existente
*/
export async function atualizarContaReceber(id: number | string, conta: Partial<ContaReceber>): Promise<ContaReceber> {
try {
console.log('Atualizando conta a receber', id, conta);
const response = await blingClient.put(`/contas/receber/${id}`, conta);
if (response.data && response.data.data) {
return response.data.data as ContaReceber;
}
return response.data as ContaReceber;
} catch (error) {
return handleApiError(error, 'atualizarContaReceber', { id, conta });
}
}
/**
* Remove uma conta a receber pelo ID
*/
export async function excluirContaReceber(id: number | string): Promise<void> {
try {
console.log('Excluindo conta a receber', id);
await blingClient.delete(`/contas/receber/${id}`);
console.log('Conta a receber excluída com sucesso');
} catch (error) {
return handleApiError(error, 'excluirContaReceber', { id });
}
}
/**
* Baixa (recebe) uma conta a receber
*/
export async function baixarContaReceber(id: number | string, payload: any): Promise<any> {
try {
console.log('Baixando conta a receber', id, payload);
const response = await blingClient.post(`/contas/receber/${id}/baixar`, payload);
return response.data;
} catch (error) {
return handleApiError(error, 'baixarContaReceber', { id, payload });
}
}
/**
* Função auxiliar para tratamento de erros da API
*/
async function handleApiError(error: unknown, funcName: string, params: any): Promise<any> {
if (axios.isAxiosError(error) && error.response?.status === 401) {
console.log(`Token expirado (401) em ${funcName}, tentando renovar...`);
try {
await renovarToken();
if (funcName === 'listarContasReceber') return listarContasReceber(params as ListarContasReceberParams);
if (funcName === 'obterContaReceber') return obterContaReceber(params.id);
if (funcName === 'criarContaReceber') return criarContaReceber(params);
if (funcName === 'atualizarContaReceber') return atualizarContaReceber(params.id, params.conta);
if (funcName === 'excluirContaReceber') return excluirContaReceber(params.id);
if (funcName === 'baixarContaReceber') return baixarContaReceber(params.id, params.payload);
throw new Error(`Função desconhecida: ${funcName}`);
} catch (renewError) {
console.error(`Erro ao renovar token em ${funcName}:`, renewError);
throw new Error(`Falha na renovação do token: ${renewError instanceof Error ? renewError.message : 'Erro desconhecido'}`);
}
}
if (axios.isAxiosError(error)) {
console.error(`Erro em ${funcName}:`);
console.error('Status:', error.response?.status);
console.error('Data:', JSON.stringify(error.response?.data, null, 2));
throw new Error(`Erro ao ${funcName}: ${error.response?.data?.message || error.message}`);
}
console.error(`Erro não relacionado ao Axios em ${funcName}:`, error);
throw error;
}