diff --git a/pos/blueprints/config_bp.py b/pos/blueprints/config_bp.py index 0aa8a85..90257c7 100644 --- a/pos/blueprints/config_bp.py +++ b/pos/blueprints/config_bp.py @@ -759,6 +759,7 @@ def get_business(): 'nombre': cfg.get('tenant_nombre', cfg.get('tenant_razon_social', '')), 'rfc': cfg.get('tenant_rfc', ''), 'regimen_fiscal': cfg.get('tenant_regimen_fiscal', ''), + 'cp': cfg.get('tenant_cp', ''), 'direccion': cfg.get('tenant_direccion', ''), 'telefono': cfg.get('tenant_telefono', ''), 'email': cfg.get('tenant_email', ''), @@ -775,14 +776,16 @@ def update_business(): 'nombre': 'tenant_nombre', 'rfc': 'tenant_rfc', 'regimen_fiscal': 'tenant_regimen_fiscal', + 'cp': 'tenant_cp', 'direccion': 'tenant_direccion', 'telefono': 'tenant_telefono', 'email': 'tenant_email', - # Tax params + # Tax params (also keep cfdi_* aliases in sync) 'tax_iva': 'tax_iva', 'tax_ieps': 'tax_ieps', 'invoice_serie': 'invoice_serie', 'invoice_folio': 'invoice_folio', + 'cfdi_serie': 'cfdi_serie', 'default_currency': 'default_currency', 'default_payment_method': 'default_payment_method', } diff --git a/pos/blueprints/invoicing_bp.py b/pos/blueprints/invoicing_bp.py index dd85908..1374c88 100644 --- a/pos/blueprints/invoicing_bp.py +++ b/pos/blueprints/invoicing_bp.py @@ -43,9 +43,9 @@ def _get_issuer_config(cur, branch_id=None): result = { "rfc": config.get("tenant_rfc", ""), "razon_social": config.get("tenant_razon_social", ""), - "regimen_fiscal": config.get("cfdi_regimen_fiscal", "601"), + "regimen_fiscal": config.get("cfdi_regimen_fiscal") or config.get("tenant_regimen_fiscal", "601"), "cp": config.get("tenant_cp", "00000"), - "serie": config.get("cfdi_serie", "A"), + "serie": config.get("cfdi_serie") or config.get("invoice_serie", "A"), "facturapi_key": config.get("cfdi_facturapi_key", ""), "facturapi_org_id": config.get("cfdi_facturapi_org_id", ""), } diff --git a/pos/static/js/invoicing.js b/pos/static/js/invoicing.js index 98e4d06..def585b 100644 --- a/pos/static/js/invoicing.js +++ b/pos/static/js/invoicing.js @@ -62,7 +62,10 @@ const Invoicing = (() => { if (name === 'notas') loadNotas(); if (name === 'complementos') loadComplementos(); if (name === 'cancelaciones') loadCancelaciones(); - if (name === 'config') loadFacturapiStatus(); + if (name === 'config') { + loadFacturapiStatus(); + loadEmisorData(); + } } // ---- Badge helpers ---- @@ -377,6 +380,70 @@ const Invoicing = (() => { } } + // ---- Emisor data (config tab) ---- + async function loadEmisorData() { + const rfcEl = document.getElementById('rfc-emisor'); + const cpEl = document.getElementById('cp-fiscal'); + const razonEl = document.getElementById('razon-social'); + const regimenEl = document.getElementById('regimen-fiscal'); + if (!rfcEl || !cpEl || !razonEl || !regimenEl) return; + + try { + const res = await fetch('/pos/api/config/business', { headers: headers() }); + if (!res.ok) throw new Error('Error al cargar datos fiscales'); + const data = await res.json(); + rfcEl.value = data.rfc || ''; + cpEl.value = data.cp || ''; + razonEl.value = data.razon_social || ''; + const regimen = data.regimen_fiscal || '601'; + regimenEl.value = regimen + ' — ' + (regimenEl.querySelector('option[value^="' + regimen + '"')?.textContent.split('—')[1]?.trim() || ''); + // If exact value not matched, leave first option selected by SAT code prefix + if (!regimenEl.value.startsWith(regimen)) { + Array.from(regimenEl.options).forEach(function(opt) { + if (opt.value.startsWith(regimen)) opt.selected = true; + }); + } + } catch (e) { + console.error('Invoicing.loadEmisorData:', e); + } + } + + async function saveEmisorData() { + const rfc = (document.getElementById('rfc-emisor')?.value || '').trim(); + const cp = (document.getElementById('cp-fiscal')?.value || '').trim(); + const razon_social = (document.getElementById('razon-social')?.value || '').trim(); + const regimenValue = document.getElementById('regimen-fiscal')?.value || '601'; + const regimen_fiscal = regimenValue.split('—')[0].trim(); + const statusEl = document.getElementById('emisor-save-status'); + + if (!rfc || !razon_social || !cp) { + if (statusEl) statusEl.textContent = 'RFC, Razón Social y C.P. son obligatorios'; + return; + } + + try { + const res = await fetch('/pos/api/config/business', { + method: 'PUT', + headers: headers(), + body: JSON.stringify({ rfc, razon_social, regimen_fiscal, cp, cfdi_regimen_fiscal: regimen_fiscal, cfdi_serie: 'A' }) + }); + if (!res.ok) { + const err = await res.json().catch(() => ({ error: res.statusText })); + throw new Error(err.error || 'Error al guardar'); + } + if (statusEl) { + statusEl.textContent = 'Datos fiscales guardados'; + statusEl.style.color = 'var(--color-success)'; + } + setTimeout(() => { if (statusEl) { statusEl.textContent = ''; statusEl.style.color = ''; } }, 4000); + } catch (e) { + if (statusEl) { + statusEl.textContent = e.message; + statusEl.style.color = 'var(--color-error)'; + } + } + } + async function setupFacturapi(btn) { if (!btn) return; btn.disabled = true; @@ -747,6 +814,7 @@ const Invoicing = (() => { return { switchTab, loadFacturas, loadNotas, loadComplementos, loadCancelaciones, loadFacturapiStatus, + loadEmisorData, saveEmisorData, showDetail, showCancelModal, confirmCancel, processQueue, showNewInvoiceModal, closeNewInvoiceModal, submitNewInvoice, notaCreditoPlaceholder, openGlobalInvoiceModal, previewGlobalInvoice, generateGlobalInvoice, setupFacturapi, diff --git a/pos/templates/invoicing.html b/pos/templates/invoicing.html index 0d8446e..04e0d93 100644 --- a/pos/templates/invoicing.html +++ b/pos/templates/invoicing.html @@ -759,9 +759,10 @@ -
- - +