import api from './axios-instance'; import { API_ENDPOINTS } from '@shared/constants/api-endpoints'; import type { BaseEntity } from '@shared/types/entities.types'; import type { ApiResponse, PaginatedResponse, PaginationParams } from '@shared/types/api.types'; // ============================================================================ // Interfaces // ============================================================================ export interface Account extends BaseEntity { code: string; name: string; type: 'asset' | 'liability' | 'equity' | 'income' | 'expense'; accountType: string; parentId?: string; currencyId?: string; reconcile: boolean; isActive: boolean; balance?: number; tenantId: string; } export interface Journal extends BaseEntity { code: string; name: string; type: 'sale' | 'purchase' | 'cash' | 'bank' | 'general'; defaultDebitAccountId?: string; defaultCreditAccountId?: string; currencyId?: string; isActive: boolean; tenantId: string; } export interface JournalEntryLine { id?: string; accountId: string; accountName?: string; partnerId?: string; partnerName?: string; name?: string; debit: number; credit: number; currencyId?: string; amountCurrency?: number; } export interface JournalEntry extends BaseEntity { name: string; journalId: string; journalName?: string; date: string; ref?: string; status: 'draft' | 'posted' | 'cancelled'; lines: JournalEntryLine[]; tenantId: string; } export interface InvoiceLine { id?: string; productId?: string; productName?: string; accountId: string; name: string; quantity: number; unitPrice: number; discount?: number; taxIds?: string[]; subtotal?: number; } export interface Invoice extends BaseEntity { name: string; type: 'out_invoice' | 'out_refund' | 'in_invoice' | 'in_refund'; partnerId: string; partnerName?: string; dateInvoice: string; dateDue?: string; journalId: string; status: 'draft' | 'open' | 'paid' | 'cancelled'; paymentState?: 'not_paid' | 'partial' | 'paid'; lines: InvoiceLine[]; amountUntaxed: number; amountTax: number; amountTotal: number; amountResidual: number; currencyId?: string; notes?: string; tenantId: string; } export interface Payment extends BaseEntity { name: string; partnerId: string; partnerName?: string; paymentType: 'inbound' | 'outbound' | 'transfer'; paymentMethod: 'manual' | 'check' | 'bank_transfer' | 'electronic'; journalId: string; journalName?: string; date: string; amount: number; currencyId?: string; memo?: string; status: 'draft' | 'posted' | 'reconciled' | 'cancelled'; invoiceIds?: string[]; tenantId: string; } // ============================================================================ // DTOs // ============================================================================ export interface CreateAccountDto { code: string; name: string; type: Account['type']; accountType: string; parentId?: string; currencyId?: string; reconcile?: boolean; isActive?: boolean; } export interface UpdateAccountDto { code?: string; name?: string; type?: Account['type']; accountType?: string; parentId?: string; currencyId?: string; reconcile?: boolean; isActive?: boolean; } export interface CreateJournalDto { code: string; name: string; type: Journal['type']; defaultDebitAccountId?: string; defaultCreditAccountId?: string; currencyId?: string; isActive?: boolean; } export interface UpdateJournalDto { code?: string; name?: string; type?: Journal['type']; defaultDebitAccountId?: string; defaultCreditAccountId?: string; currencyId?: string; isActive?: boolean; } export interface CreateJournalEntryDto { journalId: string; date: string; ref?: string; lines: Omit[]; } export interface CreateInvoiceDto { type: Invoice['type']; partnerId: string; dateInvoice?: string; dateDue?: string; journalId: string; lines: Omit[]; currencyId?: string; notes?: string; } export interface UpdateInvoiceDto { partnerId?: string; dateInvoice?: string; dateDue?: string; journalId?: string; lines?: Omit[]; currencyId?: string; notes?: string; } export interface CreatePaymentDto { partnerId: string; paymentType: Payment['paymentType']; paymentMethod: Payment['paymentMethod']; journalId: string; date?: string; amount: number; currencyId?: string; memo?: string; invoiceIds?: string[]; } export interface UpdatePaymentDto { partnerId?: string; paymentMethod?: Payment['paymentMethod']; journalId?: string; date?: string; amount?: number; currencyId?: string; memo?: string; invoiceIds?: string[]; } // ============================================================================ // Filters // ============================================================================ export interface AccountFilters extends PaginationParams { type?: Account['type']; isActive?: boolean; code?: string; } export interface JournalFilters extends PaginationParams { type?: Journal['type']; isActive?: boolean; } export interface JournalEntryFilters extends PaginationParams { journalId?: string; status?: JournalEntry['status']; dateFrom?: string; dateTo?: string; } export interface InvoiceFilters extends PaginationParams { type?: Invoice['type']; partnerId?: string; status?: Invoice['status']; paymentState?: Invoice['paymentState']; dateFrom?: string; dateTo?: string; } export interface PaymentFilters extends PaginationParams { partnerId?: string; paymentType?: Payment['paymentType']; status?: Payment['status']; journalId?: string; dateFrom?: string; dateTo?: string; } // ============================================================================ // API Client // ============================================================================ export const financialApi = { // Accounts getAccounts: async (filters?: AccountFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.FINANCIAL.ACCOUNTS, { params: filters } ); return response.data; }, getAccountById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.FINANCIAL.ACCOUNTS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Cuenta contable no encontrada'); } return response.data.data; }, createAccount: async (data: CreateAccountDto): Promise => { const response = await api.post>( API_ENDPOINTS.FINANCIAL.ACCOUNTS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear cuenta contable'); } return response.data.data; }, updateAccount: async (id: string, data: UpdateAccountDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.FINANCIAL.ACCOUNTS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar cuenta contable'); } return response.data.data; }, deleteAccount: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.FINANCIAL.ACCOUNTS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar cuenta contable'); } }, // Journals getJournals: async (filters?: JournalFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.FINANCIAL.JOURNALS, { params: filters } ); return response.data; }, getJournalById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.FINANCIAL.JOURNALS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Diario contable no encontrado'); } return response.data.data; }, createJournal: async (data: CreateJournalDto): Promise => { const response = await api.post>( API_ENDPOINTS.FINANCIAL.JOURNALS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear diario contable'); } return response.data.data; }, updateJournal: async (id: string, data: UpdateJournalDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.FINANCIAL.JOURNALS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar diario contable'); } return response.data.data; }, deleteJournal: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.FINANCIAL.JOURNALS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar diario contable'); } }, // Journal Entries (Moves) getJournalEntries: async (filters?: JournalEntryFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.FINANCIAL.MOVES, { params: filters } ); return response.data; }, getJournalEntryById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.FINANCIAL.MOVES}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Asiento contable no encontrado'); } return response.data.data; }, createJournalEntry: async (data: CreateJournalEntryDto): Promise => { const response = await api.post>( API_ENDPOINTS.FINANCIAL.MOVES, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear asiento contable'); } return response.data.data; }, postJournalEntry: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.MOVES}/${id}/post` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al publicar asiento contable'); } return response.data.data; }, cancelJournalEntry: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.MOVES}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar asiento contable'); } return response.data.data; }, deleteJournalEntry: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.FINANCIAL.MOVES}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar asiento contable'); } }, // Invoices getInvoices: async (filters?: InvoiceFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.FINANCIAL.INVOICES, { params: filters } ); return response.data; }, getInvoiceById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.FINANCIAL.INVOICES}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Factura no encontrada'); } return response.data.data; }, createInvoice: async (data: CreateInvoiceDto): Promise => { const response = await api.post>( API_ENDPOINTS.FINANCIAL.INVOICES, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear factura'); } return response.data.data; }, updateInvoice: async (id: string, data: UpdateInvoiceDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.FINANCIAL.INVOICES}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar factura'); } return response.data.data; }, validateInvoice: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.INVOICES}/${id}/validate` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al validar factura'); } return response.data.data; }, cancelInvoice: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.INVOICES}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar factura'); } return response.data.data; }, deleteInvoice: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.FINANCIAL.INVOICES}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar factura'); } }, // Payments getPayments: async (filters?: PaymentFilters): Promise> => { const response = await api.get>( API_ENDPOINTS.FINANCIAL.PAYMENTS, { params: filters } ); return response.data; }, getPaymentById: async (id: string): Promise => { const response = await api.get>( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Pago no encontrado'); } return response.data.data; }, createPayment: async (data: CreatePaymentDto): Promise => { const response = await api.post>( API_ENDPOINTS.FINANCIAL.PAYMENTS, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al crear pago'); } return response.data.data; }, updatePayment: async (id: string, data: UpdatePaymentDto): Promise => { const response = await api.patch>( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}`, data ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al actualizar pago'); } return response.data.data; }, postPayment: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}/post` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al publicar pago'); } return response.data.data; }, reconcilePayment: async (id: string, invoiceIds: string[]): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}/reconcile`, { invoiceIds } ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al reconciliar pago'); } return response.data.data; }, cancelPayment: async (id: string): Promise => { const response = await api.post>( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}/cancel` ); if (!response.data.success || !response.data.data) { throw new Error(response.data.error || 'Error al cancelar pago'); } return response.data.data; }, deletePayment: async (id: string): Promise => { const response = await api.delete( `${API_ENDPOINTS.FINANCIAL.PAYMENTS}/${id}` ); if (!response.data.success) { throw new Error(response.data.error || 'Error al eliminar pago'); } }, };