añadir boton descargar facatura como pdf

This commit is contained in:
Алекс 2026-04-16 12:11:09 +02:00
parent 28e5bbfbfe
commit 7f11d34e83
2 changed files with 61 additions and 1 deletions

View File

@ -1,4 +1,4 @@
import { getInvoiceById, updateInvoice, validateInvoice, addInvoiceLine, deleteInvoiceLine, addPayment, getPayments } from '../services/invoices.js';
import { getInvoiceById, updateInvoice, validateInvoice, addInvoiceLine, deleteInvoiceLine, addPayment, getPayments, downloadInvoicePdf } from '../services/invoices.js';
import { showConfirmExitModal, FormChangeTracker } from './ConfirmExitModal.js';
export function InvoiceModal(invoiceId, onClose, onUpdate) {
@ -79,6 +79,7 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
const isDraft = invoice.status === 'draft';
const canEdit = isDraft || invoice.status === 'validated' || invoice.status === 'unpaid';
const canDownloadPdf = invoice.status === 'validated' || invoice.status === 'paid';
modalContent.innerHTML = `
<div class="modal-header">
@ -317,6 +318,7 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
<div class="modal-footer">
<div class="footer-actions-left">
${canDownloadPdf ? '<button type="button" class="btn-download-invoice btn-primary"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Descargar factura</button>' : ''}
${isDraft ? '<button type="button" class="btn-validate btn-success"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle; margin-right: 4px;"><polyline points="20 6 9 17 4 12"/></svg>Validar Factura</button>' : ''}
</div>
<div class="footer-actions-right">
@ -356,6 +358,10 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
const validateBtn = modal.querySelector('.btn-validate');
validateBtn?.addEventListener('click', handleValidate);
// Botón descargar factura PDF
const downloadBtn = modal.querySelector('.btn-download-invoice');
downloadBtn?.addEventListener('click', handleDownloadPdf);
// Botón añadir línea
const addLineBtn = modal.querySelector('.btn-add-line');
addLineBtn?.addEventListener('click', toggleAddLineForm);
@ -510,6 +516,42 @@ export function InvoiceModal(invoiceId, onClose, onUpdate) {
}
};
// Manejar descarga del PDF
const handleDownloadPdf = async () => {
if (!invoice?.number) {
alert('No se puede descargar la factura porque no tiene número.');
return;
}
const downloadBtn = modal.querySelector('.btn-download-invoice');
const originalHtml = downloadBtn?.innerHTML;
try {
if (downloadBtn) {
downloadBtn.disabled = true;
downloadBtn.textContent = 'Descargando...';
}
const pdfBlob = await downloadInvoicePdf(invoice.number);
const blobUrl = URL.createObjectURL(pdfBlob);
const link = document.createElement('a');
link.href = blobUrl;
link.download = `Factura-${invoice.number}.pdf`;
document.body.appendChild(link);
link.click();
link.remove();
URL.revokeObjectURL(blobUrl);
} catch (error) {
console.error('Error al descargar factura:', error);
alert('Error al descargar la factura: ' + error.message);
} finally {
if (downloadBtn) {
downloadBtn.disabled = false;
downloadBtn.innerHTML = originalHtml;
}
}
};
// Mostrar/ocultar formulario de añadir línea
const toggleAddLineForm = () => {
const form = modal.querySelector('.add-line-form');

View File

@ -123,6 +123,24 @@ export async function getPayments(invoiceId) {
return await response.json();
}
export async function downloadInvoicePdf(invoiceNumber) {
const token = localStorage.getItem('token');
const response = await fetch(`${API_BASE_URL}/api/document/invoice/${encodeURIComponent(invoiceNumber)}/pdf`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/pdf'
}
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(error.detail || 'Error al descargar la factura');
}
return await response.blob();
}
export async function deleteInvoice(id) {
// Nota: No hay endpoint DELETE en el OpenAPI spec,
// pero podríamos usar el endpoint de cambio de estado a "canceled"