nfse 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/danfe/danfse_generator.rb +122 -0
- data/lib/danfe/descricao.rb +46 -0
- data/lib/danfe/document.rb +84 -0
- data/lib/danfe/helper.rb +101 -0
- data/lib/danfe/xml.rb +90 -0
- data/lib/municipios.json +1 -0
- data/lib/nfse/base.rb +20 -0
- data/lib/nfse/consultalote.rb +30 -0
- data/lib/nfse/envialote.rb +72 -0
- data/lib/nfse/lote.rb +68 -0
- data/lib/nfse/prestador.rb +19 -0
- data/lib/nfse/rps.rb +28 -0
- data/lib/nfse/servico.rb +32 -0
- data/lib/nfse/tomador.rb +59 -0
- data/lib/nfse_gem.rb +27 -0
- data/lib/templates/nfse/consulta_lote.mustache +17 -0
- data/lib/templates/nfse/envia_lote.mustache +13 -0
- data/lib/templates/nfse/envio/lote.mustache +25 -0
- data/lib/templates/nfse/envio/prestador.mustache +4 -0
- data/lib/templates/nfse/envio/rps.mustache +34 -0
- data/lib/templates/nfse/envio/servico.mustache +22 -0
- data/lib/templates/nfse/envio/tomador.mustache +51 -0
- metadata +147 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0356ae06d8a620fcfe5fcdd8f63f67759aa569c9fb5da003b06a790ba6622094
|
|
4
|
+
data.tar.gz: 56ed8bf906bc0ad0f036bdaec169eb78b35fffebf85a3a8bf9e7ac04594a19ea
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1748e61542e41829bcaee9ac32750798db03ded918224aca35ab7eeaa48f33192f44c4d28e90b65d24906a1313b9b245f3444c37cf83935f6502b9c528994981
|
|
7
|
+
data.tar.gz: f6d97c3542f4b5105b2eae7983837e982d6ff926de6fb631ddc2b5cc10ca8a6e26044f5ff6a4e711af899e1ca5643c5cf3b87ee1157c5dd6f2c6b4598bdb2814
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
require "prawn"
|
|
4
|
+
require "prawn/table"
|
|
5
|
+
require "prawn/measurement_extensions"
|
|
6
|
+
require "nokogiri"
|
|
7
|
+
require 'ostruct'
|
|
8
|
+
require 'yaml'
|
|
9
|
+
require 'date'
|
|
10
|
+
require 'time'
|
|
11
|
+
require 'json'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
module Nfse
|
|
15
|
+
|
|
16
|
+
module Pdf
|
|
17
|
+
class DanfseGenerator
|
|
18
|
+
def initialize(xml)
|
|
19
|
+
@xml = Nfse::Pdf::XML.new(xml)
|
|
20
|
+
@pdf = Document.new
|
|
21
|
+
@vol = 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :municipios
|
|
25
|
+
|
|
26
|
+
def municipios
|
|
27
|
+
lib_path = File.expand_path("../../", __FILE__)
|
|
28
|
+
@municipios ||= JSON.parse(File.read(File.join(lib_path, 'municipios.json')))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def generatePDF
|
|
32
|
+
render_titulo
|
|
33
|
+
render_prestador
|
|
34
|
+
render_tomador
|
|
35
|
+
render_intermediario
|
|
36
|
+
render_discriminacao
|
|
37
|
+
render_valor_total
|
|
38
|
+
render_outras
|
|
39
|
+
return @pdf.render
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
def render_titulo
|
|
44
|
+
@pdf.ibox 2.55, 16.10, 0.25, 0.42, '',
|
|
45
|
+
"PREFEITURA DO MUNICÍPIO DE #{municipios[@xml['InfNfse/PrestadorServico/Endereco/CodigoMunicipio']].upcase} \n" +
|
|
46
|
+
"Secretaria Municipal da Fazenda \n" +
|
|
47
|
+
"NOTA FISCAL ELETRÔNICA DE SERVIÇOS - NFS-e \n" +
|
|
48
|
+
"RPS n° #{@xml['IdentificacaoRps/Numero']}, emitido em #{@xml['DataEmissao']}", {:align => :center, :valign => :center}
|
|
49
|
+
|
|
50
|
+
@pdf.ibox 0.85, 4.47, 16.35, 0.42, "NÚMERO DA NOTA", "#{@xml['InfNfse/Numero'].rjust(8,'0')}"
|
|
51
|
+
@pdf.ibox 0.85, 4.47, 16.35, 1.27, "DATA E HORA DE EMISSÃO", "#{@xml['InfNfse/DataEmissao'].gsub('T', ' ')}"
|
|
52
|
+
@pdf.ibox 0.85, 4.47, 16.35, 2.12, "CÓDIGO DE VERIFICAÇÃO", "#{@xml['CodigoVerificacao']}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def render_prestador
|
|
56
|
+
@pdf.ibox 4.25, 20.57, 0.25, 2.97
|
|
57
|
+
@pdf.ibox 0.85, 20.57, 0.25, 2.97, '', 'PRESTADOR DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
58
|
+
@pdf.ibox 0.85, 20.57, 0.25, 3.82, "Nome/Razão Social", "#{@xml['PrestadorServico/RazaoSocial']}", {border: 0}
|
|
59
|
+
@pdf.ibox 0.85, 12, 0.25, 4.67, "CPF/CNPJ", "#{@xml['PrestadorServico/IdentificacaoPrestador/Cnpj'] || @xml['PrestadorServico/IdentificacaoPrestador/Cpf']}", {border: 0}
|
|
60
|
+
@pdf.ibox 0.85, 4.47, 12, 4.67, "Inscrição Municipal", "#{@xml['IdentificacaoPrestador/InscricaoMunicipal']}", {border: 0}
|
|
61
|
+
@pdf.ibox 0.85, 20.57, 0.25, 5.52, "Endereço", "#{@xml['PrestadorServico/Endereco/Endereco']}", {border: 0}
|
|
62
|
+
@pdf.ibox 0.85, 10, 0.25, 6.37, "Município", "#{municipios[@xml['PrestadorServico/Endereco/CodigoMunicipio']]}", {border: 0}
|
|
63
|
+
@pdf.ibox 0.85, 4.47, 10, 6.37, "UF", "#{@xml['PrestadorServico/Endereco/Uf']}", {border: 0}
|
|
64
|
+
@pdf.ibox 0.85, 4.47, 15, 6.37, "E-mail", "#{@xml['PrestadorServico/Contato/Email']}", {border: 0}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def render_tomador
|
|
68
|
+
@pdf.ibox 4.25, 20.57, 0.25, 7.22
|
|
69
|
+
@pdf.ibox 0.85, 20.57, 0.25, 7.22, '', 'TOMADOR DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
70
|
+
@pdf.ibox 0.85, 20.57, 0.25, 8.07, "Nome/Razão Social", "#{@xml['TomadorServico/RazaoSocial']}", {border: 0}
|
|
71
|
+
cpf_cnpj = @xml['TomadorServico/IdentificacaoTomador/CpfCnpj/Cnpj']
|
|
72
|
+
if cpf_cnpj.empty? then cpf_cnpj = @xml['TomadorServico/IdentificacaoTomador/CpfCnpj/Cpf'] end
|
|
73
|
+
@pdf.ibox 0.85, 12, 0.25, 8.92, "CPF/CNPJ", "#{cpf_cnpj}", {border: 0}
|
|
74
|
+
@pdf.ibox 0.85, 4.47, 12, 8.92, "Inscrição Municipal", "#{@xml['TomadorServico/IdentificacaoTomador/InscricaoMunicipal']}", {border: 0}
|
|
75
|
+
@pdf.ibox 0.85, 20.57, 0.25, 9.77, "Endereço", "#{@xml['TomadorServico/Endereco/Endereco']}", {border: 0}
|
|
76
|
+
@pdf.ibox 0.85, 10, 0.25, 10.62, "Município", "#{municipios[@xml['TomadorServico/Endereco/CodigoMunicipio']]}", {border: 0}
|
|
77
|
+
@pdf.ibox 0.85, 4.47, 10, 10.62, "UF", "#{@xml['TomadorServico/Endereco/Uf']}", {border: 0}
|
|
78
|
+
@pdf.ibox 0.85, 4.47, 15, 10.62, "E-mail", "#{@xml['TomadorServico/Contato/Email']}", {border: 0}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def render_intermediario
|
|
82
|
+
@pdf.ibox 1.70, 20.57, 0.25, 11.47
|
|
83
|
+
@pdf.ibox 0.85, 20.57, 0.25, 11.47, '', 'INTERMEDIÁRIO DE SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
84
|
+
@pdf.ibox 0.85, 12, 0.25, 12.32, "Nome/Razão Social", "#{@xml['IntermediarioServico/IdentificacaoIntermediarioServico/RazaoSocial']}", {border: 0}
|
|
85
|
+
cpf_cnpj = @xml['IntermediarioServico/IdentificacaoIntermediarioServico/CpfCnpj/Cnpj']
|
|
86
|
+
if cpf_cnpj.empty? then cpf_cnpj = @xml['IntermediarioServico/IdentificacaoIntermediarioServico/CpfCnpj/Cpf'] end
|
|
87
|
+
@pdf.ibox 0.85, 8, 12.25, 12.32, "CPF/CNPJ", "#{cpf_cnpj}", {border: 0}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def render_discriminacao
|
|
91
|
+
@pdf.ibox 9.35, 20.57, 0.25, 13.17
|
|
92
|
+
@pdf.ibox 0.85, 20.57, 0.25, 13.17, '', 'DISCRIMINAÇÃO DOS SERVIÇOS', {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
93
|
+
@pdf.ibox 8, 19.57, 0.75, 14.02, "", "#{@xml['Servico/Discriminacao']}", {border: 0}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def render_valor_total
|
|
97
|
+
@pdf.ibox 1.70, 20.57, 0.25, 22.52
|
|
98
|
+
@pdf.ibox 0.85, 20.57, 0.25, 22.52, '', "VALOR TOTAL DO SERVIÇO = R$#{Helper.numerify(@xml['Servico/Valores/ValorServicos'])}", {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
99
|
+
@pdf.inumeric 0.85, 4.06, 0.25, 23.37, "INSS", @xml['Servico/Valores/ValorInss']
|
|
100
|
+
@pdf.inumeric 0.85, 4.06, 4.31, 23.37, "IRRF", @xml['Servico/Valores/ValorIr']
|
|
101
|
+
@pdf.inumeric 0.85, 4.06, 8.37, 23.37, "CSLL", @xml['Servico/Valores/ValorCsll']
|
|
102
|
+
@pdf.inumeric 0.85, 4.06, 12.43, 23.37, "COFINS", @xml['Servico/Valores/ValorCofins']
|
|
103
|
+
@pdf.inumeric 0.85, 4.32, 16.49, 23.37, "PIS/PASEP", @xml['Servico/Valores/ValorPis']
|
|
104
|
+
@pdf.ibox 0.85, 20.57, 0.25, 24.22, "Código do Serviço", @xml['Servico/CodigoTributacaoMunicipio']
|
|
105
|
+
@pdf.inumeric 0.85, 3.46, 0.25, 25.07, "Valor Total das Deduções", @xml['Servico/Valores/ValorDeducoes']
|
|
106
|
+
@pdf.inumeric 0.85, 3.46, 3.71, 25.07 , "Base de Cálculo", @xml['Servico/Valores/BaseCalculo']
|
|
107
|
+
@pdf.ibox 0.85, 3.46, 7.17, 25.07, "Alíquota", @xml['Servico/Valores/Aliquota']
|
|
108
|
+
@pdf.inumeric 0.85, 3.46, 10.63, 25.07, "Valor do ISS", @xml['Servico/Valores/ValorIss']
|
|
109
|
+
@pdf.inumeric 0.85, 6.73, 14.09, 25.07, "Crédito", @xml['InfNfse/ValorCredito']
|
|
110
|
+
@pdf.ibox 0.85, 10.38, 0.25, 25.92, "Muncípio da Prestação do Serviço", municipios[@xml['OrgaoGerador/CodigoMunicipio']], :style => :bold
|
|
111
|
+
@pdf.ibox 0.85, 10.19, 10.63, 25.92, "Número Inscrição da Obra", @xml['DadosConstrucaoCivil/CodigoObra'], :style => :bold
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def render_outras
|
|
115
|
+
@pdf.ibox 2.55, 20.57, 0.25, 26.77
|
|
116
|
+
@pdf.ibox 0.85, 20.57, 0.25, 26.77, '', 'OUTRAS INFORMAÇÕES', {border: 0, style: :bold,:align => :center, :valign => :center}
|
|
117
|
+
@pdf.ibox 1.70, 19.57, 0.75, 27.62, "", "#{@xml['InfNfse/OutrasInformacoes']}", {border: 0}
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#encoding: utf-8
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Nfse::Pdf
|
|
5
|
+
class Descricao
|
|
6
|
+
LINEBREAK = "\n"
|
|
7
|
+
|
|
8
|
+
def self.generate(det)
|
|
9
|
+
descricao = "#{det.css('prod/xProd').text}"
|
|
10
|
+
|
|
11
|
+
if need_infAdProd(det)
|
|
12
|
+
descricao += LINEBREAK
|
|
13
|
+
descricao += det.css('infAdProd').text
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if need_fci(det)
|
|
17
|
+
descricao += LINEBREAK
|
|
18
|
+
descricao += "FCI: #{det.css('prod/nFCI').text}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if need_st(det)
|
|
22
|
+
descricao += LINEBREAK
|
|
23
|
+
descricao += "ST: MVA: #{det.css('ICMS/*/pMVAST').text}% "
|
|
24
|
+
descricao += "* Alíq: #{det.css('ICMS/*/pICMSST').text}% "
|
|
25
|
+
descricao += "* BC: #{det.css('ICMS/*/vBCST').text} "
|
|
26
|
+
descricao += "* Vlr: #{det.css('ICMS/*/vICMSST').text}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
descricao
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
def self.need_infAdProd(det)
|
|
34
|
+
!det.css('infAdProd').text.empty?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.need_fci(det)
|
|
38
|
+
!det.css('prod/nFCI').text.empty?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.need_st(det)
|
|
42
|
+
det.css('ICMS/*/vBCST').text.to_i > 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require "prawn"
|
|
2
|
+
require "prawn/measurement_extensions"
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Nfse
|
|
6
|
+
|
|
7
|
+
module Pdf
|
|
8
|
+
class Document
|
|
9
|
+
def initialize(opts = {})
|
|
10
|
+
default_opts = {
|
|
11
|
+
:page_size => 'A4',
|
|
12
|
+
:page_layout => :portrait,
|
|
13
|
+
:left_margin => 0,
|
|
14
|
+
:right_margin => 0,
|
|
15
|
+
:top_margin => 0,
|
|
16
|
+
:botton_margin => 0
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@document = Prawn::Document.new(default_opts.merge(opts))
|
|
20
|
+
|
|
21
|
+
@document.font "Times-Roman"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def method_missing(method_name, *args, &block)
|
|
25
|
+
@document.send(method_name, *args, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
29
|
+
@document.respond_to?(method_name, include_private) || super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def ititle(h, w, x, y, title)
|
|
33
|
+
self.text_box title, :size => 10, :at => [x.cm, Helper.invert(y.cm) - 2], :width => w.cm, :height => h.cm, :style => :bold
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def irectangle(h, w, x, y)
|
|
39
|
+
self.stroke_rectangle [x.cm, Helper.invert(y.cm)], w.cm, h.cm
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def ibox(h, w, x, y, title = '', info = '', options = {})
|
|
43
|
+
box [x.cm, Helper.invert(y.cm)], w.cm, h.cm, title, info, options
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def idate(h, w, x, y, title = '', info = '', options = {})
|
|
47
|
+
tt = info.gsub(/T.*/, '').split('-')
|
|
48
|
+
ibox h, w, x, y, title, "#{tt[2]}/#{tt[1]}/#{tt[0]}", options
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def box(at, w, h, title = '', info = '', options = {})
|
|
52
|
+
options = {
|
|
53
|
+
:align => :left,
|
|
54
|
+
:size => 10,
|
|
55
|
+
:style => nil,
|
|
56
|
+
:valign => :top,
|
|
57
|
+
:border => 1
|
|
58
|
+
}.merge(options)
|
|
59
|
+
self.stroke_rectangle at, w, h if options[:border] == 1
|
|
60
|
+
self.text_box title, :size => 6, :style => :italic, :at => [at[0] + 2, at[1] - 2], :width => w - 4, :height => 8 if title != ''
|
|
61
|
+
self.text_box info, :size => options[:size], :at => [at[0] + 2, at[1] - (title != '' ? 14 : 4) ], :width => w - 4, :height => h - (title != '' ? 14 : 4), :align => options[:align], :style => options[:style], :valign => options[:valign]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def inumeric(h, w, x, y, title = '', info = '', options = {})
|
|
65
|
+
numeric [x.cm, Helper.invert(y.cm)], w.cm, h.cm, title, info, options
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def numeric(at, w, h, title = '', info = '', options = {})
|
|
69
|
+
options = {:decimals => 2}.merge(options)
|
|
70
|
+
info = Helper.numerify(info, options[:decimals]) if info != ''
|
|
71
|
+
box at, w, h, title, info, options.merge({:align => :right})
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def itable(h, w, x, y, data, options = {}, &block)
|
|
75
|
+
self.bounding_box [x.cm, Helper.invert(y.cm)], :width => w.cm, :height => h.cm do
|
|
76
|
+
self.table data, options do |table|
|
|
77
|
+
yield(table)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
data/lib/danfe/helper.rb
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require "prawn/measurement_extensions"
|
|
2
|
+
|
|
3
|
+
module Nfse::Pdf
|
|
4
|
+
class Helper
|
|
5
|
+
def self.numerify(number, decimals = 2)
|
|
6
|
+
number = number.tr("\n","").delete(" ")
|
|
7
|
+
return "" if !number || number == ""
|
|
8
|
+
int, frac = ("%.#{decimals}f" % number).split(".")
|
|
9
|
+
int.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1\.")
|
|
10
|
+
int + "," + frac
|
|
11
|
+
rescue
|
|
12
|
+
number
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.numerify_default_zero(number, decimals = 2)
|
|
16
|
+
number = number.tr("\n","").delete(" ")
|
|
17
|
+
return "0,00" if !number || number == ""
|
|
18
|
+
int, frac = ("%.#{decimals}f" % number).split(".")
|
|
19
|
+
int.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1\.")
|
|
20
|
+
int + "," + frac
|
|
21
|
+
rescue
|
|
22
|
+
number
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.invert(y)
|
|
26
|
+
28.7.cm - y
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.format_quantity(qty)
|
|
30
|
+
return Helper.numerify(qty, RubyDanfe.options.quantity_decimals) if RubyDanfe.options.numerify_prod_qcom
|
|
31
|
+
qty.gsub!(",", ".")
|
|
32
|
+
qty[qty.rindex('.')] = ',' if qty.rindex('.')
|
|
33
|
+
qty
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.format_datetime(string)
|
|
37
|
+
formated_datetime = ""
|
|
38
|
+
|
|
39
|
+
if not string.empty?
|
|
40
|
+
date = extract_date_time(string)
|
|
41
|
+
formated_datetime = date.strftime("%d/%m/%Y %H:%M:%S")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
formated_datetime
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.format_date(string)
|
|
48
|
+
formated_date = ""
|
|
49
|
+
|
|
50
|
+
if not string.empty?
|
|
51
|
+
date = Date.strptime(string, "%Y-%m-%d")
|
|
52
|
+
formated_date = date.strftime("%d/%m/%Y")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
formated_date
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.format_time(string)
|
|
59
|
+
formated_time = ""
|
|
60
|
+
|
|
61
|
+
if not string.empty?
|
|
62
|
+
time = Time.strptime(string, "%H:%M:%S")
|
|
63
|
+
formated_time = time.strftime("%H:%M:%S")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
formated_time
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.extract_time_from_date(string)
|
|
70
|
+
formated_time = ""
|
|
71
|
+
|
|
72
|
+
if not string.empty?
|
|
73
|
+
date = extract_date_time(string)
|
|
74
|
+
formated_time = date.strftime("%H:%M:%S")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
formated_time
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.format_cnpj(string)
|
|
81
|
+
formated_cnpj = ""
|
|
82
|
+
|
|
83
|
+
if not (string.empty? || string.size != 14)
|
|
84
|
+
formated_cnpj = string[0,2] + '.' + string[2,3] + '.' + string[5,3] +
|
|
85
|
+
'/' + string[8,4] + '-' + string[12,2]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
formated_cnpj
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def self.extract_date_time(string)
|
|
94
|
+
begin
|
|
95
|
+
DateTime.strptime(string, "%Y-%m-%dT%H:%M:%S")
|
|
96
|
+
rescue ArgumentError
|
|
97
|
+
DateTime.strptime(string, "%d/%m/%Y %H:%M:%S")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
data/lib/danfe/xml.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require "prawn"
|
|
2
|
+
require "prawn/table"
|
|
3
|
+
require "prawn/measurement_extensions"
|
|
4
|
+
require "nokogiri"
|
|
5
|
+
require 'ostruct'
|
|
6
|
+
require 'yaml'
|
|
7
|
+
require 'date'
|
|
8
|
+
require 'time'
|
|
9
|
+
require 'json'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module Nfse::Pdf
|
|
13
|
+
class XML
|
|
14
|
+
def css(xpath)
|
|
15
|
+
@xml.css(xpath)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def xpath(regex)
|
|
19
|
+
doc = Nokogiri::HTML(@xml.to_s)
|
|
20
|
+
return doc.xpath(regex)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def regex_string(search_string, regex)
|
|
24
|
+
doc = Nokogiri::HTML(search_string)
|
|
25
|
+
return doc.xpath(regex)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(xml)
|
|
29
|
+
@xml = Nokogiri::XML(xml)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def [](xpath)
|
|
33
|
+
node = @xml.css(xpath)
|
|
34
|
+
return node ? node.text : ""
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def render
|
|
38
|
+
if @xml.at_css('infNFe/ide')
|
|
39
|
+
RubyDanfe.render @xml.to_s, :danfe
|
|
40
|
+
elsif @xml.at_css('InfNfse/Numero')
|
|
41
|
+
RubyDanfe.render @xml.to_s, :danfse
|
|
42
|
+
else
|
|
43
|
+
if @xml.at_css('CTeOS')
|
|
44
|
+
RubyDanfe.render @xml.to_s, :dacteos
|
|
45
|
+
else
|
|
46
|
+
RubyDanfe.render @xml.to_s, :dacte
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def collect(ns, tag, &block)
|
|
52
|
+
result = []
|
|
53
|
+
# Tenta primeiro com uso de namespace
|
|
54
|
+
begin
|
|
55
|
+
@xml.xpath("//#{ns}:#{tag}").each do |det|
|
|
56
|
+
result << yield(det)
|
|
57
|
+
end
|
|
58
|
+
rescue
|
|
59
|
+
# Caso dê erro, tenta sem
|
|
60
|
+
@xml.xpath("//#{tag}").each do |det|
|
|
61
|
+
result << yield(det)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
result
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def inject(ns, tag, acc, &block)
|
|
68
|
+
# Tenta primeiro com uso de namespace
|
|
69
|
+
begin
|
|
70
|
+
@xml.xpath("//#{ns}:#{tag}").each do |det|
|
|
71
|
+
acc = yield(acc, det)
|
|
72
|
+
end
|
|
73
|
+
rescue
|
|
74
|
+
# Caso dê erro, tenta sem
|
|
75
|
+
@xml.xpath("//#{tag}").each do |det|
|
|
76
|
+
acc = yield(acc, det)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
acc
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def attrib(node, attrib)
|
|
83
|
+
begin
|
|
84
|
+
return @xml.css(node).attr(attrib).text
|
|
85
|
+
rescue
|
|
86
|
+
""
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|