{"id":47624,"date":"2025-10-21T09:04:27","date_gmt":"2025-10-21T16:04:27","guid":{"rendered":"https:\/\/www.caninca.com\/?page_id=47624"},"modified":"2025-10-29T12:43:53","modified_gmt":"2025-10-29T19:43:53","slug":"generador-de-facturas","status":"publish","type":"page","link":"https:\/\/www.caninca.com\/en\/apps\/generador-de-facturas\/","title":{"rendered":"Generador de Facturas"},"content":{"rendered":"\n\n<div class=\"wp-block-kadence-column kadence-column47624_dc1554-94\"><div class=\"kt-inside-inner-col\">\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Generador de Facturas<\/title>\n    <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jspdf\/2.5.1\/jspdf.umd.min.js\"><\/script>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            padding: 20px;\n            min-height: 100vh;\n        }\n\n        .container {\n            max-width: 1000px;\n            margin: 0 auto;\n            background: white;\n            border-radius: 12px;\n            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);\n            padding: 30px;\n        }\n\n        h1 {\n            color: #333;\n            text-align: center;\n            margin-bottom: 10px;\n            font-size: 2rem;\n        }\n\n        .subtitle {\n            text-align: center;\n            color: #666;\n            margin-bottom: 30px;\n            font-size: 0.9rem;\n        }\n\n        .section {\n            margin-bottom: 30px;\n            padding: 20px;\n            border: 1px solid #e0e0e0;\n            border-radius: 8px;\n            background: #fafafa;\n        }\n\n        .section-title {\n            font-size: 1.3rem;\n            color: #007bff;\n            margin-bottom: 15px;\n            font-weight: 600;\n        }\n\n        .form-grid {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n            gap: 15px;\n        }\n\n        .form-group {\n            display: flex;\n            flex-direction: column;\n        }\n\n        label {\n            font-weight: 600;\n            color: #555;\n            margin-bottom: 5px;\n            font-size: 0.9rem;\n        }\n\n        input[type=\"text\"],\n        input[type=\"email\"],\n        input[type=\"number\"],\n        textarea {\n            padding: 10px;\n            border: 1px solid #ddd;\n            border-radius: 6px;\n            font-size: 0.95rem;\n            transition: border-color 0.3s, box-shadow 0.3s;\n        }\n\n        input:focus,\n        textarea:focus {\n            outline: none;\n            border-color: #007bff;\n            box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);\n        }\n\n        textarea {\n            resize: vertical;\n            min-height: 60px;\n        }\n\n        .logo-upload {\n            margin-bottom: 15px;\n        }\n\n        .logo-preview {\n            max-width: 150px;\n            max-height: 100px;\n            margin-top: 10px;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n            display: none;\n        }\n\n        .file-input-wrapper {\n            position: relative;\n            display: inline-block;\n            width: 100%;\n        }\n\n        .file-input-wrapper input[type=\"file\"] {\n            position: absolute;\n            opacity: 0;\n            width: 100%;\n            height: 100%;\n            cursor: pointer;\n        }\n\n        .file-input-label {\n            display: inline-block;\n            padding: 10px 15px;\n            background: #007bff;\n            color: white;\n            border-radius: 6px;\n            cursor: pointer;\n            font-weight: 600;\n            transition: background 0.3s;\n        }\n\n        .file-input-label:hover {\n            background: #0056b3;\n        }\n\n        .file-name {\n            display: inline-block;\n            margin-left: 10px;\n            color: #666;\n            font-size: 0.9rem;\n        }\n\n        .products-section {\n            background: white;\n        }\n\n        .products-table {\n            width: 100%;\n            overflow-x: auto;\n        }\n\n        table {\n            width: 100%;\n            border-collapse: collapse;\n            margin-bottom: 15px;\n        }\n\n        th {\n            background: #007bff;\n            color: white;\n            padding: 12px;\n            text-align: left;\n            font-weight: 600;\n            font-size: 0.9rem;\n        }\n\n        td {\n            padding: 10px;\n            border-bottom: 1px solid #e0e0e0;\n        }\n\n        td input {\n            width: 100%;\n            padding: 8px;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n        }\n\n        .btn {\n            padding: 10px 20px;\n            border: none;\n            border-radius: 6px;\n            cursor: pointer;\n            font-size: 0.95rem;\n            font-weight: 600;\n            transition: all 0.3s;\n            display: inline-flex;\n            align-items: center;\n            gap: 8px;\n        }\n\n        .btn-primary {\n            background: #007bff;\n            color: white;\n        }\n\n        .btn-primary:hover {\n            background: #0056b3;\n            transform: translateY(-2px);\n            box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3);\n        }\n\n        .btn-success {\n            background: #28a745;\n            color: white;\n        }\n\n        .btn-success:hover {\n            background: #218838;\n            transform: translateY(-2px);\n            box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3);\n        }\n\n        .btn-danger {\n            background: #dc3545;\n            color: white;\n            padding: 6px 12px;\n            font-size: 0.85rem;\n        }\n\n        .btn-danger:hover {\n            background: #c82333;\n        }\n\n        .btn-secondary {\n            background: #6c757d;\n            color: white;\n        }\n\n        .btn-secondary:hover {\n            background: #5a6268;\n            transform: translateY(-2px);\n            box-shadow: 0 4px 12px rgba(108, 117, 125, 0.3);\n        }\n\n        .totals {\n            margin-top: 20px;\n            padding: 20px;\n            background: #f8f9fa;\n            border-radius: 8px;\n            border: 2px solid #007bff;\n        }\n\n        .total-row {\n            display: flex;\n            justify-content: space-between;\n            margin-bottom: 10px;\n            font-size: 1.1rem;\n        }\n\n        .total-row.final {\n            font-size: 1.4rem;\n            font-weight: bold;\n            color: #007bff;\n            padding-top: 10px;\n            border-top: 2px solid #007bff;\n        }\n\n        .actions {\n            display: flex;\n            gap: 15px;\n            justify-content: center;\n            margin-top: 30px;\n            flex-wrap: wrap;\n        }\n\n        .error {\n            color: #dc3545;\n            font-size: 0.85rem;\n            margin-top: 5px;\n            display: none;\n        }\n\n        @media (max-width: 768px) {\n            .container {\n                padding: 20px;\n            }\n\n            h1 {\n                font-size: 1.5rem;\n            }\n\n            .form-grid {\n                grid-template-columns: 1fr;\n            }\n\n            table {\n                font-size: 0.85rem;\n            }\n\n            th, td {\n                padding: 8px 4px;\n            }\n\n            .actions {\n                flex-direction: column;\n            }\n\n            .btn {\n                width: 100%;\n                justify-content: center;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"container\">\n        <h1>\ud83d\udcc4 Generador de Facturas<\/h1>\n        <p class=\"subtitle\">Sistema profesional de facturaci\u00f3n gratuito<\/p>\n\n        <!-- Datos de la Empresa -->\n        <div class=\"section\">\n            <h2 class=\"section-title\">Datos de la Empresa<\/h2>\n            <div class=\"logo-upload\">\n                <label>Logo de la Empresa (opcional)<\/label>\n                <div class=\"file-input-wrapper\">\n                    <input type=\"file\" id=\"logoInput\" accept=\"image\/*\">\n                    <label for=\"logoInput\" class=\"file-input-label\">\ud83d\udcc1 Buscar<\/label>\n                    <span class=\"file-name\" id=\"fileName\">Ning\u00fan archivo seleccionado<\/span>\n                <\/div>\n                <img id=\"logoPreview\" class=\"logo-preview\" alt=\"Vista previa del logo\">\n            <\/div>\n            <div class=\"form-grid\">\n                <div class=\"form-group\">\n                    <label>Nombre de la Empresa *<\/label>\n                    <input type=\"text\" id=\"empresaNombre\" placeholder=\"Ej: Mi Empresa S.A. de C.V.\">\n                    <span class=\"error\" id=\"errorEmpresaNombre\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>RFC *<\/label>\n                    <input type=\"text\" id=\"empresaRFC\" placeholder=\"Ej: ABC123456XXX\">\n                    <span class=\"error\" id=\"errorEmpresaRFC\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>Direcci\u00f3n *<\/label>\n                    <textarea id=\"empresaDireccion\" placeholder=\"Calle, N\u00famero, Colonia, Ciudad, Estado, CP\"><\/textarea>\n                    <span class=\"error\" id=\"errorEmpresaDireccion\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>Email *<\/label>\n                    <input type=\"email\" id=\"empresaEmail\" placeholder=\"contacto@empresa.com\">\n                    <span class=\"error\" id=\"errorEmpresaEmail\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>N\u00famero de Factura *<\/label>\n                    <input type=\"text\" id=\"facturaNumero\" placeholder=\"Ej: F-001\">\n                    <span class=\"error\" id=\"errorFacturaNumero\">Este campo es requerido<\/span>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Datos del Cliente -->\n        <div class=\"section\">\n            <h2 class=\"section-title\">Datos del Cliente<\/h2>\n            <div class=\"form-grid\">\n                <div class=\"form-group\">\n                    <label>Nombre del Cliente *<\/label>\n                    <input type=\"text\" id=\"clienteNombre\" placeholder=\"Nombre completo o raz\u00f3n social\">\n                    <span class=\"error\" id=\"errorClienteNombre\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>Direcci\u00f3n *<\/label>\n                    <textarea id=\"clienteDireccion\" placeholder=\"Direcci\u00f3n completa del cliente\"><\/textarea>\n                    <span class=\"error\" id=\"errorClienteDireccion\">Este campo es requerido<\/span>\n                <\/div>\n                <div class=\"form-group\">\n                    <label>Email *<\/label>\n                    <input type=\"email\" id=\"clienteEmail\" placeholder=\"cliente@email.com\">\n                    <span class=\"error\" id=\"errorClienteEmail\">Este campo es requerido<\/span>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Productos\/Servicios -->\n        <div class=\"section products-section\">\n            <h2 class=\"section-title\">Productos \/ Servicios<\/h2>\n            <div class=\"products-table\">\n                <table id=\"productosTable\">\n                    <thead>\n                        <tr>\n                            <th style=\"width: 40%;\">Descripci\u00f3n<\/th>\n                            <th style=\"width: 15%;\">Cantidad<\/th>\n                            <th style=\"width: 20%;\">Precio Unitario<\/th>\n                            <th style=\"width: 20%;\">Subtotal<\/th>\n                            <th style=\"width: 5%;\"><\/th>\n                        <\/tr>\n                    <\/thead>\n                    <tbody id=\"productosBody\">\n                        <tr>\n                            <td><input type=\"text\" class=\"producto-desc\" placeholder=\"Descripci\u00f3n del producto\/servicio\"><\/td>\n                            <td><input type=\"number\" class=\"producto-cant\" min=\"1\" value=\"1\" step=\"1\"><\/td>\n                            <td><input type=\"number\" class=\"producto-precio\" min=\"0\" step=\"0.01\" placeholder=\"0.00\"><\/td>\n                            <td><input type=\"text\" class=\"producto-subtotal\" readonly value=\"$0.00\"><\/td>\n                            <td><button class=\"btn btn-danger\" onclick=\"eliminarProducto(this)\">\u2715<\/button><\/td>\n                        <\/tr>\n                    <\/tbody>\n                <\/table>\n            <\/div>\n            <button class=\"btn btn-primary\" onclick=\"agregarProducto()\">\u2795 Agregar Producto<\/button>\n            \n            <div class=\"totals\">\n                <div class=\"total-row\">\n                    <span>Subtotal:<\/span>\n                    <span id=\"subtotalGeneral\">$0.00<\/span>\n                <\/div>\n                <div class=\"total-row\">\n                    <span>IVA (16%):<\/span>\n                    <span id=\"ivaTotal\">$0.00<\/span>\n                <\/div>\n                <div class=\"total-row final\">\n                    <span>TOTAL:<\/span>\n                    <span id=\"totalFinal\">$0.00<\/span>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Botones de Acci\u00f3n -->\n        <div class=\"actions\">\n            <button class=\"btn btn-secondary\" onclick=\"nuevoFormulario()\">\ud83d\udd04 Nuevo<\/button>\n            <button class=\"btn btn-success\" onclick=\"generarPDF()\">\ud83d\udce5 Generar PDF<\/button>\n        <\/div>\n    <\/div>\n\n    <script>\n        let logoDataURL = null;\n\n        \/\/ Manejo del logo\n        document.getElementById('logoInput').addEventListener('change', function(e) {\n            const file = e.target.files[0];\n            const fileNameSpan = document.getElementById('fileName');\n            \n            if (file) {\n                fileNameSpan.textContent = file.name;\n                const reader = new FileReader();\n                reader.onload = function(event) {\n                    logoDataURL = event.target.result;\n                    document.getElementById('logoPreview').src = logoDataURL;\n                    document.getElementById('logoPreview').style.display = 'block';\n                };\n                reader.readAsDataURL(file);\n            } else {\n                fileNameSpan.textContent = 'Ning\u00fan archivo seleccionado';\n                document.getElementById('logoPreview').style.display = 'none';\n            }\n        });\n\n        \/\/ Calcular subtotales\n        function calcularSubtotales() {\n            const filas = document.querySelectorAll('#productosBody tr');\n            let subtotalGeneral = 0;\n\n            filas.forEach(fila => {\n                const cantidad = parseFloat(fila.querySelector('.producto-cant').value) || 0;\n                const precio = parseFloat(fila.querySelector('.producto-precio').value) || 0;\n                const subtotal = cantidad * precio;\n                \n                fila.querySelector('.producto-subtotal').value = '$' + subtotal.toFixed(2);\n                subtotalGeneral += subtotal;\n            });\n\n            const iva = subtotalGeneral * 0.16;\n            const total = subtotalGeneral + iva;\n\n            document.getElementById('subtotalGeneral').textContent = '$' + subtotalGeneral.toFixed(2);\n            document.getElementById('ivaTotal').textContent = '$' + iva.toFixed(2);\n            document.getElementById('totalFinal').textContent = '$' + total.toFixed(2);\n        }\n\n        \/\/ Event listeners para c\u00e1lculos autom\u00e1ticos\n        document.addEventListener('input', function(e) {\n            if (e.target.classList.contains('producto-cant') || e.target.classList.contains('producto-precio')) {\n                calcularSubtotales();\n            }\n        });\n\n        function agregarProducto() {\n            const tbody = document.getElementById('productosBody');\n            const nuevaFila = document.createElement('tr');\n            nuevaFila.innerHTML = `\n                <td><input type=\"text\" class=\"producto-desc\" placeholder=\"Descripci\u00f3n del producto\/servicio\"><\/td>\n                <td><input type=\"number\" class=\"producto-cant\" min=\"1\" value=\"1\" step=\"1\"><\/td>\n                <td><input type=\"number\" class=\"producto-precio\" min=\"0\" step=\"0.01\" placeholder=\"0.00\"><\/td>\n                <td><input type=\"text\" class=\"producto-subtotal\" readonly value=\"$0.00\"><\/td>\n                <td><button class=\"btn btn-danger\" onclick=\"eliminarProducto(this)\">\u2715<\/button><\/td>\n            `;\n            tbody.appendChild(nuevaFila);\n        }\n\n        function eliminarProducto(btn) {\n            const tbody = document.getElementById('productosBody');\n            if (tbody.children.length > 1) {\n                btn.closest('tr').remove();\n                calcularSubtotales();\n            } else {\n                alert('Debe haber al menos un producto en la factura');\n            }\n        }\n\n        function validarFormulario() {\n            let valido = true;\n            const campos = [\n                'empresaNombre', 'empresaRFC', 'empresaDireccion', 'empresaEmail', 'facturaNumero',\n                'clienteNombre', 'clienteDireccion', 'clienteEmail'\n            ];\n\n            \/\/ Ocultar todos los errores primero\n            campos.forEach(campo => {\n                document.getElementById('error' + campo.charAt(0).toUpperCase() + campo.slice(1)).style.display = 'none';\n            });\n\n            \/\/ Validar campos\n            campos.forEach(campo => {\n                const input = document.getElementById(campo);\n                if (!input.value.trim()) {\n                    document.getElementById('error' + campo.charAt(0).toUpperCase() + campo.slice(1)).style.display = 'block';\n                    valido = false;\n                }\n            });\n\n            \/\/ Validar productos\n            const filas = document.querySelectorAll('#productosBody tr');\n            let productosValidos = true;\n            \n            filas.forEach(fila => {\n                const desc = fila.querySelector('.producto-desc').value.trim();\n                const cant = parseFloat(fila.querySelector('.producto-cant').value);\n                const precio = parseFloat(fila.querySelector('.producto-precio').value);\n\n                if (!desc || cant <= 0 || precio <= 0 || isNaN(cant) || isNaN(precio)) {\n                    productosValidos = false;\n                }\n            });\n\n            if (!productosValidos) {\n                alert('Por favor, complete todos los productos con valores v\u00e1lidos (descripci\u00f3n, cantidad > 0 y precio > 0)');\n                valido = false;\n            }\n\n            return valido;\n        }\n\n        function generarPDF() {\n            if (!validarFormulario()) {\n                return;\n            }\n\n            const { jsPDF } = window.jspdf;\n            const doc = new jsPDF();\n\n            let yPos = 20;\n\n            \/\/ Header\n            doc.setFillColor(0, 123, 255);\n            doc.rect(0, 0, 210, 15, 'F');\n            doc.setTextColor(255, 255, 255);\n            doc.setFontSize(10);\n            doc.text('Factura generada con Generador de Facturas (Gratis)', 105, 10, { align: 'center' });\n\n            yPos = 25;\n\n            \/\/ Logo si existe\n            if (logoDataURL) {\n                doc.addImage(logoDataURL, 'PNG', 15, yPos, 30, 20);\n            }\n\n            \/\/ Datos de la empresa\n            doc.setTextColor(0, 0, 0);\n            doc.setFontSize(16);\n            doc.setFont(undefined, 'bold');\n            doc.text(document.getElementById('empresaNombre').value, logoDataURL ? 50 : 15, yPos + 5);\n            \n            doc.setFontSize(10);\n            doc.setFont(undefined, 'normal');\n            doc.text('RFC: ' + document.getElementById('empresaRFC').value, logoDataURL ? 50 : 15, yPos + 12);\n            doc.text(document.getElementById('empresaDireccion').value, logoDataURL ? 50 : 15, yPos + 18, { maxWidth: 90 });\n            doc.text('Email: ' + document.getElementById('empresaEmail').value, logoDataURL ? 50 : 15, yPos + 24);\n\n            \/\/ N\u00famero de factura y fecha\n            doc.setFont(undefined, 'bold');\n            doc.text('FACTURA', 150, yPos + 5);\n            doc.setFont(undefined, 'normal');\n            doc.text('No: ' + document.getElementById('facturaNumero').value, 150, yPos + 12);\n            doc.text('Fecha: ' + new Date().toLocaleDateString('es-MX'), 150, yPos + 18);\n\n            yPos += 40;\n\n            \/\/ Datos del cliente\n            doc.setFillColor(240, 240, 240);\n            doc.rect(15, yPos, 180, 8, 'F');\n            doc.setFont(undefined, 'bold');\n            doc.text('DATOS DEL CLIENTE', 20, yPos + 5);\n            \n            yPos += 12;\n            doc.setFont(undefined, 'normal');\n            doc.text('Cliente: ' + document.getElementById('clienteNombre').value, 20, yPos);\n            yPos += 6;\n            doc.text('Direcci\u00f3n: ' + document.getElementById('clienteDireccion').value, 20, yPos, { maxWidth: 170 });\n            yPos += 6;\n            doc.text('Email: ' + document.getElementById('clienteEmail').value, 20, yPos);\n\n            yPos += 15;\n\n            \/\/ Tabla de productos\n            doc.setFillColor(0, 123, 255);\n            doc.rect(15, yPos, 180, 8, 'F');\n            doc.setTextColor(255, 255, 255);\n            doc.setFont(undefined, 'bold');\n            doc.text('Descripci\u00f3n', 20, yPos + 5);\n            doc.text('Cant.', 120, yPos + 5);\n            doc.text('Precio', 140, yPos + 5);\n            doc.text('Subtotal', 170, yPos + 5);\n\n            yPos += 12;\n            doc.setTextColor(0, 0, 0);\n            doc.setFont(undefined, 'normal');\n\n            const filas = document.querySelectorAll('#productosBody tr');\n            filas.forEach(fila => {\n                const desc = fila.querySelector('.producto-desc').value;\n                const cant = fila.querySelector('.producto-cant').value;\n                const precio = parseFloat(fila.querySelector('.producto-precio').value).toFixed(2);\n                const subtotal = fila.querySelector('.producto-subtotal').value;\n\n                doc.text(desc, 20, yPos, { maxWidth: 95 });\n                doc.text(cant, 120, yPos);\n                doc.text('$' + precio, 140, yPos);\n                doc.text(subtotal, 170, yPos);\n                yPos += 8;\n            });\n\n            yPos += 10;\n\n            \/\/ Totales\n            const subtotal = document.getElementById('subtotalGeneral').textContent;\n            const iva = document.getElementById('ivaTotal').textContent;\n            const total = document.getElementById('totalFinal').textContent;\n\n            doc.setDrawColor(200, 200, 200);\n            doc.line(130, yPos, 195, yPos);\n            yPos += 6;\n\n            doc.text('Subtotal:', 130, yPos);\n            doc.text(subtotal, 180, yPos, { align: 'right' });\n            yPos += 6;\n\n            doc.text('IVA (16%):', 130, yPos);\n            doc.text(iva, 180, yPos, { align: 'right' });\n            yPos += 6;\n\n            doc.setFont(undefined, 'bold');\n            doc.setFontSize(12);\n            doc.text('TOTAL:', 130, yPos);\n            doc.text(total, 180, yPos, { align: 'right' });\n\n            \/\/ Guardar PDF\n            const nombreArchivo = 'Factura_' + document.getElementById('facturaNumero').value + '.pdf';\n            doc.save(nombreArchivo);\n        }\n\n        function nuevoFormulario() {\n            if (confirm('\u00bfEst\u00e1 seguro de que desea limpiar el formulario?')) {\n                document.querySelectorAll('input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], textarea').forEach(input => {\n                    input.value = '';\n                });\n                \n                document.getElementById('logoInput').value = '';\n                document.getElementById('fileName').textContent = 'Ning\u00fan archivo seleccionado';\n                document.getElementById('logoPreview').style.display = 'none';\n                logoDataURL = null;\n\n                \/\/ Limpiar tabla de productos excepto la primera fila\n                const tbody = document.getElementById('productosBody');\n                while (tbody.children.length > 1) {\n                    tbody.removeChild(tbody.lastChild);\n                }\n\n                \/\/ Resetear primera fila\n                tbody.children[0].querySelector('.producto-desc').value = '';\n                tbody.children[0].querySelector('.producto-cant').value = '1';\n                tbody.children[0].querySelector('.producto-precio').value = '';\n\n                calcularSubtotales();\n\n                \/\/ Ocultar mensajes de error\n                document.querySelectorAll('.error').forEach(error => {\n                    error.style.display = 'none';\n                });\n            }\n        }\n\n        \/\/ Calcular totales iniciales\n        calcularSubtotales();\n    <\/script>\n<\/body>\n<\/html>\n<\/div><\/div>\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":47620,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","slim_seo":{"title":"Generador de Facturas Gratuito","description":""},"iawp_total_views":2,"footnotes":""},"class_list":["post-47624","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"trp-custom-language-flag":false,"hp_square_small":false,"hp_landscape_small":false,"hp_landscape_large":false,"custom-1200":false,"custom-600":false,"custom-300":false,"ht_portrait_small":false,"ht_landscape_large":false,"ht_cover_large":false,"woocommerce_thumbnail":false,"woocommerce_single":false,"woocommerce_gallery_thumbnail":false},"uagb_author_info":{"display_name":"fermagnet","author_link":"https:\/\/www.caninca.com\/en\/author\/fermagnet\/"},"uagb_comment_info":0,"uagb_excerpt":null,"_links":{"self":[{"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/pages\/47624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/comments?post=47624"}],"version-history":[{"count":0,"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/pages\/47624\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/pages\/47620"}],"wp:attachment":[{"href":"https:\/\/www.caninca.com\/en\/wp-json\/wp\/v2\/media?parent=47624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}