AxiomaFiscal

Módulo embeddable de configuração fiscal para produtos

O AxiomaFiscal é um componente JavaScript auto-contido (IIFE) que renderiza um formulário completo de configuração fiscal. Qualquer produto do ecossistema Axioma pode importá-lo para adicionar dados fiscais ao cadastro de produtos.

Zero dependências. O módulo inclui todas as tabelas fiscais (NCM, CFOP, CST, CSOSN, PIS, COFINS), validação, autocomplete de NCM e suporte a dark/light theme. Basta incluir o script.

Instalação

Adicione o script no HTML do seu produto. Nenhuma dependência extra é necessária.

<!-- No HTML do seu produto -->
<div id="fiscal-config"></div>
<script src="https://axiom-nfe.web.app/modules/fiscal.js"></script>

O script expõe o objeto global window.AxiomaFiscal com todos os métodos.

Uso básico

Exemplo mínimo: renderizar o form, validar e obter os dados.

<div id="fiscal-config"></div>
<script src="https://axiom-nfe.web.app/modules/fiscal.js"></script>
<script>
  // 1. Renderizar o formulário
  AxiomaFiscal.render('fiscal-config', {
    regime: 'simples_nacional'
  });

  // 2. No submit do form de produto:
  function salvarProduto() {
    const { valid, errors } = AxiomaFiscal.validate();
    if (!valid) {
      alert('Corrija os campos fiscais: ' + errors.join(', '));
      return;
    }

    const fiscal = AxiomaFiscal.getData();
    // fiscal = { NCM, CFOP, origem, uCom, CSOSN, pisCST, cofinsCST, ... }
    // Salvar junto com o produto no Firestore
    await db.collection('shops/xxx/products').doc(productId).update({
      fiscal: fiscal
    });
  }

  // 3. Modo edição (produto existente):
  AxiomaFiscal.setData(produtoExistente.fiscal);
</script>

API Completa

AxiomaFiscal.render(containerId, options)

Renderiza o formulário fiscal dentro de um elemento DOM.

ParâmetroTipoDescrição
containerIdstringID do elemento DOM onde renderizar
options.regimestring'simples_nacional' | 'lucro_presumido' | 'lucro_real'
options.darkbooleanUsar tema escuro (default: false)
options.defaultsobjectValores iniciais para pré-popular os campos
options.onChangefunctionCallback chamado quando qualquer campo muda. Recebe getData() como argumento
AxiomaFiscal.render('fiscal-config', {
  regime: 'lucro_presumido',
  dark: true,
  defaults: { NCM: '61091000', CFOP: '5102' },
  onChange: (data) => console.log('Fiscal changed:', data)
});

AxiomaFiscal.getData()

Retorna um objeto com todos os dados fiscais preenchidos. Pronto para salvar no banco.

Retorno — Simples Nacional:

{
  "NCM": "61091000",
  "CFOP": "5102",
  "origem": "0",
  "uCom": "UN",
  "cest": null,
  "ean": null,
  "regime": "simples_nacional",
  "CSOSN": "102",
  "pisCST": "49",
  "cofinsCST": "49"
}

Retorno — Lucro Presumido / Real:

{
  "NCM": "61091000",
  "CFOP": "5102",
  "origem": "0",
  "uCom": "UN",
  "cest": null,
  "ean": null,
  "regime": "lucro_presumido",
  "CST": "00",
  "pICMS": 18,
  "modBC": "3",
  "pisCST": "01",
  "pisAliq": 0.65,
  "cofinsCST": "01",
  "cofinsAliq": 3
}

AxiomaFiscal.setData(data)

Popula o formulário com dados existentes (modo edição). Aceita o mesmo formato retornado por getData().

// Carregar dados fiscais do produto existente
const produto = await db.collection('shops/xxx/products').doc(id).get();
AxiomaFiscal.setData(produto.data().fiscal);

AxiomaFiscal.validate()

Valida os campos obrigatórios. Retorna objeto com valid (boolean) e errors (array de strings). Marca campos com erro visualmente (borda vermelha + mensagem).

const result = AxiomaFiscal.validate();
// { valid: false, errors: ['NCM deve ter 8 dígitos numéricos', 'CFOP é obrigatório'] }

if (result.valid) {
  const fiscal = AxiomaFiscal.getData();
  // salvar...
}

Campos obrigatórios:

AxiomaFiscal.setRegime(regime)

Troca o regime tributário e re-renderiza o formulário com os defaults apropriados. Preserva NCM, CFOP, unidade e EAN já preenchidos.

// Quando o lojista muda o regime tributário da empresa:
regimeSelect.addEventListener('change', (e) => {
  AxiomaFiscal.setRegime(e.target.value);
});

AxiomaFiscal.tables

Acesso direto às tabelas fiscais embutidas. Útil para construir UIs customizadas.

PropriedadeConteúdo
CST_ICMS11 códigos (00, 10, 20, 30, 40, 41, 50, 51, 60, 70, 90)
CSOSN10 códigos Simples Nacional (101–900)
CST_PIS_COFINS16 códigos PIS/COFINS (01–99)
CFOP_COMMON9 CFOPs mais usados (venda interna, interestadual, exportação)
ORIGEM9 origens de mercadoria (0–8)
UNIDADES20 unidades comerciais (UN, KG, L, CX, etc.)
NCM_DB38 NCMs comuns com descrição
REGIME_DEFAULTSDefaults por regime (simples, LP, LR)
// Exemplo: popular um select customizado com CFOPs
const cfops = AxiomaFiscal.tables.CFOP_COMMON;
Object.entries(cfops).forEach(([code, desc]) => {
  select.innerHTML += `<option value="${code}">${code} — ${desc}</option>`;
});

Regimes Tributários

O módulo adapta automaticamente os campos exibidos e os defaults conforme o regime:

RegimeICMSPIS/COFINSAlíquotas
simples_nacional CSOSN (102 — sem crédito) CST 49 (outras saídas) Não exibe (isento)
lucro_presumido CST (00 — tributada) CST 01 (tributável) PIS 0,65% / COFINS 3,00%
lucro_real CST (00 — tributada) CST 01 (tributável) PIS 1,65% / COFINS 7,60%

Defaults Automáticos

Ao renderizar sem options.defaults, o módulo aplica defaults inteligentes baseados no regime. O usuário pode alterar qualquer campo.

Atenção: Os defaults são sugestões genéricas. Cada empresa deve consultar seu contador para confirmar as configurações fiscais corretas para seus produtos.

Dark Theme

Passe dark: true nas opções para usar o tema escuro. Ideal para produtos com interface dark (como o próprio NFe dashboard).

AxiomaFiscal.render('fiscal-config', {
  regime: 'simples_nacional',
  dark: true
});

onChange Callback

Receba notificações em tempo real quando o usuário altera qualquer campo fiscal.

AxiomaFiscal.render('fiscal-config', {
  regime: 'simples_nacional',
  onChange: (data) => {
    // data = resultado de getData()
    console.log('NCM changed to:', data.NCM);
    // Pode salvar automaticamente, mostrar preview, etc.
  }
});

Integração com o Shop

Exemplo completo de como usar no cadastro de produto do Axioma Shop.

<!-- No form de produto (produtos.html) -->

<!-- Seção fiscal dentro do form -->
<div class="section-title">Configuração Fiscal</div>
<div id="fiscal-config"></div>

<script src="https://axiom-nfe.web.app/modules/fiscal.js"></script>
<script>
  // Detectar regime da empresa (salvo na loja)
  const regime = shop.taxRegime || 'simples_nacional';

  // Renderizar form fiscal
  AxiomaFiscal.render('fiscal-config', { regime });

  // Se editando produto existente, popular com dados salvos
  if (produto.fiscal) {
    AxiomaFiscal.setData(produto.fiscal);
  }

  // No save do produto:
  async function salvarProduto() {
    const { valid, errors } = AxiomaFiscal.validate();
    if (!valid) {
      showError('Corrija os dados fiscais: ' + errors.join(', '));
      return;
    }

    const fiscal = AxiomaFiscal.getData();

    await db.collection(`shops/${shopId}/products`).doc(productId).update({
      ...outrosCampos,
      fiscal: fiscal,
      updatedAt: new Date()
    });
  }
</script>

UI Customizada

Se preferir construir seu próprio formulário, use AxiomaFiscal.tables para acessar as tabelas e REGIME_DEFAULTS para os valores padrão.

// Pegar tabelas sem renderizar o form
const { CSOSN, CST_ICMS, CFOP_COMMON, NCM_DB } = AxiomaFiscal.tables;

// Popular seus próprios selects
const csosn = CSOSN; // { '101': 'Tributada com crédito', '102': 'Sem crédito', ... }

// Buscar NCM
const results = NCM_DB.filter(n =>
  n.code.includes('6109') || n.desc.toLowerCase().includes('camiseta')
);
// [{ code: '61091000', desc: 'Camisetas de malha, de algodão' }]

Montando o Payload NFe

Os dados retornados por getData() mapeiam diretamente para os campos do payload de emissão da API NFe.

const fiscal = AxiomaFiscal.getData();

// Montar produto para a API NFe
const produtoNFe = {
  cProd: produto.id,
  xProd: produto.name,
  NCM: fiscal.NCM,
  CFOP: fiscal.CFOP,
  uCom: fiscal.uCom,
  qCom: quantidade,
  vUnCom: produto.price,
  vProd: quantidade * produto.price,
  cEAN: fiscal.ean || 'SEM GTIN',
  cEANTrib: fiscal.ean || 'SEM GTIN',
  CEST: fiscal.cest,

  // ICMS
  icms: fiscal.regime === 'simples_nacional'
    ? { orig: fiscal.origem, CSOSN: fiscal.CSOSN }
    : {
        orig: fiscal.origem,
        CST: fiscal.CST,
        modBC: parseInt(fiscal.modBC),
        vBC: quantidade * produto.price,
        pICMS: fiscal.pICMS,
        vICMS: (quantidade * produto.price * fiscal.pICMS / 100)
      },

  // PIS
  pis: { CST: fiscal.pisCST, vBC: quantidade * produto.price,
         pPIS: fiscal.pisAliq || 0, vPIS: (quantidade * produto.price * (fiscal.pisAliq || 0) / 100) },

  // COFINS
  cofins: { CST: fiscal.cofinsCST, vBC: quantidade * produto.price,
            pCOFINS: fiscal.cofinsAliq || 0, vCOFINS: (quantidade * produto.price * (fiscal.cofinsAliq || 0) / 100) }
};

NCMs Embutidos

O módulo inclui 38 NCMs comuns para autocomplete. A lista cobre as categorias mais vendidas no varejo brasileiro.

NCMDescrição

CFOPs Disponíveis

CFOPDescrição

CSTs ICMS / CSOSN

CST ICMS (Lucro Presumido / Real)

CSTDescrição

CSOSN (Simples Nacional)

CSOSNDescrição

Demo ao Vivo

Teste o módulo diretamente nesta página.