Class: Nfcom::Models::Nota
- Inherits:
-
Object
- Object
- Nfcom::Models::Nota
- Defined in:
- lib/nfcom/models/nota.rb
Overview
Formato da chave de acesso (44 dígitos): UF (2) + AAMM (4) + CNPJ (14) + Modelo (2) + Série (3) + Número (9) + Tipo Emissão (1) + Código Numérico (8) + DV (1)
Importante:
-
O campo cNF no XML possui 7 dígitos
-
Na chave de acesso, o código numérico é representado com 8 dígitos
Representa uma Nota Fiscal de Comunicação (NF-COM) modelo 62.
A Nota é o objeto principal da gem, responsável por agregar todas as informações necessárias para a emissão da NF-COM: emitente, destinatário, fatura, itens/serviços, totais e metadados fiscais.
Tipos de Emissão:
-
:normal (1) - Emissão normal (padrão)
-
:contingencia (2) - Emissão em contingência (offline)
Finalidades:
-
:normal (0) - Nota fiscal normal (padrão)
-
:substituicao (3) - Nota de substituição
-
:ajuste (4) - Nota de ajuste
Tipos de Faturamento:
-
:normal (0) - Faturamento padrão
-
:centralizado (1) - Faturamento centralizado
-
:cofaturamento (2) - Cofaturamento
Atributos obrigatórios:
-
serie - Série da nota (padrão: 1)
-
numero - Número sequencial da nota
-
emitente - Provedor / empresa emissora
-
destinatario - Cliente / tomador do serviço
-
fatura - Informações de cobrança (obrigatória)
-
itens - Pelo menos um item/serviço
Atributos opcionais:
-
data_emissao - Data/hora de emissão (padrão: Time.now)
-
tipo_emissao - Tipo de emissão (padrão: :normal)
-
finalidade - Finalidade da nota (padrão: :normal)
-
informacoes_adicionais - Texto livre (até 5.000 caracteres)
Atributos preenchidos após autorização:
-
chave_acesso - Chave de acesso (44 dígitos)
-
codigo_verificacao - Código numérico (cNF, 7 dígitos – usado no XML)
-
protocolo - Número do protocolo SEFAZ
-
data_autorizacao - Data/hora da autorização
-
xml_autorizado - XML completo autorizado pela SEFAZ
Funcionalidades automáticas:
-
Numeração sequencial dos itens
-
Recalculo automático dos totais
-
Geração da chave de acesso com dígito verificador
-
Validação completa de todos os campos obrigatórios
-
Validação em cascata (emitente, destinatário, fatura e itens)
Validações realizadas:
-
Presença de série, número, emitente, destinatário e fatura
-
Existência de pelo menos um item
-
Validação completa do emitente (CNPJ, IE, endereço)
-
Validação completa do destinatário (CPF/CNPJ, endereço)
-
Validação da fatura
-
Validação individual de cada item
Constant Summary collapse
- MAX_INF_CPL =
5- METODOS_PAGAMENTO =
{ dinheiro: '01', cheque: '02', cartao_credito: '03', cartao_debito: '04', credito_loja: '05', vale_alimentacao: '10', vale_refeicao: '11', vale_presente: '12', vale_combustivel: '13', boleto_bancario: '15', deposito_bancario: '16', pix: '17', transferencia_bancaria: '18', programa_fidelidade: '19', sem_pagamento: '90', outros: '99' }.freeze
- TIPO_EMISSAO =
{ normal: 1, contingencia: 2 }.freeze
- FINALIDADE =
{ normal: 0, substituicao: 3, ajuste: 4 }.freeze
- TIPO_FATURAMENTO =
{ normal: 0, centralizado: 1, cofaturamento: 2 }.freeze
Instance Attribute Summary collapse
-
#assinante ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#chave_acesso ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#chave_nfcom_substituida ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#codigo_verificacao ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#competencia_fatura ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#data_autorizacao ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#data_emissao ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#data_vencimento ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#destinatario ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#emitente ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#fatura ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#finalidade ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#informacoes_adicionais ⇒ Object
Returns the value of attribute informacoes_adicionais.
-
#itens ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#metodo_pagamento ⇒ Object
Returns the value of attribute metodo_pagamento.
-
#motivo_substituicao ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#numero ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#protocolo ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#serie ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#tipo_emissao ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#tipo_faturamento ⇒ Object
Returns the value of attribute tipo_faturamento.
-
#total ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#valor_liquido_fatura ⇒ Object
rubocop:disable Metrics/ClassLength.
-
#xml_autorizado ⇒ Object
rubocop:disable Metrics/ClassLength.
Instance Method Summary collapse
- #add_item(attributes) ⇒ Object
- #autorizada? ⇒ Boolean
-
#erros ⇒ Object
rubocop:disable Metrics/MethodLength.
- #finalidade_codigo ⇒ Object
- #gerar_chave_acesso ⇒ Object
-
#initialize(attributes = {}) {|_self| ... } ⇒ Nota
constructor
A new instance of Nota.
- #recalcular_totais ⇒ Object
- #tipo_emissao_codigo ⇒ Object
- #valida? ⇒ Boolean
Constructor Details
#initialize(attributes = {}) {|_self| ... } ⇒ Nota
Returns a new instance of Nota.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/nfcom/models/nota.rb', line 225 def initialize(attributes = {}) @serie = Nfcom.configuration.serie_padrao || 1 @data_emissao = Time.now @tipo_emissao = :normal send(:tipo_faturamento=, :normal) @finalidade = :normal @itens = [] @total = Total.new attributes.each do |key, value| if key == :emitente && value.is_a?(Hash) @emitente = Emitente.new(value) elsif key == :fatura && value.is_a?(Hash) @fatura = Fatura.new(value) elsif key == :destinatario && value.is_a?(Hash) @destinatario = Destinatario.new(value) elsif respond_to?("#{key}=") send("#{key}=", value) end end yield self if block_given? end |
Instance Attribute Details
#assinante ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def assinante @assinante end |
#chave_acesso ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def chave_acesso @chave_acesso end |
#chave_nfcom_substituida ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def chave_nfcom_substituida @chave_nfcom_substituida end |
#codigo_verificacao ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def codigo_verificacao @codigo_verificacao end |
#competencia_fatura ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def competencia_fatura @competencia_fatura end |
#data_autorizacao ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def data_autorizacao @data_autorizacao end |
#data_emissao ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def data_emissao @data_emissao end |
#data_vencimento ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def data_vencimento @data_vencimento end |
#destinatario ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def destinatario @destinatario end |
#emitente ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def emitente @emitente end |
#fatura ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def fatura @fatura end |
#finalidade ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def finalidade @finalidade end |
#informacoes_adicionais ⇒ Object
Returns the value of attribute informacoes_adicionais.
144 145 146 |
# File 'lib/nfcom/models/nota.rb', line 144 def informacoes_adicionais @informacoes_adicionais end |
#itens ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def itens @itens end |
#metodo_pagamento ⇒ Object
Returns the value of attribute metodo_pagamento.
144 145 146 |
# File 'lib/nfcom/models/nota.rb', line 144 def metodo_pagamento @metodo_pagamento end |
#motivo_substituicao ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def motivo_substituicao @motivo_substituicao end |
#numero ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def numero @numero end |
#protocolo ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def protocolo @protocolo end |
#serie ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def serie @serie end |
#tipo_emissao ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def tipo_emissao @tipo_emissao end |
#tipo_faturamento ⇒ Object
Returns the value of attribute tipo_faturamento.
144 145 146 |
# File 'lib/nfcom/models/nota.rb', line 144 def tipo_faturamento @tipo_faturamento end |
#total ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def total @total end |
#valor_liquido_fatura ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def valor_liquido_fatura @valor_liquido_fatura end |
#xml_autorizado ⇒ Object
rubocop:disable Metrics/ClassLength
137 138 139 |
# File 'lib/nfcom/models/nota.rb', line 137 def xml_autorizado @xml_autorizado end |
Instance Method Details
#add_item(attributes) ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/nfcom/models/nota.rb', line 249 def add_item(attributes) item = if attributes.is_a?(Item) attributes else Item.new(attributes) end item.numero_item = itens.length + 1 itens << item recalcular_totais item end |
#autorizada? ⇒ Boolean
366 367 368 |
# File 'lib/nfcom/models/nota.rb', line 366 def autorizada? !protocolo.nil? && !data_autorizacao.nil? end |
#erros ⇒ Object
rubocop:disable Metrics/MethodLength
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/nfcom/models/nota.rb', line 313 def erros # rubocop:disable Metrics/MethodLength errors = [] errors << 'Série é obrigatória' if serie.nil? errors << 'Número é obrigatório' if numero.nil? errors << 'Emitente é obrigatório' if emitente.nil? errors << 'Destinatário é obrigatório' if destinatario.nil? errors << 'Deve haver pelo menos um item' if itens.empty? # Validações de schema (formato) errors << 'Série inválida (deve ser 0-999)' if serie && !serie.to_s.match?(/\A(0|[1-9]{1}[0-9]{0,2})\z/) if numero && !numero.to_s.match?(/\A[1-9]{1}[0-9]{0,8}\z/) errors << 'Número inválido (1-999999999, não pode começar com zero)' end if codigo_verificacao && codigo_verificacao.to_s.length != 7 errors << "cNF inválido: deve ter exatamente 7 dígitos (campo XML), tem #{codigo_verificacao.to_s.length}" end if chave_acesso && !chave_acesso.to_s.match?(/\A[0-9]{44}\z/) errors << "Chave de acesso inválida (deve ter 44 dígitos, tem #{chave_acesso.to_s.length})" end errors.concat(emitente.erros.map { |e| "Emitente: #{e}" }) if emitente && !emitente.valido? errors.concat(destinatario.erros.map { |e| "Destinatário: #{e}" }) if destinatario && !destinatario.valido? itens.each_with_index do |item, i| errors.concat(item.erros.map { |e| "Item #{i + 1}: #{e}" }) unless item.valido? end if fatura.nil? errors << 'Fatura é obrigatória' elsif !fatura.valido? errors.concat(fatura.erros.map { |e| "Fatura: #{e}" }) end informacoes_adicionais&.each_with_index do |texto, i| errors << "Informação adicional #{i + 1} inválida." unless Validators::SchemaValidator.texto_valido?(texto) end if finalidade == :substituicao if chave_nfcom_substituida.nil? errors << 'Chave da NFCom substituída é obrigatória para notas de substituição' end errors << 'Motivo da substituição é obrigatório' if motivo_substituicao.nil? unless chave_nfcom_substituida.nil? || chave_nfcom_substituida.to_s.match?(/\A[0-9]{44}\z/) errors << 'Chave da NFCom substituída inválida (deve ter 44 dígitos)' end end errors end |
#finalidade_codigo ⇒ Object
305 306 307 |
# File 'lib/nfcom/models/nota.rb', line 305 def finalidade_codigo FINALIDADE[finalidade] || FINALIDADE[:normal] end |
#gerar_chave_acesso ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/nfcom/models/nota.rb', line 269 def gerar_chave_acesso # IMPORTANTE: Discrepância no schema NFCom: # - Campo cNF no XML: 7 dígitos (ER2) # - cNF na chave de acesso: 8 dígitos (para chave ter 44 dígitos no total) # Formato da chave: UFAnoMesCNPJModSerieNumTpEmissCodNumDV # UF(2) + AAMM(4) + CNPJ(14) + Mod(2) + Serie(3) + Num(9) + TpEmiss(1) + CodNum(8) + DV(1) = 44 # Exemplo: 26 2601 07159053000107 62 001 000009670 1 01234567 9 config = Nfcom.configuration uf = config.codigo_uf ano_mes = data_emissao.strftime('%y%m') cnpj = emitente.cnpj.gsub(/\D/, '') modelo = '62' serie_fmt = serie.to_s.rjust(3, '0') numero_fmt = numero.to_s.rjust(9, '0') tipo_emiss = tipo_emissao_codigo.to_s # Gera cNF com 7 dígitos (para o campo XML) codigo_numerico_7 = SecureRandom.random_number(10_000_000).to_s.rjust(7, '0') # Mas na chave usa 8 dígitos (padding à esquerda com zero) codigo_numerico_8 = codigo_numerico_7.rjust(8, '0') chave_sem_dv = "#{uf}#{ano_mes}#{cnpj}#{modelo}#{serie_fmt}#{numero_fmt}#{tipo_emiss}#{codigo_numerico_8}" dv = calcular_digito_verificador(chave_sem_dv) # Armazena o cNF de 7 dígitos (para o XML) @codigo_verificacao = codigo_numerico_7 # Chave completa com 44 dígitos @chave_acesso = "#{chave_sem_dv}#{dv}" end |
#recalcular_totais ⇒ Object
262 263 264 265 266 267 |
# File 'lib/nfcom/models/nota.rb', line 262 def recalcular_totais @total.valor_servicos = itens.sum { |i| i.valor_total.to_f } @total.valor_desconto = itens.sum { |i| i.valor_desconto.to_f } @total.valor_outras_despesas = itens.sum { |i| i.valor_outras_despesas.to_f } @total.calcular_total end |
#tipo_emissao_codigo ⇒ Object
301 302 303 |
# File 'lib/nfcom/models/nota.rb', line 301 def tipo_emissao_codigo TIPO_EMISSAO[tipo_emissao] || TIPO_EMISSAO[:normal] end |
#valida? ⇒ Boolean
309 310 311 |
# File 'lib/nfcom/models/nota.rb', line 309 def valida? erros.empty? end |