diff --git a/src/services/cartao/cartaoCodigoUtils.ts b/src/services/cartao/cartaoCodigoUtils.ts new file mode 100644 index 0000000..6c132fa --- /dev/null +++ b/src/services/cartao/cartaoCodigoUtils.ts @@ -0,0 +1,20 @@ + +/** + * Utility functions for generating and handling credit card codes + */ + +/** + * Generates a unique code for a credit card + * @param nome Card name + * @param banco Bank name + * @returns Unique card code + */ +export function gerarCartaoCodigo(nome: string, banco: string): string { + const timestamp = new Date().getTime(); + const randomStr = Math.random().toString(36).substring(2, 7); + // Remove spaces and special characters + const nomeSanitizado = nome.replace(/[^a-zA-Z0-9]/g, '').substring(0, 8); + const bancoSanitizado = banco.replace(/[^a-zA-Z0-9]/g, '').substring(0, 5); + + return `${nomeSanitizado}_${bancoSanitizado}_${randomStr}`; +} diff --git a/src/services/cartao/cartoesService.ts b/src/services/cartao/cartoesService.ts new file mode 100644 index 0000000..dc05b9c --- /dev/null +++ b/src/services/cartao/cartoesService.ts @@ -0,0 +1,194 @@ + +import { supabase } from "@/integrations/supabase/client"; +import { CartaoCredito } from "@/types/cartaoTypes"; +import { gerarCartaoCodigo } from "./cartaoCodigoUtils"; +import { getTotalDespesasCartao } from "./despesasService"; + +/** + * Fetches all credit cards for the current user + * @returns Array of credit cards + */ +export async function getCartoes(): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return []; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + try { + const { data, error } = await supabase + .from('cartoes_credito') + .select('*') + .eq('login', normalizedEmail); + + if (error) { + console.error('Erro ao buscar cartões:', error); + throw new Error('Não foi possível carregar os cartões de crédito'); + } + + // Garantir que todos os dados têm os campos necessários da interface CartaoCredito + const cartoesCompletos = data.map(cartao => { + const cartaoCompleto = { ...cartao } as CartaoCredito; + + // Se não tiver cartao_codigo, gerar um código temporário baseado no id + if (!cartaoCompleto.cartao_codigo) { + cartaoCompleto.cartao_codigo = `cartao_${cartaoCompleto.id.substring(0, 8)}`; + } + + // Se não tiver bandeira ou banco, adicionar valores padrão + if (!cartaoCompleto.bandeira) { + cartaoCompleto.bandeira = 'Não especificada'; + } + + if (!cartaoCompleto.banco) { + cartaoCompleto.banco = 'Não especificado'; + } + + return cartaoCompleto; + }); + + // Buscar o total de despesas para cada cartão + const cartoesComTotal = await Promise.all( + cartoesCompletos.map(async (cartao: CartaoCredito) => { + const total = await getTotalDespesasCartao(cartao.cartao_codigo); + return { ...cartao, total_despesas: total }; + }) + ); + + return cartoesComTotal; + } catch (error) { + console.error('Erro ao buscar cartões:', error); + return []; + } +} + +/** + * Checks if a card with the same name and bank already exists for the user + * @param nome Card name + * @param banco Bank name + * @returns Boolean indicating if the card exists + */ +export async function verificarCartaoExistente(nome: string, banco: string): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return false; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + try { + const { data, error, count } = await supabase + .from('cartoes_credito') + .select('*', { count: 'exact' }) + .eq('login', normalizedEmail) + .eq('nome', nome) + .eq('banco', banco); + + if (error) { + console.error('Erro ao verificar cartão existente:', error); + return false; + } + + return count ? count > 0 : false; + } catch (error) { + console.error('Erro ao verificar cartão existente:', error); + return false; + } +} + +/** + * Creates a new credit card + * @param nome Card name + * @param bandeira Card brand + * @param banco Bank name + * @returns Created credit card or null if failed + */ +export async function criarCartao(nome: string, bandeira: string, banco: string): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + // Obter o ID do usuário do localStorage (mantido por compatibilidade) + const userId = localStorage.getItem('userId'); + + if (!userEmail || !userId) { + console.error('Dados do usuário não encontrados no localStorage'); + return null; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + // Verificar se já existe um cartão com o mesmo nome e banco + const cartaoExistente = await verificarCartaoExistente(nome, banco); + if (cartaoExistente) { + throw new Error(`Você já possui um cartão ${nome} do banco ${banco}.`); + } + + // Gerar um código único para o cartão + const cartao_codigo = gerarCartaoCodigo(nome, banco); + + try { + const { data, error } = await supabase + .from('cartoes_credito') + .insert([{ + nome: nome, + bandeira: bandeira, + banco: banco, + cartao_codigo: cartao_codigo, + user_id: userId, + login: normalizedEmail + }]) + .select(); + + if (error) { + console.error('Erro ao criar cartão:', error); + throw new Error('Não foi possível criar o cartão de crédito'); + } + + return data[0] as CartaoCredito; + } catch (error) { + console.error('Erro ao criar cartão:', error); + throw error; + } +} + +/** + * Fetches details of a specific credit card + * @param cartaoId Card ID + * @returns Credit card or null if not found + */ +export async function getCartao(cartaoId: string): Promise { + try { + const { data, error } = await supabase + .from('cartoes_credito') + .select('*') + .eq('id', cartaoId) + .single(); + + if (error) { + console.error('Erro ao buscar cartão:', error); + throw new Error('Não foi possível carregar os detalhes do cartão'); + } + + // Garantir que o objeto retornado tem todos os campos necessários + const cartaoCompleto = { ...data } as CartaoCredito; + + // Garantir que cartao_codigo existe + if (!cartaoCompleto.cartao_codigo) { + cartaoCompleto.cartao_codigo = `cartao_${cartaoCompleto.id.substring(0, 8)}`; + } + + return cartaoCompleto; + } catch (error) { + console.error('Erro ao buscar cartão:', error); + return null; + } +} diff --git a/src/services/cartao/despesasService.ts b/src/services/cartao/despesasService.ts new file mode 100644 index 0000000..a4cb84a --- /dev/null +++ b/src/services/cartao/despesasService.ts @@ -0,0 +1,150 @@ + +import { supabase } from "@/integrations/supabase/client"; +import { DespesaCartao } from "@/types/cartaoTypes"; +import { getCartao } from "./cartoesService"; + +/** + * Fetches expenses for a specific credit card + * @param cartaoId Card ID + * @returns Array of card expenses + */ +export async function getDespesasCartao(cartaoId: string): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return []; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + try { + // Primeiro, obter o cartao_codigo do cartão + const cartao = await getCartao(cartaoId); + + if (!cartao || !cartao.cartao_codigo) { + console.error('Cartão não encontrado ou sem código'); + return []; + } + + const { data, error } = await supabase + .from('despesas_cartao') + .select('*') + .eq('cartao_id', cartaoId) + .order('data_despesa', { ascending: false }); + + if (error) { + console.error('Erro ao buscar despesas:', error); + throw new Error('Não foi possível carregar as despesas do cartão'); + } + + // Garantir que todas as despesas têm cartao_codigo + const despesasCompletas = data.map(despesa => { + const despesaCompleta = { ...despesa } as DespesaCartao; + if (!despesaCompleta.cartao_codigo) { + despesaCompleta.cartao_codigo = cartao.cartao_codigo; + } + return despesaCompleta; + }); + + return despesasCompletas; + } catch (error) { + console.error('Erro ao buscar despesas:', error); + return []; + } +} + +/** + * Creates a new expense for a credit card + * @param cartao_id Card ID + * @param cartao_codigo Card code + * @param valor Expense value + * @param data_despesa Expense date + * @param descricao Expense description + * @returns Created expense or null if failed + */ +export async function criarDespesa( + cartao_id: string, + cartao_codigo: string, + valor: number, + data_despesa: string, + descricao: string +): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + // Obter o ID do usuário do localStorage (mantido por compatibilidade) + const userId = localStorage.getItem('userId'); + + if (!userEmail || !userId) { + console.error('Dados do usuário não encontrados no localStorage'); + return null; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + try { + const { data, error } = await supabase + .from('despesas_cartao') + .insert([{ + cartao_id: cartao_id, + cartao_codigo: cartao_codigo, + valor: valor, + data_despesa: data_despesa, + descricao: descricao, + login: normalizedEmail, + user_id: userId + }]) + .select(); + + if (error) { + console.error('Erro ao criar despesa:', error); + throw new Error('Não foi possível adicionar a despesa ao cartão'); + } + + return data[0] as DespesaCartao; + } catch (error) { + console.error('Erro ao criar despesa:', error); + return null; + } +} + +/** + * Calculates the total expenses for a credit card + * @param cartaoCodigo Card code + * @returns Total expenses amount + */ +export async function getTotalDespesasCartao(cartaoCodigo: string): Promise { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return 0; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + try { + const { data, error } = await supabase + .from('despesas_cartao') + .select('valor') + .eq('cartao_codigo', cartaoCodigo) + .eq('login', normalizedEmail); + + if (error) { + console.error('Erro ao calcular total de despesas:', error); + throw new Error('Não foi possível calcular o total de despesas'); + } + + // Somar todos os valores das despesas + const total = data.reduce((acc, item) => acc + Number(item.valor), 0); + return total; + } catch (error) { + console.error('Erro ao calcular total de despesas:', error); + return 0; + } +} diff --git a/src/services/cartaoCreditoService.ts b/src/services/cartaoCreditoService.ts index f9ef99d..f991270 100644 --- a/src/services/cartaoCreditoService.ts +++ b/src/services/cartaoCreditoService.ts @@ -1,310 +1,22 @@ -import { supabase } from "@/integrations/supabase/client"; -import { CartaoCredito, DespesaCartao } from "@/types/cartaoTypes"; +/** + * Re-export all functions from the refactored services for backward compatibility + */ -// Função para buscar todos os cartões de crédito do usuário -export async function getCartoes(): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - - if (!userEmail) { - console.error('Email do usuário não encontrado no localStorage'); - return []; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - try { - const { data, error } = await supabase - .from('cartoes_credito') - .select('*') - .eq('login', normalizedEmail); - - if (error) { - console.error('Erro ao buscar cartões:', error); - throw new Error('Não foi possível carregar os cartões de crédito'); - } - - // Garantir que todos os dados têm os campos necessários da interface CartaoCredito - const cartoesCompletos = data.map(cartao => { - // Se não tiver cartao_codigo, gerar um código temporário baseado no id - if (!cartao.cartao_codigo) { - cartao.cartao_codigo = `cartao_${cartao.id.substring(0, 8)}`; - } - // Se não tiver bandeira ou banco, adicionar valores padrão - if (!cartao.bandeira) { - cartao.bandeira = 'Não especificada'; - } - if (!cartao.banco) { - cartao.banco = 'Não especificado'; - } - return cartao as CartaoCredito; - }); - - // Buscar o total de despesas para cada cartão - const cartoesComTotal = await Promise.all( - cartoesCompletos.map(async (cartao: CartaoCredito) => { - const total = await getTotalDespesasCartao(cartao.cartao_codigo); - return { ...cartao, total_despesas: total }; - }) - ); - - return cartoesComTotal; - } catch (error) { - console.error('Erro ao buscar cartões:', error); - return []; - } -} +// Re-export all functions from cartoesService +export { + getCartoes, + verificarCartaoExistente, + criarCartao, + getCartao +} from './cartao/cartoesService'; -// Verificar se já existe um cartão com o mesmo nome e banco para o usuário -export async function verificarCartaoExistente(nome: string, banco: string): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - - if (!userEmail) { - console.error('Email do usuário não encontrado no localStorage'); - return false; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - try { - const { data, error, count } = await supabase - .from('cartoes_credito') - .select('*', { count: 'exact' }) - .eq('login', normalizedEmail) - .eq('nome', nome) - .eq('banco', banco); - - if (error) { - console.error('Erro ao verificar cartão existente:', error); - return false; - } - - return count ? count > 0 : false; - } catch (error) { - console.error('Erro ao verificar cartão existente:', error); - return false; - } -} +// Re-export all functions from despesasService +export { + getDespesasCartao, + criarDespesa, + getTotalDespesasCartao +} from './cartao/despesasService'; -// Função para gerar um código único para o cartão -function gerarCartaoCodigo(nome: string, banco: string): string { - const timestamp = new Date().getTime(); - const randomStr = Math.random().toString(36).substring(2, 7); - // Remover espaços e caracteres especiais - const nomeSanitizado = nome.replace(/[^a-zA-Z0-9]/g, '').substring(0, 8); - const bancoSanitizado = banco.replace(/[^a-zA-Z0-9]/g, '').substring(0, 5); - - return `${nomeSanitizado}_${bancoSanitizado}_${randomStr}`; -} - -// Função para criar um novo cartão de crédito -export async function criarCartao(nome: string, bandeira: string, banco: string): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - // Obter o ID do usuário do localStorage (mantido por compatibilidade) - const userId = localStorage.getItem('userId'); - - if (!userEmail || !userId) { - console.error('Dados do usuário não encontrados no localStorage'); - return null; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - // Verificar se já existe um cartão com o mesmo nome e banco - const cartaoExistente = await verificarCartaoExistente(nome, banco); - if (cartaoExistente) { - throw new Error(`Você já possui um cartão ${nome} do banco ${banco}.`); - } - - // Gerar um código único para o cartão - const cartao_codigo = gerarCartaoCodigo(nome, banco); - - try { - const { data, error } = await supabase - .from('cartoes_credito') - .insert([{ - nome: nome, - bandeira: bandeira, - banco: banco, - cartao_codigo: cartao_codigo, - user_id: userId, - login: normalizedEmail - }]) - .select(); - - if (error) { - console.error('Erro ao criar cartão:', error); - throw new Error('Não foi possível criar o cartão de crédito'); - } - - return data[0] as CartaoCredito; - } catch (error) { - console.error('Erro ao criar cartão:', error); - throw error; - } -} - -// Função para buscar detalhes de um cartão específico -export async function getCartao(cartaoId: string): Promise { - try { - const { data, error } = await supabase - .from('cartoes_credito') - .select('*') - .eq('id', cartaoId) - .single(); - - if (error) { - console.error('Erro ao buscar cartão:', error); - throw new Error('Não foi possível carregar os detalhes do cartão'); - } - - // Garantir que o objeto retornado tem todos os campos necessários - const cartaoCompleto = { ...data } as CartaoCredito; - - // Garantir que cartao_codigo existe - if (!cartaoCompleto.cartao_codigo) { - cartaoCompleto.cartao_codigo = `cartao_${cartaoCompleto.id.substring(0, 8)}`; - } - - return cartaoCompleto; - } catch (error) { - console.error('Erro ao buscar cartão:', error); - return null; - } -} - -// Função para buscar despesas de um cartão -export async function getDespesasCartao(cartaoId: string): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - - if (!userEmail) { - console.error('Email do usuário não encontrado no localStorage'); - return []; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - try { - // Primeiro, obter o cartao_codigo do cartão - const cartao = await getCartao(cartaoId); - - if (!cartao || !cartao.cartao_codigo) { - console.error('Cartão não encontrado ou sem código'); - return []; - } - - const { data, error } = await supabase - .from('despesas_cartao') - .select('*') - .eq('cartao_id', cartaoId) - .order('data_despesa', { ascending: false }); - - if (error) { - console.error('Erro ao buscar despesas:', error); - throw new Error('Não foi possível carregar as despesas do cartão'); - } - - // Garantir que todas as despesas têm cartao_codigo - const despesasCompletas = data.map(despesa => { - const despesaCompleta = { ...despesa } as DespesaCartao; - if (!despesaCompleta.cartao_codigo) { - despesaCompleta.cartao_codigo = cartao.cartao_codigo; - } - return despesaCompleta; - }); - - return despesasCompletas; - } catch (error) { - console.error('Erro ao buscar despesas:', error); - return []; - } -} - -// Função para criar uma nova despesa no cartão -export async function criarDespesa( - cartao_id: string, - cartao_codigo: string, - valor: number, - data_despesa: string, - descricao: string -): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - // Obter o ID do usuário do localStorage (mantido por compatibilidade) - const userId = localStorage.getItem('userId'); - - if (!userEmail || !userId) { - console.error('Dados do usuário não encontrados no localStorage'); - return null; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - try { - const { data, error } = await supabase - .from('despesas_cartao') - .insert([{ - cartao_id: cartao_id, - cartao_codigo: cartao_codigo, - valor: valor, - data_despesa: data_despesa, - descricao: descricao, - login: normalizedEmail, - user_id: userId - }]) - .select(); - - if (error) { - console.error('Erro ao criar despesa:', error); - throw new Error('Não foi possível adicionar a despesa ao cartão'); - } - - return data[0] as DespesaCartao; - } catch (error) { - console.error('Erro ao criar despesa:', error); - return null; - } -} - -// Função para calcular o total de despesas de um cartão -export async function getTotalDespesasCartao(cartaoCodigo: string): Promise { - // Obter o email do usuário do localStorage - const userEmail = localStorage.getItem('userEmail'); - - if (!userEmail) { - console.error('Email do usuário não encontrado no localStorage'); - return 0; - } - - // Normalizar o email (minúsculo e sem espaços) - const normalizedEmail = userEmail.trim().toLowerCase(); - - try { - const { data, error } = await supabase - .from('despesas_cartao') - .select('valor') - .eq('cartao_codigo', cartaoCodigo) - .eq('login', normalizedEmail); - - if (error) { - console.error('Erro ao calcular total de despesas:', error); - throw new Error('Não foi possível calcular o total de despesas'); - } - - // Somar todos os valores das despesas - const total = data.reduce((acc, item) => acc + Number(item.valor), 0); - return total; - } catch (error) { - console.error('Erro ao calcular total de despesas:', error); - return 0; - } -} +// Re-export from utilities +export { gerarCartaoCodigo } from './cartao/cartaoCodigoUtils';