- Catálogo de obligaciones fiscales expandido a 30 entradas con campo requierePago. - Soporte de frecuencia cuatrimestral en obligaciones y declaraciones. - Automatización de cierre de obligaciones fiscales desde Documentos › Declaraciones. - Nuevas tablas obligacion_evidencias, obligacion_periodos estados y declaracion_obligaciones. - Nuevo servicio obligacion-evidencias.service.ts y endpoints REST. - Refactor de declaraciones.service.ts para vincular obligaciones y crear evidencias. - Notificaciones por email para evidencias de obligaciones. - Adjuntar PDFs en correo de declaración subida. - Fix drill-down de CFDIs: carga completa al visualizar. - Fix sincronización SAT: tipos P/N, UUID case-insensitive, no reutilizar requestId. - Fix suscripciones pending en /configuracion/planes-despacho. - Fix sugerencias de Clave Producto SAT: importar catálogo y robustecer autocomplete. - Quitar toggle manual de completado en Configuración › Obligaciones fiscales › Tareas. - Scripts de soporte para Demo Ventas y utilerías (change-user-email, resend-welcome, import-clave-prod-serv). - Documentación de cambios en docs/CAMBIOS-2026-05-04.md.
91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
import { apiClient } from './client';
|
|
|
|
export type Impuesto = 'IVA' | 'ISR' | 'IEPS' | 'ISN' | 'DIOT' | 'OTRO' | 'ISH';
|
|
export type Periodicidad = 'mensual' | 'bimestral' | 'trimestral' | 'semestral' | 'anual';
|
|
|
|
export interface Declaracion {
|
|
id: number;
|
|
año: number;
|
|
mes: number;
|
|
tipo: 'normal' | 'complementaria';
|
|
periodicidad: Periodicidad;
|
|
impuestos: Impuesto[];
|
|
montoPago: number | null;
|
|
pdfFilename: string | null;
|
|
ligaPagoFilename: string | null;
|
|
pdfPagoFilename: string | null;
|
|
pagadoAt: string | null;
|
|
creadoPor: string | null;
|
|
notas: string | null;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
tieneLigaPago: boolean;
|
|
tienePagoPdf: boolean;
|
|
}
|
|
|
|
export interface CreateDeclaracionData {
|
|
año: number;
|
|
mes: number;
|
|
tipo: 'normal' | 'complementaria';
|
|
periodicidad?: Periodicidad;
|
|
/** Legacy: se infiere en backend si se envían obligacionesIds. */
|
|
impuestos?: Impuesto[];
|
|
/** Obligaciones fiscales que cubre esta declaración. */
|
|
obligacionesIds?: string[];
|
|
montoPago?: number;
|
|
pdfBase64: string;
|
|
pdfFilename: string;
|
|
ligaPagoBase64?: string;
|
|
ligaPagoFilename?: string;
|
|
notas?: string;
|
|
contribuyenteId?: string;
|
|
}
|
|
|
|
export const listDeclaraciones = (fechaDesde?: string, fechaHasta?: string, contribuyenteId?: string | null) => {
|
|
const params = new URLSearchParams();
|
|
if (fechaDesde) params.set('fechaDesde', fechaDesde);
|
|
if (fechaHasta) params.set('fechaHasta', fechaHasta);
|
|
if (contribuyenteId) params.set('contribuyenteId', contribuyenteId);
|
|
return apiClient.get<Declaracion[]>(`/documentos/declaraciones?${params}`).then(r => r.data);
|
|
};
|
|
|
|
export const createDeclaracion = (data: CreateDeclaracionData) =>
|
|
apiClient.post<{ declaracion: Declaracion; alertasResueltas: number }>('/documentos/declaraciones', data).then(r => r.data);
|
|
|
|
export const uploadComprobantePago = (id: number, pdfBase64: string, pdfFilename: string) =>
|
|
apiClient.post<{ declaracion: Declaracion; alertasResueltas: number }>(
|
|
`/documentos/declaraciones/${id}/comprobante-pago`,
|
|
{ pdfBase64, pdfFilename },
|
|
).then(r => r.data);
|
|
|
|
export const deleteDeclaracion = (id: number) =>
|
|
apiClient.delete(`/documentos/declaraciones/${id}`).then(r => r.data);
|
|
|
|
export const downloadDeclaracionPdf = (id: number, variant: 'declaracion' | 'liga' | 'pago') =>
|
|
apiClient.get(`/documentos/declaraciones/${id}/pdf/${variant}`, { responseType: 'blob' }).then(r => r.data as Blob);
|
|
|
|
export function fileToBase64(file: File): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
const result = reader.result as string;
|
|
// result format: "data:application/pdf;base64,..."
|
|
const base64 = result.split(',')[1] || '';
|
|
resolve(base64);
|
|
};
|
|
reader.onerror = reject;
|
|
reader.readAsDataURL(file);
|
|
});
|
|
}
|
|
|
|
export function downloadBlob(blob: Blob, filename: string) {
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
a.remove();
|
|
URL.revokeObjectURL(url);
|
|
}
|