MDX Limo
NFS-e Avulsa — Plano de Implementação

{/* PLANO-NFSE.mdx — Plano de Implementação da NFS-e Avulsa (Release 1) */}

NFS-e Avulsa — Plano de Implementação

Visão Geral

Nova funcionalidade no Módulo Fiscal da SMB Store para emissão manual de Notas Fiscais de Serviço Eletrônicas (NFSe). O prestador seleciona um tomador, adiciona serviços, preenche dados fiscais e transmite a nota à prefeitura — tudo dentro do sistema.

Estado atual: o Módulo Fiscal suporta apenas NFe e NFCe (produtos). Esta release adiciona cobertura para serviços.

Integração: API Focus NFe — endpoints /v2/nfse (próprio) e /v2/nfsen (nacional).


Arquitetura de Referência do Codebase

CamadaPadrão AtualArquivos-chave
API FocusFactory + Contracts (third_party/NotaFiscal/)Notafiscal.php, CreateNfe.php, CancelNfe.php
ControllersCodeIgniter + Ws.php como hub de operaçõesWs.php, Nfes_manual.php, Dados_fiscais_v.php
ModelsGeneric_model com enums internosNotas_fiscais_model.php, Empresa_model.php
HelpersFunções procedurais por domíniomy_nota_fiscal_helper.php, my_webhook_nfe_helper.php
FrontendVue 3 (Composition API) + Mixins + Materialize CSSDadosFiscaisController_v.js, Mixin_nota_fiscal.js
PermissõesConstantes no Permissao_model (430–433 usados)Permissao_model.php
Rotasroutes.php + controllers nomeados$route['nfes-manual/(:num)']

Mapeamento de Ambiente — API Focus

O campo nac do endpoint de municípios da Focus determina o cenário:

Regra MEI: empresas com regime tributário MEI (código 4) obrigatoriamente usam Ambiente Nacional, independente da configuração.


Seleção de Ambiente pelo Usuário

Na tela de Dados Fiscais, um dropdown permite escolher:

OpçãoFlags na API de Empresas FocusEndpoint de emissão
Ambiente Nacionalhabilita_nfsen_producao: true, habilita_nfse: false/v2/nfsen
Ambiente Própriohabilita_nfsen_producao: false, habilita_nfse: true/v2/nfse

Para municípios com nac: proxy, mesmo selecionando "Ambiente Próprio", o endpoint correto é /v2/nfsen. O sistema deve resolver isso automaticamente.


Fase 1 — Configuração e Cadastros

Entrega: A empresa está configurada para emitir NFSe. Serviços e clientes possuem dados fiscais completos. Permissões estão ativas.

1.1 Estrutura de Dados Base

Escopo: Migrações de banco, models, enums, constantes de permissão. Pré-requisito para tudo.

Novas colunas — tabela empresas

ColunaTipoDescrição
ativar_nfsetinyint(1) default 0Switch habilitar NFSe
is_nfse_prodtinyint(1) default 0Ambiente: 0=homolog, 1=prod
nfse_ambienteenum('nacional','proprio')Tipo de ambiente
inscricao_municipalvarchar(30)Inscrição municipal
nfse_numero_rpsint unsignedPróximo número RPS
nfse_login_prefeituravarchar(100)Login prefeitura
nfse_senha_prefeituratextSenha prefeitura (encriptada)
nfse_codigo_ibgevarchar(7)Código IBGE do município
nfse_info_adicionaistextInformações adicionais padrão

Novas colunas — tabela notas_fiscais

ColunaTipoDescrição
nfse_numerovarchar(20)Número oficial da NFSe
nfse_numero_rpsintNúmero RPS usado
nfse_codigo_verificacaovarchar(50)Código de verificação
nfse_urltextURL da nota na prefeitura
xml_nfselongtextXML armazenado localmente
nfse_natureza_operacaotinyintEnum 1–6
nfse_regime_tributacaotinyintEnum 1–6
nfse_data_competenciadateData de competência
nfse_discriminacaotextDiscriminação dos serviços
nfse_substituida_idint unsigned nullFK nota substituída
nfse_valor_pisdecimal(15,2)Retenção PIS
nfse_valor_cofinsdecimal(15,2)Retenção COFINS
nfse_valor_irdecimal(15,2)Retenção IR
nfse_valor_cslldecimal(15,2)Retenção CSLL
nfse_valor_inssdecimal(15,2)Retenção INSS
nfse_valor_issdecimal(15,2)Valor ISS
nfse_valor_iss_retidodecimal(15,2)ISS retido

Novas colunas — tabela nota_fiscal_itens

ColunaTipoDescrição
servico_codigo_lc116varchar(10)Código LC 116
servico_cnaevarchar(10)CNAE
servico_codigo_tributario_municipiovarchar(20)CTM
servico_aliquota_issdecimal(5,2)Alíquota ISS
servico_iss_retidotinyint(1) default 0ISS retido
servico_descricao_manualtextDescrição (serviço manual)
is_servico_manualtinyint(1) default 0Flag serviço avulso

Novas colunas — tabela produtos

ColunaTipoDescrição
servico_codigo_lc116varchar(10)Código LC 116
servico_cnaevarchar(10)CNAE
servico_codigo_tributario_municipiovarchar(20)CTM
servico_aliquota_issdecimal(5,2)Alíquota ISS
servico_iss_retidotinyint(1) default 0ISS retido
servico_nbsvarchar(20)NBS
servico_reter_pistinyint(1) default 0Reter PIS
servico_reter_cofinstinyint(1) default 0Reter COFINS
servico_reter_irtinyint(1) default 0Reter IR
servico_reter_cslltinyint(1) default 0Reter CSLL
servico_reter_insstinyint(1) default 0Reter INSS

Novas colunas — tabela clientes

ColunaTipoDescrição
codigo_ibge_municipiovarchar(7)Código IBGE do município

Nova tabela — servicos_lc116

ColunaTipo
idint PK auto_increment
codigovarchar(10) unique
descricaotext

Nova tabela — municipios_nfse

ColunaTipo
idint PK auto_increment
codigo_municipiovarchar(7) unique
nome_municipiovarchar(100)
sigla_ufchar(2)
nfse_habilitadatinyint(1)
requer_certificado_nfsetinyint(1)
possui_ambiente_homologacao_nfsetinyint(1)
possui_cancelamento_nfsetinyint(1)
provedor_nfsevarchar(50)
codigo_cnae_obrigatorio_nfsetinyint(1) null
item_lista_servico_obrigatorio_nfsetinyint(1) null
codigo_tributario_municipio_obrigatorio_nfsetinyint(1) null
status_nfsevarchar(20)
nacenum('none','proxy','oficial')
atualizado_emdatetime

Colunas reservadas — Reforma Tributária (IBS/CBS)

Adicionar nas tabelas notas_fiscais e nota_fiscal_itens sem lógica:

ColunaTipo
ibs_valordecimal(15,2) null
cbs_valordecimal(15,2) null

Enums

1class NfseNaturezaOperacaoEnum { 2 const TRIBUTACAO_MUNICIPIO = 1; 3 const TRIBUTACAO_FORA_MUNICIPIO = 2; 4 const ISENCAO = 3; 5 const IMUNE = 4; 6 const EXIGIBILIDADE_SUSPENSA_JUDICIAL = 5; 7 const EXIGIBILIDADE_SUSPENSA_ADMINISTRATIVA = 6; 8} 9 10class NfseRegimeTributacaoEnum { 11 const MICROEMPRESA_MUNICIPAL = 1; 12 const ESTIMATIVA = 2; 13 const SOCIEDADE_PROFISSIONAIS = 3; 14 const COOPERATIVA = 4; 15 const MEI_SIMPLES_NACIONAL = 5; 16 const ME_EPP_SIMPLES_NACIONAL = 6; 17}

Adicionar alias NFSE = 'nfse' no NotaFiscalTipoEnum. Adicionar status SUBSTITUIDO = '7' no NotaFiscalStatusEnum.

Constantes de Permissão

1const PERMISSAO_EMITIR_NFSE = 435; 2const PERMISSAO_CANCELAR_NFSE = 436; 3const PERMISSAO_GERENCIAR_CONF_NFSE = 437;

1.2 Configuração NFSe da Empresa

Escopo: Backend + Frontend para a tela de Dados Fiscais.

Wireframe — Seção NFSe em Dados Fiscais

1┌─────────────────────────────────────────────────────────────────┐ 2│ DADOS FISCAIS DA EMPRESA │ 3│ ┌──────────┬──────────────┬───────────────┬──────────────────┐ │ 4│ │ Empresa │ Config Notas │ Certificado │ Backup Fiscal │ │ 5│ └──────────┴──────────────┴───────────────┴──────────────────┘ │ 6│ │ 7│ ═══ Configuração de Notas ═══ │ 8│ │ 9│ --- NFe / NFCe (existente) --- │ 10│ [campos existentes...] │ 11│ │ 12│ ─── NFS-e ─────────────────────────────────────────────────── │ 13│ │ 14│ ┌───────────────────────────────────────────────┐ │ 15│ │ Habilitar emissão de NFSe [ OFF ] │ │ 16│ └───────────────────────────────────────────────┘ │ 17│ │ 18│ ▼ (campos visíveis somente com switch ON) │ 19│ │ 20│ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ 21│ │ Inscrição Municipal │ │ Número Inicial do RPS │ │ 22│ │ [________________] │ │ [________] │ │ 23│ │ Máx 30 chars, numérico │ │ Inteiro positivo, mín 1 │ │ 24│ └─────────────────────────┘ └──────────────────────────────┘ │ 25│ │ 26│ ┌──────────────────────────────────────────────┐ │ 27│ │ Município (Código IBGE) │ │ 28│ │ [🔍 Buscar município...__________________ ] │ │ 29│ │ Autocomplete via cache de municípios Focus │ │ 30│ └──────────────────────────────────────────────┘ │ 31│ │ 32│ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ 33│ │ Ambiente de Emissão │ │ Tipo de Ambiente │ │ 34│ │ [▾ Homologação ] │ │ [▾ Ambiente Próprio ] │ │ 35│ │ Homologação / Produção │ │ Nacional / Próprio │ │ 36│ └─────────────────────────┘ └──────────────────────────────┘ │ 37│ │ 38│ ─── Dados para Autenticação ─── │ 39│ │ 40│ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ 41│ │ Login da Prefeitura │ │ Senha da Prefeitura │ │ 42│ │ [________________] │ │ [********] 👁 │ │ 43│ │ Opcional (máx 100) │ │ Opcional (máx 100, mascarado)│ │ 44│ └─────────────────────────┘ └──────────────────────────────┘ │ 45│ │ 46│ ┌──────────────────────────────────────────────────────────┐ │ 47│ │ Informações Adicionais Padrão │ │ 48│ │ [ ] │ │ 49│ │ [ ] │ │ 50│ └──────────────────────────────────────────────────────────┘ │ 51│ │ 52│ ⚠ Município sem homologação: "O município configurado não │ 53│ possui ambiente de homologação. Notas em modo teste serão │ 54│ transmitidas para produção." │ 55│ │ 56│ [ Salvar Configuração ] │ 57└─────────────────────────────────────────────────────────────────┘

Fluxo de preenchimento do Código IBGE

Validações

  • Ativar switch: Inscrição Municipal deve estar preenchida. Caso contrário, alerta com link.
  • Número RPS: inteiro positivo, mínimo 1, obrigatório.
  • Senha da prefeitura: encriptada no backend antes de persistir.
  • Ambiente: seleção dispara UpdateCompany na Focus com flags corretas.

Backend

  • Endpoints em Ws.php: set/salvar_config_nfse, get/config_nfse
  • Validação em my_nfse_helper.php: validar_empresa_nfse()
  • Encriptação da senha via helper existente do CodeIgniter

Frontend

  • Nova seção no DadosFiscaisController_v.js
  • Novo mixin Mixin_nfse.js com métodos de API
  • Campos condicionais vinculados ao switch ativar_nfse

1.3 Catálogo LC 116 e Dados Fiscais do Serviço

Escopo: Seed da LC 116, autocomplete, aba fiscal no cadastro de serviço.

Wireframe — Aba Dados Fiscais do Serviço

1┌────────────────────────────────────────────────────────────┐ 2│ CADASTRO DE PRODUTO/SERVIÇO │ 3│ ┌──────────┬──────────────┬──────────────┐ │ 4│ │ Geral │ Preços │ Dados Fiscais│ ← Nova aba │ 5│ └──────────┴──────────────┴──────────────┘ │ 6│ │ 7│ (Aba visível APENAS se Tipo = Serviço E Módulo Fiscal ON) │ 8│ │ 9│ ┌──────────────────────────────────────────────────────┐ │ 10│ │ Código do Serviço (LC 116) │ │ 11│ │ [🔍 Buscar código ou descrição...______________ ] │ │ 12│ │ Autocomplete do catálogo (~200 itens) │ │ 13│ │ Ex: 17.06 - Propaganda e publicidade │ │ 14│ └──────────────────────────────────────────────────────┘ │ 15│ │ 16│ ┌────────────────────┐ ┌───────────────────────────┐ │ 17│ │ CNAE │ │ Alíquota ISS (%) │ │ 18│ │ [__________] │ │ [_____] 0–100, 2 decimais │ │ 19│ └────────────────────┘ └───────────────────────────┘ │ 20│ │ 21│ ┌────────────────────┐ ┌───────────────────────────┐ │ 22│ │ Código Trib. Munic.│ │ NBS │ │ 23│ │ [__________] │ │ [__________] │ │ 24│ └────────────────────┘ └───────────────────────────┘ │ 25│ │ 26│ ─── Retenções ─── │ 27│ ☐ Reter ISS ☐ Reter PIS ☐ Reter COFINS │ 28│ ☐ Reter IR ☐ Reter CSLL ☐ Reter INSS │ 29│ │ 30│ [ Salvar ] │ 31└────────────────────────────────────────────────────────────┘

Backend

  • Seed script: popular servicos_lc116 com ~200 itens da LC 116/2003
  • Endpoint: ws/get/ac_servicos_lc116?q= — busca por código ou texto
  • Método cadastro_completo_nfse() no model de produto: valida LC 116 + alíquota ISS preenchidos
  • Campos opcionais no cadastro — obrigatoriedade validada apenas na emissão

Frontend

  • Nova aba condicional no formulário de produto (visível quando is_servico = '1' e módulo fiscal ativo)
  • Autocomplete para LC 116 consumindo endpoint do catálogo
  • Indicador visual de cadastro fiscal incompleto (badge "Pendente")

1.4 Dados Fiscais do Cliente (Tomador)

Escopo: Campo Código IBGE no cadastro de cliente + auto-preenchimento via CEP.

Wireframe — Campo IBGE no Cadastro de Cliente

1┌────────────────────────────────────────────────────────────┐ 2│ CADASTRO DE CLIENTE — Endereço │ 3│ │ 4│ ┌────────────┐ ┌──────────────────────────────────────┐ │ 5│ │ CEP │ │ Logradouro │ │ 6│ │ [________] │ │ [________________________________] │ │ 7│ └────────────┘ └──────────────────────────────────────┘ │ 8│ │ 9│ ┌─────────────┐ ┌───────────┐ ┌────────┐ ┌──────────┐ │ 10│ │ Bairro │ │ Cidade │ │ UF │ │ Número │ │ 11│ │ [_________] │ │ [_______] │ │ [__] │ │ [_____] │ │ 12│ └─────────────┘ └───────────┘ └────────┘ └──────────┘ │ 13│ │ 14│ ┌──────────────────────────────────────────────────────┐ │ 15│ │ Código IBGE do Município ← NOVO CAMPO │ │ 16│ │ [_______] (auto-preenchido via CEP) │ │ 17│ │ Obrigatório para emissão de NFSe │ │ 18│ └──────────────────────────────────────────────────────┘ │ 19│ │ 20└────────────────────────────────────────────────────────────┘

Backend

  • Método cadastro_completo_nfse() no model de cliente: valida CPF/CNPJ + endereço + código IBGE
  • Lógica: ao receber CEP, buscar código IBGE via tabela municipios_nfse ou fonte externa
  • Referência: municipios-brasileiros JSON

Frontend

  • Novo campo no bloco de endereço do ClienteController_v.js
  • Auto-preenchimento do IBGE ao completar CEP
  • Sinalização visual quando cadastro incompleto para NFSe

1.5 Permissões de Usuário

Escopo: 3 novas permissões no sistema existente.

IDConstanteDescrição
435PERMISSAO_EMITIR_NFSEEmitir NFSe Manual
436PERMISSAO_CANCELAR_NFSECancelar NFSe
437PERMISSAO_GERENCIAR_CONF_NFSEGerenciar Configuração NFSe
  • Checkboxes na tela de permissões, visíveis apenas quando NFSe habilitada no tenant.
  • Permissão 435 controla acesso ao módulo inteiro (menu, listagem, emissão).
  • Validação no backend via $this->session->permissoes.

1.6 Cache de Municípios Suportados

Escopo: Integração com GET /v2/municipios da Focus + cache local.

Backend

  • Nova classe ListMunicipios.php em third_party/NotaFiscal/ seguindo padrão factory
  • Contrato ListMunicipiosContract.php
  • Novo método listMunicipios() na Notafiscal.php
  • Sincronização: cache com validade de 30 dias na tabela municipios_nfse
  • Endpoint: ws/get/ac_municipios_nfse para autocomplete

Dados armazenados do município

Além dos campos da tabela, o campo nac deve ser derivado do provedor_nfse:

  • Provedores com "Nacional" no nome → nac = 'proxy' ou 'oficial'
  • Demais → nac = 'none'

A fonte mais confiável para o campo nac é o JSON de cidades integradas da Focus. Script de seed inicial pode popular com base nesse JSON.


Entrega da Fase 1

  • Migrações executadas e models atualizados
  • Tela de Dados Fiscais com seção NFSe funcional
  • Autocomplete de município com cache Focus
  • Catálogo LC 116 populado e endpoint de busca funcionando
  • Aba Dados Fiscais no cadastro de serviço
  • Campo Código IBGE no cadastro de cliente
  • Permissões 435/436/437 registradas e funcionais

Fase 2 — Emissão de NFSe Manual

Entrega: Usuário pode emitir NFSe selecionando tomador e serviços. Nota transmitida de forma assíncrona com retorno automático de status via webhook. XML armazenado localmente.

2.1 Integração com API Focus NFSe

Escopo: Classes de integração — backend puro, sem frontend.

Novos arquivos em third_party/NotaFiscal/

ArquivoContratoMétodo HTTPEndpoint Focus
CreateNfse.phpCreateNfseContract.phpPOST/v2/nfse?ref={REF}
CreateNfsen.phpCreateNfsenContract.phpPOST/v2/nfsen?ref={REF}
DetailNfse.phpDetailNfseContract.phpGET/v2/nfse/{REF}
CancelNfse.phpCancelNfseContract.phpDELETE/v2/nfse/{REF}
SubstituteNfse.phpSubstituteNfseContract.phpPOST/v2/nfse/{REF}/substitucao
DownloadNfsePdf.phpGETURL retornada pela Focus
DownloadNfseXml.phpGETURL retornada pela Focus
ListMunicipios.phpListMunicipiosContract.phpGET/v2/municipios

Factory — novos métodos em Notafiscal.php

1// Novos métodos — usam is_nfse_prod em vez de is_nf_prod 2public function createNfse($apiToken) { ... } 3public function createNfsen($apiToken) { ... } 4public function detailNfse($apiToken) { ... } 5public function cancelNfse($apiToken) { ... } 6public function substituteNfse($apiToken) { ... } 7public function listMunicipios() { ... }

Importante: o ambiente NFSe (is_nfse_prod) é independente do ambiente NFe (is_nf_prod).

Resolução automática de endpoint


2.2 Webhook de Autorização NFSe

Escopo: Receber callback da Focus e atualizar status + armazenar XML.

Fluxo do Webhook

Backend

  • Novo helper: my_webhook_nfse_helper.php seguindo padrão de my_webhook_nfe_helper.php
  • Novo case em Ws.php: case "webhook_nfse":
  • Obrigatório: ao receber autorização, fazer GET no XML e armazenar na coluna xml_nfse (Focus só gera backups mensais)
  • Armazenar: nfse_url, nfse_codigo_verificacao, nfse_numero
  • Idempotência: verificar se já processou o webhook (status já AUTORIZADO → ignorar)

2.3 Formulário de Emissão — Dados Gerais e Tomador

Escopo: Página de NFSe Manual + etapas 1 e 2 do formulário.

Wireframe — Listagem de NFSe (página principal)

1┌─────────────────────────────────────────────────────────────────┐ 2│ NFSe Manual [ + Nova NFSe ] │ 3│ │ 4│ ┌──────────┐ ┌──────────────────┐ ┌─────────────┐ │ 5│ │ Status │ │ Tomador │ │ Período │ [Buscar] │ 6│ │ [▾Todos] │ │ [🔍___________] │ │ [__] a [__] │ │ 7│ └──────────┘ └──────────────────┘ └─────────────┘ │ 8│ │ 9│ ┌─────┬────────┬────────────┬─────────────┬──────────┬───────┐│ 10│ │ Nº │ RPS │ Data │ Tomador │ Valor │Status ││ 11│ ├─────┼────────┼────────────┼─────────────┼──────────┼───────┤│ 12│ │ 42 │ 15 │ 01/04/2026 │ Empresa ABC │ R$500,00 │🟢 Aut││ 13│ │ — │ 16 │ 01/04/2026 │ João Silva │ R$200,00 │🔄 Proc││ 14│ │ 41 │ 14 │ 31/03/2026 │ Maria LTDA │ R$1.000 │🔴 Erro││ 15│ │ 40 │ 13 │ 30/03/2026 │ Tech Corp │ R$750,00 │⚫ Canc││ 16│ └─────┴────────┴────────────┴─────────────┴──────────┴───────┘│ 17│ │ 18│ ← 1 2 3 ... → 20 itens por página │ 19│ │ 20│ Estado vazio: "Nenhuma NFSe emitida ainda. Clique em │ 21│ 'Nova NFSe' para começar." │ 22└─────────────────────────────────────────────────────────────────┘

Wireframe — Modal de Emissão: Etapa 1 (Dados Gerais)

1┌─────────────────────────────────────────────────────────────┐ 2│ Nova NFSe ✕ │ 3│ ═══════════════════════════════════════════════════════════ │ 4│ [1. Dados Gerais] → 2. Tomador → 3. Serviços → 4. Revisão│ 5│ ─────────────────────────────────────────────────────────── │ 6│ │ 7│ ┌────────────────────────┐ ┌───────────────────────────┐ │ 8│ │ Número RPS │ │ Data de Competência │ │ 9│ │ [ 16 ] (automático) │ │ [ 01/04/2026 ] 📅 │ │ 10│ │ Somente leitura │ │ Não pode ser futura │ │ 11│ └────────────────────────┘ └───────────────────────────┘ │ 12│ │ 13│ ┌──────────────────────────────────────────────────────┐ │ 14│ │ Natureza da Operação │ │ 15│ │ [▾ 1 - Tributação no município ] │ │ 16│ │ Enum: 1=Trib. município, 2=Fora, 3=Isenção, │ │ 17│ │ 4=Imune, 5=Susp. judicial, 6=Susp. administrativa │ │ 18│ └──────────────────────────────────────────────────────┘ │ 19│ │ 20│ ┌──────────────────────────────────────────────────────┐ │ 21│ │ Regime Especial de Tributação │ │ 22│ │ [▾ 5 - MEI - Simples Nacional ] │ │ 23│ │ Enum: 1=Microempresa, 2=Estimativa, 3=Soc. prof., │ │ 24│ │ 4=Cooperativa, 5=MEI-SN, 6=ME EPP-SN │ │ 25│ └──────────────────────────────────────────────────────┘ │ 26│ │ 27│ ┌──────────────────────────────────────────────────────┐ │ 28│ │ Discriminação dos Serviços │ │ 29│ │ [ ] │ │ 30│ │ [ ] │ │ 31│ │ Máx 2000 caracteres. Opcional. │ │ 32│ └──────────────────────────────────────────────────────┘ │ 33│ │ 34│ [ Próximo → ] │ 35└─────────────────────────────────────────────────────────────┘

Wireframe — Modal de Emissão: Etapa 2 (Tomador)

1┌─────────────────────────────────────────────────────────────┐ 2│ Nova NFSe ✕ │ 3│ ═══════════════════════════════════════════════════════════ │ 4│ 1. Dados Gerais → [2. Tomador] → 3. Serviços → 4. Revisão│ 5│ ─────────────────────────────────────────────────────────── │ 6│ │ 7│ ┌──────────────────────────────────────────────────────┐ │ 8│ │ Buscar tomador │ │ 9│ │ [🔍 Nome, CPF ou CNPJ...________________________ ] │ │ 10│ │ Autocomplete no cadastro de clientes │ │ 11│ └──────────────────────────────────────────────────────┘ │ 12│ [ + Cadastrar novo cliente ] │ 13│ │ 14│ ┌──────────────────────────────────────────────────────┐ │ 15│ │ ✓ Tomador selecionado │ │ 16│ │ ┌──────────────────────────────────────────────────┐ │ │ 17│ │ │ Nome: Empresa ABC LTDA │ │ │ 18│ │ │ CNPJ: 12.345.678/0001-90 │ │ │ 19│ │ │ Município: Fortaleza - CE (IBGE: 2304400) │ │ │ 20│ │ │ Endereço: Rua X, 100 - Centro │ │ │ 21│ │ └──────────────────────────────────────────────────┘ │ │ 22│ └──────────────────────────────────────────────────────┘ │ 23│ │ 24│ ⚠ ALERTA (se cadastro incompleto): │ 25│ ┌──────────────────────────────────────────────────────┐ │ 26│ │ ⚠ Cadastro incompleto para NFSe. │ │ 27│ │ Campos faltantes: Código IBGE do Município │ │ 28│ │ [Corrigir cadastro ↗] (abre nova aba) │ │ 29│ │ │ │ 30│ │ Após corrigir: [ 🔄 Revalidar tomador ] │ │ 31│ └──────────────────────────────────────────────────────┘ │ 32│ │ 33│ [ ← Voltar ] [ Próximo → ] │ 34└─────────────────────────────────────────────────────────────┘

Backend

  • Controller: Nfse_manual.php + rota nfse-manual
  • Helper: my_nfse_helper.php com validar_empresa_nfse(), validar_tomador_nfse()
  • Endpoint: ws/get/dados_iniciais_nfse (empresa, enums, próximo RPS)

Frontend

  • Nova página: application/views/paginas/nfse-manual.php
  • Controller Vue: NfseManualController.js
  • Modal Controller: ModalEmitirNfseController.js
  • Mixin: Mixin_nfse.js
  • Item no menu: sidebar abaixo de "NF-e Manual", visível com permissão 435

2.4 Formulário de Emissão — Serviços e Retenções

Escopo: Etapas 3 e 4 do formulário de emissão.

Wireframe — Modal de Emissão: Etapa 3 (Serviços)

1┌─────────────────────────────────────────────────────────────┐ 2│ Nova NFSe ✕ │ 3│ ═══════════════════════════════════════════════════════════ │ 4│ 1. Dados Gerais → 2. Tomador → [3. Serviços] → 4. Revisão│ 5│ ─────────────────────────────────────────────────────────── │ 6│ │ 7│ ┌──────────────────────────────────────────────────────┐ │ 8│ │ Buscar serviço do catálogo │ │ 9│ │ [🔍 Nome ou código do serviço..._______________ ] │ │ 10│ └──────────────────────────────────────────────────────┘ │ 11│ [ + Cadastrar novo serviço ] [ + Adicionar serviço manual]│ 12│ │ 13│ ── Serviços adicionados ── │ 14│ ┌──────────────────────────────────────────────────────┐ │ 15│ │ # │ Serviço │ LC116 │ Qtd │ V.Unit │Total │ │ 16│ │ 1 │ Consultoria TI │ 17.06 │ 10h │ R$150 │1.500 │ │ 17│ │ │ ISS: 5% │ ISS Retido: Não [✏🗑]│ │ 18│ │ 2 │ Suporte técnico │ 17.06 │ 5h │ R$100 │ 500 │ │ 19│ │ │ ISS: 5% │ ISS Retido: Não [✏🗑]│ │ 20│ │ 3 │ ⚠ Design gráfico │ — │ 2 │ R$500 │1.000 │ │ 21│ │ │ ⚠ Dados fiscais pendentes [Completar ↗] [✏🗑]│ │ 22│ └──────────────────────────────────────────────────────┘ │ 23│ │ 24│ ⚠ ALERTA LC 116 (se tentar misturar códigos): │ 25│ ┌──────────────────────────────────────────────────────┐ │ 26│ │ ⚠ Este serviço possui LC 116 diferente (14.01) dos │ │ 27│ │ já adicionados (17.06). Uma NFSe só aceita um código.│ │ 28│ │ Selecione 17.06 ou remova os serviços atuais. │ │ 29│ └──────────────────────────────────────────────────────┘ │ 30│ │ 31│ Subtotal: R$ 3.000,00 │ 32│ [ ← Voltar ] [ Próximo → ] │ 33└─────────────────────────────────────────────────────────────┘

Wireframe — Modal de Emissão: Etapa 4 (Revisão e Retenções)

1┌─────────────────────────────────────────────────────────────┐ 2│ Nova NFSe ✕ │ 3│ ═══════════════════════════════════════════════════════════ │ 4│ 1. Dados Gerais → 2. Tomador → 3. Serviços → [4. Revisão]│ 5│ ─────────────────────────────────────────────────────────── │ 6│ │ 7│ ── Resumo ── │ 8│ Tomador: Empresa ABC LTDA (12.345.678/0001-90) │ 9│ RPS: 16 │ Competência: 04/2026 │ Nat. Op.: Trib. munic. │ 10│ │ 11│ ── Serviços ── │ 12│ │ Consultoria TI (17.06) │ 10h × R$150 = R$ 1.500,00 │ 13│ │ Suporte técnico (17.06) │ 5h × R$100 = R$ 500,00 │ 14│ │────────────────────────────────────────────────────│ │ 15│ │ Subtotal Serviços R$ 2.000,00 │ │ 16│ │ 17│ ── Retenções (editáveis) ── │ 18│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ 19│ │ ISS (R$) │ │ PIS (R$) │ │ COFINS(R$) │ │ 20│ │ [ 100,00] │ │ [ 0,00] │ │ [ 0,00] │ │ 21│ └────────────┘ └────────────┘ └────────────┘ │ 22│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ 23│ │ IR (R$) │ │ CSLL (R$) │ │ INSS (R$) │ │ 24│ │ [ 0,00] │ │ [ 0,00] │ │ [ 0,00] │ │ 25│ └────────────┘ └────────────┘ └────────────┘ │ 26│ │ 27│ ⚠ Banner MEI (se aplicável): │ 28│ ┌──────────────────────────────────────────────────────┐ │ 29│ │ ℹ Esta nota será transmitida pelo Ambiente Nacional │ │ 30│ │ NFSe, conforme obrigatoriedade para emitentes MEI. │ │ 31│ └──────────────────────────────────────────────────────┘ │ 32│ │ 33│ ┌──────────────────────────────────────────────────────┐ │ 34│ │ VALOR TOTAL: R$ 1.900,00 │ │ 35│ │ (Serviços - Retenções = Líquido) │ │ 36│ └──────────────────────────────────────────────────────┘ │ 37│ │ 38│ [ ← Voltar ] [ 🚀 Transmitir NFSe ] │ 39└─────────────────────────────────────────────────────────────┘

Regras de negócio — Serviços

  • Restrição LC 116: todos os serviços de uma nota devem ter o mesmo código LC 116
  • Serviço manual: dados efêmeros (não salva no catálogo), mas LC 116 e alíquota são obrigatórios
  • Pendência fiscal: serviço do catálogo sem LC 116 ou alíquota → badge de pendência + link para edição

Backend

  • validar_servicos_nfse(): cadastro fiscal completo + bloqueio de mix LC 116
  • Validação por item: codigo_servico_lc116 e servico_aliquota_iss obrigatórios

2.5 Transmissão e Acompanhamento de Status

Escopo: Envio à Focus, polling de status, atualização na listagem.

Fluxo completo de emissão

Backend — Funções principais

FunçãoResponsabilidade
set_emitir_nfse()Orquestra validação → gravação → transmissão
montar_payload_nfse()JSON conforme formato Focus
get_consultar_nfse()Consulta manual de status (fallback ao webhook)
resolver_endpoint_nfse()Determina /v2/nfse ou /v2/nfsen com base no município + regime

Payload da Focus — Formato (endpoint /v2/nfse)

1{ 2 "data_emissao": "2026-04-01T10:00:00-03:00", 3 "prestador": { 4 "cnpj": "07504505000132", 5 "inscricao_municipal": "12345", 6 "codigo_municipio": "2304400" 7 }, 8 "tomador": { 9 "cnpj": "12345678000190", 10 "razao_social": "Empresa ABC LTDA", 11 "endereco": { ... }, 12 "codigo_municipio": "3550308" 13 }, 14 "servico": { 15 "aliquota": 5.0, 16 "discriminacao": "Consultoria em TI...", 17 "iss_retido": false, 18 "item_lista_servico": "1706", 19 "codigo_cnae": "6201501", 20 "codigo_tributario_municipio": "123", 21 "valor_servicos": 2000.00 22 }, 23 "natureza_operacao": "1", 24 "regime_especial_tributacao": "5", 25 "valor_pis": 0, 26 "valor_cofins": 0, 27 "valor_ir": 0, 28 "valor_csll": 0, 29 "valor_inss": 0 30}

Cota mensal

NFSe consome a mesma franquia do pacote mensal (mesma contagem de NFe/NFCe). Verificar saldo antes de emitir.


Entrega da Fase 2

  • Classes Focus NFSe criadas e funcionais (Create, Detail, Cancel, Substitute)
  • Webhook NFSe processando autorizações e armazenando XML
  • Formulário completo de emissão (4 etapas)
  • Transmissão assíncrona com retorno de status
  • Polling + consulta manual de status
  • Regra MEI forçando Ambiente Nacional
  • Resolução automática de endpoint (nfse vs nfsen)

Fase 3 — Gestão de NFSe

Entrega: Usuário pode listar, filtrar, visualizar detalhes, baixar PDF/XML, cancelar e substituir notas.

3.1 Listagem e Filtros

Wireframe da listagem já apresentado na Fase 2 (seção 2.3). Complementos:

  • Filtros: período (data início/fim), status (dropdown), tomador (busca por nome/CPF/CNPJ)
  • Busca textual: por número da nota, número RPS, nome do tomador
  • Paginação: 20 itens por página

3.2 Visualização Detalhada e Downloads

Wireframe — Modal de Detalhes da NFSe

1┌─────────────────────────────────────────────────────────────┐ 2│ Detalhes da NFSe #42 ✕ │ 3│ ═══════════════════════════════════════════════════════════ │ 4│ │ 5│ Status: 🟢 Autorizada │ 6│ Nº NFSe: 42 │ RPS: 15 │ Código Verificação: ABC123 │ 7│ Data Emissão: 01/04/2026 │ Competência: 04/2026 │ 8│ │ 9│ ── Prestador ── │ 10│ SMB Store LTDA │ CNPJ: 07.504.505/0001-32 │ 11│ Inscrição Municipal: 12345 │ 12│ │ 13│ ── Tomador ── │ 14│ Empresa ABC LTDA │ CNPJ: 12.345.678/0001-90 │ 15│ Fortaleza - CE (IBGE: 2304400) │ 16│ │ 17│ ── Serviços ── │ 18│ │ Consultoria TI (LC 116: 17.06) │ 19│ │ CNAE: 6201501 │ ISS: 5% │ ISS Retido: Não │ 20│ │ 10h × R$150,00 = R$ 1.500,00 │ 21│ │──────────────────────────────────────────────────│ │ 22│ │ Suporte técnico (LC 116: 17.06) │ 23│ │ 5h × R$100,00 = R$ 500,00 │ 24│ │ 25│ ── Retenções ── │ 26│ ISS: R$100,00 │ PIS: R$0 │ COFINS: R$0 │ 27│ IR: R$0 │ CSLL: R$0 │ INSS: R$0 │ 28│ │ 29│ ── Valor Total: R$ 1.900,00 ── │ 30│ │ 31│ ── Notas Vinculadas ── (se houver substituição) │ 32│ │ NFSe #41 │ 31/03/2026 │ Status: Substituído │ [Ver ↗] │ 33│ │ 34│ 🔗 Ver na prefeitura: https://... │ 35│ │ 36│ [ 📄 Baixar XML ] [ 📄 Baixar PDF ] [ ✕ Cancelar ] │ 37└─────────────────────────────────────────────────────────────┘

Matriz de ações por status

AçãoEm processamentoAutorizadoErroCanceladoSubstituído
Baixar XML
Baixar PDF
Cancelar
Substituir

Backend — Downloads

  • XML: prioriza coluna xml_nfse (local); fallback via DetailNfse.php + GET
  • PDF: chama Focus API; se município não suporta PDF, redireciona para nfse_url
  • Cases em Ws.php: nfse_pdf, nfse_xml

3.3 Cancelamento

Wireframe — Modal de Cancelamento

1┌─────────────────────────────────────────────────────┐ 2│ Cancelar NFSe #42 ✕ │ 3│ ═══════════════════════════════════════════════════ │ 4│ │ 5│ Tomador: Empresa ABC LTDA │ 6│ Valor: R$ 1.900,00 │ 7│ Data: 01/04/2026 │ 8│ │ 9│ ⚠ Esta ação é irreversível. │ 10│ │ 11│ ┌──────────────────────────────────────────────┐ │ 12│ │ Justificativa de cancelamento * │ │ 13│ │ [ ] │ │ 14│ │ [ ] │ │ 15│ │ Máx 255 caracteres │ │ 16│ └──────────────────────────────────────────────┘ │ 17│ │ 18│ [ Voltar ] [ Confirmar Cancel.] │ 19└─────────────────────────────────────────────────────┘
  • Município sem suporte a cancelamento: botão desabilitado com tooltip.
  • Backend: CancelNfse.php → DELETE /v2/nfse/REF com justificativa.
  • Case Ws.php: cancelar_nfse

3.4 Substituição

  • Disponível para notas com status Erro ou Cancelado.
  • Abre formulário de nova NFSe pré-preenchido com dados da nota original.
  • Banner: "Você está substituindo a nota nº X."
  • Após transmissão: nota original → status SUBSTITUÍDO; nova nota → PROCESSANDO.
  • Backend: SubstituteNfse.php → POST /v2/nfse/REF/substitucao
  • Vínculo: nfse_substituida_id na nova nota.
  • Case Ws.php: substituir_nfse

Entrega da Fase 3

  • Listagem com filtros e paginação
  • Busca por número, RPS, tomador
  • Modal de detalhes com todos os dados
  • Download XML (local) e PDF (Focus)
  • Cancelamento com justificativa
  • Substituição com pré-preenchimento
  • Cadeia de notas vinculadas

Fase 4 — Dashboard Fiscal Unificado

Entrega: Dashboard apresenta visão consolidada de NFe + NFCe + NFSe com métricas, filtros e exportação de XMLs.

4.1 Métricas e Contadores NFSe

Wireframe — Cards no Dashboard

1┌─────────────────────────────────────────────────────────────────┐ 2│ DASHBOARD FISCAL │ 3│ │ 4│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐│ 5│ │ NFCe │ │ NFe Norm │ │ NFe Dev │ │ NFe Ajus │ │ NFSe ││ 6│ │ 142 │ │ 28 │ │ 3 │ │ 1 │ │ 12 ││ 7│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────┘│ 8│ │ 9│ ┌─────────────────────┐ ┌──────────────────────────────────┐ │ 10│ │ Notas no período │ │ Cota mensal: 186/500 (37%) │ │ 11│ │ 186 │ │ ████████░░░░░░░░░░░░░░ │ │ 12│ │ (inclui NFSe) │ │ (NFe + NFCe + NFSe) │ │ 13│ └─────────────────────┘ └──────────────────────────────────┘ │ 14│ │ 15│ Tipo: [▾ Todas ▾] inclui opção "NFSe" [ 🚀 Emitir NFSe]│ 16│ │ 17└─────────────────────────────────────────────────────────────────┘
  • Card "NFSe" visível apenas com switch ativo.
  • NFSe autorizadas contam no total de "Notas emitidas no período".
  • Cota mensal inclui NFSe na contagem total.

4.2 Filtros e Navegação

  • Nova opção "NFSe" no seletor de tipo de documento no dashboard.
  • Link rápido "Emitir NFSe" na barra de ações.
  • Menu lateral: item "NFSe Manual" no grupo Módulo Fiscal.

4.3 Exportação de XMLs por Período

  • Botão "Exportar XMLs" com seletor de período.
  • Consulta coluna xml_nfse local, gera ZIP, serve para download.
  • Não depende da API Focus.

Entrega da Fase 4

  • Card contador "NFSe" no dashboard
  • NFSe na cota mensal
  • Filtro por tipo de documento incluindo NFSe
  • Link rápido "Emitir NFSe"
  • Exportação de XMLs em ZIP

Fase 5 — Testes, Validação e Rollout

Entrega: Módulo validado em homologação, regressão NFe/NFCe íntegra, rollout gradual para produção.

5.1 Testes Funcionais em Homologação

CenárioDescrição
Emissão básicaEmpresa SN, serviço simples, tomador PJ
Emissão MEISistema força Ambiente Nacional
ISS retido + retençõesPIS, COFINS, CSLL, IR, INSS preenchidos
Bloqueio dados incompletosServiço sem LC 116 → orientação
Bloqueio mix LC 1162 serviços com códigos diferentes → bloqueio
Webhook autorizaçãoStatus atualizado + XML armazenado
Webhook erroStatus erro + mensagem da Focus
Consulta manual statusFallback ao webhook
CancelamentoJustificativa + Focus API
SubstituiçãoPré-preenchimento + vínculo
Download PDFMunicípio com e sem suporte
Download XMLBase local e via API
CotaNFSe decrementa saldo do pacote
PermissõesSem permissão → menu oculto + rota bloqueada
Multi-tenantNFSe empresa A ≠ empresa B
Tomador sem IBGEBloqueio + orientação
Sem Inscrição MunicipalBloqueio ao ativar switch
Município não suportadoMensagem clara

5.2 Testes de Regressão

  • NFe/NFCe continua emitindo normalmente
  • Dashboard sem NFSe ativa não quebra
  • Produto tipo mercadoria não exibe aba serviço
  • Webhooks NFe/NFCe inalterados

5.3 Testes de Borda

  • Timeout da Focus → tratamento gracioso
  • NFSe com valor zero → bloqueio
  • Emissões simultâneas → sem duplicidade no RPS (lock/transação atômica)
  • Webhook duplicado → idempotência

5.4 Rollout Gradual

FaseEscopoCritério de entrada
Alpha3–5 clientes em municípios estáveis (SP, CWB)Testes em homolog aprovados
BetaClientes em cidades homologadas como estáveisAlpha sem bugs críticos
GA (Disponibilidade Geral)Toda a baseBeta estável por 2 semanas

Entrega da Fase 5

  • Todos os cenários de teste aprovados em homologação
  • Regressão NFe/NFCe sem impacto
  • Payloads validados com consultoria fiscal
  • Webhook NFSe configurado no painel Focus (homolog + prod)
  • Alpha concluído com sucesso
  • GA liberado

Fluxo Geral — Diagrama Completo


Dependências e Paralelismo

AtividadeDepende dePode rodar em paralelo com
1.1 Estrutura de dados
1.2 Config empresa1.11.3, 1.4, 1.5, 1.6
1.3 Catálogo LC 1161.11.2, 1.4, 1.5, 1.6
1.4 Dados cliente1.11.2, 1.3, 1.5, 1.6
1.5 Permissões1.11.2, 1.3, 1.4, 1.6
1.6 Cache municípios1.11.2, 1.3, 1.4, 1.5
2.1 Classes Focus1.12.2
2.2 Webhook1.12.1
2.3 Form (dados/tomador)1.2–1.6
2.4 Form (serviços)2.3
2.5 Transmissão2.1, 2.2, 2.4
3.1–3.42.53.3 ∥ 3.4
4.1–4.33.14.1 ∥ 4.2 ∥ 4.3
5.x4.x

Funcionalidades Futuras (pós Release 1)

FeatureRelease
Emissão de NFSe a partir de Ordem de ServiçoRelease 2
Clonagem de NFSe recorrenteFuturo
Cálculo automático de retenções federaisFuturo
Envio automático de e-mail com notaFuturo
Cálculo IBS/CBS (reforma tributária)Quando obrigatório