feat(pos/facturapi): add organization setup flow and detailed status
- get_org_status now returns has_key, has_org_id, pending_steps, error - add find_organization_by_rfc and create_organization helpers - add /facturapi/setup endpoint to link/create Facturapi org - frontend shows detailed PAC status and setup button - support using tenant sk_user_* key when FACTURAPI_USER_KEY env is absent
This commit is contained in:
@@ -267,28 +267,68 @@ const Invoicing = (() => {
|
||||
container.innerHTML = 'Cargando...';
|
||||
try {
|
||||
const status = await api('/facturapi/status');
|
||||
if (!status.configured) {
|
||||
container.innerHTML = `<p style="color:var(--color-error);">Facturapi no configurado. Configura la llave API en Configuración.</p>`;
|
||||
|
||||
if (!status.has_key) {
|
||||
container.innerHTML = `<p style="color:var(--color-error);">Falta la llave API de Facturapi. Configura <code>cfdi_facturapi_key</code> o la variable <code>FACTURAPI_USER_KEY</code>.</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!status.has_org_id) {
|
||||
container.innerHTML = `
|
||||
<p style="color:var(--color-warning);margin-bottom:var(--space-3);">No hay organización Facturapi vinculada.</p>
|
||||
<button class="btn btn--primary" onclick="Invoicing.setupFacturapi(this)">Crear / Vincular Organización</button>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
let csdHtml = status.has_csd
|
||||
? '<span style="color:var(--color-success);">Activo</span>'
|
||||
: '<span style="color:var(--color-error);">Pendiente</span>';
|
||||
|
||||
let pendingHtml = '';
|
||||
if (status.pending_steps && status.pending_steps.length) {
|
||||
pendingHtml = '<ul style="margin:var(--space-2) 0 0 0;padding-left:var(--space-5);color:var(--color-warning);">' +
|
||||
status.pending_steps.map(s => `<li>${s.description || s.type}</li>`).join('') +
|
||||
'</ul>';
|
||||
}
|
||||
|
||||
container.innerHTML = `
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4);">
|
||||
<div>
|
||||
<div style="font-size:var(--text-caption);color:var(--color-text-muted);">Organización</div>
|
||||
<div style="font-weight:var(--font-weight-semibold);">${status.legal_name || '-'}</div>
|
||||
<div style="font-weight:var(--font-weight-semibold);">${escapeHtml(status.legal_name) || '-'}</div>
|
||||
<div style="font-family:var(--font-mono);font-size:var(--text-body-sm);">${status.tax_id || ''}</div>
|
||||
<div style="font-family:var(--font-mono);font-size:var(--text-caption);color:var(--color-text-muted);">${status.org_id || ''}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size:var(--text-caption);color:var(--color-text-muted);">CSD</div>
|
||||
<div style="font-weight:var(--font-weight-semibold);">${status.has_csd ? '<span style="color:var(--color-success);">Activo</span>' : '<span style="color:var(--color-error);">Pendiente</span>'}</div>
|
||||
<div style="font-weight:var(--font-weight-semibold);">${csdHtml}</div>
|
||||
<div style="font-size:var(--text-caption);color:var(--color-text-muted);margin-top:var(--space-2);">Pasos pendientes</div>
|
||||
${pendingHtml || '<span style="color:var(--color-success);">Ninguno</span>'}
|
||||
</div>
|
||||
</div>
|
||||
${status.error ? `<p style="color:var(--color-error);margin-top:var(--space-3);">Error: ${escapeHtml(status.error)}</p>` : ''}
|
||||
`;
|
||||
} catch (e) {
|
||||
container.innerHTML = `<p style="color:var(--color-error);">Error: ${e.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function setupFacturapi(btn) {
|
||||
if (!btn) return;
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Configurando...';
|
||||
try {
|
||||
const res = await api('/facturapi/setup', { method: 'POST' });
|
||||
alert('Organización vinculada: ' + res.org_id);
|
||||
loadFacturapiStatus();
|
||||
} catch (e) {
|
||||
alert('Error: ' + e.message);
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Crear / Vincular Organización';
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Detail modal (uses modalDetalleOverlay) ----
|
||||
async function showDetail(cfdiId) {
|
||||
const overlay = document.getElementById('modalDetalleOverlay');
|
||||
@@ -571,7 +611,7 @@ const Invoicing = (() => {
|
||||
switchTab, loadFacturas, loadNotas, loadComplementos, loadCancelaciones, loadFacturapiStatus,
|
||||
showDetail, showCancelModal, confirmCancel, processQueue,
|
||||
showNewInvoiceModal, closeNewInvoiceModal, submitNewInvoice, notaCreditoPlaceholder,
|
||||
openGlobalInvoiceModal, previewGlobalInvoice, generateGlobalInvoice,
|
||||
openGlobalInvoiceModal, previewGlobalInvoice, generateGlobalInvoice, setupFacturapi,
|
||||
};
|
||||
// Register Cmd+K items
|
||||
if (typeof registerCmdKItem === "function") {
|
||||
|
||||
Reference in New Issue
Block a user