1542 lines
43 KiB
JavaScript
1542 lines
43 KiB
JavaScript
import axios from 'axios';
|
|
import { API_BASE_URL } from '../config/api';
|
|
|
|
// Crear instancia de axios
|
|
const api = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
},
|
|
});
|
|
|
|
// Interceptor para agregar token en cada request
|
|
api.interceptors.request.use(
|
|
(config) => {
|
|
const token = localStorage.getItem('token');
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
},
|
|
(error) => {
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Interceptor para manejar errores de respuesta
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
(error) => {
|
|
if (error.response?.status === 401) {
|
|
// Token expirado o inválido
|
|
localStorage.removeItem('token');
|
|
localStorage.removeItem('user');
|
|
window.location.href = '/login';
|
|
}
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Auth Services
|
|
export const authService = {
|
|
register: async (userData) => {
|
|
const response = await api.post('/register', userData);
|
|
return response.data;
|
|
},
|
|
|
|
login: async (credentials) => {
|
|
const response = await api.post('/login', credentials);
|
|
if (response.data.success) {
|
|
localStorage.setItem('token', response.data.data.token);
|
|
localStorage.setItem('user', JSON.stringify(response.data.data.user));
|
|
}
|
|
return response.data;
|
|
},
|
|
|
|
logout: async () => {
|
|
try {
|
|
await api.post('/logout');
|
|
} finally {
|
|
localStorage.removeItem('token');
|
|
localStorage.removeItem('user');
|
|
}
|
|
},
|
|
|
|
getCurrentUser: () => {
|
|
const user = localStorage.getItem('user');
|
|
return user ? JSON.parse(user) : null;
|
|
},
|
|
|
|
isAuthenticated: () => {
|
|
return !!localStorage.getItem('token');
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Account Services (Contas)
|
|
// ============================================
|
|
export const accountService = {
|
|
// Listar todas as contas
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/accounts', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma conta específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/accounts/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova conta
|
|
create: async (data) => {
|
|
const response = await api.post('/accounts', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar conta
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/accounts/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir conta
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/accounts/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Obter saldo total
|
|
getTotalBalance: async () => {
|
|
const response = await api.get('/accounts-total');
|
|
return response.data;
|
|
},
|
|
|
|
// Recalcular saldos de todas as contas
|
|
recalculateAllBalances: async () => {
|
|
const response = await api.post('/accounts/recalculate-all');
|
|
return response.data;
|
|
},
|
|
|
|
// Recalcular saldo de uma conta específica
|
|
recalculateBalance: async (id) => {
|
|
const response = await api.post(`/accounts/${id}/recalculate`);
|
|
return response.data;
|
|
},
|
|
|
|
// Ajustar saldo de uma conta (calcula initial_balance automaticamente)
|
|
adjustBalance: async (id, targetBalance) => {
|
|
const response = await api.post(`/accounts/${id}/adjust-balance`, { target_balance: targetBalance });
|
|
return response.data;
|
|
},
|
|
|
|
// Tipos de conta disponíveis
|
|
types: {
|
|
cash: 'Dinheiro',
|
|
checking: 'Conta Corrente',
|
|
savings: 'Poupança',
|
|
credit_card: 'Cartão de Crédito',
|
|
asset: 'Ativo',
|
|
liability: 'Passivo',
|
|
},
|
|
|
|
// Ícones sugeridos por tipo
|
|
icons: {
|
|
cash: 'bi-cash-stack',
|
|
checking: 'bi-bank',
|
|
savings: 'bi-piggy-bank',
|
|
credit_card: 'bi-credit-card',
|
|
asset: 'bi-graph-up-arrow',
|
|
liability: 'bi-graph-down-arrow',
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Cost Center Services (Centros de Custo)
|
|
// ============================================
|
|
export const costCenterService = {
|
|
// Listar todos os centros de custo
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/cost-centers', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter um centro de custo específico
|
|
getById: async (id) => {
|
|
const response = await api.get(`/cost-centers/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar novo centro de custo
|
|
create: async (data) => {
|
|
const response = await api.post('/cost-centers', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar centro de custo
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/cost-centers/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir centro de custo
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/cost-centers/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Adicionar palavra-chave
|
|
addKeyword: async (id, keyword, isCaseSensitive = false) => {
|
|
const response = await api.post(`/cost-centers/${id}/keywords`, {
|
|
keyword,
|
|
is_case_sensitive: isCaseSensitive,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Remover palavra-chave
|
|
removeKeyword: async (id, keywordId) => {
|
|
const response = await api.delete(`/cost-centers/${id}/keywords/${keywordId}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Encontrar centro de custo por texto
|
|
matchByText: async (text) => {
|
|
const response = await api.post('/cost-centers/match', { text });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Category Services (Categorias)
|
|
// ============================================
|
|
export const categoryService = {
|
|
// Listar todas as categorias
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/categories', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma categoria específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/categories/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova categoria
|
|
create: async (data) => {
|
|
const response = await api.post('/categories', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar categoria
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/categories/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir categoria
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/categories/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Adicionar palavra-chave
|
|
addKeyword: async (id, keyword, isCaseSensitive = false) => {
|
|
const response = await api.post(`/categories/${id}/keywords`, {
|
|
keyword,
|
|
is_case_sensitive: isCaseSensitive,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Remover palavra-chave
|
|
removeKeyword: async (id, keywordId) => {
|
|
const response = await api.delete(`/categories/${id}/keywords/${keywordId}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Encontrar categoria por texto
|
|
matchByText: async (text, type = null) => {
|
|
const response = await api.post('/categories/match', { text, type });
|
|
return response.data;
|
|
},
|
|
|
|
// Reordenar categorias
|
|
reorder: async (orders) => {
|
|
const response = await api.post('/categories/reorder', { orders });
|
|
return response.data;
|
|
},
|
|
|
|
// Categorização em lote - Preview
|
|
categorizeBatchPreview: async (onlyUncategorized = true, limit = 50, filters = null) => {
|
|
const response = await api.post('/categories/categorize-batch/preview', {
|
|
only_uncategorized: onlyUncategorized,
|
|
preview_limit: limit,
|
|
filters: filters,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Categorização em lote - Executar
|
|
categorizeBatch: async (onlyUncategorized = true, transactionIds = null, filters = null) => {
|
|
const response = await api.post('/categories/categorize-batch', {
|
|
only_uncategorized: onlyUncategorized,
|
|
transaction_ids: transactionIds,
|
|
filters: filters,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Categorização em lote manual - aplicar categoria/centro de custo selecionados
|
|
categorizeBatchManual: async (categoryId, costCenterId, filters, addKeyword = false, transactionIds = null) => {
|
|
const response = await api.post('/categories/categorize-batch/manual', {
|
|
category_id: categoryId,
|
|
cost_center_id: costCenterId,
|
|
filters: filters,
|
|
add_keyword: addKeyword,
|
|
transaction_ids: transactionIds,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Tipos de categoria disponíveis
|
|
types: {
|
|
income: 'Receita',
|
|
expense: 'Despesa',
|
|
both: 'Ambos',
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Liability Account Services (Contas Passivo)
|
|
// ============================================
|
|
export const liabilityAccountService = {
|
|
// Listar todas as contas passivo
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/liability-accounts', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma conta passivo específica com parcelas
|
|
getById: async (id) => {
|
|
const response = await api.get(`/liability-accounts/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova conta passivo manualmente
|
|
create: async (data) => {
|
|
const response = await api.post('/liability-accounts', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar conta passivo
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/liability-accounts/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir conta passivo
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/liability-accounts/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Importar contrato de arquivo Excel
|
|
import: async (formData) => {
|
|
const response = await api.post('/liability-accounts/import', formData, {
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Obter parcelas de uma conta
|
|
getInstallments: async (accountId) => {
|
|
const response = await api.get(`/liability-accounts/${accountId}/installments`);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar uma parcela
|
|
updateInstallment: async (accountId, installmentId, data) => {
|
|
const response = await api.put(`/liability-accounts/${accountId}/installments/${installmentId}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Obter resumo geral
|
|
getSummary: async () => {
|
|
const response = await api.get('/liability-summary');
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliação - Listar parcelas pendentes de conciliação
|
|
getPendingReconciliation: async () => {
|
|
const response = await api.get('/liability-accounts/pending-reconciliation');
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliação - Buscar transações elegíveis para vincular a uma parcela
|
|
getEligibleTransactions: async (accountId, installmentId, params = {}) => {
|
|
const response = await api.get(`/liability-accounts/${accountId}/installments/${installmentId}/eligible-transactions`, { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliação - Vincular uma parcela a uma transação
|
|
reconcile: async (accountId, installmentId, transactionId, markAsPaid = true) => {
|
|
const response = await api.post(`/liability-accounts/${accountId}/installments/${installmentId}/reconcile`, {
|
|
transaction_id: transactionId,
|
|
mark_as_paid: markAsPaid,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliação - Remover vínculo entre parcela e transação
|
|
unreconcile: async (accountId, installmentId) => {
|
|
const response = await api.delete(`/liability-accounts/${accountId}/installments/${installmentId}/reconcile`);
|
|
return response.data;
|
|
},
|
|
|
|
// Status disponíveis para contas
|
|
statuses: {
|
|
active: 'Ativo',
|
|
paid_off: 'Quitado',
|
|
defaulted: 'Inadimplente',
|
|
renegotiated: 'Renegociado',
|
|
},
|
|
|
|
// Status disponíveis para parcelas
|
|
installmentStatuses: {
|
|
pending: 'Pendente',
|
|
paid: 'Pago',
|
|
partial: 'Parcial',
|
|
overdue: 'Atrasado',
|
|
cancelled: 'Cancelado',
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Transaction Services (Transações)
|
|
// ============================================
|
|
export const transactionService = {
|
|
// Listar transações com filtros
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/transactions', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma transação específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/transactions/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova transação
|
|
create: async (data) => {
|
|
const response = await api.post('/transactions', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar transação
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/transactions/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir transação
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/transactions/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Marcar como concluída
|
|
complete: async (id, data = {}) => {
|
|
const response = await api.post(`/transactions/${id}/complete`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Cancelar transação
|
|
cancel: async (id) => {
|
|
const response = await api.post(`/transactions/${id}/cancel`);
|
|
return response.data;
|
|
},
|
|
|
|
// Reverter para pendente
|
|
revert: async (id) => {
|
|
const response = await api.post(`/transactions/${id}/revert`);
|
|
return response.data;
|
|
},
|
|
|
|
// Duplicar transação
|
|
duplicate: async (id) => {
|
|
const response = await api.post(`/transactions/${id}/duplicate`);
|
|
return response.data;
|
|
},
|
|
|
|
// Obter resumo
|
|
getSummary: async (params = {}) => {
|
|
const response = await api.get('/transactions-summary', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Listar transações agrupadas por semana e divisa
|
|
getByWeek: async (params = {}) => {
|
|
const response = await api.get('/transactions-by-week', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Tipos de transação
|
|
types: {
|
|
credit: 'Crédito',
|
|
debit: 'Débito',
|
|
},
|
|
|
|
// Status de transação
|
|
statuses: {
|
|
pending: 'Pendente',
|
|
completed: 'Concluída',
|
|
cancelled: 'Cancelada',
|
|
},
|
|
|
|
// Cores por status
|
|
statusColors: {
|
|
pending: 'warning',
|
|
completed: 'success',
|
|
cancelled: 'secondary',
|
|
},
|
|
|
|
// Cores por tipo
|
|
typeColors: {
|
|
credit: 'success',
|
|
debit: 'danger',
|
|
},
|
|
|
|
// Efetivação rápida (direto da listagem)
|
|
quickComplete: async (id, data = {}) => {
|
|
const response = await api.post(`/transactions/${id}/quick-complete`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Transferência entre contas
|
|
transfer: async (data) => {
|
|
const response = await api.post('/transactions/transfer', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Dividir transação em múltiplas categorias
|
|
split: async (id, splits) => {
|
|
const response = await api.post(`/transactions/${id}/split`, { splits });
|
|
return response.data;
|
|
},
|
|
|
|
// Desfazer divisão de transação
|
|
unsplit: async (id) => {
|
|
const response = await api.post(`/transactions/${id}/unsplit`);
|
|
return response.data;
|
|
},
|
|
|
|
// Obter divisões de uma transação
|
|
getSplits: async (id) => {
|
|
const response = await api.get(`/transactions/${id}/splits`);
|
|
return response.data;
|
|
},
|
|
|
|
// Desvincular transferência (remover flag is_transfer)
|
|
unlinkTransfer: async (id) => {
|
|
const response = await api.post(`/transactions/${id}/unlink-transfer`);
|
|
return response.data;
|
|
},
|
|
|
|
// Buscar parcelas de passivo compatíveis para conciliação
|
|
findLiabilityInstallments: async (id, toleranceDays = 15) => {
|
|
const response = await api.get(`/transactions/${id}/liability-installments`, {
|
|
params: { tolerance_days: toleranceDays }
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliar transação com parcela de passivo
|
|
reconcileWithLiability: async (transactionId, installmentId) => {
|
|
const response = await api.post(`/transactions/${transactionId}/reconcile-liability`, {
|
|
installment_id: installmentId
|
|
});
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Import Services (Importação de Extratos)
|
|
// ============================================
|
|
export const importService = {
|
|
// Upload de arquivo para preview
|
|
upload: async (formData) => {
|
|
const response = await api.post('/import/upload', formData, {
|
|
headers: {
|
|
'Content-Type': 'multipart/form-data',
|
|
},
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Obter headers do arquivo
|
|
getHeaders: async (data) => {
|
|
const response = await api.post('/import/headers', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Processar importação
|
|
process: async (data) => {
|
|
const response = await api.post('/import/process', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Listar mapeamentos salvos
|
|
getMappings: async () => {
|
|
const response = await api.get('/import/mappings');
|
|
return response.data;
|
|
},
|
|
|
|
// Obter um mapeamento
|
|
getMapping: async (id) => {
|
|
const response = await api.get(`/import/mappings/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar mapeamento
|
|
updateMapping: async (id, data) => {
|
|
const response = await api.put(`/import/mappings/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir mapeamento
|
|
deleteMapping: async (id) => {
|
|
const response = await api.delete(`/import/mappings/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Listar presets de bancos
|
|
getPresets: async () => {
|
|
const response = await api.get('/import/presets');
|
|
return response.data;
|
|
},
|
|
|
|
// Criar mapeamento a partir de preset
|
|
createFromPreset: async (preset) => {
|
|
const response = await api.post('/import/presets/create', { preset });
|
|
return response.data;
|
|
},
|
|
|
|
// Histórico de importações
|
|
getHistory: async () => {
|
|
const response = await api.get('/import/history');
|
|
return response.data;
|
|
},
|
|
|
|
// Obter definições de campos
|
|
getFields: async () => {
|
|
const response = await api.get('/import/fields');
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Duplicate Detection Services (Detecção de Duplicatas)
|
|
// ============================================
|
|
export const duplicateService = {
|
|
// Listar transações duplicadas potenciais
|
|
getAll: async () => {
|
|
const response = await api.get('/duplicate-transactions');
|
|
return response.data;
|
|
},
|
|
|
|
// Obter estatísticas de duplicatas
|
|
getStats: async () => {
|
|
const response = await api.get('/duplicate-transactions/stats');
|
|
return response.data;
|
|
},
|
|
|
|
// Listar pagamentos suspeitos (mesmo valor, datas próximas)
|
|
getSuspicious: async (days = 7) => {
|
|
const response = await api.get('/duplicate-transactions/suspicious', {
|
|
params: { days }
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir uma transação duplicada
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/duplicate-transactions/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Ignorar par de transações (não são duplicatas)
|
|
ignore: async (transaction1Id, transaction2Id) => {
|
|
const response = await api.post('/duplicate-transactions/ignore', {
|
|
transaction1_id: transaction1Id,
|
|
transaction2_id: transaction2Id,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Auto-delete: Deletar todas as duplicatas mantendo apenas a com maior ID
|
|
autoDelete: async (duplicateIds = null) => {
|
|
const response = await api.post('/duplicate-transactions/auto-delete', {
|
|
duplicate_ids: duplicateIds, // null = todas, array = selecionadas
|
|
});
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Transfer Detection Services (Detecção de Transferências)
|
|
// ============================================
|
|
export const transferDetectionService = {
|
|
// Listar possíveis transferências entre contas
|
|
getAll: async (toleranceDays = 3) => {
|
|
const response = await api.get('/transfer-detection', { params: { tolerance_days: toleranceDays } });
|
|
return response.data;
|
|
},
|
|
|
|
// Buscar possíveis pares para uma transação específica
|
|
findPairs: async (transactionId, toleranceDays = 7) => {
|
|
const response = await api.get(`/transfer-detection/${transactionId}/pairs`, { params: { tolerance_days: toleranceDays } });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter estatísticas de transferências
|
|
getStats: async () => {
|
|
const response = await api.get('/transfer-detection/stats');
|
|
return response.data;
|
|
},
|
|
|
|
// Confirmar transferência (vincular as duas transações)
|
|
confirm: async (debitId, creditId) => {
|
|
const response = await api.post('/transfer-detection/confirm', {
|
|
debit_id: debitId,
|
|
credit_id: creditId,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Confirmar múltiplas transferências em lote
|
|
confirmBatch: async (transfers) => {
|
|
const response = await api.post('/transfer-detection/confirm-batch', {
|
|
transfers: transfers.map(t => ({
|
|
debit_id: t.debit.id,
|
|
credit_id: t.credit.id,
|
|
})),
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Ignorar par (não é transferência)
|
|
ignore: async (debitId, creditId) => {
|
|
const response = await api.post('/transfer-detection/ignore', {
|
|
debit_id: debitId,
|
|
credit_id: creditId,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir ambas as transações
|
|
deleteBoth: async (debitId, creditId) => {
|
|
const response = await api.post('/transfer-detection/delete-both', {
|
|
debit_id: debitId,
|
|
credit_id: creditId,
|
|
});
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Refund Detection Service
|
|
// ============================================
|
|
export const refundDetectionService = {
|
|
// Listar possíveis pares de reembolso (gasto + devolução que se anulam)
|
|
getAll: async (toleranceDays = 7) => {
|
|
const response = await api.get('/refund-detection', { params: { tolerance_days: toleranceDays } });
|
|
return response.data;
|
|
},
|
|
|
|
// Confirmar par de reembolso
|
|
confirm: async (debitId, creditId) => {
|
|
const response = await api.post('/refund-detection/confirm', {
|
|
debit_id: debitId,
|
|
credit_id: creditId,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Confirmar múltiplos pares em lote
|
|
confirmBatch: async (refunds) => {
|
|
const response = await api.post('/refund-detection/confirm-batch', {
|
|
pairs: refunds.map(r => ({
|
|
debit_id: r.debit.id,
|
|
credit_id: r.credit.id,
|
|
})),
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Ignorar par
|
|
ignore: async (debitId, creditId) => {
|
|
const response = await api.post('/refund-detection/ignore', {
|
|
debit_id: debitId,
|
|
credit_id: creditId,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Desfazer par de reembolso
|
|
undo: async (transactionId) => {
|
|
const response = await api.post('/refund-detection/undo', {
|
|
transaction_id: transactionId,
|
|
});
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Dashboard Service
|
|
// ============================================
|
|
export const dashboardService = {
|
|
// Resumo geral do dashboard
|
|
getSummary: async () => {
|
|
const response = await api.get('/dashboard/summary');
|
|
return response.data;
|
|
},
|
|
|
|
// Fluxo de caixa mensal
|
|
getCashflow: async (months = 12, endDate = null) => {
|
|
const params = { months };
|
|
if (endDate) params.end_date = endDate;
|
|
const response = await api.get('/dashboard/cashflow', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Despesas por categoria
|
|
getExpensesByCategory: async (months = 3) => {
|
|
const response = await api.get('/dashboard/expenses-by-category', { params: { months } });
|
|
return response.data;
|
|
},
|
|
|
|
// Receitas por categoria
|
|
getIncomeByCategory: async (months = 3) => {
|
|
const response = await api.get('/dashboard/income-by-category', { params: { months } });
|
|
return response.data;
|
|
},
|
|
|
|
// Diferenças entre valores planejados e efetivos
|
|
getPaymentVariances: async (months = 3) => {
|
|
const response = await api.get('/dashboard/payment-variances', { params: { months } });
|
|
return response.data;
|
|
},
|
|
|
|
// Dados do calendário (transações + recorrentes pendentes)
|
|
getCalendar: async (year, month) => {
|
|
const params = {};
|
|
if (year) params.year = year;
|
|
if (month) params.month = month;
|
|
const response = await api.get('/dashboard/calendar', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Transações de um dia específico
|
|
getCalendarDay: async (date) => {
|
|
const response = await api.get('/dashboard/calendar-day', { params: { date } });
|
|
return response.data;
|
|
},
|
|
|
|
// Transações pendentes dos próximos dias
|
|
getUpcoming: async (days = 7) => {
|
|
const response = await api.get('/dashboard/upcoming', { params: { days } });
|
|
return response.data;
|
|
},
|
|
|
|
// Transações em atraso
|
|
getOverdue: async (limit = 50) => {
|
|
const response = await api.get('/dashboard/overdue', { params: { limit } });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Recurring Transactions Service (Transações Recorrentes)
|
|
// ============================================
|
|
export const recurringService = {
|
|
// Obter frequências disponíveis
|
|
getFrequencies: async () => {
|
|
const response = await api.get('/recurring/frequencies');
|
|
return response.data;
|
|
},
|
|
|
|
// === TEMPLATES ===
|
|
|
|
// Listar todos os templates
|
|
getTemplates: async (params = {}) => {
|
|
const response = await api.get('/recurring', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter um template específico
|
|
getTemplate: async (id) => {
|
|
const response = await api.get(`/recurring/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar template manualmente
|
|
createTemplate: async (data) => {
|
|
const response = await api.post('/recurring', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar template a partir de uma transação
|
|
createFromTransaction: async (data) => {
|
|
const response = await api.post('/recurring/from-transaction', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar template
|
|
updateTemplate: async (id, data) => {
|
|
const response = await api.put(`/recurring/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir template
|
|
deleteTemplate: async (id) => {
|
|
const response = await api.delete(`/recurring/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Pausar template
|
|
pauseTemplate: async (id) => {
|
|
const response = await api.post(`/recurring/${id}/pause`);
|
|
return response.data;
|
|
},
|
|
|
|
// Retomar template
|
|
resumeTemplate: async (id) => {
|
|
const response = await api.post(`/recurring/${id}/resume`);
|
|
return response.data;
|
|
},
|
|
|
|
// Listar instâncias de um template
|
|
getTemplateInstances: async (templateId, params = {}) => {
|
|
const response = await api.get(`/recurring/${templateId}/instances`, { params });
|
|
return response.data;
|
|
},
|
|
|
|
// === INSTÂNCIAS ===
|
|
|
|
// Listar todas as instâncias pendentes
|
|
getPendingInstances: async (params = {}) => {
|
|
const response = await api.get('/recurring/pending', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Listar instâncias vencidas
|
|
getOverdueInstances: async () => {
|
|
const response = await api.get('/recurring/overdue');
|
|
return response.data;
|
|
},
|
|
|
|
// Listar instâncias próximas do vencimento
|
|
getDueSoonInstances: async (days = 7) => {
|
|
const response = await api.get('/recurring/due-soon', { params: { days } });
|
|
return response.data;
|
|
},
|
|
|
|
// Marcar instância como paga (cria transação)
|
|
payInstance: async (instanceId, data = {}) => {
|
|
const response = await api.post(`/recurring-instances/${instanceId}/pay`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Conciliar instância com transação existente
|
|
reconcileInstance: async (instanceId, transactionId, notes = null) => {
|
|
const response = await api.post(`/recurring-instances/${instanceId}/reconcile`, {
|
|
transaction_id: transactionId,
|
|
notes,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Buscar transações candidatas para conciliação
|
|
findCandidates: async (instanceId, daysTolerance = 7) => {
|
|
const response = await api.get(`/recurring-instances/${instanceId}/candidates`, {
|
|
params: { days_tolerance: daysTolerance },
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Pular instância
|
|
skipInstance: async (instanceId, reason = null) => {
|
|
const response = await api.post(`/recurring-instances/${instanceId}/skip`, { reason });
|
|
return response.data;
|
|
},
|
|
|
|
// Cancelar instância
|
|
cancelInstance: async (instanceId, reason = null) => {
|
|
const response = await api.post(`/recurring-instances/${instanceId}/cancel`, { reason });
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar instância individual
|
|
updateInstance: async (instanceId, data) => {
|
|
const response = await api.put(`/recurring-instances/${instanceId}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Regenerar instâncias para todos os templates ativos
|
|
regenerateAll: async () => {
|
|
const response = await api.post('/recurring/regenerate-all');
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Business Settings Services (Configurações de Negócio - Markup)
|
|
// ============================================
|
|
export const businessSettingService = {
|
|
// Listar todas as configurações
|
|
getAll: async () => {
|
|
const response = await api.get('/business-settings');
|
|
return response.data;
|
|
},
|
|
|
|
// Obter configuração padrão ativa
|
|
getDefault: async () => {
|
|
const response = await api.get('/business-settings/default');
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma configuração específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/business-settings/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova configuração
|
|
create: async (data) => {
|
|
const response = await api.post('/business-settings', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar configuração
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/business-settings/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir configuração
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/business-settings/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Recalcular markup
|
|
recalculateMarkup: async (id) => {
|
|
const response = await api.post(`/business-settings/${id}/recalculate-markup`);
|
|
return response.data;
|
|
},
|
|
|
|
// Simular preço de venda
|
|
simulatePrice: async (id, cmv) => {
|
|
const response = await api.post(`/business-settings/${id}/simulate-price`, { cmv });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Product Sheet Services (Fichas Técnicas - CMV)
|
|
// ============================================
|
|
export const productSheetService = {
|
|
// Listar todas as fichas
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/product-sheets', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma ficha específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/product-sheets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova ficha
|
|
create: async (data) => {
|
|
const response = await api.post('/product-sheets', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar ficha
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/product-sheets/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir ficha
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/product-sheets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Adicionar item à ficha
|
|
addItem: async (sheetId, itemData) => {
|
|
const response = await api.post(`/product-sheets/${sheetId}/items`, itemData);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar item da ficha
|
|
updateItem: async (sheetId, itemId, itemData) => {
|
|
const response = await api.put(`/product-sheets/${sheetId}/items/${itemId}`, itemData);
|
|
return response.data;
|
|
},
|
|
|
|
// Remover item da ficha
|
|
removeItem: async (sheetId, itemId) => {
|
|
const response = await api.delete(`/product-sheets/${sheetId}/items/${itemId}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Recalcular preço de venda
|
|
recalculatePrice: async (id, businessSettingId = null) => {
|
|
const response = await api.post(`/product-sheets/${id}/recalculate-price`, {
|
|
business_setting_id: businessSettingId,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Duplicar ficha
|
|
duplicate: async (id) => {
|
|
const response = await api.post(`/product-sheets/${id}/duplicate`);
|
|
return response.data;
|
|
},
|
|
|
|
// Listar categorias
|
|
getCategories: async () => {
|
|
const response = await api.get('/product-sheets/categories');
|
|
return response.data;
|
|
},
|
|
|
|
// Listar tipos de componentes
|
|
getItemTypes: async () => {
|
|
const response = await api.get('/product-sheets/item-types');
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Fichas Técnicas de Serviços (Service Sheets)
|
|
// ============================================
|
|
export const serviceSheetService = {
|
|
// Listar todas as fichas de serviço
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/service-sheets', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma ficha específica
|
|
get: async (id) => {
|
|
const response = await api.get(`/service-sheets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova ficha
|
|
create: async (data) => {
|
|
const response = await api.post('/service-sheets', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar ficha
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/service-sheets/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir ficha
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/service-sheets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Adicionar item/insumo à ficha
|
|
addItem: async (sheetId, itemData) => {
|
|
const response = await api.post(`/service-sheets/${sheetId}/items`, itemData);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar item da ficha
|
|
updateItem: async (sheetId, itemId, itemData) => {
|
|
const response = await api.put(`/service-sheets/${sheetId}/items/${itemId}`, itemData);
|
|
return response.data;
|
|
},
|
|
|
|
// Remover item da ficha
|
|
removeItem: async (sheetId, itemId) => {
|
|
const response = await api.delete(`/service-sheets/${sheetId}/items/${itemId}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Duplicar ficha
|
|
duplicate: async (id) => {
|
|
const response = await api.post(`/service-sheets/${id}/duplicate`);
|
|
return response.data;
|
|
},
|
|
|
|
// Listar categorias
|
|
getCategories: async () => {
|
|
const response = await api.get('/service-sheets/categories');
|
|
return response.data;
|
|
},
|
|
|
|
// Listar tipos de itens
|
|
getItemTypes: async () => {
|
|
const response = await api.get('/service-sheets/item-types');
|
|
return response.data;
|
|
},
|
|
|
|
// Simular preço
|
|
simulate: async (data) => {
|
|
const response = await api.post('/service-sheets/simulate', data);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Campanhas Promocionais (Promotional Campaigns)
|
|
// ============================================
|
|
export const campaignService = {
|
|
// Listar todas as campanhas
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/campaigns', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obter uma campanha específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/campaigns/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Criar nova campanha
|
|
create: async (data) => {
|
|
const response = await api.post('/campaigns', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar campanha
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/campaigns/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Excluir campanha
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/campaigns/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Duplicar campanha
|
|
duplicate: async (id) => {
|
|
const response = await api.post(`/campaigns/${id}/duplicate`);
|
|
return response.data;
|
|
},
|
|
|
|
// Adicionar produtos à campanha
|
|
addProducts: async (campaignId, productIds) => {
|
|
const response = await api.post(`/campaigns/${campaignId}/products`, {
|
|
product_ids: productIds,
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Remover produtos da campanha
|
|
removeProducts: async (campaignId, productIds) => {
|
|
const response = await api.delete(`/campaigns/${campaignId}/products`, {
|
|
data: { product_ids: productIds },
|
|
});
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar desconto de um produto na campanha
|
|
updateProductDiscount: async (campaignId, productId, discountData) => {
|
|
const response = await api.put(
|
|
`/campaigns/${campaignId}/products/${productId}`,
|
|
discountData
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
// Obter presets disponíveis
|
|
getPresets: async () => {
|
|
const response = await api.get('/campaigns/presets');
|
|
return response.data;
|
|
},
|
|
|
|
// Preview de preços com desconto
|
|
preview: async (data) => {
|
|
const response = await api.post('/campaigns/preview', data);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Financial Goals (Metas Financieras)
|
|
// ============================================
|
|
export const financialGoalService = {
|
|
// Listar todas las metas
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/financial-goals', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obtener una meta específica
|
|
getById: async (id) => {
|
|
const response = await api.get(`/financial-goals/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Crear nueva meta
|
|
create: async (data) => {
|
|
const response = await api.post('/financial-goals', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Actualizar meta
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/financial-goals/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Eliminar meta
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/financial-goals/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Añadir contribución
|
|
addContribution: async (goalId, data) => {
|
|
const response = await api.post(`/financial-goals/${goalId}/contributions`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Eliminar contribución
|
|
removeContribution: async (goalId, contributionId) => {
|
|
const response = await api.delete(`/financial-goals/${goalId}/contributions/${contributionId}`);
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Budgets (Presupuestos)
|
|
// ============================================
|
|
export const budgetService = {
|
|
// Listar presupuestos de un período
|
|
getAll: async (params = {}) => {
|
|
const response = await api.get('/budgets', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Obtener un presupuesto específico
|
|
getById: async (id) => {
|
|
const response = await api.get(`/budgets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Crear nuevo presupuesto
|
|
create: async (data) => {
|
|
const response = await api.post('/budgets', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Actualizar presupuesto
|
|
update: async (id, data) => {
|
|
const response = await api.put(`/budgets/${id}`, data);
|
|
return response.data;
|
|
},
|
|
|
|
// Eliminar presupuesto
|
|
delete: async (id) => {
|
|
const response = await api.delete(`/budgets/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
// Obtener categorías disponibles
|
|
getAvailableCategories: async (params = {}) => {
|
|
const response = await api.get('/budgets/available-categories', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Copiar al próximo mes
|
|
copyToNextMonth: async (year, month) => {
|
|
const response = await api.post('/budgets/copy-to-next-month', { year, month });
|
|
return response.data;
|
|
},
|
|
|
|
// Resumen anual
|
|
getYearSummary: async (params = {}) => {
|
|
const response = await api.get('/budgets/year-summary', { params });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Reports (Reportes)
|
|
// ============================================
|
|
export const reportService = {
|
|
// Resumen general
|
|
getSummary: async (params = {}) => {
|
|
const response = await api.get('/reports/summary', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Resumen ejecutivo
|
|
getExecutiveSummary: async (params = {}) => {
|
|
const response = await api.get('/reports/executive-summary', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Por categoría
|
|
getByCategory: async (params = {}) => {
|
|
const response = await api.get('/reports/by-category', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Por centro de costos
|
|
getByCostCenter: async (params = {}) => {
|
|
const response = await api.get('/reports/by-cost-center', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Evolución mensual
|
|
getMonthlyEvolution: async (params = {}) => {
|
|
const response = await api.get('/reports/monthly-evolution', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Por día de la semana
|
|
getByDayOfWeek: async (params = {}) => {
|
|
const response = await api.get('/reports/by-day-of-week', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Top gastos
|
|
getTopExpenses: async (params = {}) => {
|
|
const response = await api.get('/reports/top-expenses', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Comparar períodos
|
|
comparePeriods: async (params = {}) => {
|
|
const response = await api.get('/reports/compare-periods', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Reporte de cuentas
|
|
getAccountsReport: async () => {
|
|
const response = await api.get('/reports/accounts');
|
|
return response.data;
|
|
},
|
|
|
|
// Proyección
|
|
getProjection: async (params = {}) => {
|
|
const response = await api.get('/reports/projection', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Gráfico de projeção de saldo
|
|
getProjectionChart: async (params = {}) => {
|
|
const response = await api.get('/reports/projection-chart', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Reporte de recurrentes
|
|
getRecurringReport: async () => {
|
|
const response = await api.get('/reports/recurring');
|
|
return response.data;
|
|
},
|
|
|
|
// Reporte de pasivos/deudas
|
|
getLiabilities: async () => {
|
|
const response = await api.get('/reports/liabilities');
|
|
return response.data;
|
|
},
|
|
|
|
// Transacciones futuras
|
|
getFutureTransactions: async (params = {}) => {
|
|
const response = await api.get('/reports/future-transactions', { params });
|
|
return response.data;
|
|
},
|
|
|
|
// Transacciones vencidas
|
|
getOverdue: async () => {
|
|
const response = await api.get('/reports/overdue');
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Financial Health (Salud Financiera)
|
|
// ============================================
|
|
export const financialHealthService = {
|
|
// Obtener salud financiera completa
|
|
get: async () => {
|
|
const response = await api.get('/financial-health');
|
|
return response.data;
|
|
},
|
|
|
|
// Historial de puntuación
|
|
getHistory: async (params = {}) => {
|
|
const response = await api.get('/financial-health/history', { params });
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// User Preferences (Preferências do Usuário)
|
|
// ============================================
|
|
export const preferencesService = {
|
|
// Obter preferências
|
|
get: async () => {
|
|
const response = await api.get('/preferences');
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar preferências
|
|
update: async (data) => {
|
|
const response = await api.put('/preferences', data);
|
|
return response.data;
|
|
},
|
|
|
|
// Enviar notificação de teste
|
|
testNotification: async () => {
|
|
const response = await api.post('/preferences/test-notification');
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
// ============================================
|
|
// Profile Service (Perfil do Usuário)
|
|
// ============================================
|
|
export const profileService = {
|
|
// Obter dados do usuário
|
|
get: async () => {
|
|
const response = await api.get('/me');
|
|
return response.data;
|
|
},
|
|
|
|
// Atualizar perfil (nome, email, senha)
|
|
update: async (data) => {
|
|
const response = await api.put('/profile', data);
|
|
// Atualizar localStorage se sucesso
|
|
if (response.data.success && response.data.data?.user) {
|
|
localStorage.setItem('user', JSON.stringify(response.data.data.user));
|
|
}
|
|
return response.data;
|
|
},
|
|
};
|
|
|
|
export default api;
|