import { apiClient } from './client'; export interface OrgStatus { configured: boolean; orgId?: string; legalName?: string; hasCsd?: boolean; } export interface TimbreStatus { configured: boolean; // Backward compat (flat fields representan el pool mensual) tipo?: string; limite?: number; usados?: number; disponibles?: number; periodoFin?: string; // Shape extendido mensual?: { tipo: string; limite: number; usados: number; disponibles: number; periodoFin: string; }; adicionales?: { total: number; usados: number; disponibles: number; paquetes: Array<{ id: number; cantidad: number; usados: number; disponibles: number; adquiridoEn: string; expiraEn: string; }>; }; totalDisponibles?: number; } export interface InvoiceCustomer { legalName: string; taxId: string; taxSystem: string; email?: string; zip: string; } export interface InvoiceLineItem { description: string; productKey: string; unitKey?: string; unitName?: string; quantity: number; price: number; taxIncluded?: boolean; taxes?: Array<{ type: string; rate: number }>; } export interface InvoiceData { customer: InvoiceCustomer; items: InvoiceLineItem[]; use: string; paymentForm: string; paymentMethod?: string; currency?: string; exchangeRate?: number; series?: string; folioNumber?: number; conditions?: string; } export interface InvoiceResult { id: string; uuid: string; total: number; status: string; } export const getOrgStatus = () => apiClient.get('/facturacion/org/status').then(r => r.data); export const createOrg = () => apiClient.post('/facturacion/org').then(r => r.data); export const uploadCsd = (data: { cerFile: string; keyFile: string; password: string }) => apiClient.post('/facturacion/csd', data).then(r => r.data); export const getTimbres = () => apiClient.get('/facturacion/timbres').then(r => r.data); export interface PaqueteCatalogo { id: number; cantidad: number; precio: number; } export const getPaquetesCatalogo = () => apiClient.get('/facturacion/timbres/paquetes-catalogo').then(r => r.data); export const comprarPaquete = (catalogoId: number) => apiClient.post<{ paymentId: string; checkoutUrl: string }>('/facturacion/timbres/paquetes/comprar', { catalogoId }) .then(r => r.data); export interface PaqueteCatalogoAdmin { id: number; cantidad: number; precio: number; active: boolean; updatedAt: string; } export const getPaquetesCatalogoAdmin = () => apiClient.get('/facturacion/timbres/paquetes-catalogo/admin').then(r => r.data); export const updatePaqueteCatalogo = (id: number, data: { precio?: number; active?: boolean }) => apiClient.put(`/facturacion/timbres/paquetes-catalogo/${id}`, data).then(r => r.data); export const emitirFactura = (data: InvoiceData) => apiClient.post('/facturacion/emitir', data).then(r => r.data); export const cancelarFactura = (uuid: string, motive?: string, substitution?: string) => apiClient.post(`/facturacion/cancelar/${uuid}`, { motive, substitution }).then(r => r.data); export const downloadPdf = (id: string) => apiClient.get(`/facturacion/pdf/${id}`, { responseType: 'blob' }).then(r => r.data); export const downloadXml = (id: string) => apiClient.get(`/facturacion/xml/${id}`, { responseType: 'blob' }).then(r => r.data); export interface RfcSearchResult { id: number; rfc: string; razonSocial: string | null; regimenFiscal: string | null; codigoPostal: string | null; } export const searchRfcs = (q: string, contribuyenteId?: string) => { const params = new URLSearchParams({ q }); if (contribuyenteId) params.set('contribuyenteId', contribuyenteId); return apiClient.get(`/facturacion/rfcs/search?${params.toString()}`).then(r => r.data); }; export interface CfdiPpdPendiente { uuid: string; serie: string | null; folio: string | null; totalMxn: number; fechaEmision: string; rfcReceptor: string; nombreReceptor: string; ivaTrasladoMxn: number; saldoPendiente: number; } export const getCfdisPpd = (rfc: string, contribuyenteId?: string) => { const params = new URLSearchParams({ rfc }); if (contribuyenteId) params.set('contribuyenteId', contribuyenteId); return apiClient.get(`/facturacion/cfdis-ppd?${params.toString()}`).then(r => r.data); }; export interface CfdiRelacionable { uuid: string; serie: string | null; folio: string | null; totalMxn: number; fechaEmision: string; tipoComprobante: 'I' | 'E'; metodoPago: string | null; } export const getCfdisRelacionables = (rfcReceptor: string, contribuyenteId: string) => apiClient .get( `/facturacion/cfdis-relacionables?rfcReceptor=${encodeURIComponent(rfcReceptor)}&contribuyenteId=${encodeURIComponent(contribuyenteId)}`, ) .then(r => r.data); export interface ConceptoPrevio { claveProdServ: string; descripcion: string; claveUnidad: string | null; unidad: string | null; valorUnitario: number; importe: number; ivaTraslado: number; isrRetencion: number; ivaRetencion: number; tipoCfdi: string; rfcEmisor: string; nombreEmisor: string; rfcReceptor: string; nombreReceptor: string; fechaEmision: string; } export const getPagosSinFactura = () => apiClient.get>('/facturacion/pagos-sin-factura').then(r => r.data); export const emitirFacturaPago = (paymentId: string) => apiClient.post<{ success: boolean; invoiceId: string; paymentId: string }>(`/facturacion/emitir-factura-pago/${paymentId}`).then(r => r.data); export const searchConceptos = (q: string, tipo?: string, contribuyenteId?: string | null) => { const params = new URLSearchParams(); if (q) params.set('q', q); if (tipo) params.set('tipo', tipo); if (contribuyenteId) params.set('contribuyenteId', contribuyenteId); return apiClient.get(`/facturacion/conceptos/search?${params}`).then(r => r.data); };