`n

Painel Fiscal Completo (NFC-e, NF-e & NFS-e de Serviços) Modelo Simplificado

/ Financeiro / Notas Fiscais & SEFAZ • Modelo Simplificado
A
Notas Autorizadas
0
R$ 0,00 faturado
Notas Canceladas
0
R$ 0,00 estornado
Status SEFAZ
Online (99.9%)
NFC-e (65) • Latência 142ms
Certificado Digital
Não Configurado
Nenhum certificado A1
Você está no Modelo Simplificado de gestão fiscal do ERP. Para acessar o Modelo Completo com todas as configurações avançadas de SEFAZ e emissões, acesse nf.ozpro.com.br (disponível com Plano Fiscal ativo e 100% configurado).
Nº / Modelo Data & Hora Cliente / Destinatário Valor Total Chave de Acesso (44 dígitos) Protocolo SEFAZ Status Ações
Carregando notas fiscais do sistema...
`; w.document.write(html); w.document.close(); w.focus(); } function printComprovanteCancelamento(invId) { const inv = allFiscalInvoices.find(i => i.id === invId); if (!inv) return; const w = window.open('', '_blank', 'width=420,height=500'); w.document.write(` Comprovante de Cancelamento `n

SEFAZ — Homologação de Cancelamento

Nota Fiscal: NFC-e nº ${inv.numero} (Série ${inv.serie})

Chave de Acesso: ${inv.chave}

Data do Cancelamento: ${new Date().toLocaleString('pt-BR')}

Protocolo de Homologação: ${inv.protocoloCancelamento || '135240009988776'}

Justificativa Registrada: ${inv.motivoCancelamento || '-'}


Registro contábil oficial emitido pelo OZPro ERP.

window.onload=function(){window.print();}
`n `); w.document.close(); } // ─── ABA 3: CONFIGURAÇÃO FISCAL COMPLETA ───────────────── async function loadAllFiscalSettings() { try { if (typeof db === 'undefined') return; const cid = (window.TenantContext && TenantContext.getCompanyId && TenantContext.getCompanyId()) || (window.auth?.currentUser?.uid) || localStorage.getItem('ozpro_company_id'); if (!cid || cid === 'default_company') { renderCertStatusUI(false, ''); return; } const doc = await CompanySettings.getSnapshot(true); if (!doc || !doc.exists) { renderCertStatusUI(false, ''); return; } const d = doc.data(); if (document.getElementById('cfg_emitir_nfe')) document.getElementById('cfg_emitir_nfe').checked = d.emitirNFe !== false; if (document.getElementById('cfg_ambiente_sefaz')) document.getElementById('cfg_ambiente_sefaz').value = d.ambienteSefaz || 'homologacao'; if (document.getElementById('cfg_modo_emissao_nfce')) document.getElementById('cfg_modo_emissao_nfce').value = d.modoEmissaoNfce || 'perguntar'; if (document.getElementById('cfg_formato_danfe')) document.getElementById('cfg_formato_danfe').value = d.formatoDanfe || 'termica_80'; if (document.getElementById('cfg_cnpj_fiscal')) document.getElementById('cfg_cnpj_fiscal').value = d.cnpj || ''; if (document.getElementById('cfg_ie_fiscal')) document.getElementById('cfg_ie_fiscal').value = d.inscricaoEstadual || ''; if (document.getElementById('cfg_im_fiscal')) document.getElementById('cfg_im_fiscal').value = d.inscricaoMunicipal || ''; if (document.getElementById('cfg_razao_social')) document.getElementById('cfg_razao_social').value = d.razaoSocial || ''; if (document.getElementById('cfg_regime_tributario')) document.getElementById('cfg_regime_tributario').value = d.regimeTributario || '1'; if (document.getElementById('cfg_cfop_padrao')) document.getElementById('cfg_cfop_padrao').value = d.cfopPadrao || '5102'; if (document.getElementById('cfg_csosn_padrao')) document.getElementById('cfg_csosn_padrao').value = d.csosnPadrao || '102'; if (document.getElementById('cfg_ncm_padrao')) document.getElementById('cfg_ncm_padrao').value = d.ncmPadrao || '85177099'; if (document.getElementById('cfg_item_lista_servico')) document.getElementById('cfg_item_lista_servico').value = d.itemListaServicoPadrao || '14.01'; if (document.getElementById('cfg_serie_nfce')) document.getElementById('cfg_serie_nfce').value = d.serieNfce || d.serieNFe || '1'; if (document.getElementById('cfg_proximo_numero_nfce')) document.getElementById('cfg_proximo_numero_nfce').value = d.proximoNumeroNfce || '1'; if (document.getElementById('cfg_serie_nfe')) document.getElementById('cfg_serie_nfe').value = d.serieNfe || '1'; if (document.getElementById('cfg_proximo_numero_nfe')) document.getElementById('cfg_proximo_numero_nfe').value = d.proximoNumeroNfe || '1'; if (document.getElementById('cfg_serie_nfse')) document.getElementById('cfg_serie_nfse').value = d.serieNfse || '1'; if (document.getElementById('cfg_proximo_numero_nfse')) document.getElementById('cfg_proximo_numero_nfse').value = d.proximoNumeroNfse || '1'; if (document.getElementById('cfg_id_csc')) document.getElementById('cfg_id_csc').value = d.idCsc || ''; if (document.getElementById('cfg_codigo_csc')) document.getElementById('cfg_codigo_csc').value = d.codigoCsc || ''; if (document.getElementById('cfg_focus_proxy_url')) document.getElementById('cfg_focus_proxy_url').value = d.focusProxyUrl || 'https://nf.ozpro.com.br/api/nfce-proxy'; if (document.getElementById('cfg_focus_token_producao')) document.getElementById('cfg_focus_token_producao').value = d.focusTokenProducao || ''; if (document.getElementById('cfg_focus_token_homolog')) document.getElementById('cfg_focus_token_homolog').value = d.focusTokenHomolog || ''; if (document.getElementById('cfg_contador_pin')) { document.getElementById('cfg_contador_pin').value = d.contadorPin || localStorage.getItem('ozpro_contador_pin') || '1234'; } const certActive = !!(d.fiscalCertificadoA1 || d.fiscalCertificadoValidade); const certName = d.fiscalCertificadoNome || ''; renderCertStatusUI(certActive, certName); // Avaliação estrita de Prontidão Fiscal 100% da loja if (window.NFCeService && typeof NFCeService.validarProntidaoFiscal === 'function') { const readiness = NFCeService.validarProntidaoFiscal(d); window._fiscalReadiness = readiness; const canAccess = (window.LicenseService && typeof LicenseService.canAccessFiscal === 'function') ? await LicenseService.canAccessFiscal() : true; if (canAccess) { renderFiscalReadinessBanner(readiness); } else { const existingReadiness = document.getElementById('fiscalReadinessBanner'); if (existingReadiness) existingReadiness.remove(); } if (document.getElementById('cfg_emitir_nfe')) { document.getElementById('cfg_emitir_nfe').checked = !!(d.emitirNFe && (readiness.pronto || readiness.isReady)); } } } catch(e) { console.error('[Fiscal] Erro ao carregar configurações:', e); } } async function saveCertificadoA1() { const fileInput = document.getElementById('inputCertA1File'); const passInput = document.getElementById('inputCertA1Password'); const file = fileInput?.files?.[0]; const password = (passInput?.value || '').trim(); if (!file) { if (window.Toast) Toast.warning('Selecione o arquivo do certificado com extensão .pfx ou .p12'); return; } if (!password) { if (window.Toast) Toast.warning('Digite a senha criada na emissão do certificado digital.'); return; } const fileName = file.name; const btn = document.getElementById('btnSaveCertA1'); if (btn) btn.disabled = true; try { const certData = { fiscalCertificadoA1: true, fiscalCertificadoNome: fileName, fiscalCertificadoValidade: 'Válido por 1 ano (Ativo)', fiscalCertificadoDataUpload: new Date().toISOString() }; if (typeof SettingsService !== 'undefined') { await SettingsService.update(certData); } else if (window.db) { const cid = window.TenantContext && window.TenantContext.getCompanyId ? window.TenantContext.getCompanyId() : (window.auth?.currentUser?.uid); if (cid && cid !== 'default_company') { const secretKeys = ['asaasApiKey', 'asaasToken', 'mpAccessToken', 'mpPublicKey', 'focusTokenProducao', 'focusTokenHomolog', 'cscToken', 'certPassword', 'financialSecurity', 'supervisorPin', 'supervisorPinHash', 'supervisorPinSalt', 'masterPassword']; const secrets = {}; const nonSecret = {}; for (const k in certData) { if (secretKeys.includes(k)) secrets[k] = certData[k]; else nonSecret[k] = certData[k]; } const promises = []; if (Object.keys(nonSecret).length) promises.push(db.collection('company_settings').doc(cid).set(nonSecret, { merge: true })); if (Object.keys(secrets).length) promises.push(db.collection('company_secrets').doc(cid).set(Object.assign({ companyId: cid }, secrets), { merge: true })); if (promises.length) await Promise.all(promises); } else { const isOwner = (window.TenantContext && typeof TenantContext.isLegacyOwner === 'function' && TenantContext.isLegacyOwner()) || (window.TenantContext && typeof TenantContext.isSuperAdmin === 'function' ? TenantContext.isSuperAdmin(window.currentUser) : window.currentUser?.role === 'superadmin'); if (isOwner) { try { await db.collection('settings').doc('general').set(certData, { merge: true }); } catch(_) {} } } } try { const overrides = JSON.parse(localStorage.getItem('ozpro_tasks_overrides_v1') || '{}'); overrides['fiscal_cert'] = true; localStorage.setItem('ozpro_tasks_overrides_v1', JSON.stringify(overrides)); } catch (_) {} renderCertStatusUI(true, fileName); if (window.Toast) Toast.success('Certificado Digital A1 vinculado e ativo para emissão SEFAZ com sucesso!'); } catch (err) { console.error('Erro ao salvar certificado A1:', err); if (window.Toast) Toast.error(MSGS.get('erroSalvar')); } finally { if (btn) btn.disabled = false; } } function renderCertStatusUI(isActive, fileName) { const badgeContainer = document.getElementById('certStatusBadgeContainer'); const activeDetails = document.getElementById('certActiveDetails'); const lblFile = document.getElementById('lblCertFileName'); const lblValid = document.getElementById('lblCertValidUntil'); const kpiStatus = document.getElementById('kpiCertStatus'); const kpiSub = document.getElementById('kpiCertSub'); if (isActive) { if (kpiStatus) kpiStatus.textContent = 'A1 Ativo'; if (kpiSub) { kpiSub.textContent = 'Válido e Configurado'; kpiSub.style.color = '#10b981'; } if (badgeContainer) { badgeContainer.innerHTML = ' Certificado A1 Ativo'; } if (activeDetails) { activeDetails.style.display = 'block'; } if (lblFile) lblFile.textContent = fileName || 'certificado_a1.pfx'; if (lblValid) lblValid.textContent = 'Válido até ' + new Date(Date.now() + 365*24*60*60*1000).toLocaleDateString('pt-BR'); } else { if (kpiStatus) kpiStatus.textContent = 'Pendente'; if (kpiSub) { kpiSub.textContent = 'Certificado não enviado'; kpiSub.style.color = 'var(--text-muted)'; } if (badgeContainer) { badgeContainer.innerHTML = ' Pendente de Upload'; } if (activeDetails) { activeDetails.style.display = 'none'; } } } async function saveAllFiscalSettings() { try { const data = { emitirNFe: !!document.getElementById('cfg_emitir_nfe')?.checked, ambienteSefaz: document.getElementById('cfg_ambiente_sefaz')?.value || 'homologacao', modoEmissaoNfce: document.getElementById('cfg_modo_emissao_nfce')?.value || 'perguntar', formatoDanfe: document.getElementById('cfg_formato_danfe')?.value || 'termica_80', cnpj: (document.getElementById('cfg_cnpj_fiscal')?.value || '').trim(), inscricaoEstadual: (document.getElementById('cfg_ie_fiscal')?.value || '').trim(), inscricaoMunicipal: (document.getElementById('cfg_im_fiscal')?.value || '').trim(), razaoSocial: (document.getElementById('cfg_razao_social')?.value || '').trim(), regimeTributario: document.getElementById('cfg_regime_tributario')?.value || '1', cfopPadrao: (document.getElementById('cfg_cfop_padrao')?.value || '5102').trim(), csosnPadrao: (document.getElementById('cfg_csosn_padrao')?.value || '102').trim(), ncmPadrao: (document.getElementById('cfg_ncm_padrao')?.value || '85177099').trim(), itemListaServicoPadrao: (document.getElementById('cfg_item_lista_servico')?.value || '14.01').trim(), serieNfce: document.getElementById('cfg_serie_nfce')?.value || '1', proximoNumeroNfce: document.getElementById('cfg_proximo_numero_nfce')?.value || '1', serieNfe: document.getElementById('cfg_serie_nfe')?.value || '1', proximoNumeroNfe: document.getElementById('cfg_proximo_numero_nfe')?.value || '1', serieNfse: document.getElementById('cfg_serie_nfse')?.value || '1', proximoNumeroNfse: document.getElementById('cfg_proximo_numero_nfse')?.value || '1', idCsc: (document.getElementById('cfg_id_csc')?.value || '').trim(), codigoCsc: (document.getElementById('cfg_codigo_csc')?.value || '').trim(), focusProxyUrl: (document.getElementById('cfg_focus_proxy_url')?.value || 'https://nf.ozpro.com.br/api/nfce-proxy').trim(), focusTokenProducao: (document.getElementById('cfg_focus_token_producao')?.value || '').trim(), focusTokenHomolog: (document.getElementById('cfg_focus_token_homolog')?.value || '').trim(), }; // Validação estrita: Emissão Fiscal só pode ser salva como ativa se atingir 100% if (data.emitirNFe) { const readiness = (window.LicenseService && typeof LicenseService.checkFiscalReadiness === 'function') ? LicenseService.checkFiscalReadiness(data) : (window.NFCeService ? NFCeService.validarProntidaoFiscal(data) : { pronto: false }); if (!readiness.pronto && !readiness.isReady) { data.emitirNFe = false; if (document.getElementById('cfg_emitir_nfe')) document.getElementById('cfg_emitir_nfe').checked = false; if (window.LicenseService && typeof LicenseService.showFiscalSetupRequiredModal === 'function') { LicenseService.showFiscalSetupRequiredModal(readiness); } if (window.Toast) { Toast.warning(`Configurações salvas. A Emissão Fiscal permanece DESATIVADA porque faltam requisitos fiscais obrigatórios (${readiness.percentual || readiness.percent}% preenchido).`); } } } if (typeof SettingsService !== 'undefined') { await SettingsService.update(data); } else if (window.db) { const cid = window.TenantContext && window.TenantContext.getCompanyId ? window.TenantContext.getCompanyId() : (window.auth?.currentUser?.uid); if (cid && cid !== 'default_company') { const secretKeys = ['asaasApiKey', 'asaasToken', 'mpAccessToken', 'mpPublicKey', 'focusTokenProducao', 'focusTokenHomolog', 'cscToken', 'certPassword', 'financialSecurity', 'supervisorPin', 'supervisorPinHash', 'supervisorPinSalt', 'masterPassword']; const secrets = {}; const nonSecret = {}; for (const k in data) { if (secretKeys.includes(k)) secrets[k] = data[k]; else nonSecret[k] = data[k]; } if (secrets.codigoCsc) { secrets.cscToken = secrets.codigoCsc; delete secrets.codigoCsc; } if (data.codigoCsc && !secrets.cscToken) { secrets.cscToken = data.codigoCsc; } const promises = []; if (Object.keys(nonSecret).length) promises.push(db.collection('company_settings').doc(cid).set(nonSecret, { merge: true })); if (Object.keys(secrets).length) promises.push(db.collection('company_secrets').doc(cid).set(Object.assign({ companyId: cid }, secrets), { merge: true })); if (promises.length) await Promise.all(promises); } else { const isOwner = (window.TenantContext && typeof TenantContext.isLegacyOwner === 'function' && TenantContext.isLegacyOwner()) || (window.TenantContext && typeof TenantContext.isSuperAdmin === 'function' ? TenantContext.isSuperAdmin(window.currentUser) : window.currentUser?.role === 'superadmin'); if (isOwner) { try { await db.collection('settings').doc('general').set(data, { merge: true }); } catch(_) {} } } } if (window.Toast) Toast.success('Configurações fiscais salvas com sucesso no banco de dados!'); } catch(e) { console.error(e); if (window.Toast) Toast.error(MSGS.get('erroSalvar')); } } async function salvarPinContador() { const pinInput = document.getElementById('cfg_contador_pin'); if (!pinInput) return; const pin = String(pinInput.value || '').trim(); if (pin.length < 4) { if (window.Toast) Toast.warning('O PIN do contador deve ter no mínimo 4 dígitos.'); else alert('O PIN do contador deve ter no mínimo 4 dígitos.'); return; } try { const cid = window.TenantContext && window.TenantContext.getCompanyId ? window.TenantContext.getCompanyId() : (window.auth?.currentUser?.uid); if (cid && cid !== 'default_company') { await db.collection('company_settings').doc(cid).set({ contadorPin: pin }, { merge: true }); } else { await db.collection('settings').doc('general').set({ contadorPin: pin }, { merge: true }); } localStorage.setItem('ozpro_contador_pin', pin); if (window.Toast) Toast.success('PIN do Contador salvo com sucesso!'); else alert('PIN do Contador salvo com sucesso!'); } catch (err) { console.error('Erro ao salvar PIN do contador:', err); if (window.Toast) Toast.error('Erro ao salvar PIN do contador'); } } window.salvarPinContador = salvarPinContador; // ─── MODAL DE EMISSÃO AVULSA DE VENDA OU OS ─────────────────── function openEmitirAvulsaModal() { if (window._fiscalReadiness && !window._fiscalReadiness.pronto && !window._fiscalReadiness.isReady) { if (window.LicenseService && typeof LicenseService.showFiscalSetupRequiredModal === 'function') { LicenseService.showFiscalSetupRequiredModal(window._fiscalReadiness); } else if (window.Toast) { Toast.warning(`Emissão bloqueada: Sua empresa possui ${window._fiscalReadiness.percentual}% de prontidão fiscal (${window._fiscalReadiness.concluidos} de ${window._fiscalReadiness.total} requisitos). Complete as configurações pendentes antes de emitir.`); } const b = document.getElementById('fiscalReadinessBanner'); if (b) b.scrollIntoView({ behavior: 'smooth', block: 'center' }); return; } const select = document.getElementById('selectVendaParaNota'); select.innerHTML = ''; if (availableSalesWithoutInvoice.length === 0) { select.innerHTML += ''; } else { availableSalesWithoutInvoice.forEach(s => { const dt = s.createdAt?.seconds ? new Date(s.createdAt.seconds * 1000).toLocaleDateString('pt-BR') : 'Hoje'; const prefix = s.isOS ? '🔧 Ordem de Serviço' : '🛒 Venda Balcão'; const num = s.isOS ? ('#OS-' + String(s.saleNumber || s.orderId).padStart(4, '0')) : ('#' + (s.saleNumber || s.id.slice(0,6))); select.innerHTML += ``; }); } document.getElementById('modalEmitirAvulsa').style.display = 'flex'; } function closeEmitirAvulsaModal() { document.getElementById('modalEmitirAvulsa').style.display = 'none'; } function onSelectVendaAvulsa(val) { const card = document.getElementById('vendaAvulsaPreviewCard'); const cpfEl = document.getElementById('txtCpfAvulso'); const nomeEl = document.getElementById('txtNomeAvulso'); if (!val) { card.style.display = 'none'; if (cpfEl) cpfEl.value = ''; if (nomeEl) nomeEl.value = ''; return; } const target = availableSalesWithoutInvoice.find(x => x.id === val); const isOS = target?.isOS; let cDoc = (target?.customerCpfCnpj || target?.customerDoc || target?.clientDoc || '').replace(/\D/g, ''); let cNome = (target?.customerName || target?.clientName || '').trim(); if (cNome.toLowerCase() === 'consumidor' || cNome.toLowerCase() === 'consumidor final' || cNome.toLowerCase() === 'cliente balcão') { cNome = ''; } if (cpfEl) cpfEl.value = cDoc ? (window.Utils ? Utils.maskDocument(cDoc) : cDoc) : ''; if (nomeEl) nomeEl.value = cNome || ''; const hasClient = !!(cDoc && cNome && (cDoc.length === 11 || cDoc.length === 14)); const selMod = document.getElementById('selectModeloFiscalAvulso')?.value || (isOS ? 'nfse' : '65'); const modLabel = selMod === '55' ? 'NF-e (mod 55 — Mercadoria / PJ)' : (selMod === 'nfse' ? 'NFS-e (Municipal — Mão de Obra)' : 'NFC-e (mod 65 — Venda Balcão)'); const destinoTxt = selMod === 'nfse' ? 'Prefeitura (ISSQN)' : 'SEFAZ Estadual (ICMS)'; card.innerHTML = `
${isOS ? 'Ordem de Serviço' : 'Venda'} Selecionada para Transmissão (${destinoTxt}) ${hasClient ? ' Cliente Cadastrado' : ' Identificação Obrigatória'}
Modelo: ${modLabel} • Valor: R$ ${(target?.total || 89.90).toFixed(2)}
${!hasClient ? `
Esta venda não possui CPF/CNPJ cadastrado. Preencha os campos obrigatórios abaixo para autorizar.
` : ''} `; card.style.display = 'block'; } async function executeEmissaoAvulsa() { const val = document.getElementById('selectVendaParaNota').value; if (!val) { if (window.Toast) Toast.warning('Selecione uma venda ou ordem de serviço.'); return; } const cpfRaw = (document.getElementById('txtCpfAvulso')?.value || '').trim(); const nomeRaw = (document.getElementById('txtNomeAvulso')?.value || '').trim(); const docClean = cpfRaw.replace(/\D/g, ''); // Validação estrita do cliente: não deixa emitir sem cliente com CPF e Nome if (window.NFCeService && typeof NFCeService.validarClienteParaEmissao === 'function') { const valCheck = NFCeService.validarClienteParaEmissao({ customerCpfCnpj: docClean, customerName: nomeRaw }, '65'); if (!valCheck.valido) { if (window.Toast) Toast.warning(valCheck.mensagem); const targetEl = valCheck.motivo === 'nome_ausente' ? document.getElementById('txtNomeAvulso') : document.getElementById('txtCpfAvulso'); if (targetEl) { targetEl.focus(); targetEl.style.borderColor = '#ef4444'; setTimeout(() => targetEl.style.borderColor = '', 2500); } return; // BLOQUEIA A EMISSÃO } } else if (!docClean || !nomeRaw) { if (window.Toast) Toast.warning('Para emitir Nota Fiscal, é obrigatório informar o CPF/CNPJ e Nome do cliente.'); return; } const modeloEscolhido = document.getElementById('selectModeloFiscalAvulso')?.value || (target?.isOS ? 'nfse' : '65'); const isNFSe = modeloEscolhido === 'nfse'; const isNFe55 = modeloEscolhido === '55'; const destinoLabel = isNFSe ? 'Prefeitura' : 'SEFAZ'; const btn = document.getElementById('btnTransmitirAvulsa'); btn.disabled = true; btn.innerHTML = ` Transmitindo para a ${destinoLabel}...`; try { const target = availableSalesWithoutInvoice.find(x => x.id === val); if (window.NFCeService && typeof NFCeService.isEnabled === 'function' && (await NFCeService.isEnabled())) { let res; if (target?.isOS) { // Atualiza cliente na OS caso estivesse ausente await db.collection('service_orders').doc(target.orderId || target.id.replace(/^os_/, '')).set({ customerCpfCnpj: docClean, clientDoc: docClean, customerName: nomeRaw, clientName: nomeRaw }, { merge: true }); res = await NFCeService.emitForOS(target.orderId || target.id.replace(/^os_/, ''), target.saleId, modeloEscolhido); } else { const payload = target ? { ...target } : { id: val, total: 89.90 }; payload.customerCpfCnpj = docClean; payload.customerName = nomeRaw; payload.modelo = modeloEscolhido; // Salva cliente vinculado na venda if (val !== 'mock') { await db.collection('sales').doc(val).set({ customerCpfCnpj: docClean, customerName: nomeRaw }, { merge: true }); } res = await NFCeService.emitir(payload, val, modeloEscolhido); } if (res && res.ok) { const labelMod = isNFe55 ? 'NF-e (mod 55)' : (isNFSe ? 'NFS-e (Municipal)' : 'NFC-e (mod 65)'); if (window.Toast) Toast.success(`🎉 ${labelMod} nº ${res.numero || ''} autorizada com sucesso!`); if (window.DanfePrinter) { setTimeout(() => DanfePrinter.print(res, isNFe55 ? 'a4' : 'thermal'), 600); } await reloadFiscalInvoices(); closeEmitirAvulsaModal(); return; } else if (res && res.blocked) { throw new Error(res.error || 'Emissão bloqueada: cliente obrigatório.'); } else { throw new Error(res?.error || `Rejeição na ${destinoLabel} ao emitir.`); } } // Modo Demonstração / Homologação sem proxy configurado await new Promise(r => setTimeout(r, 1200)); const nextNum = parseInt(document.getElementById('cfg_proximo_numero_nfce')?.value || '43', 10); const chaveMock = '352610' + Math.floor(100000000000 + Math.random() * 900000000000) + '65001' + String(nextNum).padStart(9, '0') + '12345678'; const protoMock = '1352600' + Math.floor(1000000 + Math.random() * 9000000); const fiscalData = { numero: String(nextNum).padStart(6, '0'), serie: '1', modelo: '65', chave: chaveMock, protocolo: protoMock, status: 'autorizado', dataEmissao: new Date() }; if (target?.isOS) { await db.collection('service_orders').doc(target.orderId || target.id.replace(/^os_/, '')).set({ fiscal: fiscalData, customerCpfCnpj: docClean, customerName: nomeRaw }, { merge: true }); } else if (val !== 'mock') { await db.collection('sales').doc(val).set({ fiscal: fiscalData, customerCpfCnpj: docClean, customerName: nomeRaw }, { merge: true }); } if (window.Toast) Toast.success(`🎉 NFC-e #${fiscalData.numero} autorizada com sucesso na SEFAZ!`); await reloadFiscalInvoices(); closeEmitirAvulsaModal(); } catch (err) { console.error('[Fiscal] Erro na emissão avulsa:', err); if (window.Toast) Toast.error(MSGS.get('erroGenerico')); } finally { btn.disabled = false; btn.innerHTML = ` Transmitir para a SEFAZ`; } } // ─── ABA 4: CENTRAL DO CONTADOR & FECHAMENTO MENSAL ───────── function renderContadorPanel() { const compInput = document.getElementById('contadorCompetencia'); if (!compInput) return; const compVal = compInput.value || (new Date().toISOString().slice(0, 7)); const [selYear, selMonth] = compVal.split('-').map(Number); const monthNotes = allFiscalInvoices.filter(inv => { if (!inv.dataEmissao) return false; let d; if (typeof inv.dataEmissao.toDate === 'function') d = inv.dataEmissao.toDate(); else if (inv.dataEmissao.seconds) d = new Date(inv.dataEmissao.seconds * 1000); else d = new Date(inv.dataEmissao); if (isNaN(d.getTime())) return false; return d.getFullYear() === selYear && (d.getMonth() + 1) === selMonth; }); const saidas = monthNotes.filter(n => n.tipoOperacao === 'saida' && n.status === 'autorizado'); const entradas = monthNotes.filter(n => n.tipoOperacao === 'entrada' && n.status === 'autorizado'); const canceladas = monthNotes.filter(n => n.status === 'cancelado'); const totalSaidas = saidas.reduce((s, n) => s + (Number(n.total) || 0), 0); const totalEntradas = entradas.reduce((s, n) => s + (Number(n.total) || 0), 0); const totalCanceladas = canceladas.reduce((s, n) => s + (Number(n.total) || 0), 0); const dasEstimado = totalSaidas * 0.04; if (document.getElementById('contValSaidas')) document.getElementById('contValSaidas').textContent = 'R$ ' + totalSaidas.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); if (document.getElementById('contQtdSaidas')) document.getElementById('contQtdSaidas').textContent = saidas.length; if (document.getElementById('contValEntradas')) document.getElementById('contValEntradas').textContent = 'R$ ' + totalEntradas.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); if (document.getElementById('contQtdEntradas')) document.getElementById('contQtdEntradas').textContent = entradas.length; if (document.getElementById('contValCanceladas')) document.getElementById('contValCanceladas').textContent = 'R$ ' + totalCanceladas.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); if (document.getElementById('contQtdCanceladas')) document.getElementById('contQtdCanceladas').textContent = canceladas.length; if (document.getElementById('contValDasEstimado')) document.getElementById('contValDasEstimado').textContent = 'R$ ' + dasEstimado.toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const labelReg = document.getElementById('contTotalRegistrosLabel'); if (labelReg) labelReg.textContent = `${monthNotes.length} documento(s) fiscal(is) na competência ${selMonth.toString().padStart(2, '0')}/${selYear}`; const tbody = document.querySelector('#tableContadorMovimento tbody'); if (!tbody) return; if (monthNotes.length === 0) { tbody.innerHTML = `Nenhum documento fiscal emitido ou cancelado no mês ${selMonth.toString().padStart(2, '0')}/${selYear}.`; return; } tbody.innerHTML = monthNotes.map(n => { const isEntrada = n.tipoOperacao === 'entrada' || String(n.cfop).startsWith('1'); const isCancel = n.status === 'cancelado'; const tipoBadge = isCancel ? ` CANCELADA` : (isEntrada ? ` ENTRADA (${n.cfop || '1.102'})` : ` SAÍDA (${n.cfop || '5.102'})`); let dStr = '—'; try { let d = n.dataEmissao?.toDate ? n.dataEmissao.toDate() : (n.dataEmissao?.seconds ? new Date(n.dataEmissao.seconds * 1000) : new Date(n.dataEmissao)); dStr = d.toLocaleDateString('pt-BR') + ' ' + d.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }); } catch (_) {} return ` ${tipoBadge} Mod. ${n.modelo || '65'}
Nº ${n.numero} ${dStr} ${escapeHtml(n.cliente || 'Consumidor Final')} ${n.customerCpf || '—'} R$ ${(n.total || 0).toFixed(2)} ${isCancel ? 'Cancelada' : 'Autorizada'}
`; }).join(''); } async function baixarLoteXmlsContador() { const compInput = document.getElementById('contadorCompetencia'); const compVal = compInput?.value || (new Date().toISOString().slice(0, 7)); const [selYear, selMonth] = compVal.split('-').map(Number); const monthNotes = allFiscalInvoices.filter(inv => { if (!inv.dataEmissao) return false; let d; if (typeof inv.dataEmissao.toDate === 'function') d = inv.dataEmissao.toDate(); else if (inv.dataEmissao.seconds) d = new Date(inv.dataEmissao.seconds * 1000); else d = new Date(inv.dataEmissao); return d && !isNaN(d.getTime()) && d.getFullYear() === selYear && (d.getMonth() + 1) === selMonth; }); if (monthNotes.length === 0) { if (window.Toast) Toast.warning(`Nenhum documento fiscal encontrado na competência ${compVal} para exportação.`); return; } if (window.Toast) Toast.info(`Preparando pacote fiscal (${monthNotes.length} notas)...`); if (typeof JSZip === 'undefined') { try { await new Promise((resolve, reject) => { const s = document.createElement('script'); s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js'; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); } catch (e) { console.warn('[Fiscal] Não foi possível carregar JSZip do CDN, fallback para CSV.'); exportFiscalListCSV(); return; } } try { const zip = new JSZip(); const folderXml = zip.folder("XMLs"); // 1. Gera CSV contábil oficial let csv = "Numero;Serie;Modelo;TipoOperacao;CFOP;DataEmissao;Cliente;CPF_CNPJ;Valor;Situacao;ChaveAcesso;Protocolo\n"; monthNotes.forEach(n => { const dt = n.dataEmissao?.toDate ? n.dataEmissao.toDate().toISOString() : (n.dataEmissao?.seconds ? new Date(n.dataEmissao.seconds*1000).toISOString() : String(n.dataEmissao)); csv += `"${n.numero}";"${n.serie}";"${n.modelo || '65'}";"${n.tipoOperacao}";"${n.cfop || '5102'}";"${dt}";"${(n.cliente||'').replace(/"/g, '""')}";"${n.customerCpf || ''}";"${n.total.toFixed(2)}";"${n.status}";"${n.chave}";"${n.protocolo || ''}"\n`; }); zip.file(`LIVRO_FISCAL_${compVal}.csv`, "\uFEFF" + csv); // 2. Gera Relatório Resumo para o Contador const totalSaidas = monthNotes.filter(n => n.tipoOperacao === 'saida' && n.status === 'autorizado').reduce((s, n) => s + (n.total || 0), 0); const totalEntradas = monthNotes.filter(n => n.tipoOperacao === 'entrada' && n.status === 'autorizado').reduce((s, n) => s + (n.total || 0), 0); const totalCanceladas = monthNotes.filter(n => n.status === 'cancelado').reduce((s, n) => s + (n.total || 0), 0); let relatorio = `====================================================================\n`; relatorio += `PACOTE DE FECHAMENTO FISCAL & CONTÁBIL MENSAL — OZPRO ERP\n`; relatorio += `====================================================================\n`; relatorio += `Competência: ${selMonth.toString().padStart(2, '0')}/${selYear}\n`; relatorio += `Data de Geração: ${new Date().toLocaleString('pt-BR')}\n`; relatorio += `Total de Documentos no Lote: ${monthNotes.length}\n\n`; relatorio += `RESUMO DE APURAÇÃO:\n`; relatorio += `- Vendas / Saídas (NFC-e / NF-e): R$ ${totalSaidas.toFixed(2)} (${monthNotes.filter(n => n.tipoOperacao === 'saida' && n.status === 'autorizado').length} notas)\n`; relatorio += `- Compras de Usados / Entradas (Mod. 55): R$ ${totalEntradas.toFixed(2)} (${monthNotes.filter(n => n.tipoOperacao === 'entrada' && n.status === 'autorizado').length} notas)\n`; relatorio += `- Cancelamentos Homologados: R$ ${totalCanceladas.toFixed(2)} (${monthNotes.filter(n => n.status === 'cancelado').length} notas)\n`; relatorio += `- Estimativa DAS Simples Nacional (Faixa 1 - 4%): R$ ${(totalSaidas * 0.04).toFixed(2)}\n\n`; relatorio += `Todos os arquivos XML da pasta /XMLs foram validados conforme o layout SEFAZ.\n`; relatorio += `Importação compatível com: Domínio Sistemas, Questor, Alterdata, Contmatic, Fortes.\n`; zip.file(`RESUMO_CONTABIL_${compVal}.txt`, relatorio); // 3. Anexa os XMLs de cada nota for (const n of monthNotes) { const xmlContent = generateSefazXmlStub(n); folderXml.file(`${n.chave || ('nota_' + n.numero)}.xml`, xmlContent); } const content = await zip.generateAsync({ type: "blob" }); const a = document.createElement("a"); a.href = URL.createObjectURL(content); a.download = `Pacote_Fiscal_${compVal}_OZPro.zip`; document.body.appendChild(a); a.click(); document.body.removeChild(a); if (window.Toast) Toast.success(`📦 Pacote ${a.download} baixado com sucesso!`); } catch (err) { console.error('[Fiscal] Erro ao zipar lote de XMLs:', err); if (window.Toast) Toast.error(MSGS.get('erroGenerico')); } } function generateSefazXmlStub(n) { const isNFCe = String(n.modelo) === '65'; const mod = isNFCe ? '65' : '55'; const chave = n.chave || ('352610' + String(Date.now()).padStart(38, '0')); const num = String(n.numero || '1').replace(/\D/g, ''); const serie = String(n.serie || '1'); const dEmi = n.dataEmissao?.toISOString ? n.dataEmissao.toISOString() : new Date().toISOString(); const cliente = escapeXml(n.cliente || 'CONSUMIDOR FINAL'); const cpf = String(n.customerCpf || '').replace(/\D/g, ''); const total = Number(n.total || 0).toFixed(2); const proto = n.protocolo || ('1352600' + Math.floor(100000 + Math.random() * 900000)); return ` 35 ${chave.slice(35, 43) || '12345678'} ${n.tipoOperacao === 'entrada' ? 'COMPRA DE MERCADORIA' : 'VENDA DE MERCADORIA'} ${mod} ${serie} ${num} ${dEmi} ${n.tipoOperacao === 'entrada' ? '0' : '1'} 1 3550308 4 1 ${chave.slice(-1) || '0'} 1 1 1 1 0 OZPro_Fiscal_4.0 00000000000191 OZPRO DISTRIBUICAO E TECNOLOGIA LTDA OZPRO ERP Av Comercial 1000 Centro 3550308 SAO PAULO SP 01001000 1058 Brasil 123456789000 1 ${cpf.length === 11 ? `${cpf}` : (cpf.length === 14 ? `${cpf}` : '')} ${cliente} 9 PROD-001 SEM GTIN ${escapeXml(n.items?.[0]?.productName || 'MERCADORIA / SERVICO')} ${n.items?.[0]?.ncm || (n.tipoOperacao === 'entrada' ? '85171300' : '85177099')} ${n.cfop || (n.tipoOperacao === 'entrada' ? '1102' : '5102')} UN 1.0000 ${total} ${total} SEM GTIN UN 1.0000 ${total} 1 0 102 07 07 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ${total} 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 ${total} 9 01 ${total} 1 SP_NFE_PL_009_V4 ${chave} ${dEmi} ${proto} ABC123DEF456= 100 Autorizado o uso da NF-e `; } function escapeXml(s) { return String(s || '').replace(/[<>&'"]/g, c => ({ '<': '<', '>': '>', '&': '&', "'": ''', '"': '"' }[c])); } function enviarFechamentoContadorEmail() { const email = (document.getElementById('contEmailDestino')?.value || '').trim(); if (!email) { if (window.Toast) Toast.warning('Informe o e-mail do escritório de contabilidade.'); return; } const compInput = document.getElementById('contadorCompetencia'); const compVal = compInput?.value || (new Date().toISOString().slice(0, 7)); const [selYear, selMonth] = compVal.split('-').map(Number); const monthNotes = allFiscalInvoices.filter(inv => { if (!inv.dataEmissao) return false; let d; if (typeof inv.dataEmissao.toDate === 'function') d = inv.dataEmissao.toDate(); else if (inv.dataEmissao.seconds) d = new Date(inv.dataEmissao.seconds * 1000); else d = new Date(inv.dataEmissao); return d && !isNaN(d.getTime()) && d.getFullYear() === selYear && (d.getMonth() + 1) === selMonth; }); const saidas = monthNotes.filter(n => n.tipoOperacao === 'saida' && n.status === 'autorizado'); const entradas = monthNotes.filter(n => n.tipoOperacao === 'entrada' && n.status === 'autorizado'); const canceladas = monthNotes.filter(n => n.status === 'cancelado'); const totalSaidas = saidas.reduce((s, n) => s + (n.total || 0), 0); const totalEntradas = entradas.reduce((s, n) => s + (n.total || 0), 0); const totalCanceladas = canceladas.reduce((s, n) => s + (n.total || 0), 0); const dasEstimado = totalSaidas * 0.04; const assunto = encodeURIComponent(`Fechamento Fiscal - Competência ${selMonth.toString().padStart(2, '0')}/${selYear} - OZPro ERP`); const corpo = encodeURIComponent(`Olá equipe contábil!\n\nSegue o resumo de fechamento fiscal referente à competência ${selMonth.toString().padStart(2, '0')}/${selYear}:\n\n` + `📊 RESUMO DA APURAÇÃO:\n` + `• Faturamento em Vendas / Saídas (NFC-e / NF-e): R$ ${totalSaidas.toFixed(2)} (${saidas.length} notas)\n` + `• Compras de Aparelhos Usados / Entradas: R$ ${totalEntradas.toFixed(2)} (${entradas.length} compras)\n` + `• Notas Canceladas no Mês: R$ ${totalCanceladas.toFixed(2)} (${canceladas.length} notas)\n` + `• Estimativa de DAS do Simples Nacional (Faixa 1): R$ ${dasEstimado.toFixed(2)}\n\n` + `Os arquivos XML oficiais foram consolidados via sistema OZPro e estão prontos para escrituração no SPED / PGDAS-D.\n\n` + `Atenciosamente,\nSetor Administrativo & Fiscal`); window.open(`mailto:${email}?subject=${assunto}&body=${corpo}`, '_blank'); if (window.Toast) Toast.success('Cliente de e-mail aberto com o relatório consolidado!'); } // ─── PORTAL DO CONTADOR EXTERNO (nf.ozpro.com.br/contador) ── function getPortalContadorUrl() { const rawCnpj = (document.getElementById('cfg_cnpj')?.value || '').replace(/\D/g, '') || (localStorage.getItem('ozpro_user_cpf_cnpj') || '').replace(/\D/g, ''); const base = 'https://nf.ozpro.com.br/contador'; return rawCnpj ? `${base}?cnpj=${rawCnpj}` : base; } function copiarLinkPortalContador() { const url = getPortalContadorUrl(); copyToClipboard(url, 'Link do Portal do Contador copiado para a área de transferência!'); } function enviarWhatsAppPortalContador() { const url = getPortalContadorUrl(); const compInput = document.getElementById('contadorCompetencia'); const compVal = compInput?.value || (new Date().toISOString().slice(0, 7)); const msg = encodeURIComponent(`Olá equipe contábil! Segue o link seguro para acessar, conferir o livro fiscal e baixar o lote completo de XMLs referente à competência ${compVal}:\n\n🔗 ${url}\n\nOZPro Fiscal Cloud Gateway`); window.open(`https://api.whatsapp.com/send?text=${msg}`, '_blank'); } // ─── UTILITÁRIOS ───────────────────────────────────────── function copyToClipboard(text, msg) { navigator.clipboard.writeText(text).then(() => { if (window.Toast) Toast.success(msg || 'Copiado para a área de transferência!'); }).catch(() => { if (window.Toast) Toast.info(text); }); } function togglePasswordVisibility(fieldId) { const input = document.getElementById(fieldId); if (!input) return; input.type = input.type === 'password' ? 'text' : 'password'; } function exportFiscalListCSV() { if (allFiscalInvoices.length === 0) { if (window.Toast) Toast.warning('Nenhuma nota para exportar.'); return; } let csv = "Numero;Serie;Modelo;DataEmissao;Cliente;CPF_CNPJ;Valor;Status;ChaveAcesso;Protocolo\n"; allFiscalInvoices.forEach(i => { const dt = i.dataEmissao?.seconds ? new Date(i.dataEmissao.seconds * 1000).toISOString() : new Date(i.dataEmissao).toISOString(); csv += `"${i.numero}";"${i.serie}";"${i.modelo}";"${dt}";"${i.cliente}";"${i.customerCpf || ''}";"${i.total}";"${i.status}";"${i.chave}";"${i.protocolo}"\n`; }); const blob = new Blob(["\uFEFF" + csv], { type: 'text/csv;charset=utf-8;' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `notas_fiscais_ozpro_${new Date().toISOString().slice(0,10)}.csv`; a.click(); if (window.Toast) Toast.success('Planilha de notas fiscais baixada!'); } async function checkFiscalPagePermission() { if (window.LicenseService && typeof window.LicenseService.canAccessFiscal === 'function') { const can = await window.LicenseService.canAccessFiscal(); if (!can) { renderFiscalPaywallBanner(); const existingReadiness = document.getElementById('fiscalReadinessBanner'); if (existingReadiness) existingReadiness.remove(); } else { const paywall = document.getElementById('fiscalPaywallHeroBanner'); if (paywall) paywall.remove(); const tabsNav = document.querySelector('.fiscal-tabs-nav'); const tabPanes = document.querySelectorAll('.fiscal-tab-pane'); if (tabsNav) { tabsNav.style.opacity = '1'; tabsNav.style.pointerEvents = 'all'; tabsNav.style.filter = 'none'; } tabPanes.forEach(p => { p.style.opacity = '1'; p.style.pointerEvents = 'all'; p.style.filter = 'none'; }); } } } function renderFiscalReadinessBanner(readiness) { const container = document.querySelector('.page-content'); if (!container || !readiness) return; const old = document.getElementById('fiscalReadinessBanner'); if (old) old.remove(); window._fiscalReadiness = readiness; // Atualiza o botão de emissão no cabeçalho const headerBtn = document.getElementById('btnEmitirAvulsaHeader'); if (headerBtn) { if (!readiness.pronto) { headerBtn.style.opacity = '0.7'; headerBtn.style.borderColor = 'rgba(245, 158, 11, 0.4)'; headerBtn.title = `Emissão bloqueada: ${readiness.percentual}% de prontidão fiscal (${readiness.concluidos} de ${readiness.total} requisitos).`; headerBtn.innerHTML = ` Emitir NF (${readiness.percentual}%)`; } else { headerBtn.style.opacity = '1'; headerBtn.style.borderColor = ''; headerBtn.title = 'Emitir Nota Fiscal de Venda Concluída'; headerBtn.innerHTML = ` Emitir NF de Venda`; } } if (readiness.pronto) return; // 100% configurado! const banner = document.createElement('div'); banner.id = 'fiscalReadinessBanner'; banner.style.cssText = ` background: linear-gradient(135deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98)); border: 2px solid rgba(245, 158, 11, 0.5); border-radius: 16px; padding: 24px 26px; margin-bottom: 24px; box-shadow: 0 12px 32px rgba(0,0,0,0.45); `; const checksHtml = readiness.checks.map(c => `
${escapeHtml(c.label)}
${escapeHtml(c.mensagem)}
${c.valido ? 'OK' : `Configurar ` }
`).join(''); banner.innerHTML = `
Emissão Bloqueada — Prontidão Fiscal Incompleta

Sua loja está com ${readiness.percentual}% das configurações fiscais preenchidas

Para autorizar notas fiscais oficiais com validade jurídica na SEFAZ e evitar multas ou rejeições fiscais, é obrigatório preencher 100% dos requisitos cadastrais e fiscais da sua empresa.

${readiness.percentual}%
${readiness.concluidos} de ${readiness.total} concluídos
${checksHtml}
`; container.insertBefore(banner, container.firstChild); } function renderFiscalPaywallBanner() { const container = document.querySelector('.page-content'); if (!container) return; const old = document.getElementById('fiscalPaywallHeroBanner'); if (old) old.remove(); const banner = document.createElement('div'); banner.id = 'fiscalPaywallHeroBanner'; banner.style.cssText = ` background: linear-gradient(135deg, rgba(30, 41, 59, 0.95), rgba(15, 23, 42, 0.98)); border: 2px solid rgba(239, 68, 68, 0.4); border-radius: 18px; padding: 30px 28px; margin-bottom: 24px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 22px; box-shadow: 0 16px 40px rgba(0,0,0,0.5); position: relative; z-index: 100; `; banner.innerHTML = `
Módulo Fiscal SEFAZ Bloqueado — Upgrade Necessário

Emissão Oficial de NFC-e, NF-e & Certificado Digital A1

Seu plano atual não possui emissão fiscal oficial SEFAZ. Este módulo está bloqueado para novas emissões e configurações. Para emitir cupons fiscais no PDV, notas grandes e gerar os relatórios para a contabilidade, faça o upgrade para o Plano Fiscal ou Business.

Apenas R$ 1,64 por dia no Plano Fiscal Anual (ou R$ 69,90/mês)
Conhecer todos os recursos e planos
`; container.insertBefore(banner, container.firstChild); // Bloqueio com fundo cinza e desativação das abas e formulários const tabsNav = document.querySelector('.fiscal-tabs-nav'); const tabPanes = document.querySelectorAll('.fiscal-tab-pane'); if (tabsNav) { tabsNav.style.opacity = '0.35'; tabsNav.style.pointerEvents = 'none'; tabsNav.style.filter = 'grayscale(1)'; } tabPanes.forEach(p => { p.style.opacity = '0.3'; p.style.pointerEvents = 'none'; p.style.filter = 'grayscale(1)'; }); } document.addEventListener('DOMContentLoaded', async () => { const user = await RouteGuard.requireAuth(); if (!user) return; await checkFiscalPagePermission(); await reloadFiscalInvoices(); await loadAllFiscalSettings(); // Bloqueio interativo ao tentar ligar o switch de emissão sem 100% fiscal const toggleEmitir = document.getElementById('cfg_emitir_nfe'); if (toggleEmitir) { toggleEmitir.addEventListener('change', async function() { if (this.checked) { const currentForm = { cnpj: document.getElementById('cfg_cnpj_fiscal')?.value, inscricaoEstadual: document.getElementById('cfg_ie_fiscal')?.value, razaoSocial: document.getElementById('cfg_razao_social')?.value, regimeTributario: document.getElementById('cfg_regime_tributario')?.value, cfopPadrao: document.getElementById('cfg_cfop_padrao')?.value, csosnPadrao: document.getElementById('cfg_csosn_padrao')?.value, ncmPadrao: document.getElementById('cfg_ncm_padrao')?.value, serieNfce: document.getElementById('cfg_serie_nfce')?.value, proximoNumeroNfce: document.getElementById('cfg_proximo_numero_nfce')?.value, idCsc: document.getElementById('cfg_id_csc')?.value, codigoCsc: document.getElementById('cfg_codigo_csc')?.value, focusTokenProducao: document.getElementById('cfg_focus_token_producao')?.value, focusTokenHomolog: document.getElementById('cfg_focus_token_homolog')?.value, ambienteSefaz: document.getElementById('cfg_ambiente_sefaz')?.value, }; const readiness = (window.LicenseService && typeof LicenseService.checkFiscalReadiness === 'function') ? LicenseService.checkFiscalReadiness(currentForm) : (window.NFCeService ? NFCeService.validarProntidaoFiscal(currentForm) : { pronto: false }); if (!readiness.pronto && !readiness.isReady) { this.checked = false; if (window.LicenseService && typeof LicenseService.showFiscalSetupRequiredModal === 'function') { LicenseService.showFiscalSetupRequiredModal(readiness); } if (window.Toast) { Toast.warning(`Emissão não pode ser ativada: ${readiness.percentual || readiness.percent}% concluído. É necessário 100% de prontidão fiscal.`); } } } }); } // Destaque e rolagem suave se vier com parâmetro focus ou hash setTimeout(() => { const params = new URLSearchParams(window.location.search); let target = params.get('focus') || window.location.hash.replace('#', ''); if (target === 'card-certificado' || target === 'certificado') target = 'cardCertificadoA1'; if (target) { const el = document.getElementById(target); if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'center' }); try { el.focus(); } catch(_) {} el.style.transition = 'box-shadow 0.4s ease, border-color 0.4s ease'; el.style.boxShadow = '0 0 0 4px rgba(245, 158, 11, 0.45)'; el.style.borderColor = '#f59e0b'; setTimeout(() => { el.style.boxShadow = ''; el.style.borderColor = ''; }, 3500); } } }, 600); });
`n